android 9.0 bindService绑定Servcie的过程分析

在Activity中使用bindService绑定Service时,会调用ContextWrapper的bindService方法

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/content/ContextWrapper.java

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

这个方法的mBase就是一个ContextImpl类型的对象。所以这里调用了ContextImpl类的bindService方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.java

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

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
        handler, UserHandle user) {
    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 {
        // ...
	// 关键代码
        int res = ActivityManager.getService().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());
        // ...
    }
    // ...
}

在bindServiceCommon方法中,先调用LoadedApk类型的变量mPackageInfo.getServiceDispatcher方法,获取一个IServiceConnection类型的对象sd,下面看看LoadedApk类中的这个方法的具体实现:


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java

public final IServiceConnection getServiceDispatcher(ServiceConnection c,
        Context context, Handler handler, int flags) {
    synchronized (mServices) {
        LoadedApk.ServiceDispatcher sd = null;
        ArrayMap 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 (map == null) {
                map = new ArrayMap<>();
                mServices.put(context, map);
            }
            map.put(c, sd);
        } else {
            sd.validate(context, handler);
        }
	// 关键代码
        return sd.getIServiceConnection();
    }
}


ServiceDispatcher(ServiceConnection conn,
        Context context, Handler activityThread, int flags) {
    // 关键代码
    mIServiceConnection = new InnerConnection(this);
    // ...
}

private static class InnerConnection extends IServiceConnection.Stub {
	// ...
}

从LoadedApk类的getServiceDispatcher方法内部的逻辑主要是创建其内部类ServiceDispatcher对象,在ServiceDispatcher对象的创建过程中,又创建了ServiceDispatcher的静态内部类InnerConnection的实例。InnerConnection其实是继承IServiceConnection.Stub,所以它是一个Binder。在getServiceDispatcher方法的最后一行,通过sd.getIServiceConnection();返回的就是InnerConnection这类的实例。继续看ContextImpl类的bindServiceCommon方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ContextImpl.java

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
        handler, UserHandle user) {
    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 {
        // ...
	// 关键代码
        int res = ActivityManager.getService().bindService(
            mMainThread.getApplicationThread(), getActivityToken(), service,
            service.resolveTypeIfNeeded(getContentResolver()),
            sd, flags, getOpPackageName(), user.getIdentifier());
        // ...
    }
    // ...
}

这个方法内部,通过ActivityManager.getService()获取到system_servier进程中的ActivityManagerService(后面简称AMS)在app进程中的代理对象,然后调用代理对象的bindService方法,并将前面获取的InnerConnection这个Binder对象作为参数传入,
这个过程就是进程间通信,下面看看AMS中的bindService方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

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

    // ...

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

这个方法内调用了mServices对象的bindServiceLocked方法,mServices是ActiveSerivces类型的,下面看看ActiveServices类的bindServiceLocked方法的具体实现:


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {

        //...

        try {
	    // ...

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
		//关键代码
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
            }

            // ...

            if (s.app != null && b.intent.received) {
                try {
		//关键代码
                    c.conn.connected(s.name, b.intent.binder, false);
                } 
		// ...

            } 
	    // ...

        } 
	// ...

        return 1;
    }


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);
	  // 如果要启动的Service所在 进程已经创建,并且进程的ActivityThread也不为null,则直接启动Service
          if (app != null && app.thread != null) {
              try {
                  app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                  realStartServiceLocked(r, app, execInFg);
                  return null;
              } 
              // ...
          }
      } 
      // ...
      //要启动的Service所在的进程还未创建
      if (app == null && !permissionsReviewRequired) {
      // 关键代码
          if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                  hostingType, r.name, false, isolated, false)) == null) {
              String msg = "Unable to launch app "
                      + r.appInfo.packageName + "/"
                      + r.appInfo.uid + " for service "
                      + r.intent.getIntent() + ": process is bad";
              bringDownServiceLocked(r);
              return msg;
          }
          // ...
      }

     //...

      return null;
  }

