美文网首页
三大组件启动过程

三大组件启动过程

作者: 刘佳阔 | 来源:发表于2020-05-21 08:49 被阅读0次

    title: 四大组件启动过程
    date: 2020-05-05 13:13:02
    tags:[android源码,]
    typora-copy-images-to: ./四大组件启动过程
    typora-root-url: ./四大组件启动过程


    本文主要记录四大组件在framework和APP中如何交互启动.记录大概框架.不追求完备的细节.源码根据8.0

    Activity启动过程

    主要流程

    桌面程序通常是launch.我们点击桌面图标启动app时.是由桌面launch程序通过AMS来启动Activity.这个过程大概如下

    image-20200505163411999

    简单说就是.launch通知AMS启动新Activity. AMS则会先暂停当前进程.然后在启动新进程.然后在新进程启动完成后在创建Activity并启动.

    通过intent定位Activity

    APP在安装时.通过PackageManagerService 安装.并解析出来AndroidManifest.xml里声明的所有Activity.然后吧主Activity和应用图标绑定起来.这样点击图标.就能找到对应的Activity信息.

    Instrumentation启动Activity

    execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target,
       Intent intent, int requestCode, Bundle options){
           int result = ActivityManager.getService()
                    .startActivity(whoThread, who.getBasePackageName(), intent,
                            intent.resolveTypeIfNeeded(who.getContentResolver()),
                            token, target != null ? target.mEmbeddedID : null,
                            requestCode, 0, null, options);   
       }
    

    这个可以说是代理类,他用来监控程序和系统间的交互.里边有针对Activity启动的监控ActivityMonitor.

    他会通过AMS在客户端的代理来通知AMS启动Activity.并且传给AMS一个IBinder类的ApplicationThread,这是用来让AMS回调通知客户端进程的binder本地对象.

    同时还传入一个IBinder的 token. 代表当前Activity对象在AMS中的标识. 每个启动的Activity都会有这个token.在AMS端是ActivityRecord对象.

    ActivityManager 拿到AMS的代理,进行binder通信

    ActivityManager.getService通过ServiceManager 拿到AMS对应的用户端binder.然后包装成AMS的客户端代理.

    然后通过binder通信.调用AMS服务端.启动Activity.

    image-20200505173538751

    AMS端处理请求

    这里内部会有几个类共同处理.而且每个版本的代码也有所不同.显示AcctivityStack来处理Activity的堆栈管理.

    image-20200505173614505

    PMS解析intent.找到对应的Activity.

    PMS在启动的时候,已经解析了所有apk的androidManifest.xml文件.然后就知道所有intent格式对应的Activity.这里会通过PMS来找到合适的Activity.保存在ActivityInfo中.

    检查调用进程的权限,封装信息

    通过调用进程的ProsessRecord 来在AMS端对应一个用户进程. AMS检查调用者Launcher的进程.看是否有启动Activity的权限等. 同时封装要启动的Activity的信息为ActivityRecord.也拿到了源Activity(也就是launcher)的组件信息.

    处理启动标识Intent.FLAG

    这里处理各种启动模式,然后产生Activity对应的taskRecord. TaskRecord表示任务栈. 如果这个任务已经存在,就把待启动的Activity加入进去.如果新Activity对应的是新的任务.就要创建新的TaskRecord.

    通过管理当前激活的Activity.上次中止的Activity.正在被中止的Activity.AMS来决定把旧Activity(launcher)执行暂停.然后在启动新的Activity.

    暂停旧的activity

    通过 用户进程的ApplicationThread 在AMS端的代理. AMS通知 旧Activity(launcher) 进行 pause.并把他保存在即将pause的变量中. launcher的Activity在pause后.又会通知AMS他已经pause完毕.然后AMS就会继续执行新Activity的启动过程.

    启动新的Activity

    先根据新Activity的进程名称判断对应进程是否启动.如果没有启动就先通过zygote来启动新进程.Activity的进程在AMS中的对应的对象是ProcessRecord. 新进程启动完成后必须在规定时间内通知AMS已经启动完成.新进程会执行ActivityThread的main方法.

    新进程ActivityThread.main

    通过ams.attach.通知AMS 新进程已启动完毕并传入新的ApplicationThread.创建主线程的looper和Handler.开始消息循环.

    AMS继续启动Activity

    AMS收到ActivityThread的att通知后.继续启动新Activity.此时新进程已经和ProcessRecord对应上.然后通过上边的ApplicationThread在AMS的代理.通知ActivityThread启动Activity.而客户端ApplicationThread收到AMS的消息后.通过向主线程looper 发送消息.启动Activity. ActivityThread收到消息后.取出要启动的Activity信息

    ActivityThread 启动Activity

    通过执行handleLauncherActivity,反射 创建activity所属的Application.ContextImpl.和activity.

    然后执行activity.attach .使activity和WMS建立联系.获得应用窗口.

    在执行activity.onCreate. 创建view树.

    Activity 的启动.因为之前已经写过了.这里就简单的过一下

    Service启动过程

    Service的启动分为显示启动和隐式启动.并且可以运行在不同的进程.并且可以通过startService启动.和bindService启动.

    activity启动服务

    最开始其余 startService. 他会调用到ContextWrapper.startService.有会调用到mBase.startService(service). mBase实际是一个ComtextImpl对象.每个Activity创建时都有一个ContextImpl对象. 他又会调用AMS.startService.通过binder来启动.

    AMS接收调用.启动服务

    AMS内部又通过 mServices.startServiceLocked 来启动 mService 是ActiveServices类.

    ActiveServices.java
    startServiceLocked(){
                继续启动Service,找到 intent对应的Service.
             ServiceLookupResult res =retrieveServiceLocked(service, resolvedType, callingPackage,
                        callingPid, callingUid, userId, true, callerFg, false);
          启动完的Service在AMS里抽象为ServiceRecord
          ServiceRecord r = res.record;
          然后是一些权限的验证处理
          
          生成了一个 ComponentName.这里一会看.
         ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);              
    }
    

    通过intent找到Service

    ActivityService.java
    根据intent.找到对应的Service,在AMS里.每个ServiceRecord是和ComponentName绑定的
    private ServiceLookupResult retrieveServiceLocked(Intent service...){
         ServiceRecord r = null;
         找到进程对应的 ServiceMap.然后根据componentName找Service.
         ServiceMap smap = getServiceMapLocked(userId);
         final ComponentName comp = service.getComponent();
            if (comp != null) {
                r = smap.mServicesByName.get(comp);
            }
       接下来是对ServiceRecord 权限的检查,看用户进程是否可以启动这个Service
       最后封装后返回出去
      return new ServiceLookupResult(r, null); 
    }
    

    启动服务 startServiceInnerLocked

    这里又调用的同名函数 bringUpServiceLocked 这是真正启懂Service的地方.然后又调度队列.启动所以等待的Service

    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r...){
        //启动Service
      String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
      
      //通过队列.把等待启动的Service 再次通过startServiceInnerLocked方法启动.
        if (r.startRequested && addToStarting) {
                if (first) {
                    smap.rescheduleDelayedStartsLocked();
                }
      } else if (callerFg || r.fgRequired) {
          smap.ensureNotStartingBackgroundLocked(r);
      }
    }
    

    AMS启动service对应进程

    这里会看Service对应的进程是否启动.如果启动.就直接启动Service就行了.如果没有.就先启动对应的进程.进程在AMS端的代表对象是ProsessRecord

    private String bringUpServiceLocked(ServiceRecord r){
            进程存在,直接启动Service
                 if (r.app != null && r.app.thread != null) {
                sendServiceArgsLocked(r, execInFg, false);
                return null;
            }
            
            进程不存在.启动进程,然后在把Service放入队列,等待启动
          if (app == null && !permissionsReviewRequired) {
                if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                        hostingType, r.name, false, isolated, false)) == null) {
                }
            } 
            
              if (!mPendingServices.contains(r)) {
                mPendingServices.add(r);
            }
    }
    

    AMS启动Service的进程,这里还是通过Process.start来启动新进程.这里和之前的Activity比较类似.也是通过zygote进程来fork出新进程.然后执行ActivityThread的main函数. 进程初始化完成后.会调用AMS.attachApplication.

    这里和Activity的启动是一个方法.这次他会在这里看上边加入队列的

    ActivityManagerService.java
    boolean attachApplicationLocked(IApplicationThread thread,int pid) {
        又回调到了Service的方法区去处理启动Service
           // Find any services that should be running in this process...
            if (!badApp) {
                try {
                    didSomething |= mServices.attachApplicationLocked(app, processName);
                } catch (Exception e) {
                    badApp = true;
                }
            }          
    }
    

    Service继续启动服务

    遍历pending队列,启动Service

    ActivityServices.java
    boolean attachApplicationLocked(ProcessRecord proc, String processName) {
            if (mPendingServices.size() > 0) {
                ServiceRecord sr = null;
                    for (int i=0; i<mPendingServices.size(); i++) {
                        sr = mPendingServices.get(i);
                        realStartServiceLocked(sr, proc, sr.createdFromFg);
                    }
              }
    }
    realStartServiceLocked里最主要的是,下边的.也就是通过binder调用用户进程启动service,通过ApplicationThread继而通知ActivityThread启动服务
    app.thread.scheduleCreateService(r, r.serviceInfo,
        mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),app.repProcState);
    

    用户进程启动service

    ActivityThread.java
    void handleCreateService(CreateServiceData data) {
    每个app都有一个loadedApk来描述应用程序的资源.
            LoadedApk packageInfo = getPackageInfoNoCheck(
                    data.info.applicationInfo, data.compatInfo);
            Service service = null;
            try {
            反射加载servi的类.
                java.lang.ClassLoader cl = packageInfo.getClassLoader();
                service = (Service) cl.loadClass(data.info.name).newInstance();
            } catch (Exception e) {
            }
    
            try {
        为service创建ContextImpl上下文环境. activity也有这个.
                ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
                context.setOuterContext(service);
            service 绑定Application. 执行onCreate
                Application app = packageInfo.makeApplication(false, mInstrumentation);
                service.attach(context, this, data.info.name, data.token, app,
                        ActivityManager.getService());
                service.onCreate();
          ActivityThread 保存所有的service
                mServices.put(data.token, service);
                try {
           通知AMS.service启动成功     
                    ActivityManager.getService().serviceDoneExecuting(
                            data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            } catch (Exception e) {
            }
        }
    

    最后AMS里会做一些收尾工作.

    附一个流程图.

    Sample sequence diagram

    service绑定过程

    绑定的Service也是需要先启动起来的. 过程和启动服务类似. 都是从ContextImpl通知AMS开始.这里会封装一个IServiceConnection.这个IServiceConnection 是一个adil类.这是夸进程传递给AMS 的对象. 这里.APP的进程是IServiceConnection的binder服务端. AMS则持有 IServiceConnection的binder的代理端.

    封装ServiceConnect.通知AMS

    bindServiceCommon(Intent service, ServiceConnection conn,){
         IServiceConnection sd;
         //封装成一个IBinder.
       sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
     //  调用ams的方法.
    int res = ActivityManager.getService().bindService(
                    mMainThread.getApplicationThread(), getActivityToken(), service,
                    service.resolveTypeIfNeeded(getContentResolver()),
                    sd, flags, getOpPackageName(), user.getIdentifier());
    }
    

    AMS转给ActiveServices处理.

    这里的流程比较复杂.简单说就是找到service的记录.然后和对应的Activity. 及Activity对应的process创建绑定关系ConnectionRecord并保存起来.保存在service 的ServiceRecord中.然后开始启动service

    ActivityServices.java
    bindServiceLocked (IApplicationThread caller, IBinder token, Intent service,  final IServiceConnection connection..){
            请求绑定服务的Activity的进程.
          final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
          请求的Activity的记录
     ActivityRecord activity = null;
        if (token != null) {
            activity = ActivityRecord.isInStackLocked(token);
        }
        //同启动服务一样.找到对应的service记录.
    ServiceLookupResult res =
          retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                  Binder.getCallingUid(), userId, true, callerFg, isBindExternal);            
          ServiceRecord s = res.record;
    
            找到service对应的app绑定描述对象.表示service绑定在callerApp进程中.表示绑定在这个service上的进程.
            这是一种对应关系. 一个service可以被多个进程绑定.
          AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
          这里是描述Activity.service.process 的对应关系的一个记录.
          ConnectionRecord c = new ConnectionRecord(b, activity,
                  connection, flags, clientLabel, clientIntent);
                得到connection的远程代理类.,保存上边的映射关系.
          IBinder binder = connection.asBinder();
          ArrayList<ConnectionRecord> clist = s.connections.get(binder);
                接着启动这个service
          if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                      permissionsReviewRequired) != null) {
                  return 0;
              }
           clist.add(c);
          c.conn.connected(s.name, b.intent.binder, false);
    
             
    }
    

    ActivityServices 继续启动

    bringUpServiceLocked方法.在启动service里已经出现过了.流程就是启动service对应的进程. 进程启动完后通知AMS.AMS在通知创建Service. 直到执行service的onStart.onCreate

    但是这里不太一样的是realStartServiceLocked里又会执行requestServiceBindingsLocked.进而遍历调用r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind, r.app.repProcState); 也就是变量得到该service所有对应的要绑定的activity的相关记录.

    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 {
            if ((!i.requested || rebind) && i.apps.size() > 0) {
                    r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                    r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                            r.app.repProcState);
                }
            return true;
    }
    

    ActivityThread处理绑定服务

    这时.又通过Binder通知到了ActivityThread,他调用servic的onBind. 获取服务的binder对象.然后回传给AMS

    ActivityThread.java
    private void handleBindService(BindServiceData data) {
          Service s = mServices.get(data.token);
              try {
                   if (!data.rebind) {
                   调用了service的onBind 获取service的 binder. ActivityThread保存所有的service.
                          IBinder binder = s.onBind(data.intent);
                    再把service服务的binder传递个AMS.用来发送回所有绑定到该service的进程.当然发送过去的是本地binder的代理类.
                          ActivityManager.getService().publishService(
                                  data.token, data.intent, binder);
                      } else {
                          s.onRebind(data.intent);
                          ActivityManager.getService().serviceDoneExecuting(
                                  data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                      }
                  } catch (RemoteException ex) {
                      throw ex.rethrowFromSystemServer();
                  }
              } 
          }
      }
    

    AMS获取service的binder代理对象

    ams还是把请求交个ActivityServices来处理.

    ActivityServices.java
    publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
            final long origId = Binder.clearCallingIdentity();
            try {
                Intent.FilterComparison filter= new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
                if (b != null && !b.received) {
                ConnectionRecord是上问我们介绍的 service和Activity和acitivity的process建立的绑定关系.
                这里拿到这个服务的所有ConnectionRecord.然后取出里边的binder代理类 IServiceConnection.
                在调用connected方法.并传入service发过来的binder. 就实现了 service和Activity的绑定.
                    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);
                                c.conn.connected(r.name, service, false);
                        }
                    }
                }
                serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
                }
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    

    看到这里就明白了. activity提供的ServiceConnection 被包装成Binder后.发送到AMS中.与要绑定的Service建立关系.产生ConnectionRecord对象. 而service在对应的进程启动完成.service也启动完成后. 由AMS调用service 的onBind. service 则会提供代表他的功能的binder给AMS. 在publishServiceLocked方法中.遍历所有的ConnectionRecord, 调用conn.connected 把service 传来的binder发送给 activity里的ServiceConnection .这就实现了 activity和service的绑定.

    ServiceDispatcher 处理connection

    上边的 c.conn.connected(r.name, service, false); 其实是调用的的InnerConnection的方法.他是LoadApk 里ServiceDispatcher的内部类.是aidl实现的类.这里又涉及到AMS和最初 的Activity 通过aidl 方式来进程ipc.

    loadApk.java
    public void connected(ComponentName name, IBinder service, boolean dead) {
                if (mActivityThread != null) {
                可以看到.通过handler.把connec推到住线程来处理了.
                    mActivityThread.post(new RunConnection(name, service, 0, dead));
                } else {
                    doConnected(name, service, dead);
                }
            }
    

    Runnconection 在主线程处理

    简单说就是找到旧的服务.将他断开,然后执行新的connection 的onServiceConnected方法.也就是回调activity里设置的connection.

    public void doConnected(ComponentName name, IBinder service, boolean dead) {
                ServiceDispatcher.ConnectionInfo old;
                ServiceDispatcher.ConnectionInfo info;
    
                synchronized (this) {
                    }
                    old = mActiveConnections.get(name);
                    if (service != null) {
                        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) {
                    }
                    if (old != null) {
                        old.binder.unlinkToDeath(old.deathMonitor, 0);
                    }
                }
    断开旧服务
                if (old != null) {
                    mConnection.onServiceDisconnected(name);
                }
     开启新服务           
                if (service != null) {
                    mConnection.onServiceConnected(name, service);
                }
            }
    
    Service_Start

    广播机制

    广播机制是在binder的基础上实现的.广播机制存在注册中心.就是AMS.广播订阅者要先向AMS注册,并指明接受广播的类型.然后广播发送者把广播发送给AMS.再由AMS分发给对应的接收者.

    广播分为有序广播和无序广播. 注册时有静态注册和动态注册.

    注册广播

    同样是从ContextImpl开始.先拿到主线程的handler.然后封装一个 receiverDispatcher.然后通知AMS来注册,

    这个ReceiverDispatcher也是对receiver的封装.并且内部有实现aidl 的类.也就是利用binder 把代理类发给AMS.用于回调.

    ContextImpl.java
     private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
                IntentFilter filter, String broadcastPermission,
                Handler scheduler, Context context, int flags) {
            IIntentReceiver rd = null;
            if (receiver != null) {
            封装一个receiverDispatcher .这个和service原理有点类似.都是发给AMS用来回调app进程的binder类
                if (mPackageInfo != null && context != null) {
                    if (scheduler == null) {
                    还拿到了ui线程的handler,用来向主线程发消息.
                        scheduler = mMainThread.getHandler();
                    }
                    rd = mPackageInfo.getReceiverDispatcher(
                        receiver, context, scheduler,
                        mMainThread.getInstrumentation(), true);
                }  
            }
            通过ams注册
                final Intent intent = ActivityManager.getService().registerReceiver(
                        mMainThread.getApplicationThread(), mBasePackageName, rd, filter,
                        broadcastPermission, userId, flags);
                
        }
    

    AMS中注册广播

    这里有对粘性广播和普通广播的处理. 如果存在粘性广播.就把他们保存在 allSticky中.粘性广播就是广播发送在广播注册之前.但是也能收到.粘性广播会一直留在AMS中.直到下一个同类型粘性广播的到来.

    public Intent registerReceiver(IApplicationThread caller, String callerPackage,
                IIntentReceiver receiver, IntentFilter filter, String permission, int userId,
                int flags) {
            ArrayList<Intent> stickyIntents = null;
            ProcessRecord callerApp = null;
                    callerApp = getRecordForAppLocked(caller);
    
                instantApp = isInstantApp(callerApp, callerPackage, callingUid);
    
                    找到匹配的粘性广播,保存intent
            ArrayList<Intent> allSticky = null;
            if (stickyIntents != null) {
                final ContentResolver resolver = mContext.getContentResolver();
                // Look for any matching sticky broadcasts...
                for (int i = 0, N = stickyIntents.size(); i < N; i++) {
                    Intent intent = stickyIntents.get(i);
                    if (filter.match(resolver, intent, true, TAG) >= 0) {
                        allSticky.add(intent);
                    }
                }
            }
                    
            每个广播接收者是用BroadcastFilter 来描述.BroadcastFilter和APP传过来的InnerReceiver.而可能多个activity会使用同一个InnerReceiver.因此用集合来保存相同InneReceiver的广播接收者.
            也就是如果多个activity注册同一个广播.就会有一个InnerReceiver.对应多个BroadcastFilter.
            synchronized (this) {
                ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
                if (rl == null) {
                    rl = new ReceiverList(this, callerApp, callingPid, callingUid,
                            userId, receiver);
                    mRegisteredReceivers.put(receiver.asBinder(), rl);
                }
                BroadcastFilter bf = new BroadcastFilter(filter, rl, callerPackage,
                        permission, callingUid, userId, instantApp, visibleToInstantApps);
                rl.add(bf);
                if (!bf.debugCheck()) {
                    Slog.w(TAG, "==> For Dynamic broadcast");
                }
                加到这里后.以后来了广播.就能找到对应的接收者.
                mReceiverResolver.addFilter(bf);
    
                把粘性广播返回给activity组件.也就实现了粘性广播的发送.
                if (allSticky != null) {
                    ArrayList receivers = new ArrayList();
                    receivers.add(bf);
    
                    final int stickyCount = allSticky.size();
                    for (int i = 0; i < stickyCount; i++) {
                        Intent intent = allSticky.get(i);
                        BroadcastQueue queue = broadcastQueueForIntent(intent);
                        每个广播对应的就是 BroadCastRecord 记录.这里是入栈.然后发送粘性广播.
                        BroadcastRecord r = new BroadcastRecord(queue, intent, null,
                                null, -1, -1, false, null, null, AppOpsManager.OP_NONE, null, receivers,
                                null, 0, null, null, false, true, true, -1);
                        queue.enqueueParallelBroadcastLocked(r);
                        queue.scheduleBroadcastsLocked();
                    }
                }
    
                return sticky;
            }
        }
    

    发送广播

    首先广播发送者把广播发送给AMS.

    然后AMS找到这个广播对应的接收者,再把这个广播和接收者添加到广播队列中.并向AMS中发送一个BROADCAST_INTENT_MSG的消息.等待AMS处理.

    当AMS处理到这个消息时,取出广播及接收者,分别将广播发给接收者的进程

    接受者进程的ActivityThread会再次把消息发送到主线程的消息队列.等消息被处理时在交给广播接收者.

    发送广播给AMS

    由ContextImpl 通过binder通信把广播发给AMS.

    AMS接收处理广播

    broadcastIntent()

    验证广播intent参数的合法性.

    broadcastIntentLocked()

    先是对intent里的action的不同类型的处理.如检查权限.同时对系统广播进行处理.

    接着是对粘性广播的处理.所有的粘性广播都保存在一个hashmap中,并已action作为key

    然后如果广播指定了接收者的Component.就从pms中找到对应的接收者,保存起来

    然后在判断intent的flag 是发给动态接收者还是动态接收者以及静态接收者.静态和动态的广播接收者分别保存在不同的集合中.

    针对无序广播.并且有动态接收者.在发给静态接收者.封装成BroadcastRecord,加入队列.

    接着把剩下的广播都加入到BroadcastQueue,并且接收者会按照优先级排序.合并静态动态接受者.

    BroadcastQueue.scheduleBroadcastsLocked

    将广播加入队列后.通过handler发送给AMS的线程.可以看到广播的发送和接收是异步的

    BroadcastQueue.processNextBroadcast

    取出广播对象BroadcastRecord,处理无序广播队列,找到所有的无序接收者.遍历执行deliverToRegisteredReceiverLocked

    然后执行有序广播的处理. 如果对应的广播接收者还没启动.则先启动对应的进程,然后继续处理下一个有序广播接收者.

    入股有序广播不能再一个限定时间内处理完成.就会结束这个有序广播.

    BroadcastQueue.deliverToRegisteredReceiverLocked

    这里AMS把广播转发给APP所在进程.其实是通过回调ApplicationThread的scheduleRegisteredReceiver把消息发给ActivityThread的.这时发送给APP进程的是之前包装过的InntentReceiver的代理类. 他内部封装了一个广播接收者.

    ActivityThread.scheduleRegisteredReceiver

    这里就到了APP进程.然后由之前传入的InnerReceiver 来继续执行.

    他内部会发消息给ActivityThread的主线程. 发一个runnable过去.等主线程处理这个消息. runnable是Args

    的内部类.

    Args.getRunnable

    最后调用receiver.onReceive .也就是接收者接收到了消息.然后在回调AMS.finishReceive表示消息接收完成

    contentprovider 以后再补充.他是用共享内存作为夸进程传输数据的.

    相关文章

      网友评论

          本文标题:三大组件启动过程

          本文链接:https://www.haomeiwen.com/subject/spbaohtx.html