美文网首页
2019-04-19 startService 源码解析

2019-04-19 startService 源码解析

作者: 猫KK | 来源:发表于2019-04-19 16:44 被阅读0次

    先来一张时序图 注:本次的源码是 9.0 版本。

    startService-时序图.png
    先来看 startService 方法
    @Override
        public ComponentName startService(Intent service) {
            return mBase.startService(service);
        }
    

    直接调用 mBase 的 startService 方法,其中 mBase 是 ContextImpl 实例。为什么是呢?来看 Activity 创建的时候

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
            ActivityInfo aInfo = r.activityInfo;
            //......
            //创建 ContextImpl 实例
            ContextImpl appContext = createBaseContextForActivity(r);
            Activity activity = null;
            try {
                //创建 activity
                java.lang.ClassLoader cl = appContext.getClassLoader();
                activity = mInstrumentation.newActivity(
                        cl, component.getClassName(), r.intent);
    
                  //......
                    activity.attach(appContext, this, getInstrumentation(), r.token,
                            r.ident, app, r.intent, r.activityInfo, title, r.parent,
                            r.embeddedID, r.lastNonConfigurationInstances, config,
                            r.referrer, r.voiceInteractor, window, r.configCallback);
    
                   //.......
    
            return activity;
        }
    
    private ContextImpl createBaseContextForActivity(ActivityClientRecord r) {
          //....
         ContextImpl appContext = ContextImpl.createActivityContext(
                    this, r.packageInfo, r.activityInfo, r.token, displayId, r.overrideConfig);
        //....
    }
    
    static ContextImpl createActivityContext(ActivityThread mainThread,
                LoadedApk packageInfo, ActivityInfo activityInfo, IBinder activityToken, int displayId,
                Configuration overrideConfiguration) {
        //....
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, activityInfo.splitName,
                    activityToken, null, 0, classLoader);
        //...
    }
    

    在 Activity 创建的时候会调用 createBaseContextForActivity 方法创建 ContextImpl 实例,并在 attach 方法中赋值

    final void attach(Context context, ActivityThread aThread,
                Instrumentation instr, IBinder token, int ident,
                Application application, Intent intent, ActivityInfo info,
                CharSequence title, Activity parent, String id,
                NonConfigurationInstances lastNonConfigurationInstances,
                Configuration config, String referrer, IVoiceInteractor voiceInteractor,
                Window window, ActivityConfigCallback activityConfigCallback) {
            attachBaseContext(context);
            //.....
    }
    
         @Override
        protected void attachBaseContext(Context newBase) {
            super.attachBaseContext(newBase);
            if (newBase != null) {
                newBase.setAutofillClient(this);
            }
        }
    
          //super 方法
         @Override
        protected void attachBaseContext(Context newBase) {
            super.attachBaseContext(newBase);
        }
    
        //super 方法
        protected void attachBaseContext(Context base) {
            if (mBase != null) {
                throw new IllegalStateException("Base context already set");
            }
            mBase = base;
        }
    

    所以 mBase 是 ContextImpl 实例。

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

    调用自身的 startServiceCommon 方法

        private ComponentName startServiceCommon(Intent service, boolean requireForeground,
                UserHandle user) {
            try {
                //做一下检查
                validateServiceIntent(service);
                service.prepareToLeaveProcess(this);
                //调用ActivityManagerService 中的startService
                ComponentName cn = ActivityManager.getService().startService(
                    mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                                getContentResolver()), requireForeground,
                                getOpPackageName(), user.getIdentifier());
                //.....
        }
    

    很熟悉,ActivityManager.getService() 就是 ActivityManagerService

        @Override
        public ComponentName startService(IApplicationThread caller, Intent service,
                String resolvedType, boolean requireForeground, String callingPackage, int userId)
                throws TransactionTooLargeException {
            //做一些校验
            enforceNotIsolatedCaller("startService");
            // Refuse possible leaked file descriptors
            if (service != null && service.hasFileDescriptors() == true) {
                throw new IllegalArgumentException("File descriptors passed in Intent");
            }
            if (callingPackage == null) {
                throw new IllegalArgumentException("callingPackage cannot be null");
            }
            //.....
                try {
                    res = mServices.startServiceLocked(caller, service,
                            resolvedType, callingPid, callingUid,
                            requireForeground, callingPackage, userId);
                } finally {
                    Binder.restoreCallingIdentity(origId);
                }
                return res;
            }
        }
    

    做一些验证,调用 ActiveServices 的 startServiceLocked 方法

        ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
                int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
                throws TransactionTooLargeException {
            //........
            //往 pendingStarts 中增加数据
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    service, neededGrants, callingUid));
    
            //.....
            ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
            return cmp;
        }
    

    省略一大堆,需要注意的是在r.pendingStarts中增加了一条数据,这个是用来调用onStartCommand方法的。最后到 startServiceInnerLocked 方法中

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

    又是省略一大堆,到 bringUpServiceLocked 方法中

        private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
                boolean whileRestarting, boolean permissionsReviewRequired)
                throws TransactionTooLargeException {
            //假如该service已经启动了,则直接调用 onStartCommand 方法,而不会在走onCreate
            if (r.app != null && r.app.thread != null) {
                sendServiceArgsLocked(r, execInFg, false);
                return null;
            }
    
             //....
    
            if (!isolated) {
                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.longVersionCode, 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);
                    }
    
                    // If a dead object exception was thrown -- fall through to
                    // restart the application.
                }
            //....
            //开启新进程调用
            if (app == null && !permissionsReviewRequired) {
                if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                        hostingType, r.name, false, isolated, false)) == null) {
                    String msg = "Unable to launch app "
                            + r.appInfo.packageName + "/"
                            + r.appInfo.uid + " for service "
                            + r.intent.getIntent() + ": process is bad";
                    Slog.w(TAG, msg);
                    bringDownServiceLocked(r);
                    return msg;
                }
                if (isolated) {
                    r.isolatedProc = app;
                }
            }
           //....
            return null;
        }
    

    bringUpServiceLocked 是用来判断需要启动的 service 是否已经启动了,如果是,则直接调用 service 的 onStartCommand 方法。如果没有,则判断时候需要在新进程中启动,不需要则直接走 realStartServiceLocked 方法;需要则开启新的进程。这里讨论不需要的情况

        private final void realStartServiceLocked(ServiceRecord r,
                ProcessRecord app, boolean execInFg) throws RemoteException {
           //....
            try {
                //调用 ApplicationThread 中的 scheduleCreateService 方法
                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;
           
    
            if (r.whitelistManager) {
                app.whitelistManager = true;
            }
            //.....
    
            //创建完成后调用 service 的 onStartCommand 方法
            sendServiceArgsLocked(r, execInFg, true);
          //...
        }
    

    realStartServiceLocked 方法分两步:
    1.调用 ApplicationThread 的 scheduleCreateService 方法,创建 service 并调用 onCreate 方法
    2.service 创建完成后调用 sendServiceArgsLocked 即调用 service 的 onStartCommand 方法
    先来看第一步

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

    发送 handler ,其中 mH 是 ActivityThread 的内部类,根据 handler 原理可以知道最后会回调 mH 的 handleMessage 方法

        public void handleMessage(Message msg) {
            switch (msg.what) {
                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;
            }
        }
    

    根据 msg.what ,知道又会调用 handleCreateService 方法

        private void handleCreateService(CreateServiceData data) {
            //获取 LoadedApk
            LoadedApk packageInfo = getPackageInfoNoCheck(
                    data.info.applicationInfo, data.compatInfo);
            Service service = null;
            try {
                java.lang.ClassLoader cl = packageInfo.getClassLoader();
                //创建service
                service = packageInfo.getAppFactory()
                        .instantiateService(cl, data.info.name, data.intent);
            } 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);
                //创建 service 的 context
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                context.setOuterContext(service);
    
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                //赋值
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManager.getService());
                //调用 service.onCreate();
                service.onCreate();
                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) {
                if (!mInstrumentation.onException(service, e)) {
                    throw new RuntimeException(
                        "Unable to create service " + data.info.name
                        + ": " + e.toString(), e);
                }
            }
        }
    

    很简单,创建 service 并调用 onCreate 方法。到这里,第一步就完成,看第二步

        private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
                boolean oomAdjusted) throws TransactionTooLargeException {
            //......
            ArrayList<ServiceStartArgs> args = new ArrayList<>();
            //还记得 startServiceLocked 方法中已经往 r.pendingStarts 中增加了一条数据
            //所以这个循环会进来,bindService 方法中没有往 r.pendingStarts 增加数据
            //所以这个循环不会进来,因此 bindService 就不会调用 service 的 onStartCommand 方法
            while (r.pendingStarts.size() > 0) {
                 //.....
                //往 args 添加数据
                args.add(new ServiceStartArgs(si.taskRemoved, si.id, flags, si.intent));
            }
            //将 args 中的数据保存到 ParceledListSlice 中
            ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
    
                //调用 ApplicationThread 中的 scheduleServiceArgs 方法
                r.app.thread.scheduleServiceArgs(r, slice);
            
        //...
        }
    

    可能会忘记,r.pendingStarts 什么时候增加了一个数据,来回去看看 startServiceLocked 方法

        ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
                int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
                throws TransactionTooLargeException {
            //........
            //往 pendingStarts 中增加数据
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                    service, neededGrants, callingUid));
    
            //.....
            ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
            return cmp;
        }
    

    继续看 r.app.thread.scheduleServiceArgs(r, slice); 和第一步很像,也是调用 ApplicationThread 中的方法

         public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
                List<ServiceStartArgs> list = args.getList();
                //循环 ParceledListSlice 中的数据
                //因为上一步已经在 ParceledListSlice 中增加了数据,所以这个 ParceledListSlice 是有数据的
                for (int i = 0; i < list.size(); i++) {
                    ServiceStartArgs ssa = list.get(i);
                    ServiceArgsData s = new ServiceArgsData();
                    s.token = token;
                    s.taskRemoved = ssa.taskRemoved;
                    s.startId = ssa.startId;
                    s.flags = ssa.flags;
                    s.args = ssa.args;
    
                    sendMessage(H.SERVICE_ARGS, s);
                }
            }
    

    一样使用 handler

         public void handleMessage(Message msg) {
            switch (msg.what) {
                case SERVICE_ARGS:
                        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
                        handleServiceArgs((ServiceArgsData)msg.obj);
                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                        break;
            }
        }
    

    最后到 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();
    
                  //....
        }
    

    很简单,就是调用 Service 的 onStartCommand 方法。到这里,整个的 startService 流程就完成了。

    相关文章

      网友评论

          本文标题:2019-04-19 startService 源码解析

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