bindService流程分析二

230 阅读3分钟

之前分析了app端bindService的流程,详细juejin.cn/post/710007… 下面来分析一下AMS端的流程

AMS端bindservice的数据类可以参考juejin.cn/post/710045…

ActivityManagerService

    public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        enforceNotIsolatedCaller("bindService");

        synchronized(this) {
            // mServices是ActiveServices类型,是ams的属性
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

ActiveServices

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
          String resolvedType, final IServiceConnection connection, int flags,
          String callingPackage, final int userId) throws TransactionTooLargeException {
      // 获取caller对应的ProcessRecord进程对象
      final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);

      ......
      // step0 获取ServiceLookupResult
      ServiceLookupResult res =
          retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                  Binder.getCallingUid(), userId, true, callerFg, isBindExternal, allowInstant);
     
      ServiceRecord s = res.record;
      ......
              final ServiceRecord serviceRecord = s;
              final Intent serviceIntent = service;

      try {
          ......
          // step1 retrieveAppBindingLocked
          AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
          
          // step2 将connection与activity关联 并保存到AppBindRecord
          ConnectionRecord c = new ConnectionRecord(b, activity,
                  connection, flags, clientLabel, clientIntent);

          IBinder binder = connection.asBinder();
          // 存在多个activity关联使用同一个serviceconnetion对象的情况,
          // 所以ServiceRecord中的connections是ArrayMap<IBinder, ArrayList<ConnectionRecord>>
          // 一个connctionbinder对应的是一个ConnectionRecord列表
          ArrayList<ConnectionRecord> clist = s.connections.get(binder);
          if (clist == null) {
              // 创建ConnectionRecord集合
              clist = new ArrayList<ConnectionRecord>();
              // 保存ArrayList<ConnectionRecord>到ServiceRecord中
              s.connections.put(binder, clist);
          }
          // ConnectionRecord保存到ConnectionRecord集合中
          clist.add(c);
          // 保存到AppBindRecord的connections集合
          b.connections.add(c);
          // 将ConnectionRecord也保存到activityrecord中,这里面是HashSet
          if (activity != null) {
              if (activity.connections == null) {
                  activity.connections = new HashSet<ConnectionRecord>();
              }
              // 保存到ActivityRecord的connections集合中
              activity.connections.add(c);
          }
          // 添加到ProcessRecord进程对象中
          b.client.connections.add(c);
          
          // 属性 ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections
          // mServiceConnections也保存一份
          clist = mServiceConnections.get(binder);
          if (clist == null) {
              // 创建ArrayList<ConnectionRecord>
              clist = new ArrayList<ConnectionRecord>();
              // 添加到mServiceConnections
              mServiceConnections.put(binder, clist);
          }
          // 添加ConnectionRecord
          clist.add(c);

          if ((flags&Context.BIND_AUTO_CREATE) != 0) {
              s.lastActivity = SystemClock.uptimeMillis();
              // step3 bringUpServiceLocked
              if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                      permissionsReviewRequired) != null) {
                  return 0;
              }
          } 

          if (s.app != null && b.intent.received) {
              // Service is already running, so we can immediately
              // publish the connection.
              try {
                 // step4 与activity建立连接
                  c.conn.connected(s.name, b.intent.binder, false);
              } catch (Exception e) {
                
              }

              // If this is the first app connected back to this binding,
              // and the service had previously asked to be told when
              // rebound, then do so.
              if (b.intent.apps.size() == 1 && b.intent.doRebind) {
                  requestServiceBindingLocked(s, b.intent, callerFg, true);
              }
          } else if (!b.intent.requested) {
              step5 请求bindService
              requestServiceBindingLocked(s, b.intent, callerFg, false);
          }

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

      } finally {
          Binder.restoreCallingIdentity(origId);
      }

      return 1;
  }

下面分析每一步

step0 获取ServiceLookupResult

