【Service的工作过程】bindService的启动过程

Service 的绑定过程将分为两个部分,分别是ContextImpl到AMS的调用过程和Service的绑定过程。

目录

在这里插入图片描述

ContextImpl到AMS的调用过程

这点流程与startService方式流程一致,也是调用ContextImpl的bindService最终请求AMS的bindService。

这里就介绍下ContextImpl到AMS调用间的一个重要方法

ContextImpl#bindServiceCommon
  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) {
        //1、mPackageInfo 为LoadedApk类型,
        //这里通过LoadedApk 对象的getServiceDispatcher方法对ServiceConnection
        // 进行封装成IServiceConnection 对象即sd
        //IServiceConnection类可以看到IPC的痕迹
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        validateServiceIntent(service);
...

// 2、最终调用AMS的bindService
  int res = ActivityManager.getService().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());

}

AMS到ActivityThread请求PublishService过程

时序图

在这里插入图片描述
AMS的bindService方法会调用ActiveServices类型的对象mServices的bindServiceLocked方法具体如下:

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

...
 ServiceRecord s = res.record;
...
//1、通过ServiceRecord的retrieveAppBindingLocked方法获得AppBindRecord 对象
  AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
   ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);

            IBinder binder = connection.asBinder();
  ...
  /*
  2、启动Service
 调用bringUpServiceLocked方法,在bringUpServiceLocked方法中又调用
realStartServiceLocked 方法,最终由ActivityThread 
调用Service的onCreate 方法启动Service,
这也说明了bindService方法内部会启动Service.
*/
   if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
            }
            ...
   /*
3、s.app!=null表示Service 已经运行。
  其中s 是ServiceRecord类型对象,app是ProcessRecord类型对象。

b.intent.received表示当前应用程序进程已经接收到绑定Service时返回的Binder,
这样应用程序进程就可以通过Binder 来获取要绑定的Service的访问接口

*/
   if (s.app != null && b.intent.received) {
                try {
/*
4、c.conn 是IServiceConnection类型,具体实现为ServiceDispatcher.InnerConnection
   ServiceDispatcher是LoadedApk的内部类
   InnerConnection的connected方法内部会调用H的post方法向主线程发送消息,
   并且解决当前应用程序进程和Service跨进程通信的问题

*/
                    c.conn.connected(s.name, b.intent.binder, false);
                } catch (Exception e) {
                    Slog.w(TAG, "Failure sending service " + s.shortName
                            + " to connection " + c.conn.asBinder()
                            + " (in " + c.binding.client.processName + ")", e);
                }
  /*

5、如果当前应用程序进程是第一个与Service进行绑定的,
并且Service已经调用过onUnBind方法,则需要走if的requestServiceBindingLocked。

如果应用程序进程的Client端没有发送过绑定Service的请求,
则会调用if的requestServiceBindingLocked。

if 与else的requestServiceBindingLocked区别只是最后传递的rebind boolean参数不同
rebind 为true代表重新绑定,为false代表不是重新绑定。

*/
                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                    requestServiceBindingLocked(s, b.intent, callerFg, true);
                }
            } else if (!b.intent.requested) {
                requestServiceBindingLocked(s, b.intent, callerFg, false);
            }

            getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);

        } finally {
            Binder.restoreCallingIdentity(origId);
        }

        return 1;
}

ServiceRecord:描述一个Service信息。

ProcessRecord:描述一个进程的信息。

ConnectionRecord:描述应用程序进程和Service建立的一次通信

AppBindRecord:维护Service与应用程序进程之间的关联。其内部存储了谁绑定的Service (ProcessRecord)、被绑定的Service (AppBindRecord)、绑定Service的Intent (IntentBindRecord)和所有绑定通信记录的信息(ArraySet<ConnectionRecord>)

ActiveServices#requestServiceBindingLocked
 private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
...
//bindServiceLocked的if语句调用可知:i.requested=true,rebind=true
 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;

}

i是IntentBindRecord 类型的对象,AMS 会为每个绑定Service的Intent分配一个IntentBindRecord类型对象