bindServiceLocked这个方法内部,会调用bringUpServiceLocked方法,bringUpServiceLocked内部会根据要绑定的Service所在的进程是否创建,如果进程创建了并且ActivityThread也不为null,则直接走绑定Service流程,否则,要先创建Service所在的进程,然后在走绑定Service的流程。为了分析过程尽量全面,我们就按照Service是在一个新的进程中这种情况分析,下面看mAm.startProcessLocked()这个方法,这里的mAm就是AMS,在AMS中,通过调用几次startProcessLocked()的重载方法后,调用到startProcess方法,接着调用了Process类的start方法,接着调用了ZygoteProcess类的start方法,Process类的start方法调用是system_server进程和ZygoteProcess进程进行进程间通信,他们是通过socket方式进行进程间通信的。ZygoteProcess内部,通过调用start方法,接着调用startViaZygote方法,最终调用zygoteSendArgsAndGetResult方法,完成Servcie所在的进程的创建工作,这样Servcie所在的进程就创建了,执行ActivityThread的main方法,在main方法中,主要完成了主线程的Looper的创建,并创建ActivityThread对象,并调用其attach方法,如果sMainHandler对象为null,则给这个对象赋值,并调用Looper.loop()方法进行消息的抽取。ActivityThread的attach方法中,在次获取system_server进程在app进程的代理对象,然后调用这个代理对象attachApplication方法,这个方法中,将ApplicationThread对象作为参数传入,这样system_servier进程就可以获取到app进程的ApplicationThread这个binder对象在system_server进程中的代理对象。方便后续system_server进程(客户端)向app进程(服务端)发起进程间通信。AMS的attachApplication方法内部又调用了attachApplicationLocked方法,
这个方法内部通过调用ApplicationThread这个对象的bindApplication方法,这个时候是进程间通信(system_server作为客户端,app进程作为服务端),ApplicationThread的bindApplication方法内部,调用了sendMessage(H.Execute_Bind)方法,接着又执行了handleBindApplication方法,handleBindApplication方法内部主要做了三件事:
1.创建Instrumentation对象
2.调用LoadedApk的makeApplication方法,创建Application对象
3.调用Instrumentation的callApplicationOnCreate方法,完成Application的OnCreate方法的执行。
到这里,AMS的attachApplicationLocked方法中的ApplicationThread的bindApplication方法执行过程分析完毕,这个过程的具体分析,可以看Android 9.0 点击桌面应用图标,启动Activity的过程分析
接着继续看AMS的attachApplicationLocked方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

@GuardedBy("this")
private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
	// ...

    try {
	 // ...
        if (app.isolatedEntryPoint != null) {

            thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
        } else if (app.instr != null) {
            thread.bindApplication(processName, appInfo, providers,
                    app.instr.mClass,
                    profilerInfo, app.instr.mArguments,
                    app.instr.mWatcher,
                    app.instr.mUiAutomationConnection, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(getGlobalConfiguration()), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, isAutofillCompatEnabled);
        } else {
	    // 关键代码
            thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                    null, null, null, testMode,
                    mBinderTransactionTrackingEnabled, enableTrackAllocation,
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(getGlobalConfiguration()), app.compat,
                    getCommonServicesLocked(app.isolated),
                    mCoreSettingsObserver.getCoreSettingsLocked(),
                    buildSerial, isAutofillCompatEnabled);
        }
        // ...
    }
// ...
        // Find any services that should be running in this process...
        if (!badApp) {
            try {
	    //关键代码
                didSomething |= mServices.attachApplicationLocked(app, processName);
                checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
                badApp = true;
            }
        }
    // ...

    return true;
}

上面已经分析了thread.bindApplication方法,下面继续看mServices.attachApplicationLocked方法,mServices是ActivieServices类型的,所以代码执行到ActivieServices类的attachApplicationLocked方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

boolean attachApplicationLocked(ProcessRecord proc, String processName)
        throws RemoteException {
    boolean didSomething = false;
    if (mPendingServices.size() > 0) {
        ServiceRecord sr = null;
        try {
            for (int i=0; i 0) {
        try {
            // ...
            r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                    r.app.repProcState);
            // ...
        } 
	// ...
    }
    return true;
}

attachApplicationLocked方法内部会r.app.thread.scheduleCreateService方法,r表示ServcieRecord对象,可以理解为是Servcie, r.app其实就是ProcessRecord类型的对象,可以理解为Process,r.app.thread是一个IApplicationThread类型的对象。
所以r.app.thread.scheduleBindService最终会执行到ApplicationThread的scheduleCreateService方法,这里其实是进程间通信。下面看看这个方法的具体实现

http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java

public final void scheduleCreateService(IBinder token,
        ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
    updateProcessState(processState, false);
    // ...
    // 关键代码
    sendMessage(H.CREATE_SERVICE, s);
}

public void handleMessage(Message msg) {
        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;
}


private void handleCreateService(CreateServiceData data) {

        unscheduleGcIdler();

        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;
        try {
	// 关键代码
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
        } 
	// ...

        try {
	// 关键代码
            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            service.onCreate();
            mServices.put(data.token, service);
            // ...
        }
	// ...
}

handleCreateService方法内部做了如下事情:
1.通过类加载的方式创建Service实例对象
2.调用LoadedApk类的makeApplication方法,返回一个Application对象
3.调用servcie的attach方法,这个方法内部主要是调用了attachBaseContext方法,将servcie与ContextImpl对象关联
4.调用Servcie的onCreate方法
至此,Servcie被创建,并且OnCreate方法也得到执行。

下面继续看ActiveServices类的realStartServiceLocked方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

private final void realStartServiceLocked(ServiceRecord r,
        ProcessRecord app, boolean execInFg) throws RemoteException {
    // ...

    boolean created = false;
    try {
        // ...
	// 关键代码
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
	// ...
    }

    // ...
    // 关键代码
    requestServiceBindingsLocked(r, execInFg);

    updateServiceClientActivitiesLocked(app, null, true);

    // ...
}


private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
            throws TransactionTooLargeException {
        for (int i=r.bindings.size()-1; i>=0; i--) {
            IntentBindRecord ibr = r.bindings.valueAt(i);
	    //关键代码
            if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
                break;
            }
        }
}

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
        boolean execInFg, boolean rebind) throws TransactionTooLargeException {
    //在前面的分析中,Service所在的进程已经创建,并且ActivityThread也创建了,所以这里的判断不成立
    if (r.app == null || r.app.thread == null) {
        return false;
    }

    if ((!i.requested || rebind) && i.apps.size() > 0) {
        try {
            // ...
            r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                    r.app.repProcState);
            // ...
        } 
	// ...
    }
    return true;
}

