具体可参考“老罗的Android之旅”中的《Android应用程序绑定服务(bindService)的过程源代码分析》一文。


下面跟踪bindService流程。

Step 1、ContextWrapper::bindService()

代码位于frameworks/base/core/java/android/content/ContextWrapper.java。

    public boolean bindService(Intent service, ServiceConnection conn,            int flags) {        return mBase.bindService(service, conn, flags);    }
    Context mBase;

class ContextImpl extends Context {      ......}

其中mBase为一个ContextImpl对象(具体的分析过程请参考startService的文章)。

Step 2、ContextImpl::bindService()

代码位于frameworks/base/core/java/android/app/ContextImpl.java。

    public boolean bindService(Intent service, ServiceConnection conn,            int flags) {        warnIfCallingFromSystemProcess();        return bindServiceCommon(service, conn, flags, Process.myUserHandle());    }
Step 3、ContextImpl::bindServiceCommon()
代码位于frameworks/base/core/java/android/app/ContextImpl.java。

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,            UserHandle user) {        IServiceConnection sd;        if (conn == null) {            throw new IllegalArgumentException("connection is null");        }        if (mPackageInfo != null) {            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),                    mMainThread.getHandler(), flags);//作为ActivityManagerProxy::bindService的参数,将该IServiceConnection对象传递给AMS,后续AMS通过该IServiceConnection与ServiceConnection对象进行通信        } else {            throw new RuntimeException("Not supported in system context");        }        validateServiceIntent(service);        try {            IBinder token = getActivityToken();            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null                    && mPackageInfo.getApplicationInfo().targetSdkVersion                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {                flags |= BIND_WAIVE_PRIORITY;            }            service.prepareToLeaveProcess();            int res = ActivityManagerNative.getDefault().bindService(                mMainThread.getApplicationThread(), getActivityToken(),                service, service.resolveTypeIfNeeded(getContentResolver()),                sd, flags, user.getIdentifier());            if (res < 0) {                throw new SecurityException(                        "Not allowed to bind to service " + service);            }            return res != 0;        } catch (RemoteException e) {            return false;        }    }

ActivityManagerNative.getDefault().bindService通过binder机制,将调用ActivityManagerService::bindService()函数。

这里的mMainThread是一个ActivityThread实例,通过ActivityThread::getHandler()就可以获得一个Handler对象。有了该Handler对象就可以将消息发送到ActivityThread所在进程的消息队列中去。

随后调用了mPackageInfo.getServiceDispatcher函数。mPackageInfo的类型是LoadedApk,因此调用的是LoadedApk::getServiceDispatcher函数。该函数的代码位于frameworks/base/core/java/android/app/LoadedApk.java中。

final class LoadedApk {......public final IServiceConnection getServiceDispatcher(ServiceConnection c,Context context, Handler handler, int flags) {synchronized (mServices) {LoadedApk.ServiceDispatcher sd = null;HashMap map = mServices.get(context);if (map != null) {sd = map.get(c);}if (sd == null) {sd = new ServiceDispatcher(c, context, handler, flags);if (map == null) {map = new HashMap();mServices.put(context, map);}map.put(c, sd);} else {sd.validate(context, handler);}return sd.getIServiceConnection();}}......static final class ServiceDispatcher {private final ServiceDispatcher.InnerConnection mIServiceConnection;private final ServiceConnection mConnection;private final Handler mActivityThread;......private static class InnerConnection extends IServiceConnection.Stub {final WeakReference mDispatcher;......InnerConnection(LoadedApk.ServiceDispatcher sd) {mDispatcher = new WeakReference(sd);}......}......ServiceDispatcher(ServiceConnection conn,Context context, Handler activityThread, int flags) {mIServiceConnection = new InnerConnection(this);mConnection = conn;mActivityThread = activityThread;......}......IServiceConnection getIServiceConnection() {return mIServiceConnection;}......}......}
在getServiceDispatcher函数中,传进来的参数context是一个MainActivity实例,先以它为Key值在mServices中查看一下,是不是已经存在相应的ServiceDispatcher实例,如果有了,就不用创建了,直接取出来。在我们这个情景中,需要创建一个新的ServiceDispatcher。在创建新的ServiceDispatcher实例的过程中,将上面传下来ServiceConnection参数c和Hanlder参数保存在了ServiceDispatcher实例的内部,并且创建了一个InnerConnection对象,这是一个Binder对象,一会是要传递给ActivityManagerService的,ActivityManagerServic后续就是要通过这个Binder对象和ServiceConnection通信的。

