Service进阶篇(startService)

来源:互联网 发布:鸿星网络 编辑:程序博客网 时间:2024/05/16 09:11

先附上一张startService工作的流程图


1.从从Service 的启动过程ContextWrapper 的startService开始:

Context mBase;  @Override    public ComponentName startService(Intent service) {        return mBase.startService(service);    }
class ContextImpl extends Context

我的另一边文章:Activity源码分析中 已知Actiivty在创建时会把一个ContextImpl对象关联起来,这个ContextImpl就是mBase。查看ContextImpl的startService方法。

@Override    public ComponentName startService(Intent service) {        warnIfCallingFromSystemProcess();        return startServiceCommon(service, mUser);    }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());            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();        }    }

startService方法调用了startServiceCommon方法,而startServiceCommon又通过ActivityManagerNative.getDefault().startService方法来开启一个服务。ActivityManagerNative.getDefault()返回的是ActivityManagerService(AMS),这点已在:Activity源码分析文章中验证。这里AMS.startService是一个远程服务,查看AMS.startService方法。

final ActiveServices mServices;  @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();            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;        }    } public boolean unbindService(IServiceConnection connection) {        synchronized (this) {            return mServices.unbindServiceLocked(connection);        }    }public int bindService(IApplicationThread caller, IBinder token, Intent service,          ……        synchronized(this) {            return mServices.bindServiceLocked(caller, token, service,                    resolvedType, connection, flags, callingPackage, userId);        }    } @Override    public boolean stopServiceToken(ComponentName className, IBinder token,            int startId) {        synchronized(this) {            return mServices.stopServiceTokenLocked(className, token, startId);        }    } @Override    public int stopService(IApplicationThread caller, Intent service,            String resolvedType, int userId) {       ……        synchronized(this) {            return mServices.stopServiceLocked(caller, service, resolvedType, userId);        }    }

AMS通过mServices.startServiceLocked来开启服务。mServices的对象是ActiveServices,它是辅助AMS进行Service管理的类,包括Service的启动、绑定和停止。在startServiceLocked尾部调用startServiceInnerLocked方法

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,            int callingPid, int callingUid, String callingPackage, final int userId)            throws TransactionTooLargeException {    ……return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);}

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

ServiceRecord描述的是一个Service的记录,它会一直贯穿整个Service的启动过程。

/** * A running application service. */final class ServiceRecord extends Binder {static final int MAX_DELIVERY_COUNT = 3;    // Maximum number of times it can fail during execution before giving up.    static final int MAX_DONE_EXECUTING_COUNT = 6;    final ActivityManagerService ams;    final BatteryStatsImpl.Uid.Pkg.Serv stats;    final ComponentName name; // service component.    final String shortName; // name.flattenToShortString().    final Intent.FilterComparison intent;                            // original intent used to find service.    final ServiceInfo serviceInfo;                            // all information about the service.    final ApplicationInfo appInfo;                            // information about service's app.    final int userId;       // user that this service is running as    final String packageName; // the package implementing intent's component    final String processName; // process where this component wants to run    final String permission;// permission needed to access service    final boolean exported; // from ServiceInfo.exported    final Runnable restarter; // used to schedule retries of starting the service    final long createTime;  // when this service was created    ……}

startServiceInnerLocked方法并没有完成具体的启动工作,而是交给了bringUpServiceLocked方法处理。调用realStartService,开启真正的Service。

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,            boolean whileRestarting, boolean permissionsReviewRequired)            throws TransactionTooLargeException {        ……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);                }         ……..}realStartService方法源码: private final void realStartServiceLocked(ServiceRecord r,            ProcessRecord app, boolean execInFg) throws RemoteException {        if (app.thread == null) {            throw new RemoteException();        }…….app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);            app.thread.scheduleCreateService(r, r.serviceInfo,                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),                    app.repProcState);…….  sendServiceArgsLocked(r, execInFg, true);…………}private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,            boolean oomAdjusted) throws TransactionTooLargeException {        final int N = r.pendingStarts.size();        if (N == 0) {            return;…….r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);…….}

在realStartService方法中,app.thread通过scheduleCreateService方法来创建Service对象并调用onCreate方法,接着通过sendServiceArgsLocked方法调用Service其他方法,比如onStartCommand,这两个过程均是进程间通信。其实scheduleCreateService和sendServiceArgsLocked(该方法会调用app.thread.scheduleServiceArgs)调用逻辑基本一样,后续的源码中就只分析scheduleCreateService方法。

app.thread的对象是IApplicationThread,它的实现类是ApplicationThread,参见Activity源码分析。应此只需要查看ApplicationThread的scheduleCreateService方法。ApplicationThread是ActivityThread的内部类。

 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);        } public void handleMessage(Message msg) {    …….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;                case BIND_SERVICE:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");                    handleBindService((BindServiceData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;………}

显然这里的启动过程和Activity是一样的,通过Handle H来发送消息,在handleMessage方法中通过 handleCreateService方法来创建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 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, 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);            }        }    }

handleCreateService完成了几件事:

1.通过来加载器创建了Service的实例。

2.创建Application对象,只创建一次,并调用onCreate方法(可参照Activity源码分析)。

3.创建ContextImpl对象,并通过Service方法的attach方法建立两者的关系。这个过程与Activity类似,它们都是一个Context。 

4.Service调用onCreate方法,并将Service对象存储在ActivityThread的一个列表中。

final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();…… service.onCreate();mServices.put(data.token, service);

Service的onCreate方法执行了,Service已经启动了。上面提到过sendServiceArgsLocked方法(app.thread.scheduleServiceArgs)最终也会通过handleServiceArgs方法调动Service的onStartCommand方法,具体内容不再详细介绍。