第九章-四大组件的工作过程(Service的工作过程-基于Android8.1源码)

我们将介绍Service的启动过程和绑定过程,在分析Service的工作过程之前,我们先来了解一下如何使用Service。Service分为两种工作状态,一种是启动状态,主要用于执行后台计算;另一种是绑定状态,主要用于其他组件和Service的交互。需要注意的是,这两种状态是可以共存的。

  • 启动
Intent intent = new Intent(this, MyService.class);
startService(intent);
  • 绑定
Intent intent = new Intent(this, MyService.class);
bindService(intent,mServiceConnection,BIND_AUTO_CREATE);

一、启动服务示例
我们先写个demo示例,再来源码分析。

MyService.java

package com.example.service;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {
    private static final String TAG = "MyService";

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG,"onCreate || thread = " + Thread.currentThread().getName());
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG,"onStartCommand || thread = " + Thread.currentThread().getName());
        return super.onStartCommand(intent, flags, startId);
    }


    public IBinder onBind(Intent intent) {
        Log.d(TAG,"onBind || thread = " + Thread.currentThread().getName());
        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"onDestroy || thread = " + Thread.currentThread().getName());
    }
}

在AndroidManifest.xml中注册这个服务

<service android:name="com.example.service.MyService"/>

测试Activity

package com.example.service;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import com.example.test.R;

public class TestServiceActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_service);
    }

    //启动服务
    Intent startIintent;
    public void startService(View view) {
        startIintent = new Intent(this,MyService.class);
        startService(startIintent);
    }

    public void stopService(View view) {
        if(startIintent != null){
            stopService(startIintent);
        }
    }

    public void bindService(View view) {
        if(startIintent != null){
            stopService(startIintent);
        }
    }

}

布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.service.TestServiceActivity"
    android:orientation="vertical"
    >

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="启动Service"
        android:onClick="startService"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="停止Service"
        android:onClick="stopService"
        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="绑定Service"
        android:onClick="bindService"
        />

</LinearLayout>

点击启动和停止服务打印如下:

2020-04-09 16:28:19.286 6157-6157/com.example.test D/MyService: onCreate || thread = main
2020-04-09 16:28:19.287 6157-6157/com.example.test D/MyService: onStartCommand || thread = main
2020-04-09 16:28:21.670 6157-6157/com.example.test D/MyService: onStartCommand || thread = main  //第二次点击启动
2020-04-09 16:28:24.852 6157-6157/com.example.test D/MyService: onDestroy || thread = main

可以看到,onStartCommand会调用多次。回调都是运行在主线程

备注:下面都是基于Androidd8.1的源码进行分析的。

二、Service的启动过程

下面从代码层面分析Service的启动过程。(其实和Activity的启动过程类似,也是IPC过程。调用到AMS中 >
ApplicationThread中 > 发消息 > 切换到ActivityThread中 > 调用service的生命周期方法)

Service的启动过程从ContextWrapper的startService开始,如下所示

    @Override
    public ComponentName startService(Intent service) {
        return mBase.startService(service);
    }

上面的代码中,mBase是ContextImpl类型,Activity启动分析知道,在Activity被创建的时候会通过attach方法将一个ContextImpl对象关联起来,这个ContextImpl对象就是上述代码的mBase
从ContextWrapper的实现可以看出,其大部分操作都在mBase里实现,在设计模式中这是一种典型的桥接模式。

========疑问解答,mBase是怎么赋值的?

//android.content.ContextWrapper
Context mBase;

//android.app.ActivityThread
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
	...
	 ContextImpl appContext = createBaseContextForActivity(r);
	 ...
	activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
						
	...
}

//android.app.Activity
final void attach(Context context, ActivityThread aThread,
		Instrumentation instr, IBinder token, int ident,
		Application application, Intent intent, ActivityInfo info,
		CharSequence title, Activity parent, String id,
		NonConfigurationInstances lastNonConfigurationInstances,
		Configuration config, String referrer, IVoiceInteractor voiceInteractor,
		Window window, ActivityConfigCallback activityConfigCallback) {
	attachBaseContext(context);
	...
}


