博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
startService() 过程
阅读量:6880 次
发布时间:2019-06-27

本文共 23051 字,大约阅读时间需要 76 分钟。

client端的startService()

我们在Application或者Activity里调用bindService()的时候,其实调用的是Context中的抽象方法:

public abstract ComponentName startService(Intent service);复制代码

真正的是现在ContextImpl中:

@Override    public ComponentName startService(Intent service) {		//当system进程调用此方法时输出warn信息,system进程建立调用startServiceAsUser方法        warnIfCallingFromSystemProcess();        return startServiceCommon(service, mUser);    }复制代码

而startServiceCommon()方法实现如下:

private ComponentName startServiceCommon(Intent service, UserHandle user) {        try {			//检验service,当service为空则throw异常            validateServiceIntent(service);            service.prepareToLeaveProcess(this);			// 调用ActivityManagerNative类            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 e.rethrowFromSystemServer();        }    }复制代码

该方法主要调用AMS.startService(),一些参数,然后通过IPC调用到AMS的startService()方法。

@Override    public ComponentName startService(IApplicationThread caller, Intent service,            String resolvedType, 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");        }        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,                "startService: " + service + " type=" + resolvedType);        synchronized(this) {            final int callingPid = Binder.getCallingPid();//调用者pid            final int callingUid = Binder.getCallingUid();//调用者uid            final long origId = Binder.clearCallingIdentity();			//此次的mServices为ActiveServices对象            ComponentName res = mServices.startServiceLocked(									caller,//IApplicationThread类型									service,//Intent类型,包含需要运行的service信息									resolvedType,//String类型									callingPid,									callingUid,									callingPackage,//String类型,调用该方法的package									userId//用户的id								);            Binder.restoreCallingIdentity(origId);            return res;        }    }复制代码

mServices是ActiveServices对象,其bindServiceLocked()方法如下:

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,            int callingPid, int callingUid, String callingPackage, final int userId)            throws TransactionTooLargeException {        if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service                + " type=" + resolvedType + " args=" + service.getExtras());        final boolean callerFg;        if (caller != null) {            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);            if (callerApp == null) {                throw new SecurityException(                        "Unable to find app for caller " + caller                        + " (pid=" + Binder.getCallingPid()                        + ") when starting service " + service);            }            callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;        } else {            callerFg = true;        }		//检索服务信息        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;		//检查是否存在启动服务的user        if (!mAm.mUserController.exists(r.userId)) {            Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);            return null;        }        if (!r.startRequested) {            final long token = Binder.clearCallingIdentity();            try {                // Before going further -- if this app is not allowed to run in the                // background, then at this point we aren't going to let it period.                final int allowed = mAm.checkAllowBackgroundLocked(                        r.appInfo.uid, r.packageName, callingPid, true);                if (allowed != ActivityManager.APP_START_MODE_NORMAL) {                    Slog.w(TAG, "Background start not allowed: service "                            + service + " to " + r.name.flattenToShortString()                            + " from pid=" + callingPid + " uid=" + callingUid                            + " pkg=" + callingPackage);                    return null;                }            } finally {                Binder.restoreCallingIdentity(token);            }        }        NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(                callingUid, r.packageName, service, service.getFlags(), null, r.userId);        // If permissions need a review before any of the app components can run,        // we do not start the service and launch a review activity if the calling app        // is in the foreground passing it a pending intent to start the service when        // review is completed.        if (Build.PERMISSIONS_REVIEW_REQUIRED) {            if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,                    callingUid, service, callerFg, userId)) {                return null;            }        }        if (unscheduleServiceRestartLocked(r, callingUid, false)) {            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);        }        r.lastActivity = SystemClock.uptimeMillis();        r.startRequested = true;        r.delayedStop = false;        r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),                service, neededGrants));        final ServiceMap smap = getServiceMap(r.userId);        boolean addToStarting = false;		//对于非前台进程的调度        if (!callerFg && r.app == null                && mAm.mUserController.hasStartedUserState(r.userId)) {            ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);            if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {                // If this is not coming from a foreground caller, then we may want                // to delay the start if there are already other background services                // that are starting.  This is to avoid process start spam when lots                // of applications are all handling things like connectivity broadcasts.                // We only do this for cached processes, because otherwise an application                // can have assumptions about calling startService() for a service to run                // in its own process, and for that process to not be killed before the                // service is started.  This is especially the case for receivers, which                // may start a service in onReceive() to do some additional work and have                // initialized some global state as part of that.                if (DEBUG_DELAYED_SERVICE) Slog.v(TAG_SERVICE, "Potential start delay of "                        + r + " in " + proc);                if (r.delayed) {//已计划延迟启动                    // This service is already scheduled for a delayed start; just leave                    // it still waiting.                    if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r);                    return r.name;                }                if (smap.mStartingBackground.size() >= mMaxStartingBackground) {                    // Something else is starting, delay!                    Slog.i(TAG_SERVICE, "Delaying start of: " + r);					//当超出 同一时间允许后续启动的最大服务数,则将该服务加入延迟启动的队列。                    smap.mDelayedStartList.add(r);                    r.delayed = true;                    return r.name;                }                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r);                addToStarting = true;            } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {                // We slightly loosen when we will enqueue this new service as a background                // starting service we are waiting for, to also include processes that are                // currently running other services or receivers.				//将新的服务加入到后台启动队列,该队列也包含当前正在运行其他services或者receivers的进程                addToStarting = true;                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,                        "Not delaying, but counting as bg: " + r);            } else if (DEBUG_DELAYED_STARTS) {                StringBuilder sb = new StringBuilder(128);                sb.append("Not potential delay (state=").append(proc.curProcState)                        .append(' ').append(proc.adjType);                String reason = proc.makeAdjReason();                if (reason != null) {                    sb.append(' ');                    sb.append(reason);                }                sb.append("): ");                sb.append(r.toString());                Slog.v(TAG_SERVICE, sb.toString());            }        } else if (DEBUG_DELAYED_STARTS) {			//当发起方进程不等于Process.THREAD_GROUP_BG_NONINTERACTIVE,或者发起方为空, 则callerFg= true;			//否则,callerFg= false;            if (callerFg) {                Slog.v(TAG_SERVICE, "Not potential delay (callerFg=" + callerFg + " uid="                        + callingUid + " pid=" + callingPid + "): " + r);            } else if (r.app != null) {                Slog.v(TAG_SERVICE, "Not potential delay (cur app=" + r.app + "): " + r);            } else {                Slog.v(TAG_SERVICE,                        "Not potential delay (user " + r.userId + " not started): " + r);            }        }        return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);    }复制代码

该方法主要包括了:

  • 调用retrieveServiceLocked()方法来获取ServiceLookupResult这个查询结果,这个方法会先尝试从缓存中取出ServiceRecord对象,如果没有则新建ServiceRecord并且存入缓存中,最后返回的ServiceLookupResult是ServiceRecord的包装类;
  • 调用unscheduleServiceRestartLocked(),即如果要启动的Service在重启名单中,那么就将它从AMS的mHandler中移除重启的Callback;
  • 调用startServiceInnerLocked()将启动Service,这个过程还可能伴随启动Service所在进程(如果进程没有启动的话);

startServiceInnerLocked()如下:

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {        ServiceState stracker = r.getTracker();        if (stracker != null) {            stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);        }        r.callStart = false;        synchronized (r.stats.getBatteryStats()) {            r.stats.startRunningLocked();//用于耗电统计,开启运行的状态        }        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);        if (error != null) {            return new ComponentName("!!", error);        }        if (r.startRequested && addToStarting) {            boolean first = smap.mStartingBackground.size() == 0;            smap.mStartingBackground.add(r);            r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;            if (DEBUG_DELAYED_SERVICE) {                RuntimeException here = new RuntimeException("here");                here.fillInStackTrace();                Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);            } else if (DEBUG_DELAYED_STARTS) {                Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);            }            if (first) {                smap.rescheduleDelayedStarts();            }        } else if (callerFg) {            smap.ensureNotStartingBackground(r);        }        return r.name;    }复制代码

service端进程启动以及service启动

可以参考bindService()。

启动service

service所在进程已经启动

如果需要启动的service已经启动

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;            sendMessage(H.SERVICE_ARGS, s);        }复制代码

在Handler里处理:

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) {                    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) {                    throw e.rethrowFromSystemServer();                }                ensureJitEnabled();            } catch (Exception e) {                if (!mInstrumentation.onException(s, e)) {                    throw new RuntimeException(                            "Unable to start service " + s                            + " with " + data.args + ": " + e.toString(), e);                }            }        }    }复制代码