private ServiceLookupResult retrieveServiceLocked(Intent service,
            String resolvedType, String callingPackage, int callingPid, int callingUid, int userId,
            boolean createIfNeeded, boolean callingFromFg, boolean isBindExternal,
            boolean allowInstant) {
        ServiceRecord r = null;
        
        userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
                ActivityManagerService.ALLOW_NON_FULL_IN_PROFILE, "service", null);
        // 获取ServiceMap, 是继承handler的类,里面包装了两个ArrayMap,<ComponentName, ServiceRecord> 和
        // <Intent.FilterComparison, ServiceRecord>
        ServiceMap smap = getServiceMapLocked(userId);
        final ComponentName comp = service.getComponent();
        if (comp != null) {
        // 先通过ComponentName 查找ServiceRecord
            r = smap.mServicesByName.get(comp);
          
        }
        // 没有找到查找ServiceRecord 入参isBindExternal为false,再通过FilterComparison查找ServiceRecord
        if (r == null && !isBindExternal) {
            Intent.FilterComparison filter = new Intent.FilterComparison(service);
            r = smap.mServicesByIntent.get(filter);
      
        }
        
        if (r == null) {
            try {
                // 查找pms
                ResolveInfo rInfo = mAm.getPackageManagerInternalLocked().resolveService(service,
                        resolvedType, flags, userId, callingUid);
                ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null;
                // 创建ComponentName
                ComponentName name = new ComponentName(
                        sInfo.applicationInfo.packageName, sInfo.name);
                
                r = smap.mServicesByName.get(name);
               
                if (r == null && createIfNeeded) {
                    // 创建FilterComparison
                    final Intent.FilterComparison filter = new Intent.FilterComparison(service.cloneFilter());
                    final ServiceRestarter res = new ServiceRestarter();
                    final BatteryStatsImpl.Uid.Pkg.Serv ss;
                    final BatteryStatsImpl stats = mAm.mBatteryStatsService.getActiveStatistics();
                    synchronized (stats) {
                        ss = stats.getServiceStatsLocked(
                                sInfo.applicationInfo.uid, sInfo.packageName,
                                sInfo.name);
                    }
                    // 创建ServiceRecord
                    r = new ServiceRecord(mAm, ss, name, filter, sInfo, callingFromFg, res);
                    res.setService(r);
                    // 缓存到ServiceMap的两个集合
                    smap.mServicesByName.put(name, r);
                    smap.mServicesByIntent.put(filter, r);
                  
                }
            } catch (RemoteException ex) {
            }
        }
        if (r != null) {
            // 返回ServiceLookupResult
            return new ServiceLookupResult(r, null);
        }
        return null;
    }

大致流程是先在ServiceMap的两个集合中查找缓存,如果没有就通过pms查找注册的service信息,构造对应的ServiceRecord对象。然后加到ServiceMap的两个集合中。最后创建返回ServiceLookupResult

step1 ServiceRecord#retrieveAppBindingLocked

public AppBindRecord retrieveAppBindingLocked(Intent intent,
            ProcessRecord app) {
        // 包装了FilterComparison
        Intent.FilterComparison filter = new Intent.FilterComparison(intent);
        // 查询成员属性bindings,是一个map<Intent.FilterComparison, IntentBindRecord> 保存了FilterComparison和IntentBindRecord的映射
        IntentBindRecord i = bindings.get(filter);
        if (i == null) {
             // 本地缓存没有, new一个加入本地
            i = new IntentBindRecord(this, filter);
            bindings.put(filter, i);
        }
        // 根据ProcessRecord获取对应的AppBindRecord,这里面可以拿到所有的conn
        AppBindRecord a = i.apps.get(app);
        if (a != null) {
            return a;
        }
        // 本地没有找到 new一个AppBindRecord,保存到intent的apps集合中
        a = new AppBindRecord(this, i, app);
        i.apps.put(app, a);
        返回AppBindRecord
        return a;
    }

在ServiceRecord中查找AppBindRecord, 先在本地缓存bindings中找IntentBindRecord,在根据IntentBindRecord找AppBindRecord,并返回

step2 将connection与activity关联 并保存到AppBindRecord

根据activityrecord 和 IServiceConnection 创建ConnectionRecord,并将ConnectionRecord保存到AppBindRecord、ProcessRecord、mServiceConnections各数据结构中。

step3 ActiveServices#bringUpServiceLocked

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        .......

        final boolean isolated = (r.serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;
        // 没有设置ServiceInfo.FLAG_ISOLATED_PROCESS 
        if (!isolated) {
            // step3.1 查找对应的进程
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            // 进程存在
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                    // step3.2 启动service
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                }
            }
        }
        // 进程未启动
        // Not running -- get it started, and enqueue this service record
        // to be executed when the app comes up.
        if (app == null && !permissionsReviewRequired) {
            // step3.3 启动进程
            if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
                bringDownServiceLocked(r);
                return msg;
            }
        }
        // 添加到mPendingServices中
        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }

        return null;
    }

这边就是真正的启动service的地方了。这里分成两种情况,service运行在同app进程,那么直接 realStartServiceLocked,如果是在新进程中运行的,那么先启动进程,再启动sercie