从Android6.0源码的角度剖析Service启动过程

Service是Android四大组件之一,与Activity的可视化界面相反,Service没有向用户提供交互界面,因此常被用于执行后台任务。Service的启动方式有两种:普通启动绑定启动,其中,前者通过Context.startService方法启动,常用于执行普通的后台任务;后者通过Context.bindService方法启动,用于执行与启动组件有数据交互的后台任务。本文将从Android6.0源码角度,重点阐述这两种方式的具体启动过程。

1. 启动普通Service

 在Android应用开发中,通常普通启动一个Service是调用Context的startService()方法实现的,Context描述一个应用程序环境的信息(即上下文),通过它我们可以获取应用程序的资源和类(包括应用级别操作,如启动Activity,发广播,接受Intent等)。Context是一个抽象类,它的具体实现类是ContextImpl,因此当我们调用Context的startService方法普通启动Service时,实际执行的是ContextImpl的startService方法。在ContextImpl的startService()方法中,该方法会直接调用ContextImpl的startServiceCommon()方法执行接下来的调用逻辑,其源码如下:

private ComponentName startServiceCommon(Intent service, UserHandle user) {
    try {
        validateServiceIntent(service);
        service.prepareToLeaveProcess();
        // ActivityManagerNative.getDefault()即AMS
        ComponentName cn = ActivityManagerNative.getDefault().startService(
            mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                getContentResolver()), 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());
            }
        }
        return cn;
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
}

 从startServiceCommon()方法源码可知,它主要完成两部分任务:(1) 调用ActivityManagerNative.getDefault()的startService()方法执行具体的启动过程,并返回一个ComponentName的对象cn;(2) 如果(1)执行完毕后返回的cn不为空,就判断启动service是否具有执行权限等情况。其中,ActivityManagerNative.getDefault()返回一个IActivityManager,它继承于接口android.os.IInterface,这个接口就厉害了,还记得在我的另一篇文章《Android源码解析之浅析Binder工作原理》中有提到过,IIterface接口通常出现在Binder通信机制中,它表明在IPC通信过程中远程Server能够提供什么样的能力或称Client与Server之间的契约,Server端的Binder本地对象和Client端的Binder代理对象均需要继承该接口。也就是说,关于service的启动,很可能是一次跨进程通信。当然,现在下结论还有点早,我们还需要把Binder本地对象和Binder代理对象找出来。果然,ActivityManagerNative就是那个Server端的Binder实体,因为它同时继承了IBinder和IIterface。同时,我们也在ActivityManagerNative源码中找到了一个内部类ActivityManagerProxy,从名字我们就能够猜测到它就是那个Binder的代理对象,何况它继承了IInterface。这就验证了:Service的启动实质是一次基于Binder机制的远程跨进程通信,即最终的Service启动工作是交给系统进程中的服务ActivityManagerService(简称"AMS")来完成。
 为什么是ActivityManagerService?从gDefault对象的定义来看,它是一个单例对象,当该对象的get()方法被调用时,Singleton的create()方法会被调用,具体工作为:首先,调用ServiceManager的getService()获得名为"activity"的远程服务Binder实体引用,通过跟踪与ServiceManager相关源码,我们可以知道其实这一步也是一次远程IPC,而ServiceManager只是一个用于管理这些Service的管理器;然后,调用ActivityManagerNative的asInterface()方法返回一个ActivityManagerProxy对象给应用进程,之所以一定返回该代理对象,是因为我们的应用进程与系统进程不可能是同一个进程。getDefault()相关源码如下:

// 位于ActivityManagerNative.java
static public IActivityManager getDefault() {
    // 返回ActivityManagerSevice实例
    return gDefault.get();
}

// 位于ActivityManagerNative.java
// 单例模式
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        // Binder本地实体的引用
        IBinder b = ServiceManager.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        // 返回Binder代理对象ActivityManagerProxy
        // 因为我们的应用不可能与系统进程归属于同一个进程
        IActivityManager am = asInterface(b);
        if (false) {
            Log.v("ActivityManager", "default service = " + am);
        }
        return am;
    }
};
// 位于ActivityManagerNative.java
// 将Binder对象转换为IActivityManager
static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    // 返回Binder本地对象,但这里in应该恒为null
    IActivityManager in =
        (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
	// 返回Binder代理对象
    return new ActivityManagerProxy(obj);
}

 也就是说,gDefault.get()=ActivityManagerProxy?此言差矣!我们知道,ActivityManagerProxy中的方法,比如startService,它只是对调用参数进行了封装,真正的实现是交给远程服务的Binder实体(本地对象)完成,这个Binder实体就是ActivityManagerNative,但是ActivityManagerNative又是个抽象类,像startService这些方法均是抽象方法,ActivityManagerService才是它的实现类。因此,我们可以得出:gDefault.get()=ActivityManagerService

