• Android 源码 <Activity> 桌面启动一 [5]


    在这里插入图片描述

    Read The Fucking Source Code. —— Linus

    站在’巨人’的肩膀上开始自己的旅途。—— 佚名

    愉快的周末,从打开💻开始,到骑行归来结束。—— 佚名

    注: 本系列文章源码基于 Android 11-r21 master 分支

    在系列文章中,上一章我们对 package 目录下的内容有了一定的了解,我们知道设备上的桌面其实就是一个系统应用AOSP 原生有提供,但是厂商定制的 ROM 往往会自己重写或重新实现,扩展功能;那么继续 Android 系统启动思考往下走,我们是不是应该看看手机桌面是如何显示的———桌面程序是如何启动的?

    [Launcher enter point]

    虽然我们知道桌面程序是Launcher,但是我们作为刚阅读源码的小白,如何在源码中快速找到桌面程序启动的入口? 这是一个可以思考的问题, 当然,站在‘巨人的肩膀’直接使用百度也是可以的,但这里我想到另外一种方式————无障碍服务 Accessebility;在平时开发中,无障碍服务除了满足项目需求应用于项目中外,还有一种就是利用该服务作为我们的辅助工具,提高开发效率,我个人最常用的就是查看系统当前最顶部显示的 activity。作为辅助手段,早已有成熟的软件工具,这里推荐两个工具。

    看看自己,废话一大堆,我写文章就这样,hai! 如果没有高山流水,也可以通过⌨️与屏幕对话,就当我是胡言乱语吧

    • 开发者助手
    • Android 开发工具箱

    systemReady

    我们知道,SystemServer 在被调用时先执行 main 函数,紧接着执行当前类的静态方法 run,然后分三个阶段启动 启动服务、核心服务、其他服务,最后进入 Looper().loop 循环忘不停歇的 打工 等待消息到来并处理。

    启动服务是一部分,难道不做点别的吗?刚好在启动 其他服务 这里看到这一段注释:

    // We now tell the activity manager it is okay to run third party
    // code.  It will call back into us once it has gotten to the state
    // where third party code can really run (but before it has actually
    // started launching the initial applications), for us to complete our
    // initialization.
    
    SystemServer:AMS 你所需的一些服务已准备就绪,可以启动第三方应用了,收到请回答,收到请回答,over!over!
    
    AMS:收到!收到!看我回调行事,over!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    先是 AMS systemReady 进入准备阶段

    //ActivityManagerService.java
    public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
    
        /*
            1、管理 activity 的任务栈【这种内容太细了,以后逐个看看,先略过】
            2、包含 RecentTasks 最近运行的任务列表
        */
        mActivityTaskManager.onSystemReady();
        mUserController.onSystemReady();
        //访问控制,主要与权限、限制相关
        mAppOpsService.systemReady();
        mProcessList.onSystemReady();
    
        /*
            1、如果进程或进程组被标记为杀死,将调用 Process.killProcessQuiet(mPid);ProcessList.killProcessGroup(uid, mPid);杀死进程,为启动新进程做准备
            2、当然,进程也可能被标记为重启,便不会从进程队列中移除       
        */
        mProcessList.removeProcessLocked
        //注册启动监听,ATM:activitTaskManager
        mAtmInternal.getLaunchObserverRegistry().registerLaunchObserver(mActivityLaunchObserver);
        //UGM:uri global manager,uri 作为数据访问地址、数据传递也是很常用的
        mUgmInternal.onSystemReady();
        //pmi:power manager internal,低电量监控
        pmi.registerLowPowerModeObserver
        
        
        //😓执行到一半就返回去执行回调【请参考 —— 回调1】
        if (goingCallback != null) goingCallback.run();
            
        /*
            1、启动持久应用(不会休眠的、启动唤醒程序),待启动的是哪些应用,又来到了 IPackageManager.aidl 的 getPersistentApplications,
               实现类是 PackageManagerService.java
            2、getPersistentApplications 实际上获取到的是一个 ApplicationInfo 列表
            3、通过 applicationInfo 创建 processRecorder,接着通过 ProcessList 一顿判断、调整 processRecorder
            4、最后可能通过 wzygote 或 Process.start 启动
        */
        startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
    
        //ActivityTaskManagerInternal.java 实现类在 ActivityManagerService 的一个内部类 LocalService;
        //‼️启动桌面程序
        mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
        
        mAtmInternal.resumeTopActivities(false /* scheduleIdle */);    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    AMS 准备完毕,请求 SystemServer 超级管家执行回调

    //SystemServer.java 【回调1】
    mActivityManagerService.systemReady(() -> {
    
        //service.onBootPhase(mCurrentPhase=500); 系统服务那么多到底谁在执行 500 这个标记?
        //不用过多关注,这只是一个通知,回调告知其他服务 AMS 启动了,你们可以使用 AMS 做别的事情
        mSystemServiceManager.startBootPhase(t, SystemService.PHASE_ACTIVITY_MANAGER_READY);
        
        //AMS 需要监控 native 崩溃,里面启动了一个线程 Thread,内部使用阻塞的 socket 接收崩溃信息并返回给上层或输出
        mActivityManagerService.startObservingNativeCrashes();
    
        //看到 ops 往往是跟限制策略有关🚫
        mActivityManagerService.setAppOpsPolicy(new AppOpsPolicy(mSystemContext));
    
        // Wait for all packages to be prepared
        mPackageManagerService.waitForAppDataPrepared();
        //第三方应用准备好了,又发起一个启动第三方应用的回调,让各自实现此状态码的服务执行相应操作【见图1】
        mSystemServiceManager.startBootPhase(t, SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
    
        ... etc
        
        //到这里我们算是回调执行完成,我们又要回到 systemReady 里面去,继续看执行 goingCallback.run(); 之后的代码
        
    }, t);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    startHomeOnAllDisplays

    我们想知道 startHomeOnAllDisplays 的具体实现在哪里?有谁执行的?不妨找找看。

    • ActivityManagerService#mAtmInternal.startHomeOnAllDisplays(currentUserId, “systemReady”); AMS 中调用
    • ActivityTaskManagerInternal#startHomeOnAllDisplays 这是一个抽象类的抽象方法
    • ActivityTaskManagerService#LocalService 实现类是 ATMS 的内部类
    • ActivityTaskManagerService#mInternal; 实现类实例赋给了 ATMS 的成员
    • ActivityTaskManagerService#LocalServices.addService(ActivityTaskManagerInternal.class, mInternal); 在 ATMS 启动周期 onStart 中被缓存到本地服务列表
    • com.android.server#private static final ArrayMap, Object> sLocalServiceObjects 本地服务列表就是这么一个简单的数组
    • ActivityTaskManagerService#mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class); 从本地服务缓存列表中获取实例赋给 ATMS

    了解了,直接找实现类 LocalService

    //ActivityTaskManagerService.java#LocalService
    @Override
    public boolean startHomeOnAllDisplays(int userId, String reason) {
        synchronized (mGlobalLock) {
            return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    //RootWindowContainer.java
    boolean startHomeOnAllDisplays(int userId, String reason) {
        //桌面主界面是否启动完毕
        boolean homeStarted = false;
        //这里的循环表示对应 AllDisplays,设备是可能存在多个显示器的
        for (int i = getChildCount() - 1; i >= 0; i--) {
            final int displayId = getChildAt(i).mDisplayId;
            homeStarted |= startHomeOnDisplay(userId, reason, displayId);
        }
        return homeStarted;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    //RootWindowContainer.java
    boolean startHomeOnDisplay(int userId, String reason, int displayId) {
        return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
                false /* fromHomeKey */);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    //RootWindowContainer.java
    boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
            boolean fromHomeKey) {
        //如果遇到无效的显示设备,则使用默认的或已获得焦点的最顶部显示ID
        if (displayId == INVALID_DISPLAY) {
            final Task rootTask = getTopDisplayFocusedRootTask();
            displayId = rootTask != null ? rootTask.getDisplayId() : DEFAULT_DISPLAY;
        }
    
        final DisplayContent display = getDisplayContent(displayId);
        return display.reduceOnAllTaskDisplayAreas((taskDisplayArea, result) ->
                        result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
                                allowInstrumenting, fromHomeKey),
                false /* initValue */);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    //RootWindowContainer.java
    boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
            boolean allowInstrumenting, boolean fromHomeKey) {
        //如果提供的现实区域无效,同样的恢复默认
        if (taskDisplayArea == null) {
            final Task rootTask = getTopDisplayFocusedRootTask();
            taskDisplayArea = rootTask != null ? rootTask.getDisplayArea()
                    : getDefaultTaskDisplayArea();
        }
    
        //‼️重要的来了,桌面也是一个 activity,启动一个 activity,最重要的便是启动目标信息
        Intent homeIntent = null;
        ActivityInfo aInfo = null;
        //
        if (taskDisplayArea == getDefaultTaskDisplayArea()) {
            /*
                1、mService 是 ActivityTaskManagerService
                2、【默认】intent.addCategory(Intent.CATEGORY_HOME); mTopAction = Intent.ACTION_MAIN;
            */
            homeIntent = mService.getHomeIntent();
            aInfo = resolveHomeActivity(userId, homeIntent);
        } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
            Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
            aInfo = info.first;
            homeIntent = info.second;
        }
        if (aInfo == null || homeIntent == null) {
            return false;
        }
    
        //显示总是有一些显示
        if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, allowInstrumenting)) {
            return false;
        }
    
        homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
        homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
        if (fromHomeKey) {
            homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
            if (mWindowManager.getRecentsAnimationController() != null) {
                mWindowManager.getRecentsAnimationController().cancelAnimationForHomeStart();
            }
        }
        homeIntent.putExtra(WindowManagerPolicy.EXTRA_START_REASON, reason);
    
        //启动 activity 还得看 activityStartController
        mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
                taskDisplayArea);
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    activitStartController

    //ActivityStartController.java
    //⚠️:这里启动的是 homeItent
    void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
            TaskDisplayArea taskDisplayArea) {
        //没有任何附加属性,比如没有 activity 动画
        final ActivityOptions options = ActivityOptions.makeBasic();
        //全屏窗口模式
        options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
        if (!ActivityRecord.isResolverActivity(aInfo.name)) {
            //指定这是一个桌面 activity 
            options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
        }
    
        //显示设备ID也指定,似乎 activity 启动需要的参数都将封装到 ActivitOptions 
        final int displayId = taskDisplayArea.getDisplayId();
        options.setLaunchDisplayId(displayId);
        options.setLaunchTaskDisplayArea(taskDisplayArea.mRemoteToken
                .toWindowContainerToken());
    
        //只是一个变量递增 mDeferResumeCount++,这如何使用 
        mSupervisor.beginDeferResume();
    
        final Task rootHomeTask;
        try {
            /*
                1、activity 需要依赖 task 容器,所以启动前必须确保 Task 已创建
                2、TaskDisplayArea#createRootTask 需指定 activityType=home_activity,ontop=true 在显示器的顶部创建 rootTask
                3、最终创建是通过 Task.Builder()......build();  至此,存储桌面 activity 的 Task 已经有了
                4、mRootWindowContainer 这个很重要,我们所见到的界面都要依附于它
            */
            rootHomeTask = taskDisplayArea.getOrCreateRootHomeTask(ON_TOP/*true*/);
        } finally {
            //这个跟 mDeferResumeCount++ 对应,这里是 mDeferResumeCount--
            //关于这个还有一个方法:readyToResume() {return mDeferResumeCount == 0;} 
            //true if resume can be called:那估计是哪里进行轮询监听 readyToResume()
            mSupervisor.endDeferResume();
        }
    
        /*
            1、有了可承载桌面程序的任务栈,接着就要启动桌面 activity
            2、获得一个 activity 启动器 ActivitStarter,开始执行 excute()
            3、启动器似乎使用了工厂模式,默认启动器数量 3 个
            4、启动器主要成员有 ActivityStartController、ActivityTaskManagerService、ActivityTaskSupervisor、ActivityStartInterceptor
            5、在构建请求器过程中还需要构造启动请求参数 mRequest 
        */
        mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
                .setOutActivity(tmpOutRecord)
                .setCallingUid(0)
                .setActivityInfo(aInfo)
                .setActivityOptions(options.toBundle())
                .execute();
        mLastHomeActivityStartRecord = tmpOutRecord[0];
        if (rootHomeTask.mInResumeTopActivity) {
            //开始调用 onResume 声明周期方法,回到 activity 最熟悉的地方
            mSupervisor.scheduleResumeTopActivities();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    关于 ActivityTaskSupervisor 负责的任务太多了,估计像个版本要分离部分代码吧

    // TODO: This class has become a dumping ground. Let's
    // - Move things relating to the hierarchy to RootWindowContainer
    // - Move things relating to activity life cycles to maybe a new class called ActivityLifeCycler
    // - Move interface things to ActivityTaskManagerService.
    // - All other little things to other files.
    public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    activityStarter

    //ActivityStarter.java
    int execute() {
        try {
            /*
                1、如果启动请求信息无效,则重新解析并填充启动请求参数
                2、请求参数包括 pid、uid、resolveInfo、activityInfo  .etc
            */
            if (mRequest.activityInfo == null) {
                mRequest.resolveActivity(mSupervisor);
            }
    
            int res;
            //mGlobalLock 全局服务锁,并没有什么特别,就是一个普通对象
            synchronized (mService.mGlobalLock) {
                final boolean globalConfigWillChange = mRequest.globalConfig != null
                        && mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
                final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
                if (rootTask != null) {
                    rootTask.mConfigWillChange = globalConfigWillChange;
                }
                final long origId = Binder.clearCallingIdentity();
    
                /*
                    1、什么重量级进程切换,我都懵了😺
                    2、如果找不到调用者 app 进程,则终止启动请求 ATMS.getProcessController(request.caller) == null
                */
                res = resolveToHeavyWeightSwitcherIfNeeded();
                if (res != START_SUCCESS) {
                    return res;
                }
    
                //‼️执行启动请求
                res = executeRequest(mRequest);
    
                mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
                        newActivityCreated, mLastStartActivityRecord, originalOptions);
                if (mRequest.waitResult != null) {
                    mRequest.waitResult.result = res;
                    res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,
                            launchingState);
                }
                return getExternalResult(res);
            }
        } finally {
            //执行完成最后一定要回收 activity 启动器
            onExecutionComplete();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    activity 启动请求正式开始,这里将会有很多的启动限制🚫等。

    //ActivitStarter.java
    private int executeRequest(Request request) {
        //很好奇这个 reason 这么总要吗?干什么用的
        if (TextUtils.isEmpty(request.reason)) {
            throw new IllegalArgumentException("Need to specify a reason.");
        }
        
        //如果中途检测到是非启动成功(触发启动限制),那么立马结束请求,返回结果
        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;
    
        //❌限制1:根据启动请求调用者 caller 寻找是否存在启动 app 进程,如果不存在则返回拦截请求
        WindowProcessController callerApp = null;
        if (caller != null) {
            callerApp = mService.getProcessController(caller);
            if (callerApp != null) {
                callingPid = callerApp.getPid();
                callingUid = callerApp.mInfo.uid;
            } else {
                err = START_PERMISSION_DENIED;
            }
        }
    
        final int launchFlags = intent.getFlags();
        if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
            //❌什么请求冲突???
            if (requestCode >= 0) {
                SafeActivityOptions.abort(options);
                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
            }
        }
    
        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
            //❌启动目标 activity 未知,失败
            err = ActivityManager.START_INTENT_NOT_RESOLVED;
        }
    
        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
            //❌同样的,请求所需要的基础信息都未知,自然中断本次请求
            err = ActivityManager.START_CLASS_NOT_FOUND;
        }
    
        // voiceSession 语音交互相关 activity【这里其实是 activity 启动都会经过的路途,只是我们本次分析的是‘启动桌面 activity’】
        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
                && sourceRecord.getTask().voiceSession != null) {
            if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
                try {
                    intent.addCategory(Intent.CATEGORY_VOICE);
                    if (!mService.getPackageManager().activitySupportsIntent(
                            intent.getComponent(), intent, resolvedType)) {
                        //❌不支持语音交互功能?
                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                    }
                } catch (RemoteException e) {
                    //❌不支持语音交互功能?
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            }
        }
    
        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
            try {
                if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
                        intent, resolvedType)) {
                    //❌不支持
                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
                }
            } catch (RemoteException e) {
                //❌不支持
                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
            }
        }
    
        if (err != START_SUCCESS) {
            SafeActivityOptions.abort(options);
            return err;
        }
    
        //检查 activity 启动是否满足条件
        boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
                requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
                request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord,
                resultRootTask);
        abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
                callingPid, resolvedType, aInfo.applicationInfo);
        abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
                callingPackage);
    
        boolean restrictedBgActivity = false;
        if (!abort) {
            try {
                //继续检查是否满足启动条件
                restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                        callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                        request.originatingPendingIntent, request.allowBackgroundActivityStart,
                        intent);
            } finally {
    
            }
        }
    
         
        //略略略~~~
    
    
        //没有通过启动检查就要结束执行了
        if (abort) {
            ActivityOptions.abort(checkedOptions);
            return START_ABORTED;
        }
    
        if (aInfo != null) {
            if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
                    aInfo.packageName, userId)) {
                final IIntentSender target = mService.getIntentSenderLocked(
                        ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage, callingFeatureId,
                        callingUid, userId, null, null, 0, new Intent[]{intent},
                        new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
                                | PendingIntent.FLAG_ONE_SHOT, null);
    
                Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
    
                int flags = intent.getFlags();
                flags |= Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
    
                //设置启动标识,仅设置 NEW_TASK 某些场景不一定会真的创建一个任务栈,但可以置为 MULTIPLE_TASK
                if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0) {
                    flags |= Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
                }
                newIntent.setFlags(flags);
    
                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;
    
                //一堆数据解析和赋值就不看了
                intentGrants = null;
                resolvedType = null;
                callingUid = realCallingUid;
                callingPid = realCallingPid;
                rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0,
                        computeResolveFilterUid(
                                callingUid, realCallingUid, request.filterCallingUid));
                aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
                        null /*profilerInfo*/);
            }
        }
    
        if (rInfo != null && rInfo.auxiliaryInfo != null) {
            //万事俱备,准备待发,创建一个可以启动的 intent (也就是启动数据每个必要的不可少)
            //应该是有特别之处的,不然为什么不直接使用外部传进来的 intent,具体就不纠结了
            intent = createLaunchIntent(rInfo.auxiliaryInfo, request.ephemeralIntent,
                    callingPackage, callingFeatureId, verificationBundle, resolvedType, userId);
            resolvedType = null;
            callingUid = realCallingUid;
            callingPid = realCallingPid;
            intentGrants = null;
            aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
        }
    
        //每一个 activity 的信息都将记录在 ActivityRecord 中
        final ActivityRecord r = new ActivityRecord.Builder(mService)
                .setCaller(callerApp)
                .setLaunchedFromPid(callingPid)
                .setLaunchedFromUid(callingUid)
                .setLaunchedFromPackage(callingPackage)
                .setLaunchedFromFeature(callingFeatureId)
                .setIntent(intent)
                .setResolvedType(resolvedType)
                .setActivityInfo(aInfo)
                .setConfiguration(mService.getGlobalConfiguration())
                .setResultTo(resultRecord)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setComponentSpecified(request.componentSpecified)
                .setRootVoiceInteraction(voiceSession != null)
                .setActivityOptions(checkedOptions)
                .setSourceRecord(sourceRecord)
                .build();
    
        mLastStartActivityRecord = r;
        //‼️好了,又到下一个启动阶段
        mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
                request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,
                inTask, inTaskFragment, restrictedBgActivity, intentGrants);
    
        if (request.outActivity != null) {
            request.outActivity[0] = mLastStartActivityRecord;
        }
        return mLastStartActivityResult;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197

    checkStartAnyActivityPremission

    任何一个 activity 启动都需要检查权限问题。

    //ActivitTaskSupervisor.java
    boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo, String resultWho,
            int requestCode, int callingPid, int callingUid, String callingPackage,
            @Nullable String callingFeatureId, boolean ignoreTargetSecurity,
            boolean launchingInTask, WindowProcessController callerApp, ActivityRecord resultRecord,
            Task resultRootTask) {
        //0、✅如果是最近任务列表中的组件 并且 是当前栈中请求启动是允许的
        final boolean isCallerRecents = mService.getRecentTasks() != null
                && mService.getRecentTasks().isCallerRecents(callingUid);
        /*
            1、✅如果是具有超级用户权限的应用请求启动是允许的 appID=Process.ROOT_UID
            2、✅如果是系统应用请求启动是允许的 appID=Process.SYSTEM_UID
            3、❌如果是不同进程是不允许的 UserHandle.isIsolated(uid)
            4、✅如果是设备所有者请求启动是允许的 UserHandle.isSameApp(uid, owningUid)
            5、❌如果目标 activity exported=false 是不被允许启动的
            6、❌如果检查的权限存在 ‘禁止权限列表’中是不被允许的  [至于列表中都有哪些权限我们以后讨论]
        */
        final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid,
                callingUid);
        if (startAnyPerm == PERMISSION_GRANTED || (isCallerRecents && launchingInTask)) {
            return true;
        }
    
        //❌component 限制 【跟上述限制差不多,会调用到 checkComponentPermission】
        final int componentRestriction = getComponentRestrictionForCallingPackage(aInfo,
                callingPackage, callingFeatureId, callingPid, callingUid, ignoreTargetSecurity);
        //❌action 限制  【跟上述限制差不多,会调用到 checkPermission】
        final int actionRestriction = getActionRestrictionForCallingPackage(
                intent.getAction(), callingPackage, callingFeatureId, callingPid, callingUid);
        if (componentRestriction == ACTIVITY_RESTRICTION_PERMISSION
                || actionRestriction == ACTIVITY_RESTRICTION_PERMISSION) {
            if (resultRecord != null) {
                resultRecord.sendResult(INVALID_UID, resultWho, requestCode,
                        Activity.RESULT_CANCELED, null /* data */, null /* dataGrants */);
            }
            throw new SecurityException(msg);
        }
    
        if (actionRestriction == ACTIVITY_RESTRICTION_APPOP) {
            return false;
        } else if (componentRestriction == ACTIVITY_RESTRICTION_APPOP) {
            return false;
        }
    
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    checkIntent

    mService.mIntentFirewall.checkStartActivity 最终调用的就是 intent 过滤。

    //IntentFirewall.java
    public boolean checkIntent(FirewallIntentResolver resolver, ComponentName resolvedComponent,
            int intentType, Intent intent, int callerUid, int callerPid, String resolvedType,
            int receivingUid) {
        boolean log = false;
        boolean block = false;
    
        List<Rule> candidateRules;
        candidateRules = resolver.queryIntent(intent, resolvedType, false /*defaultOnly*/, 0);
        if (candidateRules == null) {
            candidateRules = new ArrayList<Rule>();
        }
        resolver.queryByComponent(resolvedComponent, candidateRules);
    
        for (int i=0; i<candidateRules.size(); i++) {
            Rule rule = candidateRules.get(i);
            //intent 过滤规则是什么,规则是如何匹配的?不懂————略!
            if (rule.matches(this, resolvedComponent, intent, callerUid, callerPid, resolvedType,
                    receivingUid)) {
                block |= rule.getBlock();
                log |= rule.getLog();
                if (block && log) {
                    break;
                }
            }
        }
    
        if (log) {
            logIntent(intentType, intent, callerUid, resolvedType);
        }
    
        return !block;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    checkStartActivity

    PermissionPolicyInternal 是一个抽象类,实现类是 PermissionPolicyService 的一个内部类 private class Internal extends PermissionPolicyInternal

    //PermissionPolicyService.java
    private class Internal extends PermissionPolicyInternal {
    
        @Override
        public boolean checkStartActivity(@NonNull Intent intent, int callingUid,
                @Nullable String callingPackage) {
            if (callingPackage != null && isActionRemovedForCallingPackage(intent, callingUid,
                    callingPackage)) {
                return false;
            }
            return true;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    //PermissionPolicyService.java
    private boolean isActionRemovedForCallingPackage(@NonNull Intent intent, int callingUid,
            @NonNull String callingPackage) {
        String action = intent.getAction();
        if (action == null) {
            return false;
        }
        switch (action) {
            case TelecomManager.ACTION_CHANGE_DEFAULT_DIALER:
            case Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT: {
                ApplicationInfo applicationInfo;
                try {
                    applicationInfo = getContext().getPackageManager().getApplicationInfoAsUser(
                            callingPackage, 0, UserHandle.getUserId(callingUid));
                    if (applicationInfo.targetSdkVersion >= Build.VERSION_CODES.Q) {
                        //只有高版本才会检查这个问题咯
                        return true;
                    }
                } catch (PackageManager.NameNotFoundException e) {
                    
                }
              
                intent.putExtra(Intent.EXTRA_CALLING_PACKAGE, callingPackage);
                return false;
            }
            default:
                return false;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    shouldAbortBackgroundActivityStart

          你好,我好,大家好 😊 
    
    • 1

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G95WQqEe-1661130836859)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/62b2ad34162d4d909a63e1e16a98b52d~tplv-k3u1fbpfcp-watermark.image?)]

    boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
            final String callingPackage, int realCallingUid, int realCallingPid,
            WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
            boolean allowBackgroundActivityStart, Intent intent) {
        
        //1、✅系统用户应用、具有 Root 权限的应用、NFC (一般是伴生设备)应用请求启动是允许的
        final int callingAppId = UserHandle.getAppId(callingUid);
        if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
                || callingAppId == Process.NFC_UID) {
            return false;
        }
    
        //2、✅如果是桌面程序启动是允许的  [正常用户操作不就是点击桌面应用图标然后启动的嘛]
        if (isHomeApp(callingUid, callingPackage)) {
            return false;
        }
    
        //3、✅设备所有者是允许的
        final WindowState imeWindow = mRootWindowContainer.getCurrentInputMethodWindow();
        if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
            return false;
        }
    
        //4、✅如果有前台应用或可见界面存在前台,这也是允许的
        final int appSwitchState = mService.getBalAppSwitchesState();
        final int callingUidProcState = mService.mActiveUids.getUidState(callingUid);
        final boolean callingUidHasAnyVisibleWindow = mService.hasActiveVisibleWindow(callingUid);
        final boolean isCallingUidForeground = callingUidHasAnyVisibleWindow
                || callingUidProcState == ActivityManager.PROCESS_STATE_TOP
                || callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP;
        final boolean isCallingUidPersistentSystemProcess =
                callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
    
        //5、✅在应用切换过程中,如果有可见的窗口是允许的
        final boolean appSwitchAllowedOrFg =
                appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY;
        if (((appSwitchAllowedOrFg || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
                && callingUidHasAnyVisibleWindow)
                || isCallingUidPersistentSystemProcess) {
            return false;
        }
        
        final int realCallingUidProcState = (callingUid == realCallingUid)
                ? callingUidProcState
                : mService.mActiveUids.getUidState(realCallingUid);
        final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
                ? callingUidHasAnyVisibleWindow
                : mService.hasActiveVisibleWindow(realCallingUid);
        final boolean isRealCallingUidForeground = (callingUid == realCallingUid)
                ? isCallingUidForeground
                : realCallingUidHasAnyVisibleWindow
                        || realCallingUidProcState == ActivityManager.PROCESS_STATE_TOP;
        final int realCallingAppId = UserHandle.getAppId(realCallingUid);
        final boolean isRealCallingUidPersistentSystemProcess = (callingUid == realCallingUid)
                ? isCallingUidPersistentSystemProcess
                : (realCallingAppId == Process.SYSTEM_UID)
                        || realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
        if (realCallingUid != callingUid) {
            //6、✅如果调用的进程有可见的窗口是允许的
            if (realCallingUidHasAnyVisibleWindow) {
                if (DEBUG_ACTIVITY_STARTS) {
                    Slog.d(TAG, "Activity start allowed: realCallingUid (" + realCallingUid
                            + ") has visible (non-toast) window");
                }
                return false;
            }
    
            //7、✅如果是‘系统持久应用’发起的请求是允许的
            if (isRealCallingUidPersistentSystemProcess && allowBackgroundActivityStart) {
                return false;
            }
    
            //8、✅如果存在伴生设备或者相关可见应用进程是允许的
            if (mService.isAssociatedCompanionApp(UserHandle.getUserId(realCallingUid),
                    realCallingUid)) {
                return false;
            }
        }
    
        //9、✅具备系统权限 START_ACTIVITIES_FROM_BACKGROUND 是允许的
        if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
                == PERMISSION_GRANTED) {
            return false;
        }
    
        //10、✅如果最近存在相同 uid 进程启动相关组件是允许的(同一个应用)
        if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
            return false;
        }
    
        //11、✅对于设备所有者请求启动是允许的
        if (mService.isDeviceOwner(callingUid)) {
            return false;
        }
    
        //12、✅对于伴生设备的请求是允许的
        final int callingUserId = UserHandle.getUserId(callingUid);
        if (mService.isAssociatedCompanionApp(callingUserId, callingUid)) {
            return false;
        }
        
        //13、✅具备系统权限 SYSTEM_ALERT_WINDOW 是允许的
        if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
            return false;
        }
    
      
        int callerAppUid = callingUid;
        if (callerApp == null) {
            callerApp = mService.getProcessController(realCallingPid, realCallingUid);
            callerAppUid = realCallingUid;
        }
        if (callerApp != null) {
            //‼️来到了新的启动控制类:BackgroundLaunchProcessController#areBackgroundActivityStartsAllowed
            //参考下文
            if (callerApp.areBackgroundActivityStartsAllowed(appSwitchState)) {
                return false;
            }
    
            final ArraySet uidProcesses =
                    mService.mProcessMap.getProcesses(callerAppUid);
            if (uidProcesses != null) {
                for (int i = uidProcesses.size() - 1; i >= 0; i--) {
                    final WindowProcessController proc = uidProcesses.valueAt(i);
                    //参看下文
                    if (proc != callerApp
                            && proc.areBackgroundActivityStartsAllowed(appSwitchState)) {
                        return false;
                    }
                }
            }
        }
        
        return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135

    areBackgroundActivityStartsAllowed

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9oivtJ7t-1661130836860)(https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/bba4707700054738a508a8a6f1963074~tplv-k3u1fbpfcp-watermark.image?)]

    略略略略略略!!!!

    //BackgroundLaunchProcessController.java
    boolean areBackgroundActivityStartsAllowed(int pid, int uid, String packageName,
            int appSwitchState, boolean isCheckingForFgsStart,
            boolean hasActivityInVisibleTask, boolean hasBackgroundActivityStartPrivileges,
            long lastStopAppSwitchesTime, long lastActivityLaunchTime,
            long lastActivityFinishTime) {
        if (appSwitchState == APP_SWITCH_ALLOW) {
            final long now = SystemClock.uptimeMillis();
            if (now - lastActivityLaunchTime < ACTIVITY_BG_START_GRACE_PERIOD_MS
                    || now - lastActivityFinishTime < ACTIVITY_BG_START_GRACE_PERIOD_MS) {
                if (lastActivityLaunchTime > lastStopAppSwitchesTime
                        || lastActivityFinishTime > lastStopAppSwitchesTime) {
                    return true;
                }
            }
        }
        if (hasBackgroundActivityStartPrivileges) {
            return true;
        }
    
        if (hasActivityInVisibleTask
                && (appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY)) {
            return true;
        }
        if (isBoundByForegroundUid()) {
            return true;
        }
        if (isBackgroundStartAllowedByToken(uid, packageName, isCheckingForFgsStart)) {
            return true;
        }
        return false;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    startActivityUnchecked

    //ActivityStarter.java
    private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, Task inTask,
            TaskFragment inTaskFragment, boolean restrictedBgActivity,
            NeededUriGrants intentGrants) {
    
            //下周见😊
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    现在是周日、晚上六点半,是时候出去骑车了,续篇下周见 😊

    [Reference]

  • 相关阅读:
    Word控件Spire.Doc 【文本】教程(9) ;如何在C#中获取word文档中文本的高度和宽度
    frp内网穿透xtcp安全点对点p2p部署记录打洞失败解决方法
    大数据开发之词频统计传参打包成jar包发送到Hadoop运行并创建可执行文件方便运行
    OpenAI开源全新解码器,极大提升Stable Diffusion性能
    P4_toturial练习1问题:ModuleNotFoundError: No module named ‘p4.tmp‘
    从gles,vulkan到metal(二)-- 同步和内存
    《思科 - GNS3 - 备份配置》
    VSRS4.0 安装与配置
    网站变灰,6行代码,通通变灰
    C#.NET体系图文概述—2024最全总结
  • 原文地址:https://blog.csdn.net/printf123scanf/article/details/126459314