【Android源码】Service的绑定过程

前篇:Service的启动过程

刚开始的过程和startService类似:

@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) {
   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 = ActivityManagerNative.getDefault().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();
   }
}

bindServiceCommon主要完成了两件事情:

  1. 通过mPackageInfo.getServiceDispatcherServiceConnection转化成了ServiceDispatcher.InnerConnection对象,为什么需要转换呢?

    这是因为服务的绑定有可能是跨进程的,所以ServiceConnection必须借助Binder机制才能让服务器来回调自己的方法,而InnerConnection正好实现了IServiceConnection.Stub,转化成了Binder对象。

  2. 完成绑定操作。

    ActivityManagerService.bindService
    -> ActiveServices.bindServiceLocked
    -> ActiveServices.bringUpServiceLocked
    -> ActiveServices.realStartServiceLocked
    

    同样的和启动过程类似,都是通过ApplicationThread来创建Service的实例,并执行onCreate方法。

之后会调用requestServiceBindingsLocked方法来绑定Service。

ActiveServices.requestServiceBindingsLocked
-> ActiveServices.requestServiceBindingLocked
-> ApplicaitonThread.scheduleBindService

同样的是通过Handler来发送BIND_SERVICE消息

 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 (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);
                   ActivityManagerNative.getDefault().publishService(
                           data.token, data.intent, binder);
               } else {
                   s.onRebind(data.intent);
                   ActivityManagerNative.getDefault().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);
           }
       }
   }
}     

这个时候通过s.onBind(data.intent)就将Service绑定起来了。

那么客户端是如何知道已经成功连接到Service了呢?
这个时候就要调用onServiceConnected方法,这个过程就由publishService来完成。

ActivityManagerNative.getDefault().publishService(
                                data.token, data.intent, binder);
                                
-> ActivityManagerService.publishService  
-> ActiveServices.publishServiceLocked

publishServiceLocked中核心就一句c.conn.connected(r.name, service)

其中c.conn就是一开始将ServiceConnection转化成的ServiceDispatcher.InnerConnection对象。

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) throws RemoteException {
      LoadedApk.ServiceDispatcher sd = mDispatcher.get();
      if (sd != null) {
          sd.connected(name, service);
      }
  }
}
// LoadedApk.java
public void connected(ComponentName name, IBinder service) {
  if (mActivityThread != null) {
      mActivityThread.post(new RunConnection(name, service, 0));
  } else {
      doConnected(name, service);
  }
}

由代码可以知道mActivityThread是一个Handler,其实就是ActivityThread中的H,是不可能为空的,所以必定会调用post方法。

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

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

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

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

  // If there was an old service, it is not disconnected.
  if (old != null) {
      mConnection.onServiceDisconnected(name);
  }
  // If there is a new service, it is now connected.
  if (service != null) {
      mConnection.onServiceConnected(name, service);
  }
}

由于mCommand传的值为0,所以调用的是doConnected方法,这个时候很方便的调用到了onServiceConnected

至此,Service的绑定过程就完全分析结束了。

你可能感兴趣的:(【Android源码】Service的绑定过程)