【安卓12activity启动流程--进程不存在的情况】


//进程不存在,启动进程
    mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");

ATMS的startProcessAsyn方法

      void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
              String hostingType) {
          try {
              if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
                  Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
                          + activity.processName);
              }
              // Post message to start process to avoid possible deadlock of calling into AMS with the
              // ATMS lock held.
              final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
                      mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
                      isTop, hostingType, activity.intent.getComponent());
              mH.sendMessage(m);
          } finally {
              Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
          }
      }

里面调用了AMS的startProcess方法
startProcess方法里面调用了 startProcessLocked方法

        @GuardedBy("this")
  final ProcessRecord startProcessLocked(String processName,
          ApplicationInfo info, boolean knownToBeDead, int intentFlags,
          HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
          boolean isolated) {
      return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
              hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
              null /* ABI override */, null /* entryPoint */,
              null /* entryPointArgs */, null /* crashHandler */);
  }

里面调用了 /frameworks/base/services/core/java/com/android/server/am/ProcessList.java的startProcessLocked方法
发现里面有多个startProcessLocked方法

startProcessLocked方法里面进行了以下设置

    
              // Start the process.  It will either succeed and return a result containing
              // the PID of the new process, or else throw a RuntimeException.
              final String entryPoint = "android.app.ActivityThread";

startProcessLocked方法里面还调用了handleProcessStartedLocked方法

startProcessLocked方法里面还调用了newProcessRecordLocked方法

  @GuardedBy("mService")
      ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
              boolean isolated, int isolatedUid, HostingRecord hostingRecord) {
          String proc = customProcess != null ? customProcess : info.processName;
          final int userId = UserHandle.getUserId(info.uid);
          int uid = info.uid;
          if (isolated) {
              if (isolatedUid == 0) {
                  IsolatedUidRange uidRange = getOrCreateIsolatedUidRangeLocked(info, hostingRecord);
                  if (uidRange == null) {
                      return null;
                  }
                  uid = uidRange.allocateIsolatedUidLocked(userId);
                  if (uid == -1) {
                      return null;
                  }
              } else {
                  // Special case for startIsolatedProcess (internal only), where
                  // the uid of the isolated process is specified by the caller.
                  uid = isolatedUid;
              }
              mAppExitInfoTracker.mIsolatedUidRecords.addIsolatedUid(uid, info.uid);
              mService.getPackageManagerInternal().addIsolatedUid(uid, info.uid);
  
              // Register the isolated UID with this application so BatteryStats knows to
              // attribute resource usage to the application.
              //
              // NOTE: This is done here before addProcessNameLocked, which will tell BatteryStats
              // about the process state of the isolated UID *before* it is registered with the
              // owning application.
              mService.mBatteryStatsService.addIsolatedUid(uid, info.uid);
              FrameworkStatsLog.write(FrameworkStatsLog.ISOLATED_UID_CHANGED, info.uid, uid,
                      FrameworkStatsLog.ISOLATED_UID_CHANGED__EVENT__CREATED);
          }
          final ProcessRecord r = new ProcessRecord(mService, info, proc, uid);
          final ProcessStateRecord state = r.mState;
  
          if (!mService.mBooted && !mService.mBooting
                  && userId == UserHandle.USER_SYSTEM
                  && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
              // The system process is initialized to SCHED_GROUP_DEFAULT in init.rc.
              state.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
              state.setSetSchedGroup(ProcessList.SCHED_GROUP_DEFAULT);
              r.setPersistent(true);
              state.setMaxAdj(ProcessList.PERSISTENT_PROC_ADJ);
          }
          if (isolated && isolatedUid != 0) {
              // Special case for startIsolatedProcess (internal only) - assume the process
              // is required by the system server to prevent it being killed.
              state.setMaxAdj(ProcessList.PERSISTENT_SERVICE_ADJ);
          }
          addProcessNameLocked(r);
          return r;
      }

