Android Sprd省电管理(四)自启动和关联启动管理

自启动和管理启动管理介绍

自启动管理用于管理应用的开机自启动/后台自启动/关联自启动。应用自启动的管理,以包名(应
用名)进行限制,不区分 user(用户)。

(1)自启动
指开机自启动和后台自启动。应用可以监听系统的一些开机广播,从而在系统开机后自动进行启动。
同时应用也可以监听系统的任何广播,如网络连接的广播,从而在网络连接上的时候,进行自启动。
(2)关联启动
关联启动指不同的应用之间进行互起。这里指的是,该应用被其他应用后台启动。

流程分析

1)自启动reason

    private static final String REASON_START_SERVICE = "start-service";
    private static final String REASON_BIND_SERVICE = "bind-service";
    private static final String REASON_CONTENT_PROVIDER = "contentprovider";
    private static final String REASON_BROADCAST = "send-broadcast";
    private static final String REASON_START_ACTIVITY = "start-activity";

1.1 start-activity

在ActivityStarter.java-->startActivity()判断是否是异常启动

    private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
            String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
            ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
            ActivityRecord[] outActivity, TaskRecord inTask) {
              
        .......
        String targetPkg = null;
        int targetUid = aInfo != null ? aInfo.applicationInfo.uid : 0;
        if (intent.getComponent() != null) targetPkg = intent.getComponent().getPackageName();
        if(!mService.judgeStartAllowLocked(intent, targetPkg, targetUid, callingUid, callingPackage, "start-activity")){
            return ActivityManager.START_INTENT_NOT_RESOLVED;
        }
        .......
}

1.2 start-service

在ActiveServices.java-->startServiceLocked()

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
        ......
                int targetUid = r.appInfo != null ? r.appInfo.uid : 0 ;
        if(!mAm.judgeStartAllowLocked(service, r.packageName, targetUid, callingUid, callingPackage,"start-service")) {
            return null;
        }
        ......

1.3 bind-service

在ActiveServices.java-->bindServiceLocked()

    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
          ......
                  String targetPkg = s != null ? s.packageName : null;
        int targetUid = (s != null && s.appInfo != null) ? s.appInfo.uid : 0;
        int callingUid = (callerApp != null && callerApp.info != null) ? callerApp.info.uid : 0;
        if(!mAm.judgeStartAllowLocked(service, targetPkg, targetUid, callingUid, callingPackage,"bind-service")) {
            return 0;
        }
          ......

1.4 send-broadcast

final void processNextBroadcast(boolean fromMsg) {
        ......
                        skip = skip || !mService.judgeStartAllowLocked(r.intent, info.activityInfo.applicationInfo.packageName,
                    info.activityInfo.applicationInfo.uid, r.callingUid, r.callerPackage,"send-broadcast");
        ......
}

1.5 contentprovider

ActivityManagerService.java -->getContentProviderImpl()


    private ContentProviderHolder getContentProviderImpl(IApplicationThread caller,
            String name, IBinder token, boolean stable, int userId) {
        ContentProviderRecord cpr;
        ......
                        String targetPkg = (cpr != null && cpr.appInfo != null) ? cpr.appInfo.packageName : null;
                int targetUid = (cpr != null && cpr.appInfo != null) ? cpr.appInfo.uid : 0;
                if (r != null && r.info != null) {
                    String callingPackage = r.info.packageName;
                    int callerUid = r.info.uid;
                    if(!judgeStartAllowLocked(null, targetPkg, targetUid, callerUid, callingPackage,"contentprovider")) {
                        return null;
                    }
                }
        ......

可以看出自启动的拦截,就是在四大组件启动流程中进行的

2)judgeStartAllowLocked()流程分析

