Android7.0 bindService源码解析

看到标题的时候,有些同学可能会有些质疑:现在都Android12了,你讲Android7,是不是太过时了。这里有两个原因:

(1)Android8.0和Android7.0的源码有些不同,但是Android8.0和Android12的区别不是很大,所以之后我会再写一篇关于Android8.0的bindService源码的解析

(2)Android8.0开始,很多地方由AIDL生成,所以代码细节被隐藏了,看不见,直接去看Android8.0的话,思路会有断开的地方。而对比Android7.0来看的话,就会很明白:思路不通的地方是因为某些细节被隐藏了。这是个人的一些经历,看Android8.0的时候,的确有点懵,看了Android7.0之后,就清楚了。

1.AMS的bindService

我们从调用bindService方法开始来看

bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE);

我们点击进入bindService方法,进入到了Context中的bindService中,而这个方法是一个抽象方法,而这个方法的具体实现其实是ContextWrapper中,所以我们直接看ContextWrapper的bindService方法


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

我们可以看到在ContextWrapper中的bindService又调用了mBase的bindService方法,mBase是Context类型,是一个抽象类,具体的实现类是ContextImpl,所以我们看ContextImpl中的bindService方法

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                Process.myUserHandle());
    }

调用了bindServiceCommon方法

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        ...
        try {
            ...
            int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            ...
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

 在这个方法中,我们清楚的看见调用了ActivityManagerNative.getDefault()方法,我们看一下

    static public IActivityManager getDefault() {
        return gDefault.get();
    }

gDefault对象

    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

调用ServiceManager.getService("activity"),获得了IBinder对象,而这个对象其实和我们使用Binder跨进程通信时的远程Binder对象是一个意义,都是远程的一个代理对象。我们再进入asInterface方法进入看下,就更清楚了

    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

和我们使用AIDL时,生成文件中的asInterface是一样的。所以ActivityManagerNative.getDefault()调用了bindService,其实就是ActivityManagerProxy调用的bindService,我们查看这个bindService方法

    public int bindService(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType, IServiceConnection connection,
            int flags,  String callingPackage, int userId) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        data.writeStrongBinder(token);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeStrongBinder(connection.asBinder());
        data.writeInt(flags);
        data.writeString(callingPackage);
        data.writeInt(userId);
        mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        data.recycle();
        reply.recycle();
        return res;
    }

只要使用过AIDL,并且看过生成的文件,上面的代码应该很熟,Parcel包装了一些数据,并使用mRemote调用了transact方法进行了数据传输,其中的第一个参数为BIND_SERVICE_TRANSACTION,那么肯定有接收的地方,我们再在ActivityManagerNative中找到了接收的地方:

        case BIND_SERVICE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            IBinder token = data.readStrongBinder();
            Intent service = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            b = data.readStrongBinder();
            int fl = data.readInt();
            String callingPackage = data.readString();
            int userId = data.readInt();
            IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
            int res = bindService(app, token, service, resolvedType, conn, fl,
                    callingPackage, userId);
            reply.writeNoException();
            reply.writeInt(res);
            return true;
        }

我们发现,这里有调用bindService方法,这里的bindService方法是上面的AndroidManagerProxy的bindService方法吗?如果是的话,这不就是死循环了吗?显然不是,我们所了解的AIDL所生成的文件中,接收到信号之后,真正执行的应该是我们自己实现的那个Stub,所以这里应该是ActivityManagerService的bindService方法,看一下ActivityManagerService(AMS)类的实现

public final class ActivityManagerService extends ActivityManagerNative
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback

继承了ActivityManagerNative类。

2.Service的绑定过程

接着上面的,我们看AMS的bindService

    public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        ...
        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

mService是ActiveServices,我们看ActiveServices的bindServiceLocked方法

    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
    ...
    try {
        ....
        if (s.app != null && b.intent.received) {
            ....
            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);
        }
    }
}

这里的代码很多,我阉割了无关的代码。调用requestServiceBindingLocked方法,并且第三个参数是为false,第三个参数是rebind,重新绑定的意思,我们看下代码

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        ...
        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;
            } 
            ...
        }
        return true;
    }

我们可以看到,调用了thread的scheduleBindService方法,这里thread其实就是ActivityThread,所以我们直接到ActivityThread中寻找scheduleBindService方法

        public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            ...
            sendMessage(H.BIND_SERVICE, s);
        }

sendMessage方法大家应该比较熟悉,所以直接找到接收H.BIND_SERVICE的地方就行了,同样是在ActivityThread方法中,如下:

                case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;

查看handleBindService方法

    private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        if (s != null) {
            try {
                ...
                try {
                    if (!data.rebind) {
                        IBinder binder = s.onBind(data.intent);
                        ActivityManagerNative.getDefault().publishService(
                                data.token, data.intent, binder);
                    } else {
                        ...
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                    throw ex.rethrowFromSystemServer();
                }
            } catch (Exception e) {
                ...
            }
        }
    }

上面我们说了,ActivityManagerNative.getDefault是ActivityManagerProxy,所以我们直接看这个类的publishService方法

    public void publishService(IBinder token,
            Intent intent, IBinder service) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(token);
        intent.writeToParcel(data, 0);
        data.writeStrongBinder(service);
        mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

查看接收PUBLISH_SERVICE_TRANSACTION的地方,还是在ActivityManagerNative中

        case PUBLISH_SERVICE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder token = data.readStrongBinder();
            Intent intent = Intent.CREATOR.createFromParcel(data);
            IBinder service = data.readStrongBinder();
            publishService(token, intent, service);
            reply.writeNoException();
            return true;
        }

publishService的方法是在AMS中实现的,和之前的bindService是一样的,我们查看publishService方法


    public void publishService(IBinder token, Intent intent, IBinder service) {
        ...
        synchronized(this) {
            ....
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }

查看publishServiceLocked方法

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        ...
        c.conn.connected(r.name, service);
        ...
    }

关键的方法如上,这里的conn是IServiceConnection,而具体的实现类是LoadedApk.ServiceDispatcher,我们在ContextImpl的bindServiceCommon可以找到,如下

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        ...
        if (mPackageInfo != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        }
        ...
    }

感兴趣的同学可以从这里去递进的查找,我这里就不贴代码了,最后会调用到LoadedApk.ServiceDispatcher的doConnected方法,如下:

        public void doConnected(ComponentName name, IBinder service) {
            ...
            // If there is a new service, it is now connected.
            if (service != null) {
                mConnection.onServiceConnected(name, service);
            }
        }

mConnection就是我们调用bindService时传入的ServiceConnection,绑定成功后,从这里回调

bindService到此结束了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值