likes
comments
collection
share

Android Activity 启动过程(上)

作者站长头像
站长
· 阅读数 21

前言

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

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

本文中代码基于 android-security-11.0.0_r66 分支.

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

1.Launcher 进程 StartActivity 过程

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

1.1 Activity startActivity

frameworks/base/core/java/android/app/Activity.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

 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

@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

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

 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方法。

 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

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

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

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

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

@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

@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

@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

@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

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

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

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

 @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

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.

转载自:https://juejin.cn/post/7299671709476012084
评论
请登录