函数getServiceDispatcher最后就是返回了一个InnerConnection对象给ContextImpl.bindService函数。回到ContextImpl.bindService函数中,它接着就要调用ActivityManagerService的远程接口来进一步处理了。

Step 4、ActivityManagerService::bindService()

代码位于frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中。

    public int bindService(IApplicationThread caller, IBinder token,            Intent service, String resolvedType,            IServiceConnection connection, int flags, int userId) {        enforceNotIsolatedCaller("bindService");        // Refuse possible leaked file descriptors        if (service != null && service.hasFileDescriptors() == true) {            throw new IllegalArgumentException("File descriptors passed in Intent");        }        synchronized(this) {            return mServices.bindServiceLocked(caller, token, service, resolvedType,                    connection, flags, userId);        }    }

本函数的第二个参数token是由Step 3中ActivityManagerProxy::bindService参数中getActivityToken函数获得。第五个参数connection是通过LoadedApk::getServiceDispatcher函数得到的一个IServiceConnection接口。继续看看ActiveServices::bindServiceLocked函数。

Step 5、ActiveServices::bindServiceLocked()

代码位于frameworks/base/services/java/com/android/server/am/ActiveServices.java文件中。

    int bindServiceLocked(IApplicationThread caller, IBinder token,            Intent service, String resolvedType,            IServiceConnection connection, int flags, int userId) {        if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service                + " type=" + resolvedType + " conn=" + connection.asBinder()                + " flags=0x" + Integer.toHexString(flags));        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);//根据IApplicationThread对象找到ProcessRecord对象        if (callerApp == null) {            throw new SecurityException(                    "Unable to find app for caller " + caller                    + " (pid=" + Binder.getCallingPid()                    + ") when binding service " + service);        }        ActivityRecord activity = null;        if (token != null) {            activity = ActivityRecord.isInStackLocked(token);            if (activity == null) {                Slog.w(TAG, "Binding with unknown activity: " + token);                return 0;            }        }        int clientLabel = 0;        PendingIntent clientIntent = null;        if (callerApp.info.uid == Process.SYSTEM_UID) {            // Hacky kind of thing -- allow system stuff to tell us            // what they are, so we can report this elsewhere for            // others to know why certain services are running.            try {                clientIntent = (PendingIntent)service.getParcelableExtra(                        Intent.EXTRA_CLIENT_INTENT);            } catch (RuntimeException e) {            }            if (clientIntent != null) {                clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);                if (clientLabel != 0) {                    // There are no useful extras in the intent, trash them.                    // System code calling with this stuff just needs to know                    // this will happen.                    service = service.cloneFilter();                }            }        }        final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;        ServiceLookupResult res =            retrieveServiceLocked(service, resolvedType,                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);//从AMS和PMS中,获取或者新建ServiceRecord,随后封装成ServiceLoolupResult对象并返回。        if (res == null) {            return 0;        }        if (res.record == null) {            return -1;        }        ServiceRecord s = res.record;        final long origId = Binder.clearCallingIdentity();        try {            if (unscheduleServiceRestartLocked(s)) {                if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "                        + s);            }            if ((flags&Context.BIND_AUTO_CREATE) != 0) {                s.lastActivity = SystemClock.uptimeMillis();                if (!s.hasAutoCreateConnections()) {                    // This is the first binding, let the tracker know.                    ProcessStats.ServiceState stracker = s.getTracker();                    if (stracker != null) {                        stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),                                s.lastActivity);                    }                }            }            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);//在ServiceRecord的IntentBindRecord列表,AppBindRecord列表中检索AppBindRecor,若没有,则new AppBindRecord并返回            ConnectionRecord c = new ConnectionRecord(b, activity,                    connection, flags, clientLabel, clientIntent);            IBinder binder = connection.asBinder();            ArrayList clist = s.connections.get(binder);            if (clist == null) {                clist = new ArrayList();                s.connections.put(binder, clist);//将ConnectionRecor放入ServiceRecord.connections列表中,在之后的publishService中依次取出。            }            clist.add(c);            b.connections.add(c);            if (activity != null) {                if (activity.connections == null) {                    activity.connections = new HashSet();                }                activity.connections.add(c);            }            b.client.connections.add(c);            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {                b.client.hasAboveClient = true;            }            clist = mServiceConnections.get(binder);            if (clist == null) {                clist = new ArrayList();                mServiceConnections.put(binder, clist);            }            clist.add(c);            if ((flags&Context.BIND_AUTO_CREATE) != 0) {//若应用程序使用bindService时传入的参数为该标志时直接调用bringUpServiceLocked                s.lastActivity = SystemClock.uptimeMillis();                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {                    return 0;                }            }            if (s.app != null) {                // This could have made the service more important.                mAm.updateOomAdjLocked(s.app);            }            if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b                    + ": received=" + b.intent.received                    + " apps=" + b.intent.apps.size()                    + " doRebind=" + b.intent.doRebind);            if (s.app != null && b.intent.received) {                // Service is already running, so we can immediately                // publish the connection.                try {                    c.conn.connected(s.name, b.intent.binder);                } catch (Exception e) {                    Slog.w(TAG, "Failure sending service " + s.shortName                            + " to connection " + c.conn.asBinder()                            + " (in " + c.binding.client.processName + ")", e);                }                // If this is the first app connected back to this binding,                // and the service had previously asked to be told when                // rebound, then do so.                if (b.intent.apps.size() == 1 && b.intent.doRebind) {                    requestServiceBindingLocked(s, b.intent, callerFg, true);                }            } else if (!b.intent.requested) {                requestServiceBindingLocked(s, b.intent, callerFg, false);            }            getServiceMap(s.userId).ensureNotStartingBackground(s);        } finally {            Binder.restoreCallingIdentity(origId);        }        return 1;    }