@Override
protected void attachBaseContext(Context newBase) {
	super.attachBaseContext(newBase);//调用父类的ContextThemeWrapper.attachBaseContext方法
	newBase.setAutofillClient(this);
}

//android.view.ContextThremeWrapper
public ContextThemeWrapper(Context base, Resources.Theme theme) {
	super(base);//调用父类ContextWrapper的构造
	mTheme = theme;
}

//android.content.ContextWrapper
public ContextWrapper(Context base) {
	mBase = base;//可以看到前面创建的ContextImpl实例就赋值给了这个mBase的全局变量了。
}

总结:Activity继承ContextThremeWrapper,ContextThremeWrapper继承ContextWrapper,所以在activity调用startService就直接调用到了ContextWrapper中的startService,又通过mBase.startService将代码逻辑交给了ContextImpl处理了。
========疑问已解答

下面我们继续来看ContextImpl的startService实现:

	@Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, mUser);
    }

    private ComponentName startServiceCommon(Intent service, UserHandle user) {
        try {
            validateServiceIntent(service);
            service.prepareToLeaveProcess();
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service,
                service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
            if (cn != null) {
                if (cn.getPackageName().equals("!")) {
                    throw new SecurityException(
                            "Not allowed to start service " + service
                            + " without permission " + cn.getClassName());
                } else if (cn.getPackageName().equals("!!")) {
                    throw new SecurityException(
                            "Unable to start service " + service
                            + ": " + cn.getClassName());
                }
            }
            return cn;
        } catch (RemoteException e) {
            return null;
        }
    }

在ContextImpl中,startService方法会调用startServiceCommon方法,而startServiceCommon方法又是通过ActivityManagerNative.getDefault().startService的对象来启动一个服务的,对于ActivityManagerNative.getDefault()这个对象,实际就是个AMS(IPC通信前面介绍过了,这里不重复)。AMS的startService方法实现如下:

    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, int userId) {
        enforceNotIsolatedCaller("startService");
        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        if (DEBUG_SERVICE)
            Slog.v(TAG, "startService: " + service + " type=" + resolvedType);
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
			//final ActiveServices mServices;
            ComponentName res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, userId);//调用了这个方法
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

在这段代码中,我们会调用mServices的startServiceLocked方法来启动,mServices对象的类型是ActiveServices,ActiveServices是一个辅助AMS进行Service管理的类,包含Service的启动,停止,绑定和停止等。在ActiveServices的startServiceLocked的尾部会调用startServiceInnerLocked,startServiceInnerLocked的实现如下:

	ComponentName startServiceInnerLocked(ServiceMap smap, Intent service,
            ServiceRecord r, boolean callerFg, boolean addToStarting) {
        ProcessStats.ServiceState stracker = r.getTracker();
        if (stracker != null) {
            stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
        }
        r.callStart = false;
        synchronized (r.stats.getBatteryStats()) {
            r.stats.startRunningLocked();
        }
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false);//调用了这个方法
        if (error != null) {
            return new ComponentName("!!", error);
        }

        if (r.startRequested && addToStarting) {
            boolean first = smap.mStartingBackground.size() == 0;
            smap.mStartingBackground.add(r);
            r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
            if (DEBUG_DELAYED_SERVICE) {
                RuntimeException here = new RuntimeException("here");
                here.fillInStackTrace();
                Slog.v(TAG, "Starting background (first=" + first + "): " + r, here);
            } else if (DEBUG_DELAYED_STARTS) {
                Slog.v(TAG, "Starting background (first=" + first + "): " + r);
            }
            if (first) {
                smap.rescheduleDelayedStarts();
            }
        } else if (callerFg) {
            smap.ensureNotStartingBackground(r);
        }

        return r.name;
    }

在这里插入图片描述

	//ActiveServices#bringUpServiceLocked
	private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        ...

        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);//调用到这里
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }

                // If a dead object exception was thrown -- fall through to
                // restart the application.
            }
        } else {
        ...

        return null;
    }
    