// 位于ActivityManagerProxy
public ComponentName startService(IApplicationThread caller, Intent service,
     String resolvedType, String callingPackage, int userId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        // 封装函数参数到Parcel类型的data对象,
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeString(callingPackage);
        data.writeInt(userId);
        // 通过远程Binder实体的引用,调用Binder请求处理方法并将处理结果返回写入reply
        // 这步由内核中的Binder驱动控制,最终调用远程Binder实体中的onTransact,
        // 该方法会通过分析传入的函数code(编号)决定调用哪个方法
        mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        ComponentName res = ComponentName.readFromParcel(reply);
        data.recycle();
        reply.recycle();
        return res;
    }
    
// 位于ActivityManagerNative    
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
    throws RemoteException {
    switch (code) {
      	...
        // 响应远程请求start Service
        case START_SERVICE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            Intent service = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            String callingPackage = data.readString();
            int userId = data.readInt();
            // 调用ActivityManagerService完成Service的启动工作
            ComponentName cn = startService(app, service, resolvedType, 
                                            callingPackage, userId);
            reply.writeNoException();
            ComponentName.writeToParcel(cn, reply);
            return true;
        }
        ...
    }

小结1:

  • ActivityManagerNative.getDefault()即ActivityManagerService,Service启动过程实质是一次基于Binder机制的远程跨进程通信,最终的启动工作由系统进程中的ActivityManagerService服务完成。

接下来,我们就着重分析下ActivityManagerService的startService是如何启动Service,它的源码如下:

// ActivityManagerService.startService()
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
                     String resolvedType, String callingPackage, int userId)
    throws TransactionTooLargeException {
    ...
    synchronized(this) {
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        // 调用ActiveServices的startServiceLocked方法
        ComponentName res = mServices.startServiceLocked(caller, service,
                      resolvedType, callingPid, callingUid, callingPackage, userId);
        Binder.restoreCallingIdentity(origId);
        return res;
    }
}

 从上述源码来看,ActivityManagerService的startService()并没有执行具体的功能,而是直接调用了ActiveServices的startServiceLocked()方法,该方法首先会获得一个ServiceRecord对象,ServiceRecord用于描述一个Service记录,它缓存了与Service有关的变量,并且会一直贯穿整个Service的启动过程;然后将该ServiceRecord对象和Intent类型的service对象作为参数调用ActiveServices的startServiceInnerLocked()方法,该方法继续调用ActiveServices的bringUpServiceLocked()方法,在这个方法中,我们最终会看到它会调用一个名为realStartServiceLocked的方法,从名字可以猜测得到从这个方法开始就是真正进入启动过程了,我们来看看这个方法的源码:

// ActiveServices.realStartServiceLocked()
private final void realStartServiceLocked(ServiceRecord r,
             ProcessRecord app, boolean execInFg) throws RemoteException {
    // (1) 判断应用进程是否存在,如果为null,抛出异常
    if (app.thread == null) {
        throw new RemoteException();
    }
	...
    boolean created = false;
    try {
        ...
        // 执行ApplicationThread.scheduleCreateService
        // 将执行逻辑从系统进程切换到应用进程,即由“内核态”切换到“用户态”
        app.thread.scheduleCreateService(r, r.serviceInfo,
            	mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
            	app.repProcState);
        r.postNotification();
        // 设置启动标志created为true
        created = true;
    } catch (DeadObjectException e) {
        Slog.w(TAG, "Application dead when creating service " + r);
        mAm.appDiedLocked(app);
        throw e;
    } finally {
        if (!created) {
            // Keep the executeNesting count accurate.
            final boolean inDestroying = mDestroyingServices.contains(r);
            serviceDoneExecutingLocked(r, inDestroying, inDestroying);

            // Cleanup.
            if (newService) {
                app.services.remove(r);
                r.app = null;
            }

            // Retry.
            if (!inDestroying) {
                scheduleServiceRestartLocked(r, false);
            }
        }
    }

    requestServiceBindingsLocked(r, execInFg);

    updateServiceClientActivitiesLocked(app, null, true);

    // If the service is in the started state, and there are no
    // pending arguments, then fake up one so its onStartCommand() will
    // be called.
    if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                                                        null, null));
    }
	// (2)当Service的onCreate方法被调用后
    // 该方法最终会调用Service的onStartCommand()方法
    sendServiceArgsLocked(r, execInFg, true);
	...
}