倘若应用程序中bindService时传入的参数为BIND_AUTO_CREATE时,执行bringUpServiceLocked;这里分析另外一种情况——参数flags不为BIND_AUTO_CREATE的情况。

Step 6、ActiveServices::requestServiceBindingLocked

代码位于frameworks/base/services/java/com/android/am/ActiveServices.java文件中。

    private final boolean requestServiceBindingLocked(ServiceRecord r,            IntentBindRecord i, boolean execInFg, boolean rebind) {        if (r.app == null || r.app.thread == null) {//若service未运行,直接返回,不做任何操作            // If service is not currently running, can't yet bind.            return false;        }        if ((!i.requested || rebind) && i.apps.size() > 0) {//rebind表示是否重新绑定service,requested表示是否已绑定service?            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;    }

这里app.thread是ApplicationThread的代理对象,类型是AppllicationThreadProxy。

Step 7、ApplicationThreadProxy::scheduleBindService

代码位于frameworks/base/core/java/android/app/ActvityThread.java文件中。

        public final void scheduleBindService(IBinder token, Intent intent,                boolean rebind, int processState) {            updateProcessState(processState, false);            BindServiceData s = new BindServiceData();            s.token = token;            s.intent = intent;            s.rebind = rebind;            if (DEBUG_SERVICE)                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());            sendMessage(H.BIND_SERVICE, s);        }
这里首先将传入的参数封装成一个BindServiceData对象,随后与BIND_SERVICE一并封装后发送至消息队列。消息最终在handleMessage函数中处理。

Step 8、H::handleMessage

代码位于frameworks/base/core/java/android/app/ActvityThread.java文件中。

        public void handleMessage(Message msg) {            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));            switch (msg.what) {                           ......                case BIND_SERVICE:                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");                    handleBindService((BindServiceData)msg.obj);                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);                    break;                ......            }            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));        }
Step 9、ActivityThread::handleBindService

代码位于frameworks/base/core/java/android/app/ActvityThread.java文件中。

    private void handleBindService(BindServiceData data) {        Service s = mServices.get(data.token);        if (DEBUG_SERVICE)            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);        if (s != null) {            try {                data.intent.setExtrasClassLoader(s.getClassLoader());                try {                    if (!data.rebind) {                        IBinder binder = s.onBind(data.intent);//获取service的一个Binder对象,然后连同service实例传入AMS                        ActivityManagerNative.getDefault().publishService(                                data.token, data.intent, binder);                    } else {                        s.onRebind(data.intent);                        ActivityManagerNative.getDefault().serviceDoneExecuting(                                data.token, 0, 0, 0);                    }                    ensureJitEnabled();                } catch (RemoteException ex) {                }            } catch (Exception e) {                if (!mInstrumentation.onException(s, e)) {                    throw new RuntimeException(                            "Unable to bind to service " + s                            + " with " + data.intent + ": " + e.toString(), e);                }            }        }    }

这里的data是一个BindServiceData对象,之前是通过ApllicationThreadProxy的scheduleBindService经由Binder机制传入,通过data.token获取之前已启动了的service实例,即s。

Step 10、ActivityManagerService::publishService

代码位于frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中。

    public void publishService(IBinder token, Intent intent, IBinder service) {        // Refuse possible leaked file descriptors        if (intent != null && intent.hasFileDescriptors() == true) {            throw new IllegalArgumentException("File descriptors passed in Intent");        }        synchronized(this) {            if (!(token instanceof ServiceRecord)) {                throw new IllegalArgumentException("Invalid service token");            }            mServices.publishServiceLocked((ServiceRecord)token, intent, service);        }    }
直接分析mServices.publishServiceLocked函数。

Setp 11、ActiveServices::publishServiceLocked

代码位于frameworks/base/services/java/com/android/server/am/ActiveServices.java文件中。

    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 clist = r.connections.valueAt(conni);                        for (int i=0; i

每一个ConnectionRecord里面都有一个成员变量conn,它的类型是IServiceConnection,是一个Binder对象的远程接口。函数中体现为c.conn,它是在Step 3中通过LoadedApk::getServiceDispatch创建的LoadedApk.ServiceDispatcher.InnerConnection对象。因此,在调用c.conn.connected(r.name, service)时,进入到了LoadedApk.ServiceDispatcher.InnerConnection.connected函数中去了。

Step 12、InnerConnection::connected

代码位于frameworks/base/core/java/android/app/LoadedApk.java文件中。

final class LoadedApk {......static final class ServiceDispatcher {......private static class InnerConnection extends IServiceConnection.Stub {......public void connected(ComponentName name, IBinder service) throws RemoteException {LoadedApk.ServiceDispatcher sd = mDispatcher.get();if (sd != null) {sd.connected(name, service);}}......}......}......}
随后立即转交给ServiceDspatcher::connected函数。

Step 13、ServiceDspatcher::connected
这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中。

final class LoadedApk {......static final class ServiceDispatcher {......public void connected(ComponentName name, IBinder service) {if (mActivityThread != null) {mActivityThread.post(new RunConnection(name, service, 0));} else {......}}......}......}
这里的mActivityThread在Step 3中mPackageInfo.getServiceDispatcher的第三个参数获得,并辗转传入到本函数,是一个Handler实例。因此,接着进入到Handler::post函数中。

Step 14、Handler::post

这个函数定义在frameworks/base/core/java/android/os/Handler.java文件中。

public class Handler {……    public final boolean post(Runnable r)   {       return  sendMessageDelayed(getPostMessage(r), 0);    }……}

调用了这个函数之后,这个消息就真正地进入到ActivityThread的消息队列去了,与sendMessage把消息放在消息队列不一样的地方是,post方式发送的消息不是由这个Handler的handleMessage函数来处理的,而是由post的参数Runnable的run函数来处理的。这里传给post的参数是一个RunConnection类型的参数,它继承了Runnable类,因此,最终会调用RunConnection.run函数来处理这个消息。

Step 15、RunConnection::run

这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中。

final class LoadedApk {......static final class ServiceDispatcher {           private final class RunConnection implements Runnable {                     RunConnection(ComponentName name, IBinder service, int command) {                         mName = name;                         mService = service;                        mCommand = command;                     }               public void run() {                   if (mCommand == 0) {                       doConnected(mName, mService);                   } else if (mCommand == 1) {                       doDeath(mName, mService);                   }               }                final ComponentName mName;                final IBinder mService;                final int mCommand;             }......}......}
由Step 13知,函数的command参数为0,故调用doConnected函数。

Step 14、ServiceDispatcher::doConnected

这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中。

final class LoadedApk {    ......    static final class ServiceDispatcher {        ......        public void doConnected(ComponentName name, IBinder service) {            ServiceDispatcher.ConnectionInfo old;            ServiceDispatcher.ConnectionInfo info;            synchronized (this) {                if (mForgotten) {                    // We unbound before receiving the connection; ignore                    // any connection received.                    return;                }                old = mActiveConnections.get(name);                if (old != null && old.binder == service) {                    // Huh, already have this one.  Oh well!                    return;                }                if (service != null) {                    // A new service is being connected... set it all up.                    mDied = false;                    info = new ConnectionInfo();                    info.binder = service;                    info.deathMonitor = new DeathMonitor(name, service);                    try {                        service.linkToDeath(info.deathMonitor, 0);                        mActiveConnections.put(name, info);                    } catch (RemoteException e) {                        // This service was dead before we got it...  just                        // don't do anything with it.                        mActiveConnections.remove(name);                        return;                    }                } else {                    // The named service is being disconnected... clean up.                    mActiveConnections.remove(name);                }                if (old != null) {                    old.binder.unlinkToDeath(old.deathMonitor, 0);                }            }            // If there was an old service, it is not disconnected.            if (old != null) {                mConnection.onServiceDisconnected(name);            }            // If there is a new service, it is now connected.            if (service != null) {                mConnection.onServiceConnected(name, service);            }        }        ......    }    ......}
这里主要就是执行成员变量mConnection的onServiceConnected函数,这里的mConnection变量的类型的ServiceConnection,它是在前面的Step 3中mPackageInfo.getServiceDispatcher设置好的,这个ServiceConnection实例是MainActivity类内部创建的,在调用bindService函数时保存在LoadedApk.ServiceDispatcher类中,用它来换取一个IServiceConnection对象,传给ActivityManagerService。











更多相关文章

  1. mybatisplus的坑 insert标签insert into select无参数问题的解决
  2. 箭头函数的基础使用
  3. 类和 Json对象
  4. Python技巧匿名函数、回调函数和高阶函数
  5. python list.sort()根据多个关键字排序的方法实现
  6. Android应用程序组件Content Provider在应用程序之间共享数据的
  7. Android中的设计模式(结合大话设计模式+网上博客)
  8. Android系统进程Zygote启动过程的源代码分析(2)
  9. 2011.09.23——— android sample之Notepad(context menu)

随机推荐

  1. android 项目中规范使用SharedPreference
  2. android 模拟器中启用相机API支持
  3. android 来电自动接听和自动挂断
  4. 1、Android中支持的Snesor种类
  5. android 实用sax 读取xml文件内容
  6. Android(安卓)中如何得到字符的像素宽度
  7. android 开机动画修改以及默认壁纸
  8. Android问题集锦
  9. Android状态栏适配源码解析。
  10. Android调用getSimSerialNumber获取iccid