//ActiveServices#realStartServiceLocked
	private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        if (app.thread == null) {
            throw new RemoteException();
        }
        if (DEBUG_MU)
            Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
                    + ", ProcessRecord.uid = " + app.uid);
        r.app = app;
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();

        final boolean newService = app.services.add(r);
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
        mAm.updateOomAdjLocked();

        boolean created = false;
        try {
            ...
            synchronized (r.stats.getBatteryStats()) {
                r.stats.startLaunchedLocked();
            }
            mAm.notifyPackageUse(r.serviceInfo.packageName,
                                 PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);//调用到这个方法,这里就将逻辑通过IPC调用到了ApplicationThread#scheduleCreateService,追踪最后会调用到我们Server的onCreate方法
            r.postNotification();
            created = true;
        } catch (DeadObjectException e) {
            Slog.w(TAG, "Application dead when creating service " + r);
            mAm.appDiedLocked(app);
            throw e;
        } finally {
            ...
        }

        if (r.whitelistManager) {
            app.whitelistManager = true;
        }

        requestServiceBindingsLocked(r, execInFg);

        updateServiceClientActivitiesLocked(app, null, true);

        ...

        sendServiceArgsLocked(r, execInFg, true);//注意下这个方法,这个方法里面也会通过IPC回调到ApplicationThread#scheduleServiceArgs,最终会调用到我们Server的onStartCommand方法

        ...
    }	

在这里插入图片描述

	//ApplicationThread#scheduleCreateService
	public final void scheduleCreateService(IBinder token,
			ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
		updateProcessState(processState, false);
		CreateServiceData s = new CreateServiceData();
		s.token = token;
		s.info = info;
		s.compatInfo = compatInfo;

		sendMessage(H.CREATE_SERVICE, s);//和之前分析的一样,发送一个消息。因为ApplicationThread是一个Binder,这个方法是运行在Binder线程池中的。所以通过Handler将代码逻辑切换到我们的主线程ActivityThread中。
	}
	
	//Handler片段
	case CREATE_SERVICE:
		Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
		handleCreateService((CreateServiceData)msg.obj);
		Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
		break;

	//handleCreateService方法
	private void handleCreateService(CreateServiceData data) {
        // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();//1、通过类加载器创建Service实例
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);//2、创建Application
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());//3、将ContextImpl和Service建立关系
            service.onCreate();////4、onCreate方法在此调用
            mServices.put(data.token, service);//5、将服务存储到ArrayMap列表中
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

handleCreateService主要完成了如下几件事:
在这里插入图片描述
========疑问,如何调用handleServiceArgs这个方法的,其实在上面有提到过。
我们看AMS中的ActiveServices#realStartServiceLocked方法后面。会调用sendServiceArgsLocked

//ActiveServices#realStartServiceLocked
	private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
            boolean oomAdjusted) throws TransactionTooLargeException {
        ...
        ParceledListSlice<ServiceStartArgs> slice = new ParceledListSlice<>(args);
        slice.setInlineCountLimit(4);
        Exception caughtException = null;
        try {
            r.app.thread.scheduleServiceArgs(r, slice);//会调用到这个方法
        }
		...
    }
	
	//通过IPC调用到了 ApplicationThread#scheduleServiceArgs方法
	sendMessage(H.SERVICE_ARGS, s);
	
	
	//Handler片段
	case SERVICE_ARGS:
		Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceStart: " + String.valueOf(msg.obj)));
		handleServiceArgs((ServiceArgsData)msg.obj);
		Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
		break;
		
	可以看到最终调用到了ActivityThread#handleServiceArgs方法
	
	private void handleServiceArgs(ServiceArgsData data) {
		...
				if (!data.taskRemoved) {
					res = s.onStartCommand(data.args, data.flags, data.startId);//最终调用到了onStartCommand方法
				} else {
					s.onTaskRemoved(data.args);
					res = Service.START_TASK_REMOVED_COMPLETE;
				}
	
				QueuedWork.waitToFinish();
				...
		
	}