startProcessLocked方法里面还还调用了 handleProcessStart方法

    /**
       * Main handler routine to start the given process from the ProcStartHandler.
       *
       * <p>Note: this function doesn't hold the global AM lock intentionally.</p>
       */
      private void handleProcessStart(final ProcessRecord app, final String entryPoint,
              final int[] gids, final int runtimeFlags, int zygotePolicyFlags,
              final int mountExternal, final String requiredAbi, final String instructionSet,
              final String invokeWith, final long startSeq) {
          // If there is a preceding instance of the process, wait for its death with a timeout.
          // Use local reference since we are not using locks here
          final ProcessRecord predecessor = app.mPredecessor;
          int prevPid;
          if (predecessor != null && (prevPid = predecessor.getDyingPid()) > 0) {
              long now = System.currentTimeMillis();
              final long end = now + PROC_KILL_TIMEOUT;
              final int oldPolicy = StrictMode.getThreadPolicyMask();
              try {
                  StrictMode.setThreadPolicyMask(0);
                  Process.waitForProcessDeath(prevPid, PROC_KILL_TIMEOUT);
                  // It's killed successfully, but we'd make sure the cleanup work is done.
                  synchronized (predecessor) {
                      if (app.mPredecessor != null) {
                          now = System.currentTimeMillis();
                          if (now < end) {
                              try {
                                  predecessor.wait(end - now);
                              } catch (InterruptedException e) {
                              }
                              if (System.currentTimeMillis() >= end) {
                                  Slog.w(TAG, predecessor + " " + prevPid
                                          + " has died but its obituary delivery is slow.");
                              }
                          }
                      }
                      if (app.mPredecessor != null && app.mPredecessor.getPid() > 0) {
                          // The cleanup work hasn't be done yet, let's log it and continue.
                          Slog.w(TAG, predecessor + " " + prevPid
                                  + " has died, but its cleanup isn't done");
                      }
                  }
              } catch (Exception e) {
                  // It's still alive... maybe blocked at uninterruptible sleep ?
                  Slog.wtf(TAG, predecessor.toString() + " " + prevPid
                          + " refused to die, but we need to launch " + app, e);
              } finally {
                  StrictMode.setThreadPolicyMask(oldPolicy);
              }
          }
          try {
              final Process.ProcessStartResult startResult = startProcess(app.getHostingRecord(),
                      entryPoint, app, app.getStartUid(), gids, runtimeFlags, zygotePolicyFlags,
                      mountExternal, app.getSeInfo(), requiredAbi, instructionSet, invokeWith,
                      app.getStartTime());
  
              synchronized (mService) {
                  handleProcessStartedLocked(app, startResult, startSeq);
              }
          } catch (RuntimeException e) {
              synchronized (mService) {
                  Slog.e(ActivityManagerService.TAG, "Failure starting process "
                          + app.processName, e);
                  mPendingStarts.remove(startSeq);
                  app.setPendingStart(false);
                  mService.forceStopPackageLocked(app.info.packageName,
                          UserHandle.getAppId(app.uid),
                          false, false, true, false, false, app.userId, "start failure");
              }
          }
      }

startProcessLocked方法里面还调用了startProcess方法

