Service工作流程 - bindService

一:BindService流程图
Service工作流程 - bindService_第1张图片
BindService
补充一:ServiceDispatcher

bindServiceCommon(): 将客户端的ServiceConnection对象转化为ServiceDispatcher.InnerConnection对象。因为ServiceConnection对象不是一个Binder对象,不能跨进程传输。而其onServiceConnected()方法需要借助AMS回调,所以先要把它转换成对应的Binder对象。

这个对象就是IServiceConnection(IInterface)接口的实现类ServiceDispatcher.LoadApk

private boolean  bindServiceCommon(Intent service, ServiceConnection conn, int flags,
           UserHandle user) {
       IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
       }
       if (mPackageInfo != null) {
           // LoadApk mPackageInfo
           sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                    mMainThread.getHandler(), 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();
           int res = ActivityManagerNative.getDefault().bindService(
              mMainThread.getApplicationThread(), getActivityToken(),
                service, service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, user.getIdentifier());
           if (res < 0) {
               throw new SecurityException(
                      "Not allowed to bind to service " + service);
           }
          return res != 0;
        } catch (RemoteException e) {
            return false;
        }
    }

LoadApk.getServiceDispatcher():首先判段map里面是否存储的键值对,如果存储过,就取出当前ServiceConnection对应的LoadedApk.ServiceDispatcher,没有就创建一个ServiceDispatcher对象,并存储。然后根据这个ServiceDispatcher对象取出LoadedApk.ServiceDispatcher.InnerConnection对象。

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

LoadApk.ServiceDispatcher.InnerConnection:
这个类是ServiceDispatcher的内部类。而且实现了IServiceConnection.Stub类,所以它是一个Binder对象。可以跨进程传输。在它的内部调用了LoadedApk.ServiceDispatcher的connected()方法。

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

ServiceDispatcher. connected():
通过一个 handler传递到主线程;mActivityThread的类型是Handler 。

public void connected(ComponentName name, IBinder service) {
          if (mActivityThread != null) {
               mActivityThread.post(new RunConnection(name, service, 0));
          } else {
               doConnected(name, service);
       }

}
补充二 realStartServiceLocked(): realStartServiceLocked()里面有两个比较重要的方法。分别为

(1)scheduleCreateService():走创建Service的方法调用链。
(2)requestServiceBindingsLocked():走Bind Service的方法调用链。

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

    boolean created = false;
    try {
        synchronized (r.stats.getBatteryStats()) {
            r.stats.startLaunchedLocked();
        }
        mAm.ensurePackageDexOpt(r.serviceInfo.packageName);
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
        app.thread.scheduleCreateService(r, r.serviceInfo,
                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                app.repProcState);
        r.postNotification();
        created = true;
    } catch (DeadObjectException e) {
        mAm.appDiedLocked(app);
        throw e;
    } finally {
      ...
    }

    requestServiceBindingsLocked(r, execInFg);

    // 不关心,略。。
}

你可能感兴趣的:(Service工作流程 - bindService)