Android Activity 启动过程(上)

前言

(该篇文章绝大部分内容是5个月之前写的,后面放在本地文档中彻底忘记,重新梳理下上传) 在一个应用从未启动的情况下,根Activity 的启动一般是涉及到四个进程。Launcher 进程,SystemServer 进程(ActivityManagerService,简称AMS 所在进程),Zygote 进程(接收来自AMS进程创建应用的请求),被启动的应用进程。 如果该应用已经处于启动情况下,则只涉及到三个进程。Launcher 进程,SystemServer 进程, 被启动Activiity所在进程。 如果应用用于启动自身所在进程,则只涉及到两个进程。SystemServer 进程,应用进程。

本文中 ATMS 指代ActivityTaskManagerService. WMS指代 WindowManagerService. AMS 指代 ActivityManagerService. (不小心写了篇又烂又长的文章,正文和代码字符加起来超过14W了,只能拆分成三篇进行介绍了.)

下面来看下在Launcher 应用中点击一个未启动的App的图标,对应的Launch Activity的启动过程吧.

1.Launcher 进程 StartActivity 过程

在 Launcher 页面,点击启动应用后。

1.1 Activity startActivity

frameworks/base/core/java/android/app/Activity.java

java 复制代码
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);

        //代码1 调研 Instrumentation 去执行Activity启动任务
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
          //代码2 返回不为空,此处如何处理不懂,前面的代码在主线程中调用,总不可能一直是阻塞的。
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            // If this start is requesting a result, we can avoid making
            // the activity visible until the result is received.  Setting
            // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
            // activity hidden during this time, to avoid flickering.
            // This can only be done when a result is requested because
            // that guarantees we will get information back when the
            // activity is finished, no matter what happens to it.
            // 代码3 防止当前Activity在未获得返回值前可见
            mStartedActivity = true;
        }
        //清空Activity的输入事件
        cancelInputsAndStartExitTransition(options);
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            // Note we want to go through this method for compatibility with
            // existing applications that may have overridden it.
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

frameworks/base/core/java/android/app/Instrumentation.java

java 复制代码
 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
     android.util.SeempLog.record_str(377, intent.toString());
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    if (mActivityMonitors != null) {//代码1 ActivityMonitors 用于监控匹配的
        synchronized (mSync) {//
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                ActivityResult result = null;
                if (am.ignoreMatchingSpecificIntents()) {
                    result = am.onStartActivity(intent);
                }
                if (result != null) {
                    am.mHits++;
                    return result;
                } else if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData(who);
        intent.prepareToLeaveProcess(who);
        //代码2 
        int result = ActivityTaskManager.getService().startActivity(whoThread,
                who.getBasePackageName(), who.getAttributionTag(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()), token,
                target != null ? target.mEmbeddedID : null, requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;

}
  • 代码2 处调用AMS服务的startActivity方法 ActivityTaskManager.getService() 获得的是 ActivityTaskManagerService的Binder代理。

2. SystemServer 进程中创建App进程流程

2.1 ActivityTaskManagerService 查询与尝试启动过程

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

java 复制代码
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
        String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
        String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
        Bundle bOptions) {
     //代码1
    return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
            resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
            UserHandle.getCallingUserId());
}

public int startActivityAsUser(IApplicationThread caller, String callingPackage,
        String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
        String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
        Bundle bOptions, int userId) {
     //代码2
    return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
            resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
            true /*validateIncomingUser*/);
}

private int startActivityAsUser(IApplicationThread caller, String callingPackage,
        @Nullable String callingFeatureId, Intent intent, String resolvedType,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
    assertPackageMatchesCallingUid(callingPackage);// 检查调用者uid和包名是否匹配
    enforceNotIsolatedCaller("startActivityAsUser");// 判断是否是沙盒进程
    //代码3 
    userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
            Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
    //代码4
    // TODO: Switch to user app stacks here.
    return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
            .setCaller(caller)
            .setCallingPackage(callingPackage)
            .setCallingFeatureId(callingFeatureId)
            .setResolvedType(resolvedType)
            .setResultTo(resultTo)
            .setResultWho(resultWho)
            .setRequestCode(requestCode)
            .setStartFlags(startFlags)
            .setProfilerInfo(profilerInfo)
            .setActivityOptions(bOptions)
            .setUserId(userId)
            .execute();

}

