中:Android startActivity原理分析(基于Android 8,jsp技术分析

        } catch (RemoteException e) {

            Slog.w(TAG, "Failure checking voice capabilities", e);

            err = ActivityManager.START_NOT_VOICE_COMPATIBLE;

        }

    }



    final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();



    if (err != START_SUCCESS) {

        if (resultRecord != null) {

            resultStack.sendActivityResultLocked(

                    -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);

        }

        ActivityOptions.abort(options);

        return err;

    }



    //校验当前应用是否有开启权限,我们的普通开启肯定是有权限啦,所以可以忽略啦

    boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,

            requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,

            resultRecord, resultStack, options);

    abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,

            callingPid, resolvedType, aInfo.applicationInfo);



    if (mService.mController != null) {

        try {

            // The Intent we give to the watcher has the extra data

            // stripped off, since it can contain private information.

            Intent watchIntent = intent.cloneFilter();

            abort |= !mService.mController.activityStarting(watchIntent,

                    aInfo.applicationInfo.packageName);

        } catch (RemoteException e) {

            mService.mController = null;

        }

    }



    mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);

    mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid, callingUid,

            options);

    intent = mInterceptor.mIntent;

    rInfo = mInterceptor.mRInfo;

    aInfo = mInterceptor.mAInfo;

    resolvedType = mInterceptor.mResolvedType;

    inTask = mInterceptor.mInTask;

    callingPid = mInterceptor.mCallingPid;

    callingUid = mInterceptor.mCallingUid;

    options = mInterceptor.mActivityOptions;



    if (abort) {

        if (resultRecord != null) {

            resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,

                    RESULT_CANCELED, null);

        }

        // We pretend to the caller that it was really started, but

        // they will just get a cancel result.

        ActivityOptions.abort(options);

        return START_ABORTED;

    }



    // If permissions need a review before any of the app components can run, we

    // launch the review activity and pass a pending intent to start the activity

    // we are to launching now after the review is completed.

    if (mService.mPermissionReviewRequired && aInfo != null) {

        if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(

                aInfo.packageName, userId)) {

            IIntentSender target = mService.getIntentSenderLocked(

                    ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,

                    callingUid, userId, null, null, 0, new Intent[]{intent},

                    new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT

                            | PendingIntent.FLAG_ONE_SHOT, null);



            final int flags = intent.getFlags();

            Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);

            newIntent.setFlags(flags

                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);

            newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);

            newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));

            if (resultRecord != null) {

                newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);

            }

            intent = newIntent;



            resolvedType = null;

            callingUid = realCallingUid;

            callingPid = realCallingPid;



            rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);

            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,

                    null /*profilerInfo*/);



            if (DEBUG_PERMISSIONS_REVIEW) {

                Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,

                        true, false) + "} from uid " + callingUid + " on display "

                        + (mSupervisor.mFocusedStack == null

                        ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));

            }

        }

    }



    // If we have an ephemeral app, abort the process of launching the resolved intent.

    // Instead, launch the ephemeral installer. Once the installer is finished, it

    // starts either the intent we resolved here [on install error] or the ephemeral

    // app [on install success].

    if (rInfo != null && rInfo.auxiliaryInfo != null) {

        intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,

                callingPackage, verificationBundle, resolvedType, userId);

        resolvedType = null;

        callingUid = realCallingUid;

        callingPid = realCallingPid;



        aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);

    }



    //创建出我们的目标ActivityRecord对象,存到传入数组0索引上

    ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,

            callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),

            resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,

            mSupervisor, options, sourceRecord);

    if (outActivity != null) {

        outActivity[0] = 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;

    }



    final ActivityStack stack = mSupervisor.mFocusedStack;

    if (voiceSession == null && (stack.mResumedActivity == null

            || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {

        if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,

                realCallingPid, realCallingUid, "Activity start")) {

            PendingActivityLaunch pal =  new PendingActivityLaunch(r,

                    sourceRecord, startFlags, stack, callerApp);

            mPendingActivityLaunches.add(pal);

            ActivityOptions.abort(options);

            return ActivityManager.START_SWITCHES_CANCELED;

        }

    }



    if (mService.mDidAppSwitch) {

        // This is the second allowed switch since we stopped switches,

        // so now just generally allow switches.  Use case: user presses

        // home (switches disabled, switch to home, mDidAppSwitch now true);

        // user taps a home icon (coming from home so allowed, we hit here

        // and now allow anyone to switch again).

        mService.mAppSwitchesAllowedTime = 0;

    } else {

        mService.mDidAppSwitch = true;

    }



    //检查是否有需要延迟启动的Activity,如果有,则启动

    doPendingActivityLaunchesLocked(false);



    //跳转到另外一个startActivity函数中继续执行

    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,

            options, inTask, outActivity);

}



这个函数就分析完了,写的很长,但是逻辑并不复杂,主要就是处理startActivityForResult的逻辑和校验权限,最后还创建了一个目标activity的ActivityRecord对象就完了。我们继续看下一个重载函数