这里就调用到了service的onStartCommand()方法。

如果需要启动的service还没有已经启动

首先创建service

private final void realStartServiceLocked(ServiceRecord r,            ProcessRecord app, boolean execInFg) throws RemoteException {        if (app.thread == null) {            throw new RemoteException();        }        if (DEBUG_MU)            Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid                    + ", ProcessRecord.uid = " + app.uid);        r.app = app;        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();        final boolean newService = app.services.add(r);		//发送delay消息        bumpServiceExecutingLocked(r, execInFg, "create");        mAm.updateLruProcessLocked(app, false, null);        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);			//服务进入 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 {            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);                }            }        }        if (r.whitelistManager) {            app.whitelistManager = true;        }        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);        if (r.delayed) {            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);            getServiceMap(r.userId).mDelayedStartList.remove(r);            r.delayed = false;        }        if (r.delayedStop) {            // Oh and hey we've already been asked to stop!            r.delayedStop = false;            if (r.startRequested) {                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,                        "Applying delayed stop (from start): " + r);                stopServiceLocked(r); //停止服务            }        }    }复制代码

方法中主要做了,创建service并调用onCreate()方法,绑定服务,调用service的onStartCommand()方法。

service所在进程还没启动

private final String bringUpServiceLocked(ServiceRecord r,            int intentFlags, boolean execInFg, boolean whileRestarting) {        ...        //省略前两种情况了,已经分析过        if (app == null) {            //没有加载过这个进程,创建一个新的进程,然后启动service            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,                    "service", 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);                //启动service,一会分析                bringDownServiceLocked(r);                return msg;            }            if (isolated) {                r.isolatedProc = app;            }        }        //保存这个ServiceRecord        if (!mPendingServices.contains(r)) {            mPendingServices.add(r);        }        ....        return null;    }复制代码

上面判断如果需要创建进程的话是通过调用mAm.startProcessLocked生成了进程,mAm就是AMS,我们直接看startProcessLocked方法:

private final void startProcessLocked(ProcessRecord app, String hostingType,            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {        long startTime = SystemClock.elapsedRealtime();     .....        try {           .....           //注意看如果entryPoint等于null的话,会被赋值android.app.ActivityThread            boolean isActivityProcess = (entryPoint == null);            if (entryPoint == null) entryPoint = "android.app.ActivityThread";            checkTime(startTime, "startProcess: asking zygote to start proc");            //启动进程            Process.ProcessStartResult startResult = Process.start(entryPoint,                    app.processName, uid, uid, gids, debugFlags, mountExternal,                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,                    app.info.dataDir, entryPointArgs);            checkTime(startTime, "startProcess: returned from zygote!");            ....        } catch (RuntimeException e) {           .....        }    }复制代码

指定了ActivityThread的这个类后,在创建进程完成后会调用ActivityThread的main方法。进程启动过程中会回调

boolean attachApplicationLocked(ProcessRecord proc, String processName)            throws RemoteException {        boolean didSomething = false;        // Collect any services that are waiting for this process to come up.		//启动mPendingServices队列中,等待在该进程启动的服务        if (mPendingServices.size() > 0) {            ServiceRecord sr = null;            try {                for (int i=0; i
0) { ServiceRecord sr; for (int i=0; i

这边回到了就是service没有启动,但是service所在进程已经存在的情况。

创建service

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对象是APK文件在内存中的表示。        //Apk文件的相关信息,诸如Apk文件的代码和资源,        //甚至代码里面的Activity,Service等四大组件的信息我们都可以通过此对象获取。        LoadedApk packageInfo = getPackageInfoNoCheck(                data.info.applicationInfo, data.compatInfo);        Service service = null;        try {            //加载service类            java.lang.ClassLoader cl = packageInfo.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 {            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);            context.setOuterContext(service);            //判断Application是否创建,没有创建会创建Application对象,            //但是在上面创建进程的时候已经创建,所以会直接返回            Application app = packageInfo.makeApplication(false, mInstrumentation);            //初始化service            service.attach(context, this, data.info.name, data.token, app,                    ActivityManagerNative.getDefault());            //调用service的    onCreate方法            service.onCreate();            //存储service的信息            mServices.put(data.token, service);            try {                //通知AMS已经创建完毕                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);            }        }    }复制代码

转载地址:http://wkfbl.baihongyu.com/

你可能感兴趣的文章
网易漫画Swift混编实践
查看>>
PHP扩展库PEAR被攻击,近半年下载者或被影响
查看>>
全球首届APMCon,带你给“应用性能”把把脉
查看>>
爱奇艺短视频软色情识别技术解析
查看>>
微软加入开放创新网络,旨在保护Linux和开源
查看>>
与IBM的Lin Sun关于Istio 1.0和微服务的问答
查看>>
win7下的Sublime Text3 运行ES6方法
查看>>
如何抓住重点,系统高效地学习数据结构与算法?
查看>>
寻找最小可行化产品背后的真理
查看>>
IBM推出全新机器学习库Snap ML,高出现有基准性能46倍
查看>>
人脸识别技术的真相
查看>>
Netflix是这样炼成的:谁构建,谁运维
查看>>
Docker Containers LiveLessons课程的评论与问答
查看>>
独家!阿里开源自用OpenJDK版本,Java社区迎来中国力量
查看>>
Rust 1.31正式发布,首次引入Rust 2018新功能
查看>>
架构设计复杂度的6个来源
查看>>
访谈:Kotlin在Pinterest的逆势生长
查看>>
QCon讲师对对碰——洪小军采访梁宇鹏:就是爱Golang
查看>>
MultiDex工作原理分析和优化方案
查看>>
解密新一代Java JIT编译器Graal
查看>>