这方法内部继续调用到requestServiceBindingLocked的重载方法,这个重载方法内部,
调用r.app.thread,这个对象的scheduleBindService方法,r.app.thread是一个IApplicationThread类型的对象。所以r.app.thread.scheduleBindService最终会执行到ApplicationThread的scheduleBindService方法,这里其实是进程间通信。下面看看这个方法的具体实现


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/ActivityThread.java

public final void scheduleBindService(IBinder token, Intent intent,
        boolean rebind, int processState) {
    updateProcessState(processState, false);
    // ...
    // 关键代码
    sendMessage(H.BIND_SERVICE, s);
}


 public void handleMessage(Message msg) {
   case BIND_SERVICE:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
        handleBindService((BindServiceData)msg.obj);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        break;
}

private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        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);
                    }
                    // ...
                } 
		// ...
            }
	    // ...
        }
}

scheduleBindService方法最终调用到了handleBindService方法,最终调用了s.onBind()方法,这里的s就是Service,所以,至此Service的onBind方法执行。

接着调用了AMS的publishService方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/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是ActiveServices类型的,下面看看ActiveServices类的publishServiceLocked方法


http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/am/ActiveServices.java

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try {
            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

这个方法内部c.conn.connected(r.name, service, false);其中c.conn是LoadedApk类的静态内部类ServiceDispatcher的静态内部类InnerConnection类型对象,而InnerConnection 是继承 IServiceConnection.Stub,所以,c.conn其实就是app进程的InnerConnection这个binder对象在system_server进程中的代理,此时,system_server进程作为客户端,通过这个代理对象向app进程(作为服务端)发起进程间通信,这样,InnerConnection的onConnected方法就得到执行,下面看看InnerConnection的connected的具体实现


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java

public final class LoadedApk {
     static final class ServiceDispatcher {

	    private static class InnerConnection extends IServiceConnection.Stub {
            final WeakReference mDispatcher;

            InnerConnection(LoadedApk.ServiceDispatcher sd) {
                mDispatcher = new WeakReference(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);
                }
            }

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

InnerConnection的connected这个方法内部会调用ServiceDispatcher类的connected方法,
ServiceDispatcher类的connected方法又会调用
mActivityThread.post(new RunConnection(name, service, 0, dead));
这里mActivityThread其实就是个handler,下面看看这个RunConnection类,它是LoadedApk的静态内部类ServiceDispatcher的一个内部类


http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/app/LoadedApk.java

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


public void doConnected(ComponentName name, IBinder service, boolean dead) {
            ServiceDispatcher.ConnectionInfo old;
            ServiceDispatcher.ConnectionInfo info;

            synchronized (this) {
                if (mForgotten) {
                    return;
                }
                old = mActiveConnections.get(name);
                if (old != null && old.binder == service) {
                    return;
                }

                if (service != null) {
                    // A new service is being connected... set it all up.
                    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 now disconnected.
            if (old != null) {
                mConnection.onServiceDisconnected(name);
            }
            if (dead) {
                mConnection.onBindingDied(name);
            }
            if (service != null) {
	    // 关键代码
                mConnection.onServiceConnected(name, service);
            } else {
                // The binding machinery worked, but the remote returned null from onBind().
                mConnection.onNullBinding(name);
            }
}

run方法中,有调用了doConnected方法,doConnected方法中,mConnection.onServiceConnected方法,这里的mConnection就是我们bindServcie方法中传入的ServiceConnection类型的变量,所以至此,onServiceConnected方法得到回调。

以上便是bindService的整个过程分析

你可能感兴趣的:(android)