private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,

        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,

        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,

        ActivityRecord[] outActivity) {



    int result = START_CANCELED;

    try {

        //阻塞一下Surface

        mService.mWindowManager.deferSurfaceLayout();

        result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,

                startFlags, doResume, options, inTask, outActivity);

    } finally {

        // If we are not able to proceed, disassociate the activity from the task. Leaving an

        // activity in an incomplete state can lead to issues, such as performing operations

        // without a window container.

        if (!ActivityManager.isStartResultSuccessful(result)

                && mStartActivity.getTask() != null) {

            mStartActivity.getTask().removeActivity(mStartActivity);

        }

        mService.mWindowManager.continueSurfaceLayout();

    }



    postStartActivityProcessing(r, result, mSupervisor.getLastStack().mStackId,  mSourceRecord,

            mTargetStack);



    return result;

}



这个函数很简单,也只是通知Wms(WindowManagerService)阻塞一下Surface,然后就转发到了startActivityUnchecked函数中继续处理了,我们接着看startActivityUnchecked的实现吧。



private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,

        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,

        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,

        ActivityRecord[] outActivity) {



    //根据启动intent识别启动模式,如果是startActivityForResult并且启动模式是NEW_TASK的话,就会让startActivityForResult的回调失效

    setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,

            voiceInteractor);



    //判断启动模式,并且在mLaunchFlags上追加对应的标记

    computeLaunchingTaskFlags();



    //获取到Activity的启动栈

    computeSourceStack();



    //根据上面的计算,应用识别到的flags

    mIntent.setFlags(mLaunchFlags);



    ActivityRecord reusedActivity = getReusableIntentActivity();



    final int preferredLaunchStackId =

            (mOptions != null) ? mOptions.getLaunchStackId() : INVALID_STACK_ID;

    final int preferredLaunchDisplayId =

            (mOptions != null) ? mOptions.getLaunchDisplayId() : DEFAULT_DISPLAY;



    if (reusedActivity != null) {

        // When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but

        // still needs to be a lock task mode violation since the task gets cleared out and

        // the device would otherwise leave the locked task.

        if (mSupervisor.isLockTaskModeViolation(reusedActivity.getTask(),

                (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))

                        == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))) {

            mSupervisor.showLockTaskToast();

            Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");

            return START_RETURN_LOCK_TASK_MODE_VIOLATION;

        }



        if (mStartActivity.getTask() == null) {

            mStartActivity.setTask(reusedActivity.getTask());

        }

        if (reusedActivity.getTask().intent == null) {

            // This task was started because of movement of the activity based on affinity...

            // Now that we are actually launching it, we can assign the base intent.

            reusedActivity.getTask().setIntent(mStartActivity);

        }



        // This code path leads to delivering a new intent, we want to make sure we schedule it

        // as the first operation, in case the activity will be resumed as a result of later

        // operations.

        if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0

                || isDocumentLaunchesIntoExisting(mLaunchFlags)

                || mLaunchSingleInstance || mLaunchSingleTask) {

            final TaskRecord task = reusedActivity.getTask();



            // In this situation we want to remove all activities from the task up to the one

            // being started. In most cases this means we are resetting the task to its initial

            // state.

            final ActivityRecord top = task.performClearTaskForReuseLocked(mStartActivity,

                    mLaunchFlags);



            // The above code can remove {@code reusedActivity} from the task, leading to the

            // the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The

            // task reference is needed in the call below to

            // {@link setTargetStackAndMoveToFrontIfNeeded}.

            if (reusedActivity.getTask() == null) {

                reusedActivity.setTask(task);

            }



            if (top != null) {

                if (top.frontOfTask) {

                    // Activity aliases may mean we use different intents for the top activity,

                    // so make sure the task now has the identity of the new intent.

                    top.getTask().setIntent(mStartActivity);

                }

                deliverNewIntent(top);

            }

        }



        sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, reusedActivity);



        reusedActivity = setTargetStackAndMoveToFrontIfNeeded(reusedActivity);



        final ActivityRecord outResult =

                outActivity != null && outActivity.length > 0 ? outActivity[0] : null;



        // When there is a reused activity and the current result is a trampoline activity,

        // set the reused activity as the result.

        if (outResult != null && (outResult.finishing || outResult.noDisplay)) {

            outActivity[0] = reusedActivity;

        }



        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {

            // We don't need to start a new activity, and the client said not to do anything

            // if that is the case, so this is it!  And for paranoia, make sure we have

            // correctly resumed the top activity.

            resumeTargetStackIfNeeded();

            return START_RETURN_INTENT_TO_CALLER;

        }

        setTaskFromIntentActivity(reusedActivity);



        if (!mAddingToTask && mReuseTask == null) {

            // We didn't do anything...  but it was needed (a.k.a., client don't use that

            // intent!)  And for paranoia, make sure we have correctly resumed the top activity.

            resumeTargetStackIfNeeded();

            if (outActivity != null && outActivity.length > 0) {

                outActivity[0] = reusedActivity;

            }



            return START_TASK_TO_FRONT;

        }

    }



    //校验目标页面的包名,很有可能是没有安装该应用

    if (mStartActivity.packageName == null) {

        final ActivityStack sourceStack = mStartActivity.resultTo != null

                ? mStartActivity.resultTo.getStack() : null;

        if (sourceStack != null) {

            sourceStack.sendActivityResultLocked(-1 /* callingUid */, mStartActivity.resultTo,

                    mStartActivity.resultWho, mStartActivity.requestCode, RESULT_CANCELED,

                    null /* data */);

        }

        ActivityOptions.abort(mOptions);

        return START_CLASS_NOT_FOUND;

    }



    // If the activity being launched is the same as the one currently at the top, then

    // we need to check if it should only be launched once.

    final ActivityStack topStack = mSupervisor.mFocusedStack;

    final ActivityRecord topFocused = topStack.topActivity();

    final ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(mNotTop);

    final boolean dontStart = top != null && mStartActivity.resultTo == null

            && top.realActivity.equals(mStartActivity.realActivity)

            && top.userId == mStartActivity.userId

            && top.app != null && top.app.thread != null

            && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0

            || mLaunchSingleTop || mLaunchSingleTask);

    if (dontStart) {

        // For paranoia, make sure we have correctly resumed the top activity.

        topStack.mLastPausedActivity = null;

        if (mDoResume) {

            mSupervisor.resumeFocusedStackTopActivityLocked();

        }

        ActivityOptions.abort(mOptions);

        if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {

            // We don't need to start a new activity, and the client said not to do

            // anything if that is the case, so this is it!

            return START_RETURN_INTENT_TO_CALLER;

        }



        deliverNewIntent(top);



        // Don't use mStartActivity.task to show the toast. We're not starting a new activity

        // but reusing 'top'. Fields in mStartActivity may not be fully initialized.

        mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredLaunchStackId,

                preferredLaunchDisplayId, topStack.mStackId);



        return START_DELIVERED_TO_TOP;

    }



    //接下来判断是否需要新创建一个task出来,比如NEW_TASK

    //如果不需要新建就直接把目标Activity放入到对应的task内,在setTaskFromSourceRecord内执行

    boolean newTask = false;

    final TaskRecord taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)

            ? mSourceRecord.getTask() : null;

    // Should this be considered a new task?

    int result = START_SUCCESS;

    if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask

            && (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {

        newTask = true;

        result = setTaskFromReuseOrCreateNewTask(

                taskToAffiliate, preferredLaunchStackId, topStack);

    } else if (mSourceRecord != null) {

        result = setTaskFromSourceRecord();

    } else if (mInTask != null) {

        result = setTaskFromInTask();

    } else {

        // This not being started from an existing activity, and not part of a new task...

        // just put it in the top task, though these days this case should never happen.

        setTaskToCurrentTopOrCreateNewTask();

    }

    if (result != START_SUCCESS) {

        return result;

    }



    mService.grantUriPermissionFromIntentLocked(mCallingUid, mStartActivity.packageName,

            mIntent, mStartActivity.getUriPermissionsLocked(), mStartActivity.userId);

    mService.grantEphemeralAccessLocked(mStartActivity.userId, mIntent,

            mStartActivity.appInfo.uid, UserHandle.getAppId(mCallingUid));

    if (mSourceRecord != null) {

        mStartActivity.getTask().setTaskToReturnTo(mSourceRecord);

    }

    if (newTask) {

        EventLog.writeEvent(

                EventLogTags.AM_CREATE_TASK, mStartActivity.userId,

                mStartActivity.getTask().taskId);

    }

    ActivityStack.logStartActivity(

            EventLogTags.AM_CREATE_ACTIVITY, mStartActivity, mStartActivity.getTask());

    mTargetStack.mLastPausedActivity = null;



    //判断是否需要发送警告(PowerManager实现),判断依据是resumedActivity被回收或者是进程被杀死或者是目标Activity的进程和resumedActivity的进程不一致的时候

    sendPowerHintForLaunchStartIfNeeded(false /* forceSend */, mStartActivity);



    //处理新增Task和启动动画的问题

    mTargetStack.startActivityLocked(mStartActivity, topFocused, newTask, mKeepCurTransition,

            mOptions);

    //处理完启动栈任务栈的问题后,准备执行发起者的Resume状态了

    if (mDoResume) {

        final ActivityRecord topTaskActivity =

                mStartActivity.getTask().topRunningActivityLocked();

        if (!mTargetStack.isFocusable()

                || (topTaskActivity != null && topTaskActivity.mTaskOverlay

                && 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

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
img
img
img

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
img

er 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

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
[外链图片转存中…(img-0nLkqWmp-1712550668402)]
[外链图片转存中…(img-hv1GrQUZ-1712550668403)]
[外链图片转存中…(img-8TUH69de-1712550668403)]

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
[外链图片转存中…(img-zy5jz1wg-1712550668403)]

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值