i.apps.size() > 0到底是啥意思呢?表示所有用当前Intent绑定Service的应用程序进程个数大于0。

final class IntentBindRecord {
     // 记录被绑定的service
    final ServiceRecord service;
    //记录绑定service的Intent
    final Intent.FilterComparison intent; 
    //记录所有用当前Intent绑定service的应用进程
    final ArrayMap<ProcessRecord, AppBindRecord> apps
            = new ArrayMap<ProcessRecord, AppBindRecord>();
            ...

}

r.app.thread的类型为IApplicationThread,它的实现是ActivityThread的内部类ApplicationThread,scheduleBindService方法:

ActivityThread#scheduleBindService

 public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            updateProcessState(processState, false);
            // 将Service的信息封装成BindServiceData对象
            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());
            //将BindServiceData传入到sendMessage方法中。sendMessage向H发送消息
            sendMessage(H.BIND_SERVICE, s);
        }

H 类在接收到BIND_SERVICE类型消息时,会在handleMessage方法中会调用handleBindService方法

ActivityThread#handleBindService

     private void handleBindService(BindServiceData data) {
     //1、获取要绑定的service
        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 {
                /*
                  2、data为BindServiceData对象。第一次绑定时rebind为false
                     会执行service的onBind方法。
                 */
                    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);
                    }
                    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);
                }
            }
        }
    }

可知:如果当前应用程序进程第一个与Service进行绑定,并且Service已经调用过onUnBind方法,则会调用Service的onRebind方法。

这里服务的绑定就完成了,接下来就是发布服务,以及ServiceConnection 回调过程。

发布服务到ServiceConnection 回调过程

时序图

在这里插入图片描述

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");
            }
            // 内部调用ActiveServices类的publishServiceLocked
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }
ActiveServices的publishServiceLocked
 void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
...
 for (int conni=r.connections.size()-1; conni>=0; conni--) {
                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                        for (int i=0; i<clist.size(); i++) {
                            ConnectionRecord c = clist.get(i);
                            if (!filter.equals(c.binding.intent.intent)) {
                                if (DEBUG_SERVICE) Slog.v(
                                        TAG_SERVICE, "Not publishing to: " + c);
                                if (DEBUG_SERVICE) Slog.v(
                                        TAG_SERVICE, "Bound intent: " + c.binding.intent.intent);
                                if (DEBUG_SERVICE) Slog.v(
                                        TAG_SERVICE, "Published intent: " + intent);
                                continue;
                            }
                            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c);
                            try {
                            /*
c.conn:IServiceConnection类型

是ServiceConnection在本地的代理,用于解决当前应用程序进程和Service跨进程通信的问题

ServiceDispatcher.InnerConnection是具体的实现类

ServiceDispatcher是LoadedApk的内部

*/
                                c.conn.connected(r.name, service, false);
                            }
...
}
LoadApk 内部类ServiceDispatcher类的内部类InnerConnection的connected方法

  static final class ServiceDispatcher {

...
  //ServiceDispatcher 内部类
  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) {
                //1、sd为ServiceDispatcher 类对象
                    sd.connected(name, service, dead);
                }
            }
        }
  //ServiceDispatcher 方法
  public void connected(ComponentName name, IBinder service, boolean dead) {
            if (mActivityThread != null) {
            /*
           2、 mActivityThread 为Handle类型,这里调用handle的post方法。
            
            mActivityThread在这里实际指向H类,因此,通过调用H的post方法将
            RunConnection对象的内容运行在主线程中

           */
            
                mActivityThread.post(new RunConnection(name, service, 0, dead));
            } else {
                doConnected(name, service, dead);
            }
        }
   //ServiceDispatcher 内部类
   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) {
                //3、 run方法最终调用的是doConnected方法
                    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) {
    ...
 /*
调用了ServiceConnection 类型的对象mConnection 的onServiceConnected方法,
这样在客户端实现了ServiceConnection接口类的onServiceConnected方法就会被执行。
至此,Service 的绑定过程就分析完成。
  */
            if (old != null) {
                mConnection.onServiceDisconnected(name);
            }
                      
}
...

}

The end

参考:
安卓进阶解密:微信读书版

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值