该方法主要做两件事情:
 (1) 通过app.thread返回的对象判断当前应用进程是否存在,如果存在(app.thread!=null),则调用返回对象的scheduleCreateService()方法执行接下来的启动工作,否则,抛出"RemoteException"异常。那么,app.thread返回的对象是什么呢?通过跟踪源码发现,app.thread返回一个IApplicationThread对象,但是IApplicationThread是一个接口且继承系统接口android.os.IInterface,并且ApplicationThreadNative、ApplicationThreadProxy均继承于该接口。由之前对AMS IPC的分析,我们很容易可以猜测得到app.thread.scheduleCreateService()又是一次远程跨进程调用,并且ApplicationThread、ApplicationThreadProxy分别是“服务端”的Binder本地对象和"客户端"的Binder代理对象。但是,与AMS IPC相反的是,这次的"客户端"的角色由系统进程AMS“扮演”,而"服务端"角色换成了应用进程,ApplicationThreadProxy对象就是ApplicationThread在AMS中的代理,AMS将通过该代理对象与ApplicationThread进行通信。也就是说,service的最终具体启动工作还是在应用进程中完成的,且app.thread=ApplicationThread。ApplicationThreadNative、ApplicationThreadProxy等类关系如下:

// “契约”接口
public interface IApplicationThread extends IInterface{}

// 服务端Binder本地对象
public abstract class ApplicationThreadNative extends Binder
		implements IApplicationThread {
	...
	// 客户端Binder代理对象
	class ApplicationThreadProxy implements IApplicationThread {}
}

// 主线程管理器
public final class ActivityThread {
    final H mH = new H();
    ...
    // ApplicationThreadNative实现类,提供真正的服务实现(Binder本地对象)
    private class ApplicationThread extends ApplicationThreadNative {
        
    }
}

 接下来,我们重点分析下应用进程是如何完成Service的启动工作。首先,对于ApplicationThread的scheduleCreateService()方法来说,它是运行在"服务端"的Binder线程池的线程中(原因参考本文),但是该方法并没有执行具体的启动工作,而是调用sendMessage()方法向mH发送一个H.CREATE_SERVICE消息,通过查看源码可知,sendMessage()方法和mH对象均属于ActivitiyThread,并且mH是一个Handler!由源码注释我们可以了解到,ActivitiyThread是一个在应用进程中用于管理主线程(main thread)的运行,比如管理和运行activities、broadcasts或者在activity执行的一些操作,从某些程度来说,ActivitiyThread就是我们熟悉的主线程或称UI线程,它是APP的真正入口。当开启APP后,系统会调用APP的main()开始运行,此时ActivityThread就会被创建,并且在主线程中开启一个消息循环队列,而mH对象(Handler)就是这个消息循环队列的“操作手”,用来接收和处理那些传递到主线程的所有消息,其中,处理消息工作由mH.handleMessage()完成,它将根据消息编号(H.CREATE_SERVICE)执行最终的处理业务。对于CREATE_SERVICE消息,即启动service的任务,handleMessage最终交给ActivityThread的handleCreateService()方法来完成。

// ApplicationThread.scheduleCreateService()
// 运行在Binder线程池
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);
}

// ActivityThread.sendMessage()
// 主线程
public final class ActivityThread {
    // 主线程的Handler
    final H mH = new H();
    ...
    // 实现子线程向主线程发送消息
    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发送一个msg消息
        mH.sendMessage(msg);
	}
    
    private class H extends Handler {
        public static final int CREATE_SERVICE = 114;
        ...
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            	switch (msg.what) {
                    ...
                	case CREATE_SERVICE:
                    	Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, 
                                         "serviceCreate");
                        // 处理Service创建工作
                    	handleCreateService((CreateServiceData)msg.obj);
                    	Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
            }
        }
}

 最后,我们看下ActivityThread.handleCreateService()方法为了完成Service的启动,做了哪些工作:
 (a) 创建类加载器,通过该加载器创建要启动的Service对象;
 (b) 创建Application对象并调用其onCreate方法,并且在应用被启动后Application始终只会被创建一次;

// LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
	// 如果mApplication被创建,则直接返回
	if (mApplication != null) {
		return mApplication;
	}

	Application app = null;
    try {
    	java.lang.ClassLoader cl = getClassLoader();
		...
   		 ContextImpl appContext = 
   		 	ContextImpl.createAppContext(mActivityThread, this);
   		 // 创建Application
   		 app = mActivityThread.mInstrumentation.newApplication(
    						cl, appClass, appContext);
    	appContext.setOuterContext(app);
   	 } catch (Exception e) {
    	
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;
    if(instrumentation != null) {
    	// 调用Application的onCreate方法
        instrumentation.callApplicationOnCreate(app);
    }

 © 创建ContextImpl对象,并通过Service的attach方法建立两者之间的关系,这个过程与Activity的启动相似;
 (d) 调用Service的onCreate()方法,同时将Service对象插入到mService列表中。至此,随着onCreate()方法被调用,Service成功被启动,并且onCreate()运行在应用进程的主线程,所以尽量不要在该方法中执行耗时任务,否则,会出现ANR异常。

final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();

handleCreateService()源码

private void handleCreateService(CreateServiceData data) {
    // If we are getting ready to gc after going to the background, well
    // we are back active so skip it.
    unscheduleGcIdler();
	
    LoadedApk packageInfo = getPackageInfoNoCheck(
        data.info.applicationInfo, data.compatInfo);
    Service service = null;
    try {
        // (1) 创建类加载器
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        // 加载名为name的Service类,即实例化Service
        service = (Service) cl.loadClass(data.info.name).newInstance();
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to instantiate service " + data.info.name
                + ": " + e.toString(), e);
        }
    }

    try {
        if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
		// (3)创建APP的ContextImpl
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        
        context.setOuterContext(service);
		// (2) 创建Application
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        // 将Context与Service绑定
        service.attach(context, this, data.info.name, data.token, app,
                       ActivityManagerNative.getDefault());
        // (4) 调用Service的onCreate(),即Service启动成功
        service.onCreate();
        // 将Service对象插入到列表中缓存
        mServices.put(data.token, service);
        try {
            ActivityManagerNative.getDefault().serviceDoneExecuting(
                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
        } catch (RemoteException e) {
            // nothing to do.
        }
    } catch (Exception e) {
        if (!mInstrumentation.onException(service, e)) {
            throw new RuntimeException(
                "Unable to create service " + data.info.name
                + ": " + e.toString(), e);
        }
    }
}

(2) 在(1)执行完毕后,Service的onCreate()方法被调用,就说明Service已经被启动了。但我们知道,当Serivce启动后除了它的onCreate()方法被调用,还有另外一个方法也会被调用,即onStartCommand,接下来,我们就分析下onStartCommand方法是如何被调用的。首先,我们回到ActiveServices.realStartServiceLocked()中找到sendServiceArgsLocked(r, execInFg, true),该方法会从SerivceRecord中取出ApplicationThread对象,然后调用该对象中的scheduleServiceArgs()方法向主线程ActivityThread发送一个H.SERVICE_ARGS消息。当主线程接收到该消息后,就会执行ActivityThread.handleServiceArgs(),,然后再该方法中Service的onStartCommand方法就会被调用。具体的调用流程:

// ActiveServices.sendServiceArgsLocked()
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
  		boolean oomAdjusted) throws TransactionTooLargeException {
	...
    // 调用ApplicationThread的scheduleServiceArgs
    r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);
    ...
}

// ActivityThread.ApplicationThread.scheduleServiceArgs()
// 运行在Binder线程池的线程中
public final void scheduleServiceArgs(IBinder token, boolean taskRemoved, int startId,
                                      int flags ,Intent args) {
    ServiceArgsData s = new ServiceArgsData();
    s.token = token;
    s.taskRemoved = taskRemoved;
    s.startId = startId;
    s.flags = flags;
    s.args = args;
	// 向主线程发送一个H.SERVICE_ARGS消息
    sendMessage(H.SERVICE_ARGS, s);
}

