Android Service启动(二) bindService()启动过程以及原理解析

本篇文章主要讲解bindService()绑定Service的过程。(android的版本依旧是26)

通过bindService()绑定一个Service时,最终都是调用的ContextWrapper的bindService()方法,我们来看下这个方法

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

上述方法中调用了mBase对象的bindService()方法,mBase的类型是Context,Context的实现类是ContextImpl,我们来看下ContextImpl的bindService()方法

@Override
public boolean bindService(Intent service, ServiceConnection conn,int flags) {
    warnIfCallingFromSystemProcess();
    return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                Process.myUserHandle());
}
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其实指向的是一个ServiceDispatch.InnerConnection的对象
         * 最终调用ServiceConnection的onServiceConnected()方法也是通过这个对象   
         */
        sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
    } else {
        throw new RuntimeException("Not supported in system context");
    }
    //检查合法性
    validateServiceIntent(service);
    try {

        ......
    
        //调用ActivityManagerService的bindService()方法
        int res = ActivityManager.getService().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());

        ......

    } catch (RemoteException e) {
        throw e.rethrowFromSystemServer();
    }
}

由上述代码可知,相比较startService()的过程,在调用ActivityManagerService的bindService()方法之前,在bindServiceCommon()方法中多一个获取sd对象,即ServiceDispatch.InnerConnection类的对象的过程,mPackageInfo是LoadedApk类的一个引用,我们来看下mPackageInfo.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) {
           /*创建ServiceDispatcher对象
            *而在本方法中最终return的sd.getIServiceConnection()的值也是在ServiceDispatcher 
            *的构造方法中初始化的,稍后的文章中会讲到这一点。
            */
            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的是ServiceDispatcher的内部类InnerConnection对象
        return sd.getIServiceConnection();
    }
}

上述代码中提到,getServiceDispatcher()方法最终返回的sd.getIServiceConnection()是ServiceDispatcher中的内部类InnerConnection对象,我们先来看一下上述方法最终return的sd.getIServiceConnection()到底是什么

IServiceConnection getIServiceConnection() {
    return mIServiceConnection;
}

可以看到该方法最终return的是一个IServiceConnection对象,看样子像是一个跨进程通信要用的东西,那么这个对象是在哪里创建的呢

ServiceDispatcher(ServiceConnection conn,
                Context context, Handler activityThread, int flags) {
    mIServiceConnection = new InnerConnection(this);
    mConnection = conn;
    mContext = context;
    mActivityThread = activityThread;
    mLocation = new ServiceConnectionLeaked(null);
    mLocation.fillInStackTrace();
    mFlags = flags;
}

由上述代码可知,mIServiceConnection是在ServiceDispatcher的构造方法中创建的,最终mIServiceConnection引用指向的是以ServiceDispatcher为参数构造的InnerConnection这个内部类的对象。我们来一下InnerConnection这个内部类

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继承了IServiceConnection.Stub,看样子应该可以进行跨进程间的通信,内部持有了外部类ServiceDispatcher类的弱引用,代码量比较少,除了构造方法之外,只有一个connected()方法,在这个connected()方法中,获取了外部传递过来的ServiceDispatcher对象,并调用了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);
    }
}

可以看到connected()方法中会执行RunConnection的run()方法或者doConnected()方法,下面我们来看下RunCon

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值