FrameWork层源码分析(2)-startService的流

作者: ZJ_Rocky | 来源:发表于2017-11-21 14:18 被阅读79次

    主目录见:Android高级进阶知识(这是总目录索引)

    文章之前应一位网友所托,推荐一下他的公众号,我也是关注了下,里面文章还是有质量的,公众号名字是:我就是马云飞,大家有兴趣可以关注哈。

     今天这一篇同样的是为了讲插件化框架做的铺垫,我们知道,插件化框架的开发对程序员对framework知识的熟悉程度非常有要求,同时又要求大家广而采纳众人的思想和自己多思考。今天我们讲的这个startService的流程应该是不可或缺的一部分。首先呢我们来上一张图来理理整体流程:

    startService流程图
    我这里简略说下流程,首先服务会从ContextImpl调用startService方法到AMS,然后AMS调用到bringUpServiceLocked方法的时候会判断是否启动的服务在不同的进程中,如果是则调用startProcessLocked创建一个新的进程,然后调用realStartServiceLocked跨进程调用ActivityThread中的hanleCreateService创建一个新的目标服务并回调目标服务的onCreate方法,最后AMS调用sendServiceARgsLocked跨进程调用ActivityThread中的handleServiceArgs方法回调目标service的onStartCommand方法。

    一.目标

    今天我们的目标也是非常明确,毕竟无目的地分析源码是非常痛苦的一个过程:
    1.了解startService的整体流程;
    2.为插件化做准备工作;

    二.源码分析

     我们知道,服务的启动有两种方式:bindService()和startService()两种,bindService这种方式其实我们在讲从framework分析AIDL生成文件这篇文章的时候已经讲过了,我们今天这里就是讲startService这种方式,我们在Activity中调用startService(),其实是调用了ContextWrapper里面的方法:

      @Override
        public ComponentName startService(Intent service) {
            return mBase.startService(service);//这里的mBase就是ContextImpl类
        }
    

    这个地方其实是应用了一个装饰设计模式,如果对这个模式不是很清楚可以看Decorator装饰模式,ContextImpl这里代表的装饰模式里面的具体组件角色,这样我们就可以看到ContextImpl中的startService:

     @Override
        public ComponentName startService(Intent service) {
            warnIfCallingFromSystemProcess();//如果是系统进程直接调用的startService方法就会报错
            return startServiceCommon(service, mUser);
        }
    

    这里我们直接看到startServiceCommon方法:

      private ComponentName startServiceCommon(Intent service, UserHandle user) {
            try {
                validateServiceIntent(service);
                service.prepareToLeaveProcess(this);
                ComponentName cn = ActivityManagerNative.getDefault().startService(
                    mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                                getContentResolver()), getOpPackageName(), user.getIdentifier());
            ..........
                return cn;
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    

    我们如果有看到上一篇startActivity的源码分析的话,那么应该非常熟悉ActivityManagerNative#getDefault()得到的是远程AMS的ActivityManagerProxy,这里startService方法就是ActivityManagerProxy类中的,我们首先看下ActivityManagerNative类:

    public abstract class ActivityManagerNative extends Binder implements IActivityManager
    

    接着我们看他的getDefault方法:

      static public IActivityManager getDefault() {
            return gDefault.get();
        }
    
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
            protected IActivityManager create() {
    //这里获取到的其实是ActivityManagerService这个服务,在SystemServer启动的时候,就会把ActivityManagerService 注册到ServiceManager中来
                IBinder b = ServiceManager.getService("activity");
                if (false) {
                    Log.v("ActivityManager", "default service binder = " + b);
                }
                IActivityManager am = asInterface(b);
                if (false) {
                    Log.v("ActivityManager", "default service = " + am);
                }
                return am;
            }
        };
    

    这里其实就是一个单例的设计模式,获取到服务对象的IBinder,并且调用asInterface()方法把这个IBinder转换成IActivityManager返回了。这应该熟悉AIDL的人知道,这里的asInterface其实返回的是ActivityManagerProxy对象。这样我们看ActivityManagerProxy的startService方法:

      public ComponentName startService(IApplicationThread caller, Intent service,
                String resolvedType, String callingPackage, int userId) throws RemoteException
        {
            Parcel data = Parcel.obtain();
            Parcel reply = Parcel.obtain();
            data.writeInterfaceToken(IActivityManager.descriptor);
            data.writeStrongBinder(caller != null ? caller.asBinder() : null);
            service.writeToParcel(data, 0);
            data.writeString(resolvedType);
            data.writeString(callingPackage);
            data.writeInt(userId);
            mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
            reply.readException();
            ComponentName res = ComponentName.readFromParcel(reply);
            data.recycle();
            reply.recycle();
            return res;
        }
    

    这里的service就是Intent实例,它里面指定了要启动服务的名称。 参数caller是一个IApplicationThread实例,它是一个在主进程创建的一个Binder对象。在Android应用程序中,每一个进程都用一个ActivityThread实例来表示,而在ActivityThread类中,有一个成员变量mAppThread,它是一个ApplicationThread实例,实现了IApplicationThread接口,它的作用是用来辅助ActivityThread类来执行一些操作,这个我们在后面会看到它是如何用来启动服务的。
     参数resolvedType是一个字符串,表示服务这个Intent的MIME类型,在解析Intent的时候会用到,这里我们没有指定所以为null。
    ActivityManagerProxy类的startService函数把这三个参数写入到data本地变量去,接着通过mRemote.transact函数进入到Binder驱动程序,然后Binder驱动程序唤醒正在等待Client请求的ActivityManagerService进程,最后进入到ActivityManagerService的startService函数中:

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

    这里的参数caller、service和resolvedType分别对应ActivityManagerProxy#startService传进来的三个参数。然后程序会交给mServices这个对象即ActiveServices类的实例,这个类是后面版本出来的,前面旧版本并没有这个类(这次的分析是基于android-25的),所以我们看到ActiveServicesstartServiceLocked方法:

        ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
                int callingPid, int callingUid, String callingPackage, final int userId)
                throws TransactionTooLargeException {
    ......
     ServiceLookupResult res =
                retrieveServiceLocked(service, resolvedType, callingPackage,
                        callingPid, callingUid, userId, true, callerFg, false);
    ......
      ServiceRecord r = res.record;
    ......
            return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        }
    

    startServiceInnerLocked调用了 bringUpServiceLocked(),bringUpServiceLocked()内部调用了realStartServiceLocked()(当然这个地方如果我们配置了android:process属性值的话,那么程序会创建一个ActivityThread进程,在Android应用程序中,每一个进程对应一个ActivityThread实例,所以,这个函数会创建一个thread实例,然后调用ActivityThread.attach函数进一步处理),我们这里不考虑启动的服务在新进程中,我们看realStartServiceLocked()方法:

      private final void realStartServiceLocked(ServiceRecord r,
                ProcessRecord app, boolean execInFg) throws RemoteException {
            if (app.thread == null) {
                throw new RemoteException();
            }
    .....
            r.app = app;
            r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
    
            final boolean newService = app.services.add(r);
            bumpServiceExecutingLocked(r, execInFg, "create");
            mAm.updateLruProcessLocked(app, false, null);
            mAm.updateOomAdjLocked();
    
            boolean created = false;
            try {
    ........
                app.thread.scheduleCreateService(r, r.serviceInfo,
                        mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                        app.repProcState);
                r.postNotification();
                created = true;
            } catch (DeadObjectException e) {
           ......
            } finally {
           ......
            }
    
            if (r.whitelistManager) {
                app.whitelistManager = true;
            }
    
            requestServiceBindingsLocked(r, execInFg);
    
            updateServiceClientActivitiesLocked(app, null, true);
            if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
                r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                        null, null));
            }
    
            sendServiceArgsLocked(r, execInFg, true);
    .......
        }
    

    我们看到程序里面关键有一句app.thread.scheduleCreateService,这里的app是一个ProcessRecord实例,app.thread是ApplicationThreadProxy对象,我们知道客户端与远程服务进程的AIDL是双向通信的关系,ActivityManagerProxy是客户端用来与远程服务进程通讯的,ApplicationThreadProxy是远程服务进程用来与客户端通讯的,所以这里我们看到ApplicationThreadProxyscheduleCreateService方法:

      public final void scheduleCreateService(IBinder token, ServiceInfo info,
                CompatibilityInfo compatInfo, int processState) throws RemoteException {
            Parcel data = Parcel.obtain();
            data.writeInterfaceToken(IApplicationThread.descriptor);
            data.writeStrongBinder(token);
            info.writeToParcel(data, 0);
            compatInfo.writeToParcel(data, 0);
            data.writeInt(processState);
            try {
                mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
                        IBinder.FLAG_ONEWAY);
            } catch (TransactionTooLargeException e) {
                Log.e("CREATE_SERVICE", "Binder failure starting service; service=" + info);
                throw e;
            }
            data.recycle();
        }
    

    这里通过Binder驱动程序回到新进程的ApplicationThread对象中去执行scheduleCreateService方法:

           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);
            }
    

    发送一个消息,这个消息都是由H类处理的,H类就是系统Hander,专门处理系统请求的,比如一些Activity的生命周期等全在这里面。这个H对象是在应用进程的主线程中创建的,所以最终的结果是把创建 Service 的消息传到了主线程,因此Service是运行在主线程中的:

     private final class H extends Handler {  
            ......  
            public void handleMessage(Message msg) {  
                ......  
                switch (msg.what) {  
                    ......  
                    case CREATE_SERVICE:  
                        handleCreateService((CreateServiceData)msg.obj);
                        break;  
                    ......  
                }  
                ......  
            }  
            ......  
        }  
    

    这里要处理的消息是CREATE_SERVICE,它调用ActivityThread类的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 {
    //packageInfo是LoadedApk对象,包含了apk的信息,通过类加载器加载service类,然后反射创建
                java.lang.ClassLoader cl = packageInfo.getClassLoader();
                service = (Service) cl.loadClass(data.info.name).newInstance();
            } catch (Exception e) {
            ......
            }
    
            try {
                if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
     //创建ContextImpl对象
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                context.setOuterContext(service);
     //创建Application对象
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManagerNative.getDefault());
      //回调要启动的service中的onCreate方法
                service.onCreate();
                mServices.put(data.token, service);
                try {
      //通知远程服务,service创建完成
                    ActivityManagerNative.getDefault().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } catch (Exception e) {
           ......
            }
        }
    

    到这一步service的创建就已经完成,那么service的其他回调方法的调用时机是在什么时候呢?在realStartServiceLocked()方法中调用了scheduleCreateService之后,在方法最后会调用sendServiceArgsLocked()方法,和scheduleCreateService类似地,最终也会调用到H类中的handleMessage:

      case SERVICE_ARGS:
                  handleServiceArgs((ServiceArgsData)msg.obj);
                  break;
    

    然后会调用ActivityThread类中的handleServiceArgs方法:

        private void handleServiceArgs(ServiceArgsData data) {
            Service s = mServices.get(data.token);
            if (s != null) {
                try {
                ......
                    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 {
    //同样地通知远程服务service启动完成
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                    ensureJitEnabled();
                } catch (Exception e) {
    .......           
                }
            }
        }
    

    这里的onCreate和onStartCommand方法的回调流程大致一样,大家可以自己走下流程应该就很清楚了,从流程上看,其实启动服务不是非常复杂,如果有不明白的,大家可以对照前面画的流程图看看。

    总结:启动服务的流程相对而言不会太难,我们这里只要明白整体的流程,到时讲插件化框架的时候,如果有必要会把某个部分拿出来讲解清楚,希望大家发现错误能即时提出哈,共同进步。

    相关文章

      网友评论

        本文标题:FrameWork层源码分析(2)-startService的流

        本文链接:https://www.haomeiwen.com/subject/mogmvxtx.html