// ActivityThread.handleServiceArgs()
// 运行在主线程中
private void handleServiceArgs(ServiceArgsData data) {
    Service s = mServices.get(data.token);
    if (s != null) {
        try {
            if (data.args != null) {
                data.args.setExtrasClassLoader(s.getClassLoader());
                data.args.prepareToEnterProcess();
            }
            int res;
            if (!data.taskRemoved) {
                // 调用Service的onStartCommand()方法
                res = s.onStartCommand(data.args, data.flags, data.startId);
            } else {
                s.onTaskRemoved(data.args);
                res = Service.START_TASK_REMOVED_COMPLETE;
            }

            QueuedWork.waitToFinish();

            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                    data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
            } catch (RemoteException e) {
                // nothing to do.
            }
            ensureJitEnabled();
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                    "Unable to start service " + s
                    + " with " + data.args + ": " + e.toString(), e);
            }
        }
    }
}

小结2:

  • app.thread=ApplicationThread。ActivityManagerService是运行在系统进程的服务,负责系统中所有Activity、Service等组件的生命周期;ActivityThread是App的真正入口,即传说中的主线程或称UI线程,它将与ActivityManagerService配合,实现对Activity、Service等组件的管理;ApplicationThread是ActivityManagerService(系统服务)与ActivityThread(主线程)交互的桥梁,当ActivityManagerService需要管理Application(应用进程)中的Activity或Service等组件的生命周期时,会通过ApplicationThread的代理对象ApplicationThreadProxy与ActivityThread进行通信,然后告知ActivityThread需要执行什么操作。
  • 每调用一次Context.startService()启动同一个Service,它的onCreate()方法只会被调用一次,而其onStartCommand()方法每次都会被调用。需要注意的是,Service运行在主线程,因此在Service的onCreate等方法中尽量不要执行耗时任务,否则会出现ANR异常。

startService调用流程如下:
在这里插入图片描述

2. 绑定Service

 绑定启动Service的实现过程与普通启动Service的流程是大致相同的,都是借助基于Binder机制的IPC方式与AMS交互实现的,只是绑定启动调用的是Context.bindService()方法,由前面的分析可知,这步的操作实际上是执行了ContextImpl的bindService()方法。bindService方法并没有执行具体的业务逻辑,而是将工作交给了ContextImpl.bindServiceCommon()方法,它的源码下:

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

// ContextImpl
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
                                  UserHandle user) {
    IServiceConnection sd;
    if (conn == null) {
        throw new IllegalArgumentException("connection is null");
    }
    if (mPackageInfo != null) {
        // (1) 将客户端的ServiceConnection转化为ServiceDispatcher.InnerConnction对象
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                                               mMainThread.getHandler(), flags);
    } else {
        throw new RuntimeException("Not supported in system context");
    }
    validateServiceIntent(service);
    try {
        IBinder token = getActivityToken();
        if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
            && mPackageInfo.getApplicationInfo().targetSdkVersion
            < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            flags |= BIND_WAIVE_PRIORITY;
        }
        service.prepareToLeaveProcess();
        // (2) 调用AMS的binderService方法
        int res = ActivityManagerNative.getDefault().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 new RuntimeException("Failure from system", e);
    }
}

bindServiceCommon源码分析:
 (1) 首先,bindServiceCommon调用LoadedApk.getServiceDispatcher()方法获得IServiceConnection对象sd,该方法接受一个ServiceConnection对象conn作为参数,并创建一个key、value分别为ServiceConnection和LoadedApk.ServiceDispatcher的map集合,也就是说,ServiceConnction与LoadedApk.ServiceDispatcher是一个映射关系。然后,判断集合map是否为null,如果不为null,则从集合中取出与ServiceConnection对象相关联的LoadedApk.ServiceDispatcher对象。当然,如果map集合中不存在对象sd,则new一个ServiceDispatcher对象,并将其与ServiceConnection对象c作为一条key-value记录插入到map集合中缓存。源码如下:

public final IServiceConnection getServiceDispatcher(ServiceConnection c,
                       Context context, Handler handler, int flags) {
    synchronized (mServices) {
        LoadedApk.ServiceDispatcher sd = null;
        ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = 
            						mServices.get(context);
        // 从map集合中取出 LoadedApk.ServiceDispatcher缓存
        if (map != null) {
            sd = map.get(c);
        }
        // 如果sd不存在map集合中,创建它
        if (sd == null) {
            sd = new ServiceDispatcher(c, context, handler, flags);
            if (map == null) {
                map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
                // 存储一个应用当前活动的ServiceConnection
                // 与LoadedApk.ServiceDispatcher的映射关系
                mServices.put(context, map);
            }
            map.put(c, sd);
        } else {
            sd.validate(context, handler);
        }
        return sd.getIServiceConnection();
    }
}

 but,搞了半天又是IServiceConnection、又是ServiceDispatcher的到底要干嘛?实际上,考虑到bindService可能是跨进程的,而ServiceConnect对象运行在客户端,为了让自己的方法(即onServiceDisconnectedonServiceConnected)能够正常被远程服务端回调,ServiceConnect对象就必须借助Binder机制来实现。它的实现原理是将客户端的ServiceConnection对象转换化为ServiceDispatcher.InnerConnection对象,并且ServiceDispatcher是衔接ServiceConnection和InnerConnection的桥梁,而InnerConnection恰好可以充当Binder本地对象的角色。LoadedApk.ServiceDispatcher相关源码如下:

static final class ServiceDispatcher {
    private final ServiceDispatcher.InnerConnection mIServiceConnection;
    private final ServiceConnection mConnection;
    ...
    // 构造方法
    ServiceDispatcher(ServiceConnection conn,
                          Context context, Handler activityThread, int flags) {
        mIServiceConnection = new InnerConnection(this);
        mConnection = conn;
        mContext = context;
        mActivityThread = activityThread;
        mLocation = new ServiceConnectionLeaked(null);
        mLocation.fillInStackTrace();
        mFlags = flags;
    }
    
    // 运行在远程服务端的Binder实体或称Binder本地对象
    private static class InnerConnection extends IServiceConnection.Stub {
        final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;
        // 缓存当前的LoadedApk.ServiceDispatcher对象
		InnerConnection(LoadedApk.ServiceDispatcher sd) {
           mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
        }
        
        // 远程方法,执行调用客户端ServiceConnect对象的回调方法
        public void connected(ComponentName name, IBinder service) throws 
            RemoteException {
                LoadedApk.ServiceDispatcher sd = mDispatcher.get();
            	// 调用LoadedApk.ServiceDispatcher的connected方法
            	// 该方法最终会调用ServiceConnect的回调方法
                if (sd != null) {
                    sd.connected(name, service);
                }
            }
        }
}

 (2) 在(1)获得与ServiceConnect对应的LoadedApk.ServiceDispatcher对象后,bindServiceCommon接着将该对象作为参数继续调用ActivityManagerService(即app.thread,简称AMS)的bindService()方法,将业务逻辑切换由应用进程到系统进程的AMS服务中。在AMS的bindService方法中,直接调用ActiveServices的bindServiceLocked()方法,bindServiceLocked方法再调用bringUpServiceLocked,bringUpServiceLocked又会调用realStartServiceLocked。realStartServiceLocked的执行逻辑与普通启动Service一致,最终都是通过ApplicationThread来完成Service对象的创建并执行其onCreate方法,这里不再重复分析。realStartServiceLocked源码如下:

private final void realStartServiceLocked(ServiceRecord r,
                     ProcessRecord app, boolean execInFg) throws RemoteException {
    if (app.thread == null) {
        throw new RemoteException();
    }
    ...
    boolean created = false;
    try {
        ...
        // startService:调用onCreate
        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.thread.scheduleBindService
    requestServiceBindingsLocked(r, execInFg);

    updateServiceClientActivitiesLocked(app, null, true);

    // If the service is in the started state, and there are no
    // pending arguments, then fake up one so its onStartCommand() will
    // be called.
    if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                                                        null, null));
    }
    // 启动onStartCommand方法
    sendServiceArgsLocked(r, execInFg, true);
	...
}

 与普通启动Service不同的是,绑定启动Service不仅会执行app.thread.scheduleCreateService,还会执行app.thread.scheduleBindService,这个从跟踪requestServiceBindingsLocked代码可以确定。接着,我们就来看ApplicationThread(即app.thread)的scheduleBindService的方法,scheduleBindService会向主线程ActivityThread发送一个H.BIND_SERVICE消息,ActivitiyThread的H(Handler对象)接收到该消息后,就会调用ActivityThread的handleBindService方法,源码如下:

private void handleBindService(BindServiceData data) {
    // 获取对应的Service对象
    Service s = mServices.get(data.token);
    if (DEBUG_SERVICE)
        Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
    if (s != null) {
        try {
            data.intent.setExtrasClassLoader(s.getClassLoader());
            data.intent.prepareToEnterProcess();
            try {
                if (!data.rebind) {
                    // 调用Service的onBind方法
                   	// 返回远程Service中Binder本地对象的引用
                    IBinder binder = s.onBind(data.intent);
                    // 调用AMS的publicService方法
                    ActivityManagerNative.getDefault().publishService(
                        data.token, data.intent, binder);
                } else {
                    // 调用Service的onBind方法
                    s.onRebind(data.intent);
 					// 调用AMS的serviceDoneExecuting方法
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                }
                ensureJitEnabled();
            } catch (RemoteException ex) {
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                    "Unable to bind to service " + s
                    + " with " + data.intent + ": " + e.toString(), e);
            }
        }
    }
}

 在ActivityThread的handleBindService方法中,它首先会判断Service是否已经被绑定启动,如果data.rebind不为空,说明Service已经被绑定启动,这是会调用Service的onRebind方法,就不会再调用Service的onBind方法,否则,调用Service的onBind方法,然后调用AMS的publishService方法进入绑定启动Service逻辑。publishService方法会调用ActiveServices的publishServiceLocked方法,在该方法最终会调用LoadedApk.ServiceDispatcher.InnerConnection内部类的connected方法,在connected实现回调客户端的ServiceConnection的方法,相关源码如下:

// ActiveServices.publishServiceLocked()方法
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
    ...
    ConnectionRecord c = clist.get(i);
    try {
        // 调用ServiceDispatcher.InnerConnection的connected方法
        // 实现回调客户端ServiceConnection的方法
        c.conn.connected(r.name, service);
    } catch (Exception e) {
         Slog.w(TAG, "Failure sending service " + r.name +
                   " to connection " + c.conn.asBinder() +
                   " (in " + c.binding.client.processName + ")", e);
   }    
}

// LoadedApk.ServiceDispatcher.InnerConnection内部类
private static class InnerConnection extends IServiceConnection.Stub {
    final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

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

    public void connected(ComponentName name, IBinder service) throws RemoteException {
        LoadedApk.ServiceDispatcher sd = mDispatcher.get();
        if (sd != null) {
            // 调用LoadedApk.ServiceDispatcher的connected方法
            sd.connected(name, service);
        }
    }
}

 从LoadedApk.ServiceDispatcher.InnerConnection内部类的connected方法可知,它会调用LoadedApk.ServiceDispatcher方法的connected方法,该方法首先会判断mActivityThread对象的为空情况,实际上该对象是一个Handler且属于主线程,从前面ServiceDispatcher的创建来看,mActivityThread不会为null,因此,它会继续执行mActivityThread.post,从而实现将逻辑由服务端切换到主线程中。也就是说,ServiceConnection的回调方法,是在主线程中被回调的!相关源码如下:

// LoadedApk.ServiceDispatcher.connected()
public void connected(ComponentName name, IBinder service) {
    if (mActivityThread != null) {
        // 主线程中执行
        mActivityThread.post(new RunConnection(name, service, 0));
    } else {
        doConnected(name, service);
    }
}
// LoadedApk.ServiceDispatcher.RunConnection内部类
private final class RunConnection implements Runnable {
    RunConnection(ComponentName name, IBinder service, int command) {
        mName = name;
        mService = service;
        mCommand = command;
    }

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

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

