源码 service 的start工作过程

来源:互联网 发布:u站淘宝 编辑:程序博客网 时间:2024/05/29 18:11

Service 启动 从 ContextWrapper 的 startService 开始:


ContextWrapper # startService
mBase 的类型是 ContextImpl ,
public class ContextWrapper extends Context {    Context mBase;    @Override    public ComponentName startService(Intent service) {    return mBase.startService(service);    }}
ContextImpl #
class ContextImpl extends Context { @Override public ComponentName startService(Intent service) {     warnIfCallingFromSystemProcess();    return startServiceCommon(service, mUser); } @Override public boolean stopService(Intent service) {    warnIfCallingFromSystemProcess();    return stopServiceCommon(service, mUser); } @Override public ComponentName startServiceAsUser(Intent service, UserHandle user) {    return startServiceCommon(service, user); } private ComponentName startServiceCommon(Intent service, UserHandle user) {    try {        validateServiceIntent(service);        service.prepareToLeaveProcess();        ComponentName cn = ActivityManagerNative.getDefault().startService(                mMainThread.getApplicationThread(), service,                service.resolveTypeIfNeeded(getContentResolver()), 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) {        return null;    } }
ActivityManagerService # startService
@Overridepublic ComponentName startService(IApplicationThread caller, Intent service,                                  String resolvedType, int userId) {    enforceNotIsolatedCaller("startService");    // Refuse possible leaked file descriptors    if (service != null && service.hasFileDescriptors() == true) {        throw new IllegalArgumentException("File descriptors passed in Intent");    }    if (DEBUG_SERVICE)        Slog.v(TAG, "startService: " + service + " type=" + resolvedType);    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, userId);        Binder.restoreCallingIdentity(origId);        return res;    }}

ActiveServices #startServiceLocked

ComponentName startServiceLocked(IApplicationThread caller,                                 Intent service, String resolvedType,                                 int callingPid, int callingUid, int userId) {   。。。。。    return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);}
ActiveServices #startServiceInnerLocked
ServiceRecord  描述的是一个 Service 记录,ServiceRecord 一直贯穿着整个 Service 的启动过程。
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,                                      ServiceRecord r, boolean callerFg, boolean addToStarting) {    ProcessStats.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);    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, "Starting background (first=" + first + "): " + r, here);        } else if (DEBUG_DELAYED_STARTS) {            Slog.v(TAG, "Starting background (first=" + first + "): " + r);        }        if (first) {            smap.rescheduleDelayedStarts();        }    } else if (callerFg) {        smap.ensureNotStartingBackground(r);    }    return r.name;}

ActiveServices # bringUpServiceLocked

private final String bringUpServiceLocked(ServiceRecord r,                                          int intentFlags, boolean execInFg, boolean whileRestarting) {       // Service is now being launched, its package can't be stopped.    try {        AppGlobals.getPackageManager().setPackageStoppedState(                r.packageName, false, r.userId);    } catch (RemoteException e) {    } catch (IllegalArgumentException e) {        Slog.w(TAG, "Failed trying to unstop package "                + r.packageName + ": " + e);    }    final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;    final String procName = r.processName;    ProcessRecord app;    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 (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.        }    } else {              app = r.isolatedProc;    }    // Not running -- get it started, and enqueue this service record        return null;}
ActiveServices # realStartServiceLocked
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();    app.services.add(r);    bumpServiceExecutingLocked(r, execInFg, "create");    mAm.updateLruProcessLocked(app, false, null);    mAm.updateOomAdjLocked();    boolean created = false;    try {        String nameTerm;        int lastPeriod = r.shortName.lastIndexOf('.');        nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;        if (LOG_SERVICE_START_STOP) {            EventLogTags.writeAmCreateService(                    r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);        }        synchronized (r.stats.getBatteryStats()) {            r.stats.startLaunchedLocked();        }        mAm.ensurePackageDexOpt(r.serviceInfo.packageName);        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_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);    } finally {        if (!created) {            app.services.remove(r);            r.app = null;            scheduleServiceRestartLocked(r, false);            return;        }    }    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));    }    sendServiceArgsLocked(r, execInFg, true);// 调用 Service 的其他方法    }
ActivityThread # scheduleCtreateService

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 # H.create_service
case CREATE_SERVICE:    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");    handleCreateService((CreateServiceData)msg.obj);    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);    break;
ActivityThread #  handleCreateService
通过类加载 创建 service 的实例
创建 Application 对象并调用其 onCreate ,当然 Application 的创建过程只会有一次
创建 contextImpl 对象 并通过 Service 的 attach 建立关系。 activity 和 Service 都是同一个 context
Service .onCreate()
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 {        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 {        if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);        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,                ActivityManagerNative.getDefault());        service.onCreate();        mServices.put(data.token, service);        try {            ActivityManagerNative.getDefault().serviceDoneExecuting(                    data.token, 0, 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);        }    }}
ActiveServices # sendSeviceArgsLocked
private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,                                         boolean oomAdjusted) {    final int N = r.pendingStarts.size();    if (N == 0) {        return;    }    while (r.pendingStarts.size() > 0) {        try {            ServiceRecord.StartItem si = r.pendingStarts.remove(0);            if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: "                    + r + " " + r.intent + " args=" + si.intent);            if (si.intent == null && N > 1) {                // If somehow we got a dummy null intent in the middle,                // then skip it.  DO NOT skip a null intent when it is                // the only one in the list -- this is to support the                // onStartCommand(null) case.                continue;            }            si.deliveredTime = SystemClock.uptimeMillis();            r.deliveredStarts.add(si);            si.deliveryCount++;            if (si.neededGrants != null) {                mAm.grantUriPermissionUncheckedFromIntentLocked(si.neededGrants,                        si.getUriPermissionsLocked());            }            bumpServiceExecutingLocked(r, execInFg, "start");            if (!oomAdjusted) {                oomAdjusted = true;                mAm.updateOomAdjLocked(r.app);            }            int flags = 0;            if (si.deliveryCount > 1) {                flags |= Service.START_FLAG_RETRY;            }            if (si.doneExecutingCount > 0) {                flags |= Service.START_FLAG_REDELIVERY;            }            r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);        } catch (RemoteException e) {            // Remote process gone...  we'll let the normal cleanup take            // care of this.            if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r);            break;        } catch (Exception e) {            Slog.w(TAG, "Unexpected exception", e);            break;        }    }}
ActivityThread # scheduleServiceArgs
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);}
ActivityThread # H.service_args
case SERVICE_ARGS:    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");    handleServiceArgs((ServiceArgsData)msg.obj);    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);    break;
ActivityThread # handleServiceArgs
比如 调用 service 的 onStartCommand 方法
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, 1, 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);            }        }    }}
Android API :http://www.android-doc.com/reference/packages.html 
http://tool.oschina.net/uploads/apidocs/android/reference/packages.html 
Android 源码:http://androidxref.com/

原创粉丝点击