从源码角度看Service绑定过程

  Service绑定从ContextWrapper开始的。

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

  mBase是ContextImpl类型的对象。ContextImpl的bindService会调用自己的bindServiceCommon方法。

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        // Keep this in sync with DevicePolicyManager.bindDeviceAdminServiceAsUser.
        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        } 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(this);
            int res = ActivityManager.getService().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

  首先把ServiceConnection转换成ServiceDispatcher.InnerConnection。因为bindService有可能是跨进程的,InnerConnection是一个Binder类型对象。直观的我们也能猜到,这里肯定需要建立ServiceConnection和InnerConnection的联系。这个转换和对应关系的建立都是在LoadedApk的getServiceDispatcher中完成的。

public final IServiceConnection getServiceDispatcher(ServiceConnection c,
            Context context, Handler handler, int flags) {
        synchronized (mServices) {
            LoadedApk.ServiceDispatcher sd = null;
            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
            if (map != null) {
                if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
                sd = map.get(c);
            }
            if (sd == null) {
                sd = new ServiceDispatcher(c, context, handler, flags);
                if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
                if (map == null) {
                    map = new ArrayMap<>();
                    mServices.put(context, map);
                }
                map.put(c, sd);
            } else {
                sd.validate(context, handler);
            }
            return sd.getIServiceConnection();
        }
    }

  mServices是LoadedApk中的map集合,存储着ServiceConnection,和LoadedApk.ServiceDispatcher对应关系。ServiceDispatcher内部存储着ServiceConnection和InnerConnection。InnerConnection内部又保存着ServiceDispatcher的引用。这样建立连接后,系统通过binder机制跨进程调用InnerConnection的connected方法时,会调用到ServiceDispatcher的connected,ServiceDispatcher保存着ServiceConnection,最终调用到ServiceConnection的onServiceConnected。下面这个图非常直观的反应他们的对应关系。
这里写图片描述
  getServiceDispatcher创建好ServiceDispatcher和对应关系后,返回ServiceDispatcher中的InnerConnection。接着bindServiceCommon会跨进程调用到AMS的bindService。

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

  AMS调用ActiveServices的bindServiceLocked方法。ActiveServices是负责Service创建、绑定的工具类。bindServiceLocked会调用bringUpServiceLocked,bringUpServiceLocked又会调用realStartServiceLocked。realStartServiceLocked首先调用了app.thread的scheduleCreateService进行跨进程通信来创建service。app.thread是个Binder对象,会调用ApplicationThread的对应方法,然后通过Handler交给ActivityThread处理,这里不在详细赘述。接着调用requestServiceBindingLocked进行绑定。

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
1423            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
1424        if (r.app == null || r.app.thread == null) {
1425            // If service is not currently running, can't yet bind.
1426            return false;
1427        }
1428        if ((!i.requested || rebind) && i.apps.size() > 0) {
1429            try {
1430                bumpServiceExecutingLocked(r, execInFg, "bind");
1431                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
1432                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
1433                        r.app.repProcState);
1434                if (!rebind) {
1435                    i.requested = true;
1436                }
1437                i.hasBound = true;
1438                i.doRebind = false;
1439            } catch (TransactionTooLargeException e) {
1440                // Keep the executeNesting count accurate.
1441                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r, e);
1442                final boolean inDestroying = mDestroyingServices.contains(r);
1443                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
1444                throw e;
1445            } catch (RemoteException e) {
1446                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r);
1447                // Keep the executeNesting count accurate.
1448                final boolean inDestroying = mDestroyingServices.contains(r);
1449                serviceDoneExecutingLocked(r, inDestroying, inDestroying);
1450                return false;
1451            }
1452        }
1453        return true;
1454    }

  绑定调用了r.app.thread.scheduleBindService方法。ApplicationThread被调用后会向H发送BIND_SERVICE的消息。H收到信息后,会执行handleBindService方法。

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());
                data.intent.prepareToEnterProcess();
                try {
                    if (!data.rebind) {
                        IBinder binder = s.onBind(data.intent);
                        ActivityManager.getService().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManager.getService().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to bind to service " + s
                            + " with " + data.intent + ": " + e.toString(), e);
                }
            }
        }
    }

  handleBindService中拿到我们重写onBind返回的Binder对象。通过ActivityManager.getService().publishService实际上还是跨进程传递给AMS,并调用AMS的publishService方法。AMS的publishService调用了ActiveServices的publishServiceLocked方法。publishServiceLocked核心方法就是下面一句,service是onBind返回的Binder对象。c.conn就是之前提到的LoadedApk.ServiceDispatcher.InnerConnection。

c.conn.connected(r.name, service);
private static class InnerConnection extends IServiceConnection.Stub {
            final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

            InnerConnection(LoadedApk.ServiceDispatcher sd) {
                mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
            }

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

  InnerConnection的connected方法调用了对应的ServiceDispatcher的connected。

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

  ServiceDispatcher将RunConnection post到主线程,这也是为什么onServiceConnected会在主线程回调。

private final class RunConnection implements Runnable {
            RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
                mName = name;
                mService = service;
                mCommand = command;
                mDead = dead;
            }

            public void run() {
                if (mCommand == 0) {
                    doConnected(mName, mService, mDead);
                } else if (mCommand == 1) {
                    doDeath(mName, mService);
                }
            }

            final ComponentName mName;
            final IBinder mService;
            final int mCommand;
            final boolean mDead;
        }

  RunConnection调用了ServiceDispatcher的doConnected方法,doConnected调用了内部保存的ServiceConnection的onServiceConnected。至此绑定流程至此完成了。

参考《Android开发艺术探索》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值