ActivityManagerServerEx.java-->judgeStartAllowLocked()

    protected boolean judgeStartAllowLocked(Intent intent, String targetPkg, int targetUid,
        int callingUid, String callingPackage, String reason) {

        boolean allowed = true;
        if (allowed && mPowerControllerInternal != null) {
            try {
                allowed = mPowerControllerInternal.judgeAppLaunchAllowed(intent, targetPkg, targetUid, callingUid, callingPackage, reason);
            } catch (Exception e) {}
        }
        

BackgroundCleanHelper.java-->judgeAppLaunchAllowed()

     boolean judgeAppLaunchAllowed(Intent intent, String targetApp, int targetUid,
            int callerUid, String callerApp, String reason) {
        mPowerHintSceneForGts.noteAppLaunched(targetApp, callerApp, callerUid);

        boolean ret = judgeAppLaunchAllowedInternal(intent, targetApp, targetUid, callerUid, callerApp, reason);
        if (mCurrentUserId == 0 && ret && targetApp != null) {
            if (!targetApp.equals(callerApp) && !mFirstCallerAppList.containsKey(targetApp)
                && isInstalledApp(targetApp, 0)) {
                mFirstCallerAppList.put(targetApp, new CallerAppInfo(callerApp, callerUid, reason));
            }
        }
        return ret;

BackgroundCleanHelper.java-->judgeAppLaunchAllowedInternal()

/*
     * Third app can not self started:
     * 1. not allow system broadcast from "systemserver" or "com.android.systemui"
     * 2. not allow start service from ""com.android.shell"
     * 3. not allow background app to launch other third party app
     * 4. not allow self started third party app to start other third party app
     * 5. not allow third party app to start other third party app during standby
     *
     * Note: This api is call from AMS in other threads and may be in variable calling context
     *  SO BE CAREFULL : avoid call other system API that may hold lock. Otherwise, a deadlock may HAPPEN
     */
     boolean judgeAppLaunchAllowedInternal(Intent intent, String targetApp, int targetUid,
            int callerUid, String callerApp, String reason) {

        // if this function is disabled, just return true
        if (!mEnabled) return true;

        if (DEBUG_MORE) Slog.d(TAG,"judgeAppLaunchAllowed : "+targetApp+"(uid:" + targetUid
            + "), callingPackage = "+callerApp+"(uid:" + callerUid + "), reason = "+reason);
        if (DEBUG_MORE && intent != null) Slog.d(TAG,"judgeAppLaunchAllowed : intent action:" + intent);

        if (targetApp == null) return true;

        // bug#768670
        if (handleStartServiceStartAction(intent, targetApp, targetUid, callerApp, callerUid, reason)) {
            return true;
        }

        if (handleBindServiceStartAction(intent, targetApp, targetUid, callerApp, callerUid, reason)) {
            return true;
        }

        if (handleContentProviderStartAction(intent, targetApp, targetUid, callerApp, callerUid, reason)) {
            return true;
        }

        //handle inputmethod
        if (isLaunchingIMEApp(intent, targetApp, targetUid, callerApp, reason)) {
            return true;
        }

        if (handleBroadcastAction(intent, targetApp, targetUid, callerApp, callerUid, reason)) {
            return true;
        }

        //handle speech recognition
        if (isRecognizerIntent(intent, targetApp, targetUid, callerApp, callerUid, reason)) {
            return true;
        }

        // allow cts app to start any other app
        // allow autotest app
        if (Util.isCts(callerApp) || isAutoTest(callerUid, callerApp, targetApp)) {
            return true;
        }

        // check deny for ultra saving mode
        //if (denyBecauseOfUltraSavingMode(intent, targetApp, targetUid, callerApp, callerUid, reason)) {
        //    return false;
        //}

        int targetUserId = UserHandle.getUserId(targetUid);
        int callUserId = UserHandle.getUserId(callerUid);
        AppState callerAppState = mAppStateInfoCollector.getAppState(callerApp, callUserId);
        AppState targetAppState = mAppStateInfoCollector.getAppState(targetApp, targetUserId);

        // if target app already exist
        /*if (targetAppState != null
            && targetAppState.mProcState < ActivityManager.PROCESS_STATE_CACHED_EMPTY
            && targetAppState.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT) {*/
        if (isAlreadyStarted(targetAppState)) {
            if (DEBUG_MORE) Slog.d(TAG,"Start Proc : "+targetApp+", callingPackage = "+callerApp+", reason = "+reason + ": already started!!"
                + " (ProcState:" +  Util.ProcState2Str(targetAppState.mProcState)
                + " mState:" + Util.AppState2Str(targetAppState.mState)
                + ")");
            return true;
        }

        // check system app
        // allow to launch system app
        int launchState = checkLaunchStateByPreset(intent, targetApp, targetUid, callerApp, callerUid, reason);
        if (launchState == LAUNCH_STATE_ALLOW)
            return true;
        else if (launchState == LAUNCH_STATE_DENY)
            return false;

        // check user setting for third-party app(重点)
        launchState = checkLaunchStateByUserSetting(intent, targetApp, targetUid, callerApp, callerUid, reason);
        if (DEBUG_MORE) Slog.d(TAG, "launchState: " + launchState);
        if (launchState == LAUNCH_STATE_ALLOW)
            return true;
        else if (launchState == LAUNCH_STATE_DENY)
            return false;

        // not allow third party app that has been force stopped during standby
        // to be started again
        if (mStandbyStartTime > 0 && isForceStoppedAppDuringStandby(targetApp, targetUid)) {
            if (DEBUG) Slog.d(TAG,"Start Proc : "+targetApp+", callingPackage = "+callerApp+", reason = "+reason + ": denyed (has been force stopped)!!");
            return false;
        }

        // not allow system broadcast to launch third party app
        if ((callerAppState == null ||(callerApp != null && callerApp.equals("android")))
            && REASON_BROADCAST.equals(reason)) {
            if (DEBUG) Slog.d(TAG,"Start Proc : "+targetApp+", callingPackage = "+callerApp+", reason = "+reason + ": denyed!!");
            return false;
        }

        // not allow "com.android.systemui" broadcast to launch third party app
        if (callerApp != null && callerApp.equals("com.android.systemui")
            && REASON_BROADCAST.equals(reason)) {
            if (DEBUG) Slog.d(TAG,"Start Proc : "+targetApp+", callingPackage = "+callerApp+", reason = "+reason + ": denyed!!");
            return false;
        }

        // allow app to launch itself
        if (targetApp.equals(callerApp)) {
            return true;
        }

        // not allow non-top app to launch other app, except launched by UserActivity
        if (!launchedByUserActivity(intent, targetApp, targetUid, callerApp, callerUid, reason, true)) {
            if (DEBUG) {
                Slog.d(TAG,"Start Proc : "+targetApp
                    +", callingPackage = "+callerApp
                    + " (ProcState:" + (callerAppState != null ? Util.ProcState2Str(callerAppState.mProcState):"none")
                    +"), reason = "+reason
                    + ": non-UserActivity denyed!!");
            }
            return false;
        }

        // not allow background app to launch other third party app
        if (callerAppState != null && callerAppState.mProcState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
            && !REASON_START_ACTIVITY.equals(reason)) {
            if (DEBUG) {
                Slog.d(TAG,"Start Proc : "+targetApp
                    +", callingPackage = "+callerApp
                    + " (ProcState:" + (callerAppState != null ? Util.ProcState2Str(callerAppState.mProcState):"none")
                    +"), reason = "+reason
                    + ": denyed!!");
            }
            return false;
        }

        // not allow self started third party app to start other third party app
        if (callerAppState != null && callerAppState.mLaunchCount == 0 && !isSystemApp(callerAppState)
            && !REASON_START_ACTIVITY.equals(reason)) {
            if (DEBUG) Slog.d(TAG,"Start Proc : "+targetApp+", callingPackage = "+callerApp+", reason = "+reason + ": denyed!!");
            return false;
        }

        // not allow long idle third party app to start other third party app
        if (callerAppState != null && !isSystemApp(callerAppState)
            && callerAppState.mState != Event.MOVE_TO_FOREGROUND
            && callerAppState.mProcState != ActivityManager.PROCESS_STATE_TOP
            && !REASON_START_ACTIVITY.equals(reason)) {

            long nowELAPSED = SystemClock.elapsedRealtime();
            long idleDuration = 0;
            idleDuration = (callerAppState.mLastTimeUsed > 0 ? (nowELAPSED -callerAppState.mLastTimeUsed) : -1);
            if (idleDuration > DENY_START_APP_THRESHOLD) {
                if (DEBUG) Slog.d(TAG,"Start Proc : "+targetApp+", callingPackage = "+callerApp+", reason = "+reason + ": denyed!! long idle");
                return false;
            }
        }


        // not allow third party app to start other third party app during standby
        if (mStandbyStartTime > 0
            && !REASON_START_ACTIVITY.equals(reason)) {
            if (DEBUG) {
                Slog.d(TAG,"Start Proc : "+targetApp
                    +", callingPackage = "+callerApp
                    + " (ProcState:" + (callerAppState != null ? Util.ProcState2Str(callerAppState.mProcState):"none")
                    +"), reason = "+reason
                    + ": denyed during standby!!");
            }
            return false;
        }


        return true;

    }

BackgroundCleanHelper.java-->checkLaunchStateByUserSetting()

private int checkLaunchStateByUserSetting(Intent intent, String targetApp, int targetUid,
            String callerApp, int callerUid, String reason) {

        if (targetApp == null || targetApp.equals(callerApp))
            return LAUNCH_STATE_AUTO;

        boolean launchByOther = autoLaunchByOtherApp(targetApp, targetUid, callerApp, callerUid, reason);

        // allow app in whitelist
        if (inSelfStartWhiteAppList(targetApp)) {
            return LAUNCH_STATE_ALLOW;
        }

        // if in ultrasaving mode, don't allow autostart except apps in ultrasve applist
        if (!launchByOther && (PowerManagerEx.MODE_ULTRASAVING == mPowerSaveMode)
            && (PowerManagerEx.MODE_ULTRASAVING == mNextPowerSaveMode)) {
            List<String> appList = mPowerControllerInternal.getAppList_UltraMode();
            if (!appList.contains(targetApp)) {
                if (DEBUG) Slog.d(TAG, "app: " + targetApp + " in applist of ultramode, refuse to autostart, denyed");
                return LAUNCH_STATE_DENY;
            }
        }

        int autoLaunch = mPowerControllerInternal.getAppPowerSaveConfgWithTypeInternal(targetApp,AppPowerSaveConfig.ConfigType.TYPE_AUTOLAUNCH.value);
        int secondLaunch = mPowerControllerInternal.getAppPowerSaveConfgWithTypeInternal(targetApp,AppPowerSaveConfig.ConfigType.TYPE_SECONDARYLAUNCH.value);
        if (((autoLaunch == AppPowerSaveConfig.VALUE_NO_OPTIMIZE) && !launchByOther)
            || ((secondLaunch == AppPowerSaveConfig.VALUE_NO_OPTIMIZE) && launchByOther)) {
            if (DEBUG) Slog.d(TAG, "bgclean judgeAppLaunchAllowed: "+targetApp
                + ", callingPackage = "+callerApp+", reason = "+reason +" in my whitelist");
            return LAUNCH_STATE_ALLOW;
        }

        //check whether app is in black list
        boolean bInBlackList = false;
        if ((autoLaunch == AppPowerSaveConfig.VALUE_OPTIMIZE) && !launchByOther) {
            if (DEBUG_MORE) Slog.d(TAG, "in apppowerconfig autolaunch black list: " + targetApp);
            bInBlackList = true;
        }
        if ((secondLaunch == AppPowerSaveConfig.VALUE_OPTIMIZE) && launchByOther) {
            if (DEBUG_MORE) Slog.d(TAG, "in apppowerconfig 2ndlaunch black list: " + targetApp);
            bInBlackList = true;
        }

        // check whether blacklist app is in exception
        if (bInBlackList) {
            // not allow auto start app that in auto start black list
            // 1. in mAutoLaunch_BlackList AND is not launched by other app (that is launched by system broadcast etc)
            // 2. NOTE: Exception:
            //     1) Start reason is REASON_START_ACTIVITY  (this is alway happened in case of
            //         app use another app to do something, including launcher to launch a app)
            //     2) Self start self ( that is this app is alreadby started, and is start some activity internal)
            if (!launchByOther && !REASON_START_ACTIVITY.equals(reason)) {
                if (DEBUG) Slog.d(TAG, "in autolaunch black list: "+targetApp
                    + ", callingPackage = "+callerApp+", reason = "+reason +" denyed!");
                return LAUNCH_STATE_DENY;
            }
            // not allow auto start by other app that in secondary start black list
            // 1. in m2ndLaunch_BlackList AND is launched by other app
            // 2. NOTE: Exception:
            //     1) when callerApp is top AND Start reason is REASON_START_ACTIVITY  (this is alway happened in case of
            //         app use another app to do something, including launcher to launch a app)
            //     2) Self start self ( that is this app is alreadby started, and is start some activity internal)
            //     3) when callerApp is top AND targetApp is in AssociateLaunchExceptionAppList
            if (launchByOther && !launchedByUserActivity(intent, targetApp, targetUid, callerApp, callerUid, reason, true)) {
                if (DEBUG) Slog.d(TAG, "in 2ndlaunch black list: "+targetApp
                    + ", callingPackage = "+callerApp+", reason = "+ reason + " intent:" + intent + " denyed!");
                return LAUNCH_STATE_DENY;
            }

            // Although it is black list, but it start by user, so allowed to start
            return LAUNCH_STATE_ALLOW;
        }
        return LAUNCH_STATE_AUTO;
    }

BackgroundCleanHelper.java-->checkLaunchStateByUserSetting()

这个方法就是根据用户的设置,来判断是否拦截自启

private int checkLaunchStateByUserSetting(Intent intent, String targetApp, int targetUid,
            String callerApp, int callerUid, String reason) {

        if (targetApp == null || targetApp.equals(callerApp))
            return LAUNCH_STATE_AUTO;

        boolean launchByOther = autoLaunchByOtherApp(targetApp, targetUid, callerApp, callerUid, reason);

        // allow app in whitelist
        if (inSelfStartWhiteAppList(targetApp)) {
            return LAUNCH_STATE_ALLOW;
        }

        // if in ultrasaving mode, don't allow autostart except apps in ultrasve applist
        if (!launchByOther && (PowerManagerEx.MODE_ULTRASAVING == mPowerSaveMode)
            && (PowerManagerEx.MODE_ULTRASAVING == mNextPowerSaveMode)) {
            List<String> appList = mPowerControllerInternal.getAppList_UltraMode();
            if (!appList.contains(targetApp)) {
                if (DEBUG) Slog.d(TAG, "app: " + targetApp + " in applist of ultramode, refuse to autostart, denyed");
                return LAUNCH_STATE_DENY;
            }
        }

        int autoLaunch = mPowerControllerInternal.getAppPowerSaveConfgWithTypeInternal(targetApp,AppPowerSaveConfig.ConfigType.TYPE_AUTOLAUNCH.value);
        int secondLaunch = mPowerControllerInternal.getAppPowerSaveConfgWithTypeInternal(targetApp,AppPowerSaveConfig.ConfigType.TYPE_SECONDARYLAUNCH.value);
        if (((autoLaunch == AppPowerSaveConfig.VALUE_NO_OPTIMIZE) && !launchByOther)
            || ((secondLaunch == AppPowerSaveConfig.VALUE_NO_OPTIMIZE) && launchByOther)) {
            if (DEBUG) Slog.d(TAG, "bgclean judgeAppLaunchAllowed: "+targetApp
                + ", callingPackage = "+callerApp+", reason = "+reason +" in my whitelist");
            return LAUNCH_STATE_ALLOW;
        }

        //check whether app is in black list
        boolean bInBlackList = false;
        if ((autoLaunch == AppPowerSaveConfig.VALUE_OPTIMIZE) && !launchByOther) {
            if (DEBUG_MORE) Slog.d(TAG, "in apppowerconfig autolaunch black list: " + targetApp);
            bInBlackList = true;
        }
        if ((secondLaunch == AppPowerSaveConfig.VALUE_OPTIMIZE) && launchByOther) {
            if (DEBUG_MORE) Slog.d(TAG, "in apppowerconfig 2ndlaunch black list: " + targetApp);
            bInBlackList = true;
        }

        // check whether blacklist app is in exception
        if (bInBlackList) {
            // not allow auto start app that in auto start black list
            // 1. in mAutoLaunch_BlackList AND is not launched by other app (that is launched by system broadcast etc)
            // 2. NOTE: Exception:
            //     1) Start reason is REASON_START_ACTIVITY  (this is alway happened in case of
            //         app use another app to do something, including launcher to launch a app)
            //     2) Self start self ( that is this app is alreadby started, and is start some activity internal)
            if (!launchByOther && !REASON_START_ACTIVITY.equals(reason)) {
                if (DEBUG) Slog.d(TAG, "in autolaunch black list: "+targetApp
                    + ", callingPackage = "+callerApp+", reason = "+reason +" denyed!");
                return LAUNCH_STATE_DENY;
            }
            // not allow auto start by other app that in secondary start black list
            // 1. in m2ndLaunch_BlackList AND is launched by other app
            // 2. NOTE: Exception:
            //     1) when callerApp is top AND Start reason is REASON_START_ACTIVITY  (this is alway happened in case of
            //         app use another app to do something, including launcher to launch a app)
            //     2) Self start self ( that is this app is alreadby started, and is start some activity internal)
            //     3) when callerApp is top AND targetApp is in AssociateLaunchExceptionAppList
            if (launchByOther && !launchedByUserActivity(intent, targetApp, targetUid, callerApp, callerUid, reason, true)) {
                if (DEBUG) Slog.d(TAG, "in 2ndlaunch black list: "+targetApp
                    + ", callingPackage = "+callerApp+", reason = "+ reason + " intent:" + intent + " denyed!");
                return LAUNCH_STATE_DENY;
            }

            // Although it is black list, but it start by user, so allowed to start
            return LAUNCH_STATE_ALLOW;
        }
        return LAUNCH_STATE_AUTO;
    }

继续逐个分析涉及到的主要方法

BackgroundCleanHelper.java-->checkLaunchStateByUserSetting()-->autoLaunchByOtherApp()

    // return true, if app is start by system broadcast
    private boolean autoLaunchByOtherApp(String targetApp, int targetUid,
                String callerApp, int callerUid, String reason) {
        if (callerApp == null
            ||callerApp.equals("android")
            || callerApp.equals("com.android.systemui"))
            return false;

        AppState callerAppState = mAppStateInfoCollector.getAppState(callerApp, UserHandle.getUserId(callerUid));
        if (callerAppState != null && callerAppState.mUid < Process.FIRST_APPLICATION_UID)
            return false;

        return true;
    }

BackgroundCleanHelper.java-->checkLaunchStateByUserSetting()-->launchedByUserActivity()

 private boolean launchedByUserActivity(Intent intent, String targetApp, int targetUid,
            String callerApp, int callerUid, String reason, boolean ignoreTouchTime) {
        boolean userLaunched = false;

        long now = SystemClock.elapsedRealtime();
        long lastTouchTime = 0;
        AppState callerAppState = mAppStateInfoCollector.getAppState(callerApp, UserHandle.getUserId(callerUid));
        if (mPowerControllerInternal != null) {
            lastTouchTime = mPowerControllerInternal.getLastTouchEventTimeStamp();
        }

        boolean isCallerTopApp  =  false;
        if (callerAppState != null
            &&((callerAppState.mProcState == ActivityManager.PROCESS_STATE_TOP)
                || (callerAppState.mProcState == ActivityManager.PROCESS_STATE_HOME)
                || (callerAppState.mState == Event.MOVE_TO_FOREGROUND)
                || (now - callerAppState.mLastTimeUsed) < 1000
                || isLauncherApp(callerApp)) // for Bug#712736
        ) {

            isCallerTopApp = true;
        }

        // check the associated-starting because of third party push service
        if (isCallerTopApp &&
            REASON_START_ACTIVITY.equals(reason)
            && !isLauncherAction(intent)
            && intent != null
            && ThirdpartyPush.isAssociatedComponent(intent.getComponent())) {
            if (DEBUG) Slog.d(TAG,"launchedByUserActivity : Start Proc : "+targetApp
                +", callingPackage = "+callerApp
                + " (ProcState:" + (callerAppState != null ? Util.ProcState2Str(callerAppState.mProcState):"none")
                +"), reason = "+reason
                + " Associated-Starting ThirdParty Push Service");
            isCallerTopApp = false;
        }

        // see the caller of a launcher action as top app
        // add for bug#776461
        if (!isCallerTopApp && intent != null && isLauncherAction(intent)) {
            isCallerTopApp = true;
        }

        if (DEBUG_MORE) {
            Slog.d(TAG,"launchedByUserActivity : Start Proc : "+targetApp
                +", callingPackage = "+callerApp
                + " (ProcState:" + (callerAppState != null ? Util.ProcState2Str(callerAppState.mProcState):"none")
                +"), reason = "+reason);
        }

        long lastTouchElasedTime = now - lastTouchTime;
        if (DEBUG) Slog.d(TAG, "lastTouchElasedTime: "+lastTouchElasedTime);

        if (isCallerTopApp
            && (REASON_START_ACTIVITY.equals(reason)
                    || (!ignoreTouchTime && lastTouchElasedTime <= (1*1000)))
            ) {
            userLaunched = true;
        }

        // check if this call from "android"
        if (!isCallerTopApp && REASON_START_ACTIVITY.equals(reason) && lastTouchElasedTime <= (1*1000)) {
            AppState androidState = mAppStateInfoCollector.getAppState("android", UserHandle.USER_SYSTEM);
            if (androidState != null
                && (androidState.mState == Event.MOVE_TO_FOREGROUND)
                    || (now - androidState.mLastTimeUsed) < 1000) {
                userLaunched = true;
            }
        }

        // Bug#707888 setting monkey fail --> BEG
        // for callerApp is system app, and use "start-activity", then allow
        if ((callerAppState == null || callerAppState.mUid < Process.FIRST_APPLICATION_UID)
            && REASON_START_ACTIVITY.equals(reason)) {
            userLaunched = true;
        }
        // Bug#707888 setting monkey fail <-- END

        return userLaunched;
    }

BackgroundCleanHelper.java-->checkLaunchStateByUserSetting()-->launchedByUserActivity()-->isLauncherApp()

    private boolean isLauncherApp(String pkgName) {
        int index = mLauncherAppList.indexOf(pkgName);
        if (index >= 0) {
            return true;
        }
        return false;
    }

isLauncherApp主要是通过是否有CATEGORY_HOME属性判断的


    private void loadLauncherApps() {
        try {

            Intent intent = new Intent(Intent.ACTION_MAIN);
            intent.addCategory(Intent.CATEGORY_HOME);

            final List<UserInfo> users = mUserManager.getUsers();
            for (int ui = users.size() - 1; ui >= 0; ui--) {
                UserInfo user = users.get(ui);
                if (DEBUG) Slog.d(TAG, "- loadLauncherApps() for user: " + user.id);
                List<ResolveInfo> resolves =
                    mContext.getPackageManager().queryIntentActivitiesAsUser(intent, PackageManager.MATCH_DISABLED_COMPONENTS, user.id);

                // Look for the original activity in the list...
                final int N = resolves != null ? resolves.size() : 0;
                for (int i=0; i<N; i++) {
                    final ResolveInfo candidate = resolves.get(i);
                    final ActivityInfo info = candidate.activityInfo;
                    if (info != null && info.packageName != null
                        && !mLauncherAppList.contains(info.packageName)) {
        ......
            /*check if contains the default launcher*/
            for(String s : mDefaultLauncherAppList) {
                if(!mLauncherAppList.contains(s)) {
                    mLauncherAppList.add(s);
                }
            }
        ......
                        
}
    // default launcher app list
    private String[] mDefaultLauncherAppList = new String[] {
        "com.android.launcher3",
        "com.android.settings"
    };

这一篇就分析到这里!

猜你喜欢

转载自blog.csdn.net/liu362732346/article/details/85250285