========疑问已解答

到这里,Service的启动过程就分析完成了。下面看Service的绑定过程。

三、Service的绑定过程
和Service的启动过程一样,Service的绑定过程也是从ContextWrapper开始的:

	//绑定一个服务的方式:
	Intent intent = new Intent(this, MyServiceService.class);
	bindService(intent,mServiceConnection,BIND_AUTO_CREATE);
	
	private ServiceConnection mServiceConnection = new ServiceConnection() {
		@Override
		public void onServiceConnected(ComponentName name, IBinder binder) {
			
			//MyService.MyBinder这个可以在你的服务中定义,也可以定义具体的逻辑方法。
			MyService.MyBinder myBinder = (MyService.MyBinder)binder;
			
			//调用服务里面的方法,calculate可以自己去实现,这里只是个伪代码
			myBinder.calculate();
		}
	
		@Override
		public void onServiceDisconnected(ComponentName name) {
			isBound = false;
		}
    };
	
	//ContextWrapper#bindService
	@Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }

这个过程和Service的启动过程是类似的,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) {
        	//特别关注下这个方法,使用到了我们设置的ServiceConnection
            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());//这里通过Binder调用到AMS中去了
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

在这里插入图片描述

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

在这里插入图片描述
接着bindServiceCommon方法会通过AMS来完成Service的具体绑定过程,这里对应AMS的bindService方法:

    public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        enforceNotIsolatedCaller("bindService");

        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        if (callingPackage == null) {
            throw new IllegalArgumentException("callingPackage cannot be null");
        }

        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

在这里插入图片描述

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        if (r.app == null || r.app.thread == null) {
            // If service is not currently running, can't yet bind.
            return false;
        }
        if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
                + " rebind=" + rebind);
        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;
    }
    

AMS通过Binder调用到了ApplicationThread#scheduleBindService了

	ApplicationThread#scheduleBindService
	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);//发送一个消息
	}

在这里插入图片描述

    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) {
                    	//回调到onBind的方法,这个时候客户端并不知道已经绑定成功了。
                        IBinder binder = s.onBind(data.intent);
						//会调用到这个方法,又IPC调用到AMS中了。目的是回调ServiceConnection#onServiceConnected方法
                        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);
                }
            }
        }
    }
	

通过上面的分析,已经回调了onBind方法。但是我们客户端不知道,还需要一次IPC来回调我们设置的ServiceConnection#onServiceConnected方法。
在这里插入图片描述

AMS中的publishService

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

在这里插入图片描述

调用到InnerConnection#connected(可以看到又调回了我们客户端的Binder线程池了

	//android.app.LoadedApk的内部类InnerConnection 看定义也是一个Binder类
	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);
			}
		}
	}
	
	//LoadedApk.ServiceDispatcher#connected方法
	public void connected(ComponentName name, IBinder service, boolean dead) {
		if (mActivityThread != null) {
			mActivityThread.post(new RunConnection(name, service, 0, dead));//mActivityThread不会为null、走到这个分支
		} else {
			doConnected(name, service, dead);
		}
	}

在这里插入图片描述

	//LoadedApk内部类RunConnection
	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;
	}
	
	
	//LoadedApk.ServiceDispatch#doConnected
	public void doConnected(ComponentName name, IBinder service, boolean dead) {
		...

		// If there is a new service, it is now connected.
		if (service != null) {
			mConnection.onServiceConnected(name, service);//到这里就调用到了onServiceConnected,我们就知道绑定成功了。
		}
	
	}

到这里客户端的onServiceConnected回调了,并且将service这个Binder服务对象返回给客户端了。绑定过程就分析完成了。

总结下:第一次回调onBind的时候,客户端并不知道绑定成功了。紧接着需要再次IPC,通过publishService这个方法,再次进入AMS,最终回调了onServiceConnected。所以了解Binder的IPC通信很重要。将IPC放在前面介绍是很正确的。只有掌握前面的知识,这里才能完成分析。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章