ActivityStartController getActivityStartController() {
    return mActivityStartController;
}

代码3 处,检测用户 如上,从代码1到代码4处,getActivityStartController().获取 ActivityStartController 对象,调用 ActivityStartController::obtainStarter方法获得 ActivityStarter对象。ActivityStarter对象此时存储了 intent 数据。

2.2 ActivityStarter Activity启动器

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

java 复制代码
int execute() {
    try {
        // Refuse possible leaked file descriptors
        // ... 省略
        int res;
        synchronized (mService.mGlobalLock) {
            final boolean globalConfigWillChange = mRequest.globalConfig != null
                    && mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
            final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
            if (stack != null) {
                stack.mConfigWillChange = globalConfigWillChange;
            }
            if (DEBUG_CONFIGURATION) {
                Slog.v(TAG_CONFIGURATION, "Starting activity when config will change = "
                        + globalConfigWillChange);
            }

            final long origId = Binder.clearCallingIdentity();

            res = resolveToHeavyWeightSwitcherIfNeeded();
            if (res != START_SUCCESS) {
                return res;
            }
            res = executeRequest(mRequest);//代码1
            //...省略

            // Notify ActivityMetricsLogger that the activity has launched.
            // ActivityMetricsLogger will then wait for the windows to be drawn and populate
            // WaitResult.
            mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
                    mLastStartActivityRecord);// 代码2
            return getExternalResult(mRequest.waitResult == null ? res
                    : waitForResult(res, mLastStartActivityRecord)); // 代码3 waitResult 一般是在通过 adb 命令行去启动时调用
        }
    } finally {
        onExecutionComplete();//此处用于回收 `ActivityStarter`对象
    }
}

private int executeRequest(Request request) {
   
    final IApplicationThread caller = request.caller;
    Intent intent = request.intent;
    NeededUriGrants intentGrants = request.intentGrants;
    String resolvedType = request.resolvedType;
    ActivityInfo aInfo = request.activityInfo;
    ResolveInfo rInfo = request.resolveInfo;
    final IVoiceInteractionSession voiceSession = request.voiceSession;
    final IBinder resultTo = request.resultTo;
    String resultWho = request.resultWho;
    int requestCode = request.requestCode;
    int callingPid = request.callingPid;
    int callingUid = request.callingUid;
    String callingPackage = request.callingPackage;
    String callingFeatureId = request.callingFeatureId;
    final int realCallingPid = request.realCallingPid;
    final int realCallingUid = request.realCallingUid;
    final int startFlags = request.startFlags;
    final SafeActivityOptions options = request.activityOptions;
    Task inTask = request.inTask;

    int err = ActivityManager.START_SUCCESS;
    // Pull the optional Ephemeral Installer-only bundle out of the options early.
    final Bundle verificationBundle =
            options != null ? options.popAppVerificationBundle() : null;

    WindowProcessController callerApp = null;
    if (caller != null) {
        callerApp = mService.getProcessController(caller);//代码4
        if (callerApp != null) {
            callingPid = callerApp.getPid();
            callingUid = callerApp.mInfo.uid;
        } else {
            Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + callingPid
                    + ") when starting: " + intent.toString());
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }
    //...
    //代码 5
    final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
            callingPackage, callingFeatureId, intent, resolvedType, aInfo,
            mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,
            request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,
            sourceRecord);
    mLastStartActivityRecord = r;

    if (r.appTimeTracker == null && sourceRecord != null) {
        // If the caller didn't specify an explicit time tracker, we want to continue
        // tracking under any it has.
        r.appTimeTracker = sourceRecord.appTimeTracker;
    }
    // 代码6
    final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();

    // If we are starting an activity that is not from the same uid as the currently resumed
    // one, check whether app switches are allowed.
    if (voiceSession == null && stack != null && (stack.getResumedActivity() == null
            || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
                realCallingPid, realCallingUid, "Activity start")) {
            if (!(restrictedBgActivity && handleBackgroundActivityAbort(r))) {
                mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
                        sourceRecord, startFlags, stack, callerApp, intentGrants));
            }
            ActivityOptions.abort(checkedOptions);
            return ActivityManager.START_SWITCHES_CANCELED;
        }
    }

    mService.onStartActivitySetDidAppSwitch();
    mController.doPendingActivityLaunches(false);
    //代码 7
    mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
            request.voiceInteractor, startFlags, true /* doResume */, checkedOptions, inTask,
            restrictedBgActivity, intentGrants);

    if (request.outActivity != null) {
        request.outActivity[0] = mLastStartActivityRecord;
    }

    return mLastStartActivityResult;
}