private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
             ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
             int mountExternal, String seInfo, String requiredAbi, String instructionSet,
             String invokeWith, long startTime) {
         try {
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                     app.processName);
             checkSlow(startTime, "startProcess: asking zygote to start proc");
             final boolean isTopApp = hostingRecord.isTopApp();
             if (isTopApp) {
                 // Use has-foreground-activities as a temporary hint so the current scheduling
                 // group won't be lost when the process is attaching. The actual state will be
                  // refreshed when computing oom-adj.
                  app.mState.setHasForegroundActivities(true);
              }
  
              Map<String, Pair<String, Long>> pkgDataInfoMap;
              Map<String, Pair<String, Long>> allowlistedAppDataInfoMap;
              boolean bindMountAppStorageDirs = false;
              boolean bindMountAppsData = mAppDataIsolationEnabled
                      && (UserHandle.isApp(app.uid) || UserHandle.isIsolated(app.uid))
                      && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);
  
              // Get all packages belongs to the same shared uid. sharedPackages is empty array
              // if it doesn't have shared uid.
              final PackageManagerInternal pmInt = mService.getPackageManagerInternal();
              final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
                      app.info.packageName, app.userId);
              final String[] targetPackagesList = sharedPackages.length == 0
                      ? new String[]{app.info.packageName} : sharedPackages;
  
              pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
              if (pkgDataInfoMap == null) {
                  // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
                  // tmp free pass.
                  bindMountAppsData = false;
              }
  
              // Remove all packages in pkgDataInfoMap from mAppDataIsolationAllowlistedApps, so
              // it won't be mounted twice.
              final Set<String> allowlistedApps = new ArraySet<>(mAppDataIsolationAllowlistedApps);
              for (String pkg : targetPackagesList) {
                  allowlistedApps.remove(pkg);
              }
  
              allowlistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,
                      allowlistedApps.toArray(new String[0]), uid);
              if (allowlistedAppDataInfoMap == null) {
                  // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
                  // tmp free pass.
                  bindMountAppsData = false;
              }
  
              int userId = UserHandle.getUserId(uid);
              StorageManagerInternal storageManagerInternal = LocalServices.getService(
                      StorageManagerInternal.class);
              if (needsStorageDataIsolation(storageManagerInternal, app)) {
                  // We will run prepareStorageDirs() after we trigger zygote fork, so it won't
                  // slow down app starting speed as those dirs might not be cached.
                  if (pkgDataInfoMap != null && storageManagerInternal.isFuseMounted(userId)) {
                      bindMountAppStorageDirs = true;
                  } else {
                      // Fuse is not mounted or inode == 0,
                      // so we won't mount it in zygote, but resume the mount after unlocking device.
                      app.setBindMountPending(true);
                      bindMountAppStorageDirs = false;
                  }
              }

         // If it's an isolated process, it should not even mount its own app data directories,
         // since it has no access to them anyway.
             if (app.isolated) {
                 pkgDataInfoMap = null;
                 allowlistedAppDataInfoMap = null;
             }
 
             final Process.ProcessStartResult startResult;
             boolean regularZygote = false;
             if (hostingRecord.usesWebviewZygote()) {
                 startResult = startWebView(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, app.info.packageName,
                         app.getDisabledCompatChanges(),
                         new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
             } else if (hostingRecord.usesAppZygote()) {
                 final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
 
                 // We can't isolate app data and storage data as parent zygote already did that.
                 startResult = appZygote.getProcess().start(entryPoint,
                         app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, app.info.packageName,
                         /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
                         app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap,
                         false, false,
                          new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
              } else {
                  regularZygote = true;
                  startResult = Process.start(entryPoint,
                          app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                          app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                          app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
                          isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,
                          allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
                          new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});
              }
  
              if (!regularZygote) {
                  // webview and app zygote don't have the permission to create the nodes
                  if (Process.createProcessGroup(uid, startResult.pid) < 0) {
                      Slog.e(ActivityManagerService.TAG, "Unable to create process group for "
                              + app.processName + " (" + startResult.pid + ")");
                  }
              }
  
              // This runs after Process.start() as this method may block app process starting time
              // if dir is not cached. Running this method after Process.start() can make it
              // cache the dir asynchronously, so zygote can use it without waiting for it.
              if (bindMountAppStorageDirs) {
                  storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
                          app.processName);
              }
              checkSlow(startTime, "startProcess: returned from zygote!");
              return startResult;
          } finally {
              Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
          }
      }

发现里面才是真正创建了进程,里面调用了 Process.start

AMS属于系统服务进程,通过socket与zygote进行通信,zygote通过fork创建了一个子进程,前面说了程序入口设置为
android.app.ActivityThread,所以进程创建后调用ActivityThread的main方法main方法里面调用了

        ActivityThread thread = new ActivityThread();
          thread.attach(false, startSeq);
	  ......
	   Looper.loop();  //进入loop循环,等待被发消息

看一下attach方法

      @UnsupportedAppUsage
      private void attach(boolean system, long startSeq) {
          sCurrentActivityThread = this;
          mConfigurationController = new ConfigurationController(this);
          mSystemThread = system;
          if (!system) {
              android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
                                                      UserHandle.myUserId());
              RuntimeInit.setApplicationObject(mAppThread.asBinder());
              final IActivityManager mgr = ActivityManager.getService();
              try {
                  mgr.attachApplication(mAppThread, startSeq);
              } catch (RemoteException ex) {
                  throw ex.rethrowFromSystemServer();
              }
              // Watch for getting close to heap limit.
              BinderInternal.addGcWatcher(new Runnable() {
                  @Override public void run() {
                      if (!mSomeActivitiesChanged) {
                          return;
                      }
                      Runtime runtime = Runtime.getRuntime();
                      long dalvikMax = runtime.maxMemory();
                      long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                      if (dalvikUsed > ((3*dalvikMax)/4)) {
                          if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                                  + " total=" + (runtime.totalMemory()/1024)
                                  + " used=" + (dalvikUsed/1024));
                          mSomeActivitiesChanged = false;
                          try {
                              ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
                          } catch (RemoteException e) {
                              throw e.rethrowFromSystemServer();
                          }
                      }
                  }
              });
          } else {
              // Don't set application object here -- if the system crashes,
              // we can't display an alert, we just want to die die die.
              android.ddm.DdmHandleAppName.setAppName("system_process",
                      UserHandle.myUserId());
              try {
                  mInstrumentation = new Instrumentation();
                  mInstrumentation.basicInit(this);
                  ContextImpl context = ContextImpl.createAppContext(
                          this, getSystemContext().mPackageInfo);
                  mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                  mInitialApplication.onCreate();
              } catch (Exception e) {
                  throw new RuntimeException(
                          "Unable to instantiate Application():" + e.toString(), e);
              }
          }
  
          ViewRootImpl.ConfigChangedCallback configChangedCallback = (Configuration globalConfig) -> {
              synchronized (mResourcesManager) {
                  // TODO (b/135719017): Temporary log for debugging IME service.
                  if (Build.IS_DEBUGGABLE && mHasImeComponent) {
                      Log.d(TAG, "ViewRootImpl.ConfigChangedCallback for IME, "
                              + "config=" + globalConfig);
                  }
  
                  // We need to apply this change to the resources immediately, because upon returning
                  // the view hierarchy will be informed about it.
                  if (mResourcesManager.applyConfigurationToResources(globalConfig,
                          null /* compat */,
                          mInitialApplication.getResources().getDisplayAdjustments())) {
                      mConfigurationController.updateLocaleListFromAppContext(
                              mInitialApplication.getApplicationContext());
  
                      // This actually changed the resources! Tell everyone about it.
                      final Configuration updatedConfig =
                              mConfigurationController.updatePendingConfiguration(globalConfig);
                      if (updatedConfig != null) {
                          sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
                          mPendingConfiguration = updatedConfig;
                      }
                  }
              }
          };
          ViewRootImpl.addConfigCallback(configChangedCallback);
      }

可以看到里面创建了Instrumentation对象,还获取了ActivityManager的IBinder对象,
同时将自己的ApplicationThread设置到ActivityManager的IBinder对象里面,ApplicationThread也是一个IBinder
对象,它是当前进程的IBinder对象,这样AMS也能跨进程调用该进程方法,形成了双向调用。

 final IActivityManager mgr = ActivityManager.getService();
              try {
                  mgr.attachApplication(mAppThread, startSeq);
              } catch (RemoteException ex) {
                  throw ex.rethrowFromSystemServer();
              }

attachApplication方法最后会回调该进程的生命周期方法,启动activity

AMS的attachApplication方法里面调用了attachApplicationLocked方法
attachApplicationLocked方法里面调用了mAtmInternal.attachApplication(app.getWindowProcessController());
所以attachApplicationLocked方法里面调用到ATMS的attachApplication方法
ATMS的attachApplication方法里面mRootWindowContainer.attachApplication(wpc);
所以接下来看RootWindowContainer.java里面的attachApplication方法
RootWindowContainer.java里面的attachApplication方法调用了startActivityForAttachedApplicationIfNeeded方法

  private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
              WindowProcessController app, ActivityRecord top) {
          if (r.finishing || !r.okToShowLocked() || !r.visibleIgnoringKeyguard || r.app != null
                  || app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {
              return false;
          }
  
          try {
              if (mTaskSupervisor.realStartActivityLocked(r, app,
                      top == r && r.isFocusable() /*andResume*/, true /*checkConfig*/)) {
                  mTmpBoolean = true;
              }
          } catch (RemoteException e) {
              Slog.w(TAG, "Exception in new application when starting activity "
                      + top.intent.getComponent().flattenToShortString(), e);
              mTmpRemoteException = e;
              return true;
          }
          return false;
      }

可以看到最后调用到ActivityTaskSupervisor.java的realStartActivityLocked方法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值