 在RunnConnection中,由于command=0,因此,会调用LoadedApk.ServiceDispatcher.doConnected()方法,该方法最终实现对ServiceConnection的onServiceConnected的回调。源码如下:

// LoadedApk.ServiceDispatcher.doConnected()方法
public void doConnected(ComponentName name, IBinder service) {
    ServiceDispatcher.ConnectionInfo old;
    ServiceDispatcher.ConnectionInfo info;

    synchronized (this) {
        if (mForgotten) {
            // We unbound before receiving the connection; ignore
            // any connection received.
            return;
        }

        old = mActiveConnections.get(name);
        if (old != null && old.binder == service) {
            // Huh, already have this one.  Oh well!
            return;
        }

        if (service != null) {
            // A new service is being connected... set it all up.
            mDied = false;
            info = new ConnectionInfo();
            info.binder = service;
            info.deathMonitor = new DeathMonitor(name, service);
            try {
                // 调用Service的linkToDeath
                service.linkToDeath(info.deathMonitor, 0);
                mActiveConnections.put(name, info);
            } catch (RemoteException e) {
                // This service was dead before we got it...  just
                // don't do anything with it.
                mActiveConnections.remove(name);
                return;
            }

        } else {
            // The named service is being disconnected... clean up.
            mActiveConnections.remove(name);
        }

        if (old != null) {
            old.binder.unlinkToDeath(old.deathMonitor, 0);
        }
    }

    // If there was an old service, it is not disconnected.
    if (old != null) {
        mConnection.onServiceDisconnected(name);
    }
    // If there is a new service, it is now connected.
    if (service != null) {
        // 调用ServiceConnection的onServiceConnected
        mConnection.onServiceConnected(name, service);
    }
}

public void doDeath(ComponentName name, IBinder service) {
    mConnection.onServiceDisconnected(name);
}

小结3:

  • 当多次绑定同一个Service时,Service的onBind方法只会执行一次,除非Service被终止了。另外,客户端中ServiceConnection的回调方法是在主线程被回调的,用于通知客户端本地绑定连接的状态,因此,尽量不要在回调方法中执行耗时任务,否则,会出现ANR异常。当多次绑定同一个Service时,ServiceConnection的回调方法会被回调多次。
  • startService与bindService可以同时执行

3. 停止/解绑Service

3.1 停止Service

在这里插入图片描述
handleStopService()源码如下:

//ActivityThread.handleStopService()
private void handleStopService(IBinder token) {
    // (1)从缓存列表中移除Service对象,并返回
    Service s = mServices.remove(token);
    if (s != null) {
        try {
            if (localLOGV) Slog.v(TAG, "Destroying service " + s);
            // (2)调用Service的onDestory()方法
            s.onDestroy();
            Context context = s.getBaseContext();
       
            if (context instanceof ContextImpl) {
                final String who = s.getClassName();
                // (3)清理注册信息
                // 调用mPackageInfo.removeContextRegistration()
                ((ContextImpl) context).scheduleFinalCleanup(who, "Service");
            }

            QueuedWork.waitToFinish();

            try {
                ActivityManagerNative.getDefault().serviceDoneExecuting(
                    token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
            } catch (RemoteException e) {
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                    "Unable to stop service " + s
                    + ": " + e.toString(), e);
            }
            Slog.i(TAG, "handleStopService: exception for " + token, e);
        }
    } else {
        Slog.i(TAG, "handleStopService: token=" + token + " not found.");
    }
    //Slog.i(TAG, "Running services: " + mServices);
}

 从源码可知,该方法主要完成三件事情:
 (1) 从缓存列表mServices中移除指定的Service对象;
 (2) 调用Service的onDestory()方法;
 (3) 调用ActivityThread的performFinalCleanup()清除Context注册信息。

final void performFinalCleanup(String who, String what) {
	//Log.i(TAG, "Cleanup up context: " + this);
	mPackageInfo.removeContextRegistrations(getOuterContext(), who, what);
}
3.2 解绑Service

在这里插入图片描述
handleUnbindService源码如下:

private void handleUnbindService(BindServiceData data) {
    // 从缓存列表获取Service对象
    Service s = mServices.get(data.token);
    if (s != null) {
        try {
            data.intent.setExtrasClassLoader(s.getClassLoader());
            data.intent.prepareToEnterProcess();
            // 调用Service的onUnbind方法
            boolean doRebind = s.onUnbind(data.intent);
            try {
                if (doRebind) {
                    ActivityManagerNative.getDefault().unbindFinished(
                        data.token, data.intent, doRebind);
                } else {
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                }
            } catch (RemoteException ex) {
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(s, e)) {
                throw new RuntimeException(
                    "Unable to unbind to service " + s
                    + " with " + data.intent + ": " + e.toString(), e);
            }
        }
    }
}

 解绑过程与绑定过程一致,最终ServiceConnection的onServiceDisconnected在主线程中被调用。

发布了83 篇原创文章 · 获赞 293 · 访问量 30万+

猜你喜欢

转载自blog.csdn.net/AndrExpert/article/details/87893094