8 展讯Sprd设置-电池-关联自启动-judgeAppLaunchAllowedInternal 函数

本文主要是介绍8 展讯Sprd设置-电池-关联自启动-judgeAppLaunchAllowedInternal 函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 关联唤醒机制

关联唤醒中的原理在于在应用启动的各种通道中进行拦截

  1. 在ActivityStarter 进行 start-activity 监听,judgeAppLaunchAllowedInternal 判断是否拦截
  2. 在ActivityManagerService 进行 contentprovider 监听,judgeAppLaunchAllowedInternal 判断是否拦截
  3. 在BroadcastQueue 进行 send-broadcast,judgeAppLaunchAllowedInternal 判断是否拦截
  4. 在ActiveServices 进行 start-service 和 bind-service监听,judgeAppLaunchAllowedInternal 判断是否拦截

2. judgeAppLaunchAllowedInternal 函数

  • vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/BackgroundCleanHelper.java

该函数主要进行是否拦截的判断,这里的判断条件主要根据activty\contentprovid\broadcast\servie\UID范围\进程状态\设置界面的黑白名单\用户是否触摸事件\特殊场景(输入法、壁纸服务、小部件、语音输入、CTS场景等)\用户主动点击行为,等等多个维度进行条件判断,决定是否运行进程启动。

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 trueif (!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;// 是否允许 start-service 类型启动if (handleStartServiceStartAction(intent, targetApp, targetUid, callerApp, callerUid, reason)) {return true;}// 是否允许 bind-service 类型启动if (handleBindServiceStartAction(intent, targetApp, targetUid, callerApp, callerUid, reason)) {return true;}// 是否允许contentprovider 类型启动if (handleContentProviderStartAction(intent, targetApp, targetUid, callerApp, callerUid, reason)) {return true;}// 是否允许输入法类型启动if (isLaunchingIMEApp(intent, targetApp, targetUid, callerApp, reason)) {return true;}// 是否允许 send-broadcast 类型启动if (handleBroadcastAction(intent, targetApp, targetUid, callerApp, callerUid, reason)) {return true;}// 是否允许语音识别//handle speech recognitionif (isRecognizerIntent(intent, targetApp, targetUid, callerApp, callerUid, reason)) {return true;}// 是否允许 CTS 或者adb shell 测试运行// allow cts app to start any other app// allow autotest appif (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;//}// 获取target进程 UIDint targetUserId = UserHandle.getUserId(targetUid);// 获取callUser进程的 UIDint callUserId = UserHandle.getUserId(callerUid);// 获取 caller 进程信息AppState callerAppState = mAppStateInfoCollector.getAppState(callerApp, callUserId);// 获取 target 进程信息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 appint 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设置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 againif (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 appif ((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;}// 禁止"system ui"广播启动第三方应用// not allow "com.android.systemui" broadcast to launch third party appif (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// 允许进程本身启动自有activity,但不允许启动其他应用// 条件 非用户主动点击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// 不允许后台应用关联唤醒其他应用// 1. caller 不用空// 2. caller 状态为非前台进程,mProcState 数值越大进程重要度越低// 3. 启动类型不为 start-acitivtyif (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// 1. caller 状态不为空// 2. caller 启动次数为0// 3. 非系统应用// 4. 启动类型非start-activityif (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// 1. caller 状态不为空// 2. caller 非第三应用// 3. caller 不为前台进程属性// 4. 启动类型非start-activityif (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;// 待机场景持续时长 = 当前流逝时刻 - caller 最近一次运行时长idleDuration = (callerAppState.mLastTimeUsed > 0 ? (nowELAPSED -callerAppState.mLastTimeUsed) : -1);// 第三方应用在后台运行超过 DENY_START_APP_THRESHOLD,则不允许第三方进程// 即不允许长时间运行的后台应用唤醒其他应用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 standbyif (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;}

2.1 handleStartServiceStartAction

是否允许 start-service 类型启动

是否允许 start-service 类型启动

    private static final String REASON_START_SERVICE = "start-service";// 是否允许 start-service 类型启动// return true: for should be allow to be started//   false: for othersprivate boolean handleStartServiceStartAction(Intent intent, String targetApp, int targetUid,String callerApp, int callerUid, String reason) {// 是否为 start-service 类型启动if (!REASON_START_SERVICE.equals(reason)) return false;// 是否在安装列表中if (mInstalledServiceList.contains(targetApp)// 是否可以被其他应用启动&& autoLaunchByOtherApp(targetApp, targetUid, callerApp, callerUid, reason)) {if (DEBUG) Slog.d(TAG, "start installed service :" + targetApp + " from " + callerApp);return true;}return false;}
2.1.0 是否可被关联启动 autoLaunchByOtherApp

判断这是系统启动还是被第三方应用关联启动,主要通过UID进行判断

是否为关联启动.jpg

    // 判断这是系统启动还是被第三方应用关联启动,主要通过UID进行判断// return true, if app is start by system broadcastprivate boolean autoLaunchByOtherApp(String targetApp, int targetUid,String callerApp, int callerUid, String reason) {// 启动发起方是否为null或android或systemui,如果是该条件,则绝对是系统进行唤醒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;}

2.2 handleBindServiceStartAction

是否允许 bind-service 务类型启动

是否允许 bind-service 类型启动

    private static final String REASON_BIND_SERVICE = "bind-service";// return true: for should be allow to be started//   false: for othersprivate boolean handleBindServiceStartAction(Intent intent, String targetApp, int targetUid,String callerApp, int callerUid, String reason) {// 是否为 bind-service 类型启动if (!REASON_BIND_SERVICE.equals(reason)) return false;// 是否为壁纸服务// check start wallpaper serviceif (intent != null && WallpaperService.SERVICE_INTERFACE.equals(intent.getAction())) {// save the defalut wallpaper serviceif ("android".equals(callerApp))  mDefaultWallpaperService = targetApp;if (DEBUG) Slog.d(TAG, "start wallpaper service, allowed");return true;}// 是否为可用模拟辅助服务if ("android".equals(callerApp)&& intent != null && mSystemPreferredConfig.isEnabledAccessibilityService(intent.getComponent())) {if (DEBUG) Slog.d(TAG, "start enabled accessibility service" + intent.getComponent());return true;}// 是否为安装完成的模拟辅助服务// check start accessibility serviceif ("android".equals(callerApp)&& intent != null && mSystemPreferredConfig.isInstalledAccessibilityService(intent.getComponent())&& isUserTouchActive()) {if (DEBUG) Slog.d(TAG, "start installed accessibility service" + intent.getComponent());return true;}// 是否为语音服务// check start voice synthesize serviceif (intent != null && mSystemPreferredConfig.isTTSAction(intent.getAction())&& isUserTouchActive()) {if (DEBUG) Slog.d(TAG, "start voice synthesize service" + intent.getAction());return true;}// 是否为打印服务// check start print serviceif ("android".equals(callerApp)&& intent != null && mSystemPreferredConfig.isInstalledPrintService(intent.getComponent())&& isUserTouchActive()) {if (DEBUG) Slog.d(TAG, "start installed print service" + intent.getComponent());return true;}// for sinaif ( intent != null  && "com.sina.weibo.remotessoservice".equals(intent.getAction())&& "com.sina.weibo".equals(targetApp)) {if (DEBUG) Slog.d(TAG, "allow Start:using sina to login:" +callerApp);return true;}// 是否为通讯服务// check start default phone serviceif (intent != null && "android.telecom.InCallService".equals(intent.getAction())) {if (DEBUG) Slog.d(TAG, "start default phone app:" + targetApp);return true;}// 是否为没有启动入口的程序且为关联唤醒if (mInstalledServiceList.contains(targetApp)&& autoLaunchByOtherApp(targetApp, targetUid, callerApp, callerUid, reason)) {if (DEBUG) Slog.d(TAG, "bind installed service :" + targetApp + " from " + callerApp);return true;}// 是否为用户账户服务且用户当前正在触摸屏幕if ("android".equals(callerApp)&& intent != null  && ACTION_AUTHENTICATOR_INTENT.equals(intent.getAction())&& isUserTouchActive()) {if (DEBUG) Slog.d(TAG, "bind Account service :" + targetApp + " from " + callerApp);return true;}return false;}// 非常有创新的接口,用户当前是否有触摸屏幕操作private boolean isUserTouchActive() {long now = SystemClock.elapsedRealtime();long lastTouchTime = 0;if (mPowerControllerInternal != null)lastTouchTime = mPowerControllerInternal.getLastTouchEventTimeStamp();return ((now - lastTouchTime) <= 1000);}

2.3 handleContentProviderStartAction

是否为 contentprovider 类型启动

是否允许 contentprovider 类型启动

    private static final String REASON_CONTENT_PROVIDER = "contentprovider";// return true: for should be allow to be started//   false: for othersprivate boolean handleContentProviderStartAction(Intent intent, String targetApp, int targetUid,String callerApp, int callerUid, String reason) {// 是否为 contentprovider 类型启动if (!REASON_CONTENT_PROVIDER.equals(reason)) return false;int targetAppType = mPowerControllerInternal.getAppCategoryType(targetApp);;AppState callerAppState = mAppStateInfoCollector.getAppState(callerApp, UserHandle.getUserId(callerUid));// 唤醒者是否为前台进程boolean isCallerTopApp  =  false;if (callerAppState != null&&((callerAppState.mProcState == ActivityManager.PROCESS_STATE_TOP)|| (callerAppState.mState == Event.MOVE_TO_FOREGROUND))) {isCallerTopApp = true;}// 唤醒者是否为前台进程且是否用户正在点击且是否为白名单或未知类型if (isCallerTopApp && isUserTouchActive()&& (inAssociateLaunchExceptionAppList(targetApp) || PowerDataBaseControl.UNKNOWN == targetAppType)) {if (DEBUG) Slog.d(TAG,"allow Start: "+targetApp+", callingPackage = "+callerApp+ " reason = "+reason);return true;}return false;}

2.4 是否为输入法进程 isLaunchingIMEApp

    private boolean isLaunchingIMEApp(Intent intent, String targetApp, int targetUid,String callerApp, String reason) {//handle inputmethod// 是否为系统调用且为bind-service类型且为InputMethod的信号if ("android".equals(callerApp)&& REASON_BIND_SERVICE.equals(reason)&& intent != null && "android.view.InputMethod".equals(intent.getAction())) {if (targetApp != null) { // a input method// 获取当前正在使用的输入法int index = mEnabledInputMethodAppList.indexOf(targetApp);// 若当前为正在使用输入法,则添加本输入法if (index < 0) {mEnabledInputMethodAppList.add(targetApp);int userId = UserHandle.getUserId(targetUid);mAppStateInfoCollector.updateAppInputMethodState(targetApp, true, userId);mAppStateInfoCollector.setDefaultInputMethodApp(targetApp, userId);}}return true;}// allow to start input Method// 是否为系统调用且为bind-service类型且为当前使用输入法if (REASON_BIND_SERVICE.equals(reason) && "android".equals(callerApp) && isInputMethodApp(targetApp)) {if (DEBUG) Slog.d(TAG, "isLaunchingIMEApp: "+targetApp+ ", callingPackage = "+callerApp+", reason = "+reason +" allow for input method");return true;}return false;}// input method appprivate boolean isInputMethodApp(String pkgName) {int index = mEnabledInputMethodAppList.indexOf(pkgName);if (index >= 0) {return true;}return false;}

2.5 是否允许 send-broadcast 类型启动-handleBroadcastAction

是否允许 send-broadcast 类型启动

private static final String REASON_BROADCAST = "send-broadcast";// 是否允许 send-broadcast 类型启动if (handleBroadcastAction(intent, targetApp, targetUid, callerApp, callerUid, reason)) {return true;}private boolean handleBroadcastAction(Intent intent, String targetApp, int targetUid,String callerApp, int callerUid, String reason) {// 是否为send-broadcast类型校验if (!REASON_BROADCAST.equals(reason) || intent == null) return false;// 是否为系统调用且当前是桌面小部件广播if (intent != null&& "android".equals(callerApp)) {String action = intent.getAction();if (action != null && action.startsWith("android.appwidget.action.")) //AppWidget actionreturn true;}// 是否系统调用且为电话广播// check out call for phone appif ("android".equals(callerApp)&& intent != null && Intent.ACTION_NEW_OUTGOING_CALL.equals(intent.getAction())&& mSystemPreferredConfig.isDefaultPhoneApp(targetApp)) {if (DEBUG) Slog.d(TAG, "start phone app for out call:" + targetApp);return true;}// 是否为短信广播if (SMS_DELIVER_ACTION.equals(intent.getAction())) {if (DEBUG) Slog.d(TAG, "start default sms app:" + targetApp);return true;}// 是否为GMS推送服务广播// receive GMS C2DM message for bug#787547if ("com.google.android.gms".equals(callerApp)&& "com.google.android.c2dm.intent.RECEIVE".equals(intent.getAction())) {if (DEBUG) Slog.d(TAG, "start app:" + targetApp + " for receiving message");return true;}return false;}

2.6 是否允许语音识别 isRecognizerIntent

    private boolean isRecognizerIntent(Intent intent, String targetApp, int targetUid,String callerApp, int callerUid, String reason) {AppState callerAppState = mAppStateInfoCollector.getAppState(callerApp, UserHandle.getUserId(callerUid));if (isSystemApp(callerAppState)&& REASON_START_ACTIVITY.equals(reason)&& intent != null && RecognizerIntent.ACTION_WEB_SEARCH.equals(intent.getAction())) {return true;}return false;}

2.7 是否允许 CTS 或者adb shell 测试运行

vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/Util.javapublic static boolean isCts(String pkgName) {if (pkgName == null) return false;/*check if in internal white app list, like CTS app*/for(String s : mCtsWhiteAppList) {if(pkgName.contains(s)) {return true;}}// is cts appif ((pkgName.startsWith("android.") && pkgName.contains(".cts."))|| (pkgName.startsWith("android.") && pkgName.endsWith(".cts"))|| (pkgName.startsWith("com.android.") && pkgName.contains(".cts."))|| (pkgName.startsWith("com.android.") && pkgName.endsWith(".cts"))) {return true;}// is gts appif ((pkgName.startsWith("com.google.") && pkgName.contains(".gts."))|| (pkgName.startsWith("com.google.") && pkgName.endsWith(".gts"))|| (pkgName.startsWith("com.android.") && pkgName.contains(".gts."))|| (pkgName.startsWith("com.android.") && pkgName.endsWith(".gts"))|| (pkgName.startsWith("com.android.compatibility.") )) {return true;}return false;}private boolean isAutoTest(int callerUid, String callerApp, String targetApp) {if (callerUid == Process.SHELL_UID) {if (DEBUG) Slog.d(TAG, "calling from shell, see as doing auto test: " + targetApp);return true;}return false;}

2.8 判断进程是否已经启动

    private boolean isAlreadyStarted(AppState appState) {// if target app already existif ((appState != null&& appState.mProcState < ActivityManager.PROCESS_STATE_CACHED_EMPTY // 不为 cache 或者 空进程&& appState.mProcState != ActivityManager.PROCESS_STATE_NONEXISTENT) // 不为不存在状态|| (appState != null&& appState.mProcState == ActivityManager.PROCESS_STATE_CACHED_EMPTY // cache 或者 空进程&& Event.NONE != appState.mState)) { // 不为空return true;}return false;}

2.9 标记当前启动状态

标记当前启动状态

    private static final int LAUNCH_STATE_AUTO = 0;private static final int LAUNCH_STATE_ALLOW = 1;private static final int LAUNCH_STATE_DENY = 2;/*** Check the preset, including:* (1) system app should be allow to be self started* (2) system app that is the launcher black app list should not be self started*/private int  checkLaunchStateByPreset(Intent intent, String targetApp, int targetUid,String callerApp, int callerUid, String reason) {// 获取应用安装列表ArrayMap<String, PackageInfo> mInstalledAppList = getInstalledAppList(UserHandle.getUserId(targetUid));PackageInfo targetPkg = mInstalledAppList.get(targetApp);// if not a system app, just return STATE_AUTO// 若不为系统应用,则启动状态设为LAUNCH_STATE_AUTO// targetPkg不为空 表示包含在第三方安装列表中if (targetPkg != null) {return LAUNCH_STATE_AUTO;}// 启动黑名单且不是用户主动点击if (mPowerConfig != null && mPowerConfig.inLaunchBlackList(targetApp)&& !launchedByUserActivity(intent, targetApp, targetUid, callerApp, callerUid, reason, true)) {if (DEBUG) Slog.d(TAG, "in PowerConfig launch black list: " + targetApp + " denyed!!");return LAUNCH_STATE_DENY;}return LAUNCH_STATE_ALLOW;}// 应用安装列表private ArrayMap<String, PackageInfo> getInstalledAppList(int userId) {ArrayMap<String, PackageInfo> mInstalledAppList = mInstalledAppListForUsers.get(userId);if (mInstalledAppList == null) {mInstalledAppList = new ArrayMap<>();mInstalledAppListForUsers.put(userId, mInstalledAppList);}return mInstalledAppList;}// 启动黑名单// /system/etc/pwctl_config.xmlpublic boolean inLaunchBlackList(String pkgName) {int index = mConstants.mLaunchBlacklist.indexOf(pkgName);if (index >= 0) {return true;}return false;}
  • /system/etc/pwctl_config.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<config>
<item name="LaunchBlackList"><packageName>com.pp.assistant</packageName>
</item>
</config>
2.9.1 是否为用户界面启动-launchedByUserActivity

是否为用户界面启动-launchedByUserActivity

    private static final String REASON_START_ACTIVITY = "start-activity";// check if this a launched operation by user// INPUT: ignoreTouchTime if true, then don't see TouchElasedTime <= (1*1000) as a userActivity//            else see TouchElasedTime <= (1*1000) as a userActivity for Top App// NOTE: this cannot decide exactly// 本函数的逻辑确实容易疏漏,尤其是最后一个判断,觉得有点毁掉前面的苛刻的条件 - this cannot decide exactlyprivate 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) {// 获取最近一次touch事件时间lastTouchTime = mPowerControllerInternal.getLastTouchEventTimeStamp();}boolean isCallerTopApp  =  false;// 重要进程定义:属性为前台进程或者为launch桌面进程或者正在切换为前台进程或当前发生了touch事件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// 检查是否有进程push黑名单组件// 1. 检查进程为重要进程// 2. 且启动类型是为 start-activity// 3. 且进程不是top进程// 4. 且进程含有push黑名单组件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// 是否为非重要进程且为top进程// add for bug#776461if (!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);// 启动类型为 start-activityq且当前正在touch事件if (isCallerTopApp&& (REASON_START_ACTIVITY.equals(reason)|| (!ignoreTouchTime && lastTouchElasedTime <= (1*1000)))) {// 判定用户主动点击事件userLaunched = true;}// check if this call from "android"// 检查调用者是否为android// 1. isCallerTopApp false// 2. 且启动类型是为 start-activity// 3. 当前存在touch事件// 4. 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 allowif ((callerAppState == null || callerAppState.mUid < Process.FIRST_APPLICATION_UID)&& REASON_START_ACTIVITY.equals(reason)) {userLaunched = true;}// Bug#707888 setting monkey fail <-- ENDreturn userLaunched;}// 检测当前的action是不是启动界面程序,很好的方法private boolean isLauncherAction(Intent intent) {if (intent == null) return false;if (Intent.ACTION_MAIN.equals(intent.getAction())&& intent.hasCategory(Intent.CATEGORY_LAUNCHER)&& (intent.getComponent() != null)) {return true;}return false;}// a component name that will be used for associated-starting in third party push service// such as getui push serviceprivate final static String[] mAssociatedComponentNameList = new String[] {"com.igexin.sdk.GActivity", // 这个组件很贱,经常伪装前台进程唤醒};

2.10 检查省电管理设置界面的黑白名单

检查预设值白名单和省电管理界面白名单进行判断是否需要允许启动,再次进行launchState设置

检查省电设置界面的黑白名单设置情况

    // return launch state according to user settingprivate int checkLaunchStateByUserSetting(Intent intent, String targetApp, int targetUid,String callerApp, int callerUid, String reason) {// targetApp 进程不存在 或 targetApp 为 callerApp,表明为自启动if (targetApp == null || targetApp.equals(callerApp))return LAUNCH_STATE_AUTO;// 检查是否为第三方应用启动boolean launchByOther = autoLaunchByOtherApp(targetApp, targetUid, callerApp, callerUid, reason);// allow app in whitelist// 检查是否为CTS应用或者pwctl_config.xml配置的白名单if (inSelfStartWhiteAppList(targetApp)) {return LAUNCH_STATE_ALLOW;}// if in ultrasaving mode, don't allow autostart except apps in ultrasve applist// 1. 且 非关联启动// 2. 且 当前为超级省电模式// 3. 且 下一个模式为超级省电模式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);// public static final int VALUE_INVALID = -1;// public static final int VALUE_AUTO = 0; 自动// public static final int VALUE_OPTIMIZE = 1; 省电优化或禁止 即黑名单// public static final int VALUE_NO_OPTIMIZE = 2; 省电不优化或允许 即白名单// 1. 或 自启动白名单且没有被第三方应用关联启动// 2. 或 关联唤醒白名单且被第三方应用关联启动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 listboolean bInBlackList = false;// 1. 且 自启动黑名单// 2. 且 非被其他应用关联唤醒if ((autoLaunch == AppPowerSaveConfig.VALUE_OPTIMIZE) && !launchByOther) {if (DEBUG_MORE) Slog.d(TAG, "in apppowerconfig autolaunch black list: " + targetApp);// 标记为黑名单flagbInBlackList = true;}// 1. 且 关联唤醒黑名单// 2. 且 被启动应用关联唤醒if ((secondLaunch == AppPowerSaveConfig.VALUE_OPTIMIZE) && launchByOther) {if (DEBUG_MORE) Slog.d(TAG, "in apppowerconfig 2ndlaunch black list: " + targetApp);// 标记为黑名单flagbInBlackList = true;}// check whether blacklist app is in exceptionif (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)// 1. 且 非关联启动// 2. 且 非start-activity 类型启动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// 1. 且 关联启动// 2. 且非用户主动点击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 startreturn LAUNCH_STATE_ALLOW;}return LAUNCH_STATE_AUTO;}
2.10.1 是否为白名单应用启动
    private boolean inSelfStartWhiteAppList(String pkgName) {if (inCommonWhiteAppList(pkgName))return true;// if setting in the LaunchWhiteList in pwctl_config.xmlif (mPowerConfig != null && mPowerConfig.inLaunchWhiteList(pkgName)) {if (DEBUG) Slog.d(TAG, "in PowerConfig launch white list: " + pkgName);return true;}return false;}/*** 这里主要为CTS* Common white list, that is  for both lockScreen manager and auto self starting manager*/private boolean inCommonWhiteAppList(String pkgName) {if (pkgName == null) return true;/** auto start and lock screen clean do not need to care about doze white list*        try {*         if (mPowerControllerInternal.isWhitelistApp(pkgName)) {*               return true;*           }*       } catch (Exception e) {*       }*/// 在 /system/etc/pwctl_config.xml 目录预先配置的白名单/*check if in internal white app list, like CTS app*/for(String s : mInternalWhiteAppList) {if(pkgName.contains(s)) {if (DEBUG) Slog.d(TAG, "Internal white applist: " + pkgName);return true;}}// is cts/gts appif (Util.isCts(pkgName)) {if (DEBUG) Slog.d(TAG, "CTS/GTS app: " + pkgName + ", see as in white list!!");return true;}return false;}// This white list is used for some app like CTSprivate final String[] mInternalWhiteAppList = new String[] {"com.google.android.gms","com.google.android.gsf","android.app.cts","com.android.cts","android.icu.dev.test.util"};public boolean inLaunchWhiteList(String pkgName) {int index = mConstants.mLaunchWhitelist.indexOf(pkgName);if (index >= 0) {return true;}return false;}

2.11 待机模式下禁止动态待机黑名单启动

    // 待机模式下禁止第三方应用启动// not allow third party app that has been force stopped during standby// to be started again// 1. 待机时长大于0// 2. 是否为待机模式禁止被启动的应用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;}
===============================================================================================================// to recode the system elapsed time when starting standbyprivate long mStandbyStartTime = 0;/** Note device is enter standby state ( screen off / unpluged)*/void noteDeviceStateChanged(boolean bStandby, final long nowELAPSED) {if (DEBUG) Slog.d(TAG, "noteDeviceStateChanged bStandby:" + bStandby);// 更新待机时间if (bStandby) mStandbyStartTime = nowELAPSED; //SystemClock.elapsedRealtime();else mStandbyStartTime = 0;....}
===============================================================================================================// 是否为待机模式禁止被启动的应用private boolean isForceStoppedAppDuringStandby(String pkgName, int uid) {ArrayMap<String, Integer> mStoppedAppList = getStoppedAppList(UserHandle.getUserId(uid));return mStoppedAppList.containsKey(pkgName);}private ArrayMap<String, Integer> getStoppedAppList(int userId) {ArrayMap<String, Integer> mStoppedAppList = mStoppedAppListForUsers.get(userId);// 对应的userid不存在,则加入StoppedAppList中,便于下次待机中可以取到名单吗?这个逻辑暂时有些绕,存在疑问if (mStoppedAppList == null) {mStoppedAppList = new ArrayMap<>();mStoppedAppListForUsers.put(userId, mStoppedAppList);}return mStoppedAppList;}// Apps that have be stopped during this standby period// it will clear when exit standby state//private ArrayList<String> mStoppedAppList = new ArrayList<>();private SparseArray<ArrayMap<String,Integer>> mStoppedAppListForUsers = new SparseArray<>(); //<pkgName, userId>

2.12 禁止系统广播启动第三方应用

这里与 handleBroadcastAction()函数功能存在重复,且 handleBroadcastAction 的规避条件更多一些,或者本意是禁止 handleBroadcastAction 没有涉及的一些广播

=================================================================================================// not allow system broadcast to launch third party app// 1. caller 不为空// 2. caller 为系统(android)// 3. 启动类型是 send-broadcastif ((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;}

2.13 禁止system ui广播启动第三方应用

        // 禁止"system ui"广播启动第三方应用// not allow "com.android.systemui" broadcast to launch third party app// 1. caller 为system ui// 2. 启动类型为send-broadcast 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;}

2.14 不允许后台应用关联唤醒其他应用

  • frameworks/base/core/java/android/app/ActivityManager.java
// not allow background app to launch other third party app// 不允许后台应用关联唤醒其他应用// 1. caller 不用空// 2. caller 状态为非前台进程,mProcState 数值越大进程重要度越低// 3. 启动类型不为 start-acitivtyif (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;}/** @hide Process is a persistent system process. */public static final int PROCESS_STATE_PERSISTENT = 0;/** @hide Process is a persistent system process and is doing UI. */public static final int PROCESS_STATE_PERSISTENT_UI = 1;/** @hide Process is hosting the current top activities.  Note that this covers* all activities that are visible to the user. */public static final int PROCESS_STATE_TOP = 2;/** @hide Process is hosting a foreground service due to a system binding. */public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;/** @hide Process is hosting a foreground service. */public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;/** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */public static final int PROCESS_STATE_TOP_SLEEPING = 5;/** @hide Process is important to the user, and something they are aware of. */public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 6;/** @hide Process is important to the user, but not something they are aware of. */public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 7;/** @hide Process is in the background transient so we will try to keep running. */public static final int PROCESS_STATE_TRANSIENT_BACKGROUND = 8;/** @hide Process is in the background running a backup/restore operation. */public static final int PROCESS_STATE_BACKUP = 9;/** @hide Process is in the background, but it can't restore its state so we want* to try to avoid killing it. */public static final int PROCESS_STATE_HEAVY_WEIGHT = 10;/** @hide Process is in the background running a service.  Unlike oom_adj, this level* is used for both the normal running in background state and the executing* operations state. */public static final int PROCESS_STATE_SERVICE = 11;/** @hide Process is in the background running a receiver.   Note that from the* perspective of oom_adj receivers run at a higher foreground level, but for our* prioritization here that is not necessary and putting them below services means* many fewer changes in some process states as they receive broadcasts. */public static final int PROCESS_STATE_RECEIVER = 12;/** @hide Process is in the background but hosts the home activity. */public static final int PROCESS_STATE_HOME = 13;/** @hide Process is in the background but hosts the last shown activity. */public static final int PROCESS_STATE_LAST_ACTIVITY = 14;/** @hide Process is being cached for later use and contains activities. */public static final int PROCESS_STATE_CACHED_ACTIVITY = 15;/** @hide Process is being cached for later use and is a client of another cached* process that contains activities. */public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 16;/** @hide Process is being cached for later use and is empty. */public static final int PROCESS_STATE_CACHED_EMPTY = 17;/** @hide Process does not exist. */public static final int PROCESS_STATE_NONEXISTENT = 18;/** @hide The lowest process state number */public static final int MIN_PROCESS_STATE = PROCESS_STATE_PERSISTENT;/** @hide The highest process state number */public static final int MAX_PROCESS_STATE = PROCESS_STATE_NONEXISTENT;

2.15 不允许长时间运行的后台应用唤醒其他应用

======================================================================================// not allow long idle third party app to start other third party app// 1. caller 状态不为空// 2. caller 非第三应用// 3. caller 不为前台进程属性// 4. 启动类型非start-activityif (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;// 待机场景持续时长 = 当前流逝时刻 - caller 最近一次运行时长idleDuration = (callerAppState.mLastTimeUsed > 0 ? (nowELAPSED -callerAppState.mLastTimeUsed) : -1);// 第三方应用在后台运行超过 DENY_START_APP_THRESHOLD,则不允许第三方进程// 即不允许长时间运行的后台应用唤醒其他应用if (idleDuration > DENY_START_APP_THRESHOLD) {if (DEBUG) Slog.d(TAG,"Start Proc : "+targetApp+", callingPackage = "+callerApp+", reason = "+reason + ": denyed!! long idle");return false;}}
======================================================================================// if a non-top app has been idle for DENY_START_APP_THRESHOLD// then don't allow this app to start other 3-party app// 5 分钟 或者 30 分钟private final long DENY_START_APP_THRESHOLD = (TEST ? 5 * 60 * 1000L : 30 * 60 * 1000L);

这篇关于8 展讯Sprd设置-电池-关联自启动-judgeAppLaunchAllowedInternal 函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/695193

相关文章

Linux中chmod权限设置方式

《Linux中chmod权限设置方式》本文介绍了Linux系统中文件和目录权限的设置方法,包括chmod、chown和chgrp命令的使用,以及权限模式和符号模式的详细说明,通过这些命令,用户可以灵活... 目录设置基本权限命令:chmod1、权限介绍2、chmod命令常见用法和示例3、文件权限详解4、ch

SpringBoot项目引入token设置方式

《SpringBoot项目引入token设置方式》本文详细介绍了JWT(JSONWebToken)的基本概念、结构、应用场景以及工作原理,通过动手实践,展示了如何在SpringBoot项目中实现JWT... 目录一. 先了解熟悉JWT(jsON Web Token)1. JSON Web Token是什么鬼

使用Spring Cache时设置缓存键的注意事项详解

《使用SpringCache时设置缓存键的注意事项详解》在现代的Web应用中,缓存是提高系统性能和响应速度的重要手段之一,Spring框架提供了强大的缓存支持,通过​​@Cacheable​​、​​... 目录引言1. 缓存键的基本概念2. 默认缓存键生成器3. 自定义缓存键3.1 使用​​@Cacheab

java如何调用kettle设置变量和参数

《java如何调用kettle设置变量和参数》文章简要介绍了如何在Java中调用Kettle,并重点讨论了变量和参数的区别,以及在Java代码中如何正确设置和使用这些变量,避免覆盖Kettle中已设置... 目录Java调用kettle设置变量和参数java代码中变量会覆盖kettle里面设置的变量总结ja

C++11的函数包装器std::function使用示例

《C++11的函数包装器std::function使用示例》C++11引入的std::function是最常用的函数包装器,它可以存储任何可调用对象并提供统一的调用接口,以下是关于函数包装器的详细讲解... 目录一、std::function 的基本用法1. 基本语法二、如何使用 std::function

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87