代码1处调用 executeRequest 方法走到代码7处调用 startActivityUnchecked方法。

代码4处 caller是 Launcher 应用 ApplicationThreadBinder对象的代理对象,通过 caller 获取了 WindowProcessController 对象(WindowProceessController 是Android 10才出现的,在此之前此处代码获取的是 ProcessRecord对象)。

代码5处 创建一个 ActivityRecord对象 用于记录一个 Activity的信息。 代码6处 ActvityStackActivity栈对象,获取的当前处于焦点状态的任务栈. 用于检测应用是否可以启动。

代码7 处 调用 startActivityUnchecked 方法。

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java

java 复制代码
 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
                IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
                int startFlags, boolean doResume, ActivityOptions options, Task inTask,
                boolean restrictedBgActivity, NeededUriGrants intentGrants) {
    int result = START_CANCELED;
    final ActivityStack startedActivityStack;
    try {
        mService.deferWindowLayout();
        Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
        result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);// 代码1
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
        startedActivityStack = handleStartResult(r, result);
        mService.continueWindowLayout();
    }

    postStartActivityProcessing(r, result, startedActivityStack);

    return result;
}

代码1处调用 startActivityInner方法。

java 复制代码
 int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            boolean restrictedBgActivity, NeededUriGrants intentGrants) {
  
    // ...
    if (mDoResume) {//chld 此处传入值为true
        final ActivityRecord topTaskActivity =
                mStartActivity.getTask().topRunningActivityLocked();
        if (!mTargetStack.isTopActivityFocusable()
                || (topTaskActivity != null && topTaskActivity.isTaskOverlay()
                && mStartActivity != topTaskActivity)) {
            // If the activity is not focusable, we can't resume it, but still would like to
            // make sure it becomes visible as it starts (this will also trigger entry
            // animation). An example of this are PIP activities.
            // Also, we don't want to resume activities in a task that currently has an overlay
            // as the starting activity just needs to be in the visible paused state until the
            // over is removed.
            // Passing {@code null} as the start parameter ensures all activities are made
            // visible.
            mTargetStack.ensureActivitiesVisible(null /* starting */,
                    0 /* configChanges */, !PRESERVE_WINDOWS);
            // Go ahead and tell window manager to execute app transition for this activity
            // since the app transition will not be triggered through the resume channel.
            mTargetStack.getDisplay().mDisplayContent.executeAppTransition();
        } else {
            // If the target stack was not previously focusable (previous top running activity
            // on that stack was not visible) then any prior calls to move the stack to the
            // will not update the focused stack.  If starting the new activity now allows the
            // task stack to be focusable, then ensure that we now update the focused stack
            // accordingly.
            if (mTargetStack.isTopActivityFocusable()
                    && !mRootWindowContainer.isTopDisplayFocusedStack(mTargetStack)) {
                mTargetStack.moveToFront("startActivityInner");
            }
            // 代码1
            mRootWindowContainer.resumeFocusedStacksTopActivities(
                    mTargetStack, mStartActivity, mOptions);
        }
    }

}

Activity::startActivityInner 方法中涉及到了一堆栈相关,Activity启动模式,启动参数的处理。根据这些判断Activity是新建个栈还是加入某个已有的Activity 栈or 不启动新的Acitivty而是将已有的Activity 重新获得焦点(启动模式为singleTask,singleTop,singleInstance等)。 从未启动的应用程序的根Activity的启动是走到代码1处。

2.3 RootWindowContainer

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

java 复制代码
boolean resumeFocusedStacksTopActivities(
            ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (!mStackSupervisor.readyToResume()) {
        return false;
    }

    boolean result = false;
    if (targetStack != null && (targetStack.isTopStackInDisplayArea()
            || getTopDisplayFocusedStack() == targetStack)) {
        result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);//代码1 
    }

    for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
        boolean resumedOnDisplay = false;
        final DisplayContent display = getChildAt(displayNdx);
        for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
            final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
            for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
                final ActivityStack stack = taskDisplayArea.getStackAt(sNdx);
                final ActivityRecord topRunningActivity = stack.topRunningActivity();
                if (!stack.isFocusableAndVisible() || topRunningActivity == null) {
                    continue;
                }
                if (stack == targetStack) {
                    // Simply update the result for targetStack because the targetStack had
                    // already resumed in above. We don't want to resume it again, especially in
                    // some cases, it would cause a second launch failure if app process was
                    // dead.
                    resumedOnDisplay |= result;
                    continue;
                }
                if (taskDisplayArea.isTopStack(stack) && topRunningActivity.isState(RESUMED)) {
                    // Kick off any lingering app transitions form the MoveTaskToFront
                    // operation, but only consider the top task and stack on that display.
                    stack.executeAppTransition(targetOptions);
                } else {
                    resumedOnDisplay |= topRunningActivity.makeActiveIfNeeded(target);
                }
            }
        }
        if (!resumedOnDisplay) {
            // In cases when there are no valid activities (e.g. device just booted or launcher
            // crashed) it's possible that nothing was resumed on a display. Requesting resume
            // of top activity in focused stack explicitly will make sure that at least home
            // activity is started and resumed, and no recursion occurs.
            final ActivityStack focusedStack = display.getFocusedStack();
            if (focusedStack != null) {
                result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
            } else if (targetStack == null) {
                result |= resumeHomeActivity(null /* prev */, "no-focusable-task",
                        display.getDefaultTaskDisplayArea());
            }
        }
    }

    return result;
}   

代码1 处调用 ActivityStack::resumeTopActivityUncheckedLocked 方法。 frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java

java 复制代码
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    Log.d(TAG,"chld resumeTopActivityUncheckedLocked pkg:" + prev.packageName,new Exception());
    if (mInResumeTopActivity) {
        // Don't even start recursing.
        return false;
    }
    boolean result = false;
    try {
        // Protect against recursion.
        mInResumeTopActivity = true;
        result = resumeTopActivityInnerLocked(prev, options);//代码1
        // When resuming the top activity, it may be necessary to pause the top activity (for
        // example, returning to the lock screen. We suppress the normal pause logic in
        // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
        // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here
        // to ensure any necessary pause logic occurs. In the case where the Activity will be
        // shown regardless of the lock screen, the call to
        // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped.
        final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
        if (next == null || !next.canTurnScreenOn()) {
            checkReadyForSleep();
        }
    } finally {
        mInResumeTopActivity = false;
    }
    return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    //... 省略
    if (mResumedActivity != null) {
        if (DEBUG_STATES) Slog.d(TAG_STATES,
                "resumeTopActivityLocked: Pausing " + mResumedActivity);
        pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next);//代码2
    }
    if (next.attachedToProcess()) {//代码3
        mStackSupervisor.startSpecificActivity(next, true, false);//代码4
        return true;
    } else {
        //...
        mStackSupervisor.startSpecificActivity(next, true, true);//代码5
    }
//...
return true;

}

代码2处,判断当前Activity栈是否存在 resume 状态 Activity,有的话,则将其puase.

next 指代要显示的Activity 的 ActivityRecord对象。如果当前 Activity 已经在进程中了,则走到 代码4处,否则走到代码5处。其最终调用的都是 ActivityStackSupervisor::startSpecificActivity方法。 区别是最后一个参数 checkConfig 值不同。 应用未启动过,此处是走到代码5处。

2.4 ActivityStackSupervisor

frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java

java 复制代码
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    final WindowProcessController wpc =
            mService.getProcessController(r.processName, r.info.applicationInfo.uid);

    boolean knownToBeDead = false;
    if (wpc != null && wpc.hasThread()) {// 代码1
        try {
            realStartActivityLocked(r, wpc, andResume, checkConfig);//代码2
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }
        // chld 如果应用进程已死亡,携带该信息去重新启动应用
        // If a dead object exception was thrown -- fall through to
        // restart the application.
        knownToBeDead = true;
    }

    r.notifyUnknownVisibilityLaunchedForKeyguardTransition();

    final boolean isTop = andResume && r.isTopRunningActivity();
    mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");//代码3
}

WindowProcessController 是进程控制类。根据 ActivityRecord携带的processName 和 uid 去匹配。

代码1处,判断该应用进程是否已经存在且持有应用进程的 ApplicationThread代理对象,WindowProcessController::hasThread判断持有的 IApplicationThread对象是否为空。 当应用已经在后台了,此时走代码2处。 当应用未启动时,走代码3处。此时根据文章一开始描述,此时点击的是未启动的应用的图标。显然走代码3处,调用 ActivityTaskManagerService::startProcessAsync去启动应用进程。

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

java 复制代码
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());//代码1
        mH.sendMessage(m);
    } finally {
        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
    }
}

startProcessAsync 函数中通过 PooledLambda::obtainMessage 方法获取了一个有callback 的 Message,然后通过 mH Handler 对象去处理。此处的目的主要是在另个线程中去执行??。

ActivityManagerInternal::startProcess 方法对应的实现是在 ActivityManagerService::startProcess方法中

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

java 复制代码
@Override
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
        boolean isTop, String hostingType, ComponentName hostingName) {
    try {
        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                    + processName);
        }
        synchronized (ActivityManagerService.this) {
            // If the process is known as top app, set a hint so when the process is
            // started, the top priority can be applied immediately to avoid cpu being
            // preempted by other processes before attaching the process of top app.
            startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                    new HostingRecord(hostingType, hostingName, isTop),
                    ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
                    false /* isolated */, true /* keepIfLarge */);//代码2
        }
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
}
  @GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
            hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
            keepIfLarge, null /* ABI override */, null /* entryPoint */,
            null /* entryPointArgs */, null /* crashHandler */);//代码2
}

走到代码2处,调用 ProcessList::startProcessLocked方法。

2.5 ProcessList

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

java] 复制代码
@GuardedBy("mService")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
        boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
        int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
        boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,
        Runnable crashHandler) {
    long startTime = SystemClock.uptimeMillis();
    ProcessRecord app;
    if (!isolated) {
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);//代码1
        //省略
    } else {
        // If this is an isolated process, it can't re-use an existing process.
        app = null;
    }
    //...省略  

    if (app == null) {// 代码2
        checkSlow(startTime, "startProcess: creating new process record");
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord);
        if (app == null) {
            Slog.w(TAG, "Failed making new process record for "
                    + processName + "/" + info.uid + " isolated=" + isolated);
            return null;
        }
        app.crashHandler = crashHandler;
        app.isolatedEntryPoint = entryPoint;
        app.isolatedEntryPointArgs = entryPointArgs;
        if (precedence != null) {
            app.mPrecedence = precedence;
            precedence.mSuccessor = app;
        }
        checkSlow(startTime, "startProcess: done creating new process record");
    } else {
        // If this is a new package in the process, add the package to the list
        app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
        checkSlow(startTime, "startProcess: added package to existing proc");
    }
    //... 省略
    checkSlow(startTime, "startProcess: stepping in to startProcess");
    final boolean success =
            startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);//代码2
    checkSlow(startTime, "startProcess: done starting proc!");
    return success ? app : null;
}

代码1 先试探的去根据processName,uid 等去查找是否有已存在的进程。 代码2 创建一个新的 ProcessRecord 对象,并且被存在 ProcessList::mProcessNames 属性中。 代码3 调用 startProcessLocked 方法去启动进程。

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

java 复制代码
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
        int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
        boolean mountExtStorageFull, String abiOverride) {
    //... 省略
    try {
        //... 代码1 省略
        final String entryPoint = "android.app.ActivityThread";

        return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
                runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
                instructionSet, invokeWith, startTime);
    } catch (RuntimeException e) {
        Slog.e(ActivityManagerService.TAG, "Failure starting process " + app.processName, e);

        // Something went very wrong while trying to start this process; one
        // common case is when the package is frozen due to an active
        // upgrade. To recover, clean up any active bookkeeping related to
        // starting this process. (We already invoked this method once when
        // the package was initially frozen through KILL_APPLICATION_MSG, so
        // it doesn't hurt to use it again.)
        mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                false, false, true, false, false, app.userId, "start failure");
        return false;
    }
}

该函数中省略的代码主要内容为 uid(uid,标识用户),gids(对于UID的封装处理,由一组uid组成,方便系统权限的关联。一般的应用程序gids就等于uid), runtimeFlags, requiredAbi(cpu架构),mountExternal(需要加载外部存储类型) 等。

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

java 复制代码
@GuardedBy("mService")
boolean startProcessLocked(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) {
    app.pendingStart = true;
    app.killedByAm = false;
    app.removed = false;
    app.killed = false;
    if (app.startSeq != 0) {
        Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
                + " with non-zero startSeq:" + app.startSeq);
    }
    if (app.pid != 0) {
        Slog.wtf(TAG, "startProcessLocked processName:" + app.processName
                + " with non-zero pid:" + app.pid);
    }
    app.mDisabledCompatChanges = null;
    if (mPlatformCompat != null) {
        app.mDisabledCompatChanges = mPlatformCompat.getDisabledChanges(app.info);
    }
    final long startSeq = app.startSeq = ++mProcStartSeqCounter;//代码1
    app.setStartParams(uid, hostingRecord, seInfo, startTime);
    app.setUsingWrapper(invokeWith != null
            || Zygote.getWrapProperty(app.processName) != null);
    mPendingStarts.put(startSeq, app);

    if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
        //chld - FLAG_PROCESS_START_ASYNC 该值来源于ShanKa 在2017/12/16的提交 f6690100be5c5cd75c64d9a6a0345acff7b754d1,用于解决锁竞争问题。
        // 在2018/10/20  google 对AMS进行了重构,将进程启动相关代码从ActivityManagerService 移动到了 ProcessList.对应提交 98a0092e4c9a0329465b6ac113c2ddf04eb0695c
        // 该值默认为true,除非 主动修改了 settings 中 process_start_async 属性。Activity的启动习惯属性在 ActivityManagerConstants.java 文件中
        // 该方案下,将所有的进程启动操作都放入 同一个线程中。
        if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
                "Posting procStart msg for " + app.toShortString());
        mService.mProcStartHandler.post(() -> handleProcessStart(
                app, entryPoint, gids, runtimeFlags, zygotePolicyFlags, mountExternal,
                requiredAbi, instructionSet, invokeWith, startSeq));//代码2
        return true;
    } else {//代码3
        try {
            final Process.ProcessStartResult startResult = startProcess(hostingRecord,
                    entryPoint, app,
                    uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
                    requiredAbi, instructionSet, invokeWith, startTime);
            handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                    startSeq, false);
        } catch (RuntimeException e) {
            Slog.e(ActivityManagerService.TAG, "Failure starting process "
                    + app.processName, e);
            app.pendingStart = false;
            mService.forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid),
                    false, false, true, false, false, app.userId, "start failure");
        }
        return app.pid > 0;
    }
}

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) {
    // 省略...
    try {
        final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,
                entryPoint, app, app.startUid, gids, runtimeFlags, zygotePolicyFlags,
                mountExternal, app.seInfo, requiredAbi, instructionSet, invokeWith,
                app.startTime);//代码4

        synchronized (mService) {
            handleProcessStartedLocked(app, startResult, startSeq);//代码5
        }
    } catch (RuntimeException e) {
        synchronized (mService) {
            Slog.e(ActivityManagerService.TAG, "Failure starting process "
                    + app.processName, e);
            mPendingStarts.remove(startSeq);
            app.pendingStart = false;
            mService.forceStopPackageLocked(app.info.packageName,
                    UserHandle.getAppId(app.uid),
                    false, false, true, false, false, app.userId, "start failure");
        }
    }
}

代码1 处需要重点关注下,此处给 PrcoessRecord::startSeq 属性赋值了。并且执行了 mPendingStarts.put(startSeq, app);代码, mPendingStarts是一个存储 PrcocessRecord 信息的 map 对象,其key为startSeq. 后面将会通过应用进程创建后,其将 startSqe去查询其后续的操作(启动Activity,Service 或其他操作) Pending 即将发生的。mPendingStart 即 即将要启动的。

代码2 处通过 mProcStartHandler 去执行 handleProcessStart 方法,从google的历史提交描述来看,该方案将进程启动操作都放入一个线程中去处理,去解决锁的竞争问题,commit id f6690100be5c5cd75c64d9a6a0345acff7b754d1。 代码 处通过异步调用到了 ProcessList::handleProcessStart 方法。 handleProcessStart 方法中执行的操作与代码3处基本相同。

代码4 调用 starProcess 处调用 startProcess ,通过socket 与Zygote 进程通信,Zygote fork 一个子进程,并返回 Process.ProcessStartResult对象。Process.ProcessStartResult 类中只有两个属性 int pidboolean usingWrapper. pid 就是创建的进程ID.

代码5 调用 handleProcessStartedLocked 去处理进程创建后的结果,检测应用进程的启动是否超时等。

以上代码核心处就是 代码1 和代码4处了。 接下来去看下代码4 的实现吧。

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

java 复制代码
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 {
        // 省略...
        final Process.ProcessStartResult startResult;
        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.mDisabledCompatChanges,
                    new String[]{PROC_START_SEQ_IDENT + app.startSeq});
        } else if (hostingRecord.usesAppZygote()) {
            final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);//代码1

            // 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.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
                    false, false,
                    new String[]{PROC_START_SEQ_IDENT + app.startSeq});//代码2
        } else {
            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.mDisabledCompatChanges, pkgDataInfoMap,
                    whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
                    new String[]{PROC_START_SEQ_IDENT + app.startSeq});
        }
        checkSlow(startTime, "startProcess: returned from zygote!");
        return startResult;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }
  • 代码1 处创建一个 AppZygote 对象,AppZygote 主要是处理APP进程的启动,对其做了一定的封装。
  • 代码2 处 AppZygote::getProcess方法获取了 ChildZygoteProcess对象(ChildZygoteProcessZygoteProcess的子类),该对象是维护与 Zygote通信的实例。在 AppZygote::getProcess方法中会根据条件判断,如果没有就会创建一个 对应实例,并与 Zygote中的socket服务链接上,此处不具体展开了。直接去看下 ZygoteProcess::start方法吧。传入的 entryPoint 就是 ActivityThread.java的类名。 需要注意,start 方法最后传入的参数 seq={数字}(PROC_START_SEQ_IDENT 值为 seq=),后面通过该值去 mPendingStart 中检索 ProcessRecord对象。

2.6 ZygoteProcess

frameworks/base/core/java/android/os/ZygoteProcess.java

java 复制代码
public final Process.ProcessStartResult start(@NonNull final String processClass,
                                              final String niceName,
                                              int uid, int gid, @Nullable int[] gids,
                                              int runtimeFlags, int mountExternal,
                                              int targetSdkVersion,
                                              @Nullable String seInfo,
                                              @NonNull String abi,
                                              @Nullable String instructionSet,
                                              @Nullable String appDataDir,
                                              @Nullable String invokeWith,
                                              @Nullable String packageName,
                                              int zygotePolicyFlags,
                                              boolean isTopApp,
                                              @Nullable long[] disabledCompatChanges,
                                              @Nullable Map<String, Pair<String, Long>>
                                                      pkgDataInfoMap,
                                              @Nullable Map<String, Pair<String, Long>>
                                                      whitelistedDataInfoMap,
                                              boolean bindMountAppsData,
                                              boolean bindMountAppStorageDirs,
                                              @Nullable String[] zygoteArgs) {
    // TODO (chriswailes): Is there a better place to check this value?
    if (fetchUsapPoolEnabledPropWithMinInterval()) {
        informZygotesOfUsapPoolStatus();
    }

    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
                pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
                bindMountAppStorageDirs, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG,
                "Starting VM process through Zygote failed");
        throw new RuntimeException(
                "Starting VM process through Zygote failed", ex);
    }
}

走到 startViaZygote

frameworks/base/core/java/android/os/ZygoteProcess.java

java 复制代码
private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                  @Nullable final String niceName,
                                                  final int uid, final int gid,
                                                  @Nullable final int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  @Nullable String seInfo,
                                                  @NonNull String abi,
                                                  @Nullable String instructionSet,
                                                  @Nullable String appDataDir,
                                                  @Nullable String invokeWith,
                                                  boolean startChildZygote,
                                                  @Nullable String packageName,
                                                  int zygotePolicyFlags,
                                                  boolean isTopApp,
                                                  @Nullable long[] disabledCompatChanges,
                                                  @Nullable Map<String, Pair<String, Long>>
                                                          pkgDataInfoMap,
                                                  @Nullable Map<String, Pair<String, Long>>
                                                          whitelistedDataInfoMap,
                                                  boolean bindMountAppsData,
                                                  boolean bindMountAppStorageDirs,
                                                  @Nullable String[] extraArgs)
                                                  throws ZygoteStartFailedEx {
    ArrayList<String> argsForZygote = new ArrayList<>();

    //省略代码中 处理 argsForZygote 要传入的参数
    if (extraArgs != null) {
        Collections.addAll(argsForZygote, extraArgs);
    }

    synchronized(mLock) {
        // The USAP pool can not be used if the application will not use the systems graphics
        // driver.  If that driver is requested use the Zygote application start path.
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                          zygotePolicyFlags,
                                          argsForZygote);
    }
}

上面代码省略的代码主要是处理要传入的参数,调用 zygoteSendArgsAndGetResult方法去传入数据。 此处第一个参数是传入 一个 ZygoteState 对象。此处需要根据 abi 获取对应的 ZygoteState,系统一般支持 32 位和 64位的。

frameworks/base/core/java/android/os/ZygoteProcess.java

java 复制代码
 @GuardedBy("mLock")
private Process.ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
    // chld 将参数合并成一个字符串
    String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";

    if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) {
            // chld Android 新的启动方式: 通过prefork的方式提前创建好一批进程,当有应用启动时,直接将已经创建好的进程分配给它,从而省去了fork的动作,因此可以提升性能. 默认是关闭的。
            try {
                return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);//代码1
            } catch (IOException ex) {
                // If there was an IOException using the USAP pool we will log the error and
                // attempt to start the process through the Zygote.
                Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - "
                        + ex.getMessage());
            }
        }

    return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);//代码2
}

代码1 使用Usap(Unspecialized App Process) 方式,该方式下省去了 fork 过程,应用启动更快。该属性默认是关闭的,可以设置 persist.device_config.runtime_native.usap_pool_enabled 属性去动态开启关闭(需要root)。

代码2 代码1的方式默认是关闭的,一般都是走到代码2处。

frameworks/base/core/java/android/os/ZygoteProcess.java

java 复制代码
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
        ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
    try {
        final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
        final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;

        zygoteWriter.write(msgStr);
        zygoteWriter.flush();

        // Always read the entire result from the input stream to avoid leaving
        // bytes in the stream for future process starts to accidentally stumble
        // upon.
        Process.ProcessStartResult result = new Process.ProcessStartResult();
        result.pid = zygoteInputStream.readInt();
        result.usingWrapper = zygoteInputStream.readBoolean();

        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }

        return result;
    } catch (IOException ex) {
        zygoteState.close();
        Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
                + ex.toString());
        throw new ZygoteStartFailedEx(ex);
    }
}

如上,在 attemptZygoteSendArgsAndGetResult 方法中,通过 socket 将数据传入给了 Zygote 进程, 并去读取创建后的结果,获取创建的进程ID.

接下来让我们去 Zygote 进程去看看服务端怎么处理 来自 SystemServer 进程的创建应用进程需求吧.

相关推荐
网络研究院15 分钟前
Android 安卓内存安全漏洞数量大幅下降的原因
android·安全·编程·安卓·内存·漏洞·技术
凉亭下22 分钟前
android navigation 用法详细使用
android
小比卡丘3 小时前
C语言进阶版第17课—自定义类型:联合和枚举
android·java·c语言
前行的小黑炭4 小时前
一篇搞定Android 实现扫码支付:如何对接海外的第三方支付;项目中的真实经验分享;如何高效对接,高效开发
android
落落落sss5 小时前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
代码敲上天.6 小时前
数据库语句优化
android·数据库·adb
GEEKVIP8 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone
model200510 小时前
android + tflite 分类APP开发-2
android·分类·tflite
彭于晏68910 小时前
Android广播
android·java·开发语言
与衫11 小时前
掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
android·javascript·sql