Android 5.0源码分析---startService与bindService的区别

来源:互联网 发布:学习软件 编辑:程序博客网 时间:2024/06/05 07:33

startService启动过程简述

  1. 主进程调用到ActivityManagerService进程中,完成新进程的创建;
    这一步主要是解析Intent中的参数,解析前面在AndroidManifest.xml定义的Service标签的intent-filter相关内容。紧接着启动一个新的进程。
  2. 在新的进程启动完成后,从新进程调用到ActivityManagerService进程中,获取要在新进程启动的服务的相关信息;
    在此准备好了一个ServiceRecord记录Service中的信息,以及一个ProcessRecord记录了新进程的信息,当我们准备好这些参数后就要回到进程中真正启动Service了。
  3. 从ActivityManagerService进程又回到新进程中,最终将服务启动起来;
    加载这个class的类,调用其中的OnCreate方法将Service启动起来。

bindService启动过程的区别

与startService一样我们都会启动一个Service 调用它的OnCreate方法,但是在这之后我们还需要调用
ActivityManagerService.requestServiceBindingsLocked函数,这个调用是用来执行CounterService的onBind函数的。

    private final boolean requestServiceBindingLocked(ServiceRecord r,            IntentBindRecord i, boolean execInFg, boolean rebind) {        if (r.app == null || r.app.thread == null) {            // If service is not currently running, can't yet bind.            return false;        }        if ((!i.requested || rebind) && i.apps.size() > 0) {            try {                bumpServiceExecutingLocked(r, execInFg, "bind");                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,                        r.app.repProcState);                if (!rebind) {                    i.requested = true;                }                i.hasBound = true;                i.doRebind = false;            } catch (RemoteException e) {                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);                return false;            }        }        return true;    }

这里的ServiceRecord 就是先前我们创建的Service 的记录,我们可以看到在函数中我们调用了scheduleBindService:

    public final void scheduleBindService(IBinder token, Intent intent, boolean rebind,            int processState) throws RemoteException {        Parcel data = Parcel.obtain();        data.writeInterfaceToken(IApplicationThread.descriptor);        data.writeStrongBinder(token);        intent.writeToParcel(data, 0);        data.writeInt(rebind ? 1 : 0);        data.writeInt(processState);        mRemote.transact(SCHEDULE_BIND_SERVICE_TRANSACTION, data, null,                IBinder.FLAG_ONEWAY);        data.recycle();    }

最终进程间通信完成后会调用到的是:

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {        final long origId = Binder.clearCallingIdentity();        try {            if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r                    + " " + intent + ": " + service);            if (r != null) {                Intent.FilterComparison filter                        = new Intent.FilterComparison(intent);                IntentBindRecord b = r.bindings.get(filter);                if (b != null && !b.received) {                    b.binder = service;                    b.requested = true;                    b.received = true;                    for (int conni=r.connections.size()-1; conni>=0; conni--) {                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);                        for (int i=0; i<clist.size(); i++) {                            ConnectionRecord c = clist.get(i);                            if (!filter.equals(c.binding.intent.intent)) {                                if (DEBUG_SERVICE) Slog.v(                                        TAG, "Not publishing to: " + c);                                if (DEBUG_SERVICE) Slog.v(                                        TAG, "Bound intent: " + c.binding.intent.intent);                                if (DEBUG_SERVICE) Slog.v(                                        TAG, "Published intent: " + intent);                                continue;                            }                            if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);                            try {                                c.conn.connected(r.name, service);                            } catch (Exception e) {                                Slog.w(TAG, "Failure sending service " + r.name +                                      " to connection " + c.conn.asBinder() +                                      " (in " + c.binding.client.processName + ")", e);                            }                        }                    }                }                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);            }        } finally {            Binder.restoreCallingIdentity(origId);        }    }

这里传进来的参数token是一个ServiceRecord对象,它是在上面的Step 6中创建的,代表CounterService这个Service。我们曾经把一个ConnectionRecord放在ServiceRecord.connections列表中,现在我们需要把它取出来 每一个ConnectionRecord里面都有一个成员变量conn,它的类型是IServiceConnection,是一个Binder对象的远程接口,这个Binder对象又是什么呢?这就是我们在中创建的LoadedApk.ServiceDispatcher.InnerConnection对象了。因此,这里执行c.conn.connected函数后就会进入到LoadedApk.ServiceDispatcher.InnerConnection.connected函数中去了。
最终函数会调用到InnerConnection 中的connected:

            public void connected(ComponentName name, IBinder service) throws RemoteException {                LoadedApk.ServiceDispatcher sd = mDispatcher.get();                if (sd != null) {                    sd.connected(name, service);                }            }

再次跟进:

        public void connected(ComponentName name, IBinder service) {            if (mActivityThread != null) {                mActivityThread.post(new RunConnection(name, service, 0));            } else {                doConnected(name, service);            }        }

我们之前传入一个获取服务方的一个handler,这里会将这个binder发给线程

0 0