美文网首页
startService的启动过程

startService的启动过程

作者: Jesse_zhao | 来源:发表于2018-04-10 00:37 被阅读57次

    Service的启动

    一、概要

    service的启动相对activity的启动来说比较简单。这里以startService来分析它的启动流程。

    1、涉及主要类

    android.app.ContextImpl.java 
    android.app.ActivityThread.java
    com.android.server.am.ActivityManagerService.java
    com.android.server.am.ActiveServices.java
    

    2、流程图


    startService启动过程

    二、具体流程

    1、ContextImpl.startService()

    最后会调用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(), user.getIdentifier());
            //省略部分代码...
             return cn;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    

    这里就直接通过binder调用了AMS的startService()方法,这里有几个参数第一个是当前进程对应的ActivityThread实例、第二个参数是启动的Intent实例、第三个参数是resolveType数据类型,包名以及用户id。接着我们看下AMS中的startServive()方法:

    2、ActivityManagerService.startService()
    @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
       //省略部分代码 ...
        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;
        }
    }
    

    这里没啥很简单,直接看下一步:

    3.1、ActiveServices.startServiceLocked()
    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
       // 省略部分代码
        //查找相对应注册的service
        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");
        }
    
        ServiceRecord r = res.record;
        //省略部分代码...
        r.lastActivity = SystemClock.uptimeMillis();
        r.startRequested = true;
        r.delayedStop = false;
        r.fgRequired = fgRequired;
        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                service, neededGrants, callingUid));
    
        final ServiceMap smap = getServiceMapLocked(r.userId);
        boolean addToStarting = false;
       //省略部分代码...
        ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
        return cmp;
    }
    

    首先获取查找相对应注册的service信息,返回一个记录该service的信息对象ServiceRecord和相应的权限,然后接着调用了startServiceInnerLocked()方法,接着调用了bringUpServiceLocked()方法

    3.2、ActiveServices.bringUpServiceLocked()
        private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        //当service已经启动时,再次调用时只会通过ActivityThread调用Service的onStartCommand方法传递参数
        if (r.app != null && r.app.thread != null) {
            sendServiceArgsLocked(r, execInFg, false);
            return null;
        }
        //省略部分代码
        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;
        // 如果当前service不是在单独的进程中
        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.versionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }
    
                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        } 
        // 省略部分代码...
        return null;
    }
    

    这里面可以看到,如果是已经启动过的service,再次启动时之后调用service的onStartCommand()方法。当service是在单独的进程中时则通过AMS.startProcessLocked()来启动该进程。接着来看realStartServiceLocked方法:

    3.3、ActiveServices.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);
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
        mAm.updateOomAdjLocked();
    
        boolean created = false;
        try {
            if (LOG_SERVICE_START_STOP) {
                String nameTerm;
                int lastPeriod = r.shortName.lastIndexOf('.');
                nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
                EventLogTags.writeAmCreateService(
                        r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
            }
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked();
            }
            mAm.notifyPackageUse(r.serviceInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            //通过ActivityThread完成Service的创建
            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 {
             //省略部分代码
                   }
          //省略部分代码
        //通过ActivityThread执行onstartCommand()
        sendServiceArgsLocked(r, execInFg, true);
        //省略部分代码
    }
    

    执行到这framework层才完成对Service创建的准备工作,之后通过ActivityThread来完成对Service的创建:

    4、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 loadedApk = getLoadedApkNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
        //通过反射创建Service实例
            java.lang.ClassLoader cl = loadedApk.getClassLoader();
            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);
    
            ContextImpl context = ContextImpl.createAppContext(this, loadedApk);
            context.setOuterContext(service);
    
            Application app = loadedApk.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的创建和启动。

    三、总结

    startService的启动和Activity的启动相类似,但是Android 8.0对后台service的启动做了些改变。

    相关文章

      网友评论

          本文标题:startService的启动过程

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