1. UI-关联自启动

android 开机自启动关联启动 安卓关联启动管理_展讯关联唤醒

2. 源码走读-上层接口调用

2.1 字符串

strings_ex.xml

<string name="app_as_lunch">关联启动</string>
<string name="app_as_lunch_optimization">关联自启动</string>
<string name="second_launch_title">禁止应用被其他应用关联启动,有助于节省电量和内存空间,可能会对关联应用的功能产生影响。</string>

2.2 字符串所在的布局文件

  • \vendor\sprd\platform\packages\apps\Settings\res\xml\sprd_app_auto_run_fragment.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"
        android:title="@string/choose_battery_saver"
        android:key="battery_saver_list">
    <Preference
            android:key="app_auto_run"
            android:title="@string/app_auto_run_optimization" /> // 开机自启动
    <Preference
            android:key="app_as_lunch"
            android:title="@string/app_as_lunch_optimization" /> // 关联自启动
</PreferenceScreen>

2.3 布局文件所在的界面

  • \vendor\sprd\platform\packages\apps\Settings\src\com\android\settings\fuelgauge\SprdAppAutoRunFragment.java
package com.android.settings.fuelgauge;

public class SprdAppAutoRunFragment extends SettingsPreferenceFragment
        implements Preference.OnPreferenceClickListener {
    
        @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        // 加载布局
        addPreferencesFromResource(R.xml.sprd_app_auto_run_fragment);
        mAppAutoRunPref = (Preference) findPreference(KEY_APP_AUTO_RUN);
        mAppAutoRunPref.setOnPreferenceClickListener(this);

        // 关联唤醒
        mAppAsLunchPref = (Preference) findPreference(KEY_APP_AS_LUNCH);
        mAppAsLunchPref.setOnPreferenceClickListener(this);
    }

2.4 关联唤醒的跳转事件

// 关联唤醒
    private static final String KEY_APP_AS_LUNCH = "app_as_lunch";


    @Override
    public boolean onPreferenceClick(Preference preference) {
        String key = preference.getKey();
        int resID;
        int appConfigType;
            switch (key) {
                case KEY_APP_AUTO_RUN: // 应用自启动
                    resID = R.string.app_auto_run_optimization;
                    appConfigType = TYPE_APP_AUTO_RUN;
                    break;
                case KEY_APP_AS_LUNCH: // 关联唤醒
                    resID = R.string.app_as_lunch_optimization;
                    appConfigType = TYPE_APP_AS_LUNCH;
                    break;
                default:
                    resID = R.string.app_auto_run_optimization;
                    appConfigType = TYPE_APP_AUTO_RUN;
            }
        Log.d(TAG," onPreferenceClick key:" + key);
        Bundle args = new Bundle();
        args.putInt(APPLICATION_LIST_TYPE, LIST_TYPE_APP_AUTO_RUN);
        args.putInt(TYPE_APP_CONFIG, appConfigType);

        // freagment name SprdManageApplications
        Intent intent = Utils.onBuildStartFragmentIntent(getActivity(), SprdManageApplications.class.getName(),
                args, null, resID, null, false, getMetricsCategory());
        getActivity().startActivity(intent);

        return true;
    }

2.5 UI 关联唤醒 - SprdManageApplications

package com.android.settings.fuelgauge;

public class SprdManageApplications extends SettingsPreferenceFragment
        implements OnItemClickListener {

    public static final int TYPE_APP_AS_LUNCH = 1004;
    
    //the name of control all app button
    private TextView mAllAppTitle;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
     
        } else if (mArgument == TYPE_APP_AS_LUNCH) {
            // 禁止应用被其他应用关联启动,有助于节省电量和内存空间,可能会对关联应用的功能产生影响。
            mFeatureTitle.setText(R.string.second_launch_title);
            // 全部
            mAllAppTitle.setText(R.string.not_allow_all_app);

2.6 UI 关联唤醒- 按钮全部的点击事件

package com.android.settings.fuelgauge;


public class SprdManageApplications extends SettingsPreferenceFragment
        implements OnItemClickListener {

    private Switch mAllAppSwitch;

    mAllAppSwitch = (Switch) mRootView.findViewById(R.id.security_toggle_all);

    if (mAllAppSwitch != null) {
        mAllAppSwitch.setOnTouchListener(mOnTouchListener);
        mAllAppSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            public void onCheckedChanged(CompoundButton compoundButton,
                    boolean isChecked) {
                Log.d(TAG, "onCheckedChanged() mIsClickSwitch = " + mIsClickSwitch
                        + " isChecked = " + isChecked);
                if (mIsClickSwitch) {
                    mIsSelectAll = mAllAppSwitch.isChecked();
                    setAllAppState(mIsSelectAll);
                }
            }
        });
    }

2.7 关联唤醒- setAllAppState

public static final int TYPE_APP_AS_LUNCH = 1004;


    public void setAllAppState(boolean flag) {
        if (DEBUG) Log.i(TAG, "closeAllChanged flag:" + flag);
        if (mIsSelectAll) {
            mSwitchState = SWITCH_STATE_OPEN;
        } else {
            mSwitchState = SWITCH_STATE_CLOSE;
        }
        int value = AUTO;
        try {
            if (mArgument == TYPE_APP_CLOSE_LOCKED) {
                value = flag ? CLOSE : DO_NOT_CLOSE;
            } else {
                value = flag ? DO_NOT_OPTIMIZE : OPTIMIZE;
            }
            mPowerManagerEx.setAppPowerSaveConfigListWithType(mApplications.mPkgList,
                    mAppConfigType/**TYPE_APP_AS_LUNCH = 1004*/, value);
        } catch (RemoteException e) {
            // Not much we can do here
        }
        mIsClickSwitch = false;
        mApplications.notifyDataSetChanged();
    }

其中 mAppConfigType 当前为 TYPE_APP_AS_LUNCH

/*
     * as ApplicationsAdapter will been used by app close after lock sceen and
     * app as-launch automatically, so use the type to distinguish the different UI.
     */
    public int getCurrentType() {
        switch (mArgument) {
            case TYPE_APP_AUTO_RUN:
                return ConfigType.TYPE_AUTOLAUNCH.value;
            case TYPE_APP_AS_LUNCH:
                return ConfigType.TYPE_SECONDARYLAUNCH.value;
            case TYPE_APP_CLOSE_LOCKED:
                return ConfigType.TYPE_LOCKSCREENCLEANUP.value;
            default:
                return ConfigType.TYPE_AUTOLAUNCH.value;
        }
    }

2.8 PowerManagerEx.setAppPowerSaveConfigListWithType

  • vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/PowerManagerServiceEx.java
package com.android.server.power;

public class PowerManagerServiceEx extends IPowerManagerEx.Stub{

    // varibles for powercontroller
    final PowerController.LocalService mPowerControllerInternal;

    /**
     * Set the current power save config value of the apps in 'appList' in the specified type
     * @param appList The package name list of the apps
     * @param type The power save type link {@AppPowerSaveConfig#ConfigType}
     * @param value The config value link
     *    {@AppPowerSaveConfig#VALUE_INVALID, #VALUE_AUTO, #VALUE_OPTIMIZE, #VALUE_NO_OPTIMIZE}
     * @return Returns true for success, false for fail.
     */
    public boolean setAppPowerSaveConfigListWithType(List<String> appList, int type, int value) {
        return mPowerControllerInternal.setAppPowerSaveConfigListWithType(appList, type, value);
    }

2.9 PowerController.LocalService.setAppPowerSaveConfigListWithType

  • vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/PowerController.java
package com.android.server.power;

public class PowerController //extends IPowerController.Stub
	extends UsageStatsManagerInternal.AppStateEventChangeListener {

    static final int MSG_SET_APP_POWERSAVE_CONFIG_LIST_WITHTYPE = 25;


    // local service
    public final class LocalService  {
    
        boolean setAppPowerSaveConfigListWithType(List<String> appList, int type, int value) {
            if (DEBUG) Slog.d(TAG, "setAppPowerSaveConfigListWithType(), appList: " + appList + ", type: " + AppPowerSaveConfig.ConfigType2Str(type) + ", value: " + AppPowerSaveConfig.ConfigValue2Str(value));
            if ((null == appList) || ((type <= AppPowerSaveConfig.ConfigType.TYPE_NULL.value) || (type >= AppPowerSaveConfig.ConfigType.TYPE_MAX.value))
                || ((value < AppPowerSaveConfig.VALUE_AUTO) || (value > AppPowerSaveConfig.VALUE_NO_OPTIMIZE))) {
                return false;
            }

            try {
                synchronized (mMsgLock) {
                    if (!msgHandler.sendMessage(msgHandler.obtainMessage(MSG_SET_APP_POWERSAVE_CONFIG_LIST_WITHTYPE, type, value, appList))) return false;
                    mMsgLock.wait();
                }
            } catch (InterruptedException e) {
                Slog.e(TAG, e.toString());
            }

            return true;
        }
        
    
        case MSG_SET_APP_POWERSAVE_CONFIG_LIST_WITHTYPE:
        List<String> appList = (List<String>)msg.obj;
        setAppPowerSaveConfigListWithTypeInternal(appList, msg.arg1, msg.arg2);
        break;

2.10 PowerController.setAppPowerSaveConfigListWithTypeInternal

private boolean setAppPowerSaveConfigListWithTypeInternal(List<String> appList, int type, int value) {
        boolean bRet = true;
        for (int i=0; i<appList.size(); i++) {
            bRet |= setAppPowerSaveConfigWithTypeInternal(appList.get(i), type, value);
        }

        synchronized(mMsgLock) {
            mMsgLock.notify();
        }
        return bRet;
    }

2.11 PowerController.setAppPowerSaveConfigWithTypeInternal

关联自启动的黑白名单写入 AppPowerSaveConfig 中

// 关联唤醒设置写入配置信息中
    private boolean setAppPowerSaveConfigWithTypeInternal(String appName, int type, int value) {
        AppPowerSaveConfig oldConfig = mAppConfigMap.get(appName);
        if (null == oldConfig) {
            oldConfig = new AppPowerSaveConfig();
        }
        
        // 例如 config.secondaryLaunch
        int oldValue = AppPowerSaveConfig.getConfigValue(oldConfig, type);

        if (DEBUG) Slog.d(TAG, "setAppPowerSaveConfigWithTypeInternal(), appName: " + appName + ", config type: " + AppPowerSaveConfig.ConfigType2Str(type) 
            + ", new value: " + AppPowerSaveConfig.ConfigValue2Str(value)
            + ", old value: " + AppPowerSaveConfig.ConfigValue2Str(oldValue));

        if (value != oldValue) {
            onPowerSaveConfigChanged(type, appName, oldValue, value, false);
            for (int j = 0; j < mHelpers.size(); j++) {
                PowerSaveHelper helper = mHelpers.get(j);
                if (0 != (AppPowerSaveConfig.mMaskArray[type] & helper.mMask)) {
                    helper.onPowerSaveConfigChanged(type, appName, oldValue, value, false);
                }
            }
        }

        AppPowerSaveConfig.setConfigWithType(oldConfig, type, value);

        if (DEBUG) Slog.d(TAG, "setAppPowerSaveConfigWithTypeInternal() config: " + oldConfig);

        if (oldConfig.isReset()) {
            if (DEBUG) Slog.d(TAG, "setAppPowerSaveConfigWithTypeInternal() remove old");
            mAppConfigMap.remove(appName);
        } else {
            if (DEBUG) Slog.d(TAG, "setAppPowerSaveConfigWithTypeInternal() put new");
            mAppConfigMap.put(appName, oldConfig);
        }
        AppPowerSaveConfig.writeConfig(mAppConfigMap);

        synchronized(mMsgLock) {
            mMsgLock.notify();
        }
        return true;
    }

3. 源码走读-关联自启动的逻辑

如之前的走读记录,上层主要是通过界面完成黑白名单的设置,写入 AppPowerSaveConfig 中,故接下来的重点是查看 AppPowerSaveConfig 中尤其是关联自启动白名单调用的逻辑事件

3.1 AppPowerSaveConfig

  • vendor/sprd/platform/frameworks/base/core/java/android/os/AppPowerSaveConfig.java
package android.os;

public class AppPowerSaveConfig implements Parcelable{

    private static final String APPCONFIG_FILENAME = "appPowerSaveConfig.xml";


    // 构造器
    public AppPowerSaveConfig() {
        for (int i=0; i<ConfigType.TYPE_MAX.value; i++) {
            setConfigWithType(this , i, mDefConfig[i]);
        }
    }
    
    // 类型
    public enum ConfigType {
        TYPE_NULL(-1),
        TYPE_OPTIMIZE(0), // 电池优化总开关
        TYPE_ALARM(1), // 对齐唤醒
        TYPE_WAKELOCK(2), // 待机优化
        TYPE_NETWORK(3), // 网络
        TYPE_AUTOLAUNCH(4),// 自启动
        TYPE_SECONDARYLAUNCH(5), // 关联唤醒
        TYPE_LOCKSCREENCLEANUP(6), // 锁屏后清理
        TYPE_POWERCONSUMERTYPE(7), // 耗电情况,GPS耗电,长时间持锁、频繁唤醒
        TYPE_MAX(8);

        public final int value;
        private ConfigType(int value){
            this.value = value;
        }
    }

其中上述配置文件的存放位置

  • /data/system/appPowerSaveConfig.xml

上述对应如上type类型

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<app_powersave_config>
<package name="com.fadi.autoplayvedio" optimize="0" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="0" consumertype="0" />
<package name="com.fadi.autoreboot" optimize="0" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="0" consumertype="0" />
<package name="com.fadisu.cpurun" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="1" secondarylaunch="1" lockscreencleanup="0" consumertype="0" />
<package name="com.pp.assistant" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="1" secondarylaunch="1" lockscreencleanup="1" consumertype="0" />
<package name="com.sprd.sleepwakeuptest" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="sprdtest.message" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.spreadtrum.itestapp" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.test.autoreboot" optimize="0" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="0" consumertype="0" />
<package name="com.fadi.autowakeup" optimize="0" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="0" consumertype="0" />
<package name="com.fadi.autoemmctest" optimize="0" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="0" consumertype="0" />
<package name="com.fadi.autodemo" optimize="0" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="0" consumertype="0" />
<package name="com.comcat.activity" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.jio.emiddleware" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.fadi.batterywaring" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="1" secondarylaunch="1" lockscreencleanup="0" consumertype="0" />
<package name="com.greenpoint.android.mc10086.activity" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="2" secondarylaunch="2" lockscreencleanup="2" consumertype="0" />
<package name="com.spreadst.validdate" optimize="1" alarm="0" wakelock="0" network="0" autolaunch="1" secondarylaunch="1" lockscreencleanup="0" consumertype="0" />
</app_powersave_config>

3.2 查看 AppPowerSaveConfig的调用情况,尤其是secondLaunch的调用

全局搜索发现如下只有 BackgroundCleanHelper.java 比较靠谱,但是没有看到AMS\Broadcast相关,查询记录如下

./vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/BackgroundCleanHelper.java:331:            AppPowerSaveConfig.MASK_SECONDARYLAUNCH |
./vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/BackgroundCleanHelper.java:336:        m2ndLaunch_WhiteList = mPowerControllerInternal.getWhiteList(AppPowerSaveConfig.ConfigType.TYPE_SECONDARYLAUNCH.value);
./vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/BackgroundCleanHelper.java:337:        m2ndLaunch_BlackList = mPowerControllerInternal.getBlackList(AppPowerSaveConfig.ConfigType.TYPE_SECONDARYLAUNCH.value);
./vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/BackgroundCleanHelper.java:844:            AppPowerSaveConfig.ConfigType.TYPE_SECONDARYLAUNCH.value);
./vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/BackgroundCleanHelper.java:1834:        int secondLaunch = mPowerControllerInternal.getAppPowerSaveConfgWithTypeInternal(targetApp,AppPowerSaveConfig.ConfigType.TYPE_SECONDARYLAUNCH.value);

相关源码,其中发现这里有管理唤醒名单获取

调用-关联唤醒相关 1

package com.android.server.power;

public class BackgroundCleanHelper extends PowerSaveHelper {

    // 构造器
    public BackgroundCleanHelper(Context context, IActivityManager activityManager, Handler handler) {
        super(context, AppPowerSaveConfig.MASK_AUTOLAUNCH |
            AppPowerSaveConfig.MASK_SECONDARYLAUNCH |
            AppPowerSaveConfig.MASK_LOCKSCRRENCLEANUP);

        // 获取自启动列表-白名单
        mAutoLaunch_WhiteList = mPowerControllerInternal.getWhiteList(AppPowerSaveConfig.ConfigType.TYPE_AUTOLAUNCH.value);
        // 获取自启动列表-黑名单
        mAutoLaunch_BlackList = mPowerControllerInternal.getBlackList(AppPowerSaveConfig.ConfigType.TYPE_AUTOLAUNCH.value);
        // 获取关联唤醒列表-白名单
        m2ndLaunch_WhiteList = mPowerControllerInternal.getWhiteList(AppPowerSaveConfig.ConfigType.TYPE_SECONDARYLAUNCH.value);
        // 获取关联唤醒列表-黑名单
        m2ndLaunch_BlackList = mPowerControllerInternal.getBlackList(AppPowerSaveConfig.ConfigType.TYPE_SECONDARYLAUNCH.value);
        // 获取后台清理-白名单
        mLockScreen_WhiteList = mPowerControllerInternal.getWhiteList(AppPowerSaveConfig.ConfigType.TYPE_LOCKSCREENCLEANUP.value);
        // 获取后台清理-黑名单
        mLockScreen_BlackList = mPowerControllerInternal.getBlackList(AppPowerSaveConfig.ConfigType.TYPE_LOCKSCREENCLEANUP.value);
        
    上述主要为了dump出白名单

调用-关联唤醒相关 2

noteAppFirstStarted->handleAppFirstStarted

// 显示应用第一次启动的通知
    private void handleAppFirstStarted(String packageName, int userId) {
        ...
        int secondLaunch = mPowerControllerInternal.getAppPowerSaveConfgWithTypeInternal(packageName,
            AppPowerSaveConfig.ConfigType.TYPE_SECONDARYLAUNCH.value);
        
        //check whether app is in black list
        boolean bInBlackList = false;
        // 黑名单
        if ((autoLaunch == AppPowerSaveConfig.VALUE_OPTIMIZE)
            || (secondLaunch == AppPowerSaveConfig.VALUE_OPTIMIZE)) {
            bInBlackList = true;
        }

调用-关联唤醒相关 3

judgeAppLaunchAllowedInternal->checkLaunchStateByUserSetting

// 返回启动状态,初步认为是核心的函数
    // return launch state according to user setting
    private int checkLaunchStateByUserSetting(Intent intent, String targetApp, int targetUid,
            String callerApp, int callerUid, String reason) {
            
        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;
        }
        
        // 黑名单
        if ((secondLaunch == AppPowerSaveConfig.VALUE_OPTIMIZE) && launchByOther) {
            if (DEBUG_MORE) Slog.d(TAG, "in apppowerconfig 2ndlaunch black list: " + targetApp);
            bInBlackList = true;
        }

上述中 checkLaunchStateByUserSetting 为被 judgeAppLaunchAllowedInternal 唯一调用

3.3 查看 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) {
        ...
        checkLaunchStateByUserSetting()
        }

3.4 查看 judgeAppLaunchAllowed 及其被调用关系

boolean judgeAppLaunchAllowed(Intent intent, String targetApp, int targetUid,
            int callerUid, String callerApp, String reason) {

        boolean ret = judgeAppLaunchAllowedInternal(intent, targetApp, targetUid, callerUid, callerApp, reason);
        ...
        return ret;

    }
  • 搜索关键字 judgeAppLaunchAllowed ,发现被外部 ActivityManagerServiceEx 和 PowerController 被调用了,这里进行记录
root@69959bbb90c6:/home/suhuazhi/8.1/op54_int# grep -irn "judgeAppLaunchAllowed" vendor/sprd/platform/frameworks/
vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/am/ActivityManagerServiceEx.java:769:                allowed = mPowerControllerInternal.judgeAppLaunchAllowed(intent, targetPkg, targetUid, callingUid, callingPackage, reason);

    // NOTE: Bug #627645 low power Feature BEG-->
    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) {}
        }
        return allowed;
    }
    // <-- NOTE: Bug #627645 low power Feature END


vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/power/PowerController.java:2074:                boolean ret = mBackgroundCleanHelper.judgeAppLaunchAllowed(intent, targetApp, targetUid, callerUid, callerApp, reason);

    // local service
    public final class LocalService  {
        public boolean judgeAppLaunchAllowed(Intent intent, String targetApp, int targetUid,
            int callerUid, String callerApp, String reason) {
            if (mBackgroundCleanHelper != null) {
                boolean ret = mBackgroundCleanHelper.judgeAppLaunchAllowed(intent, targetApp, targetUid, callerUid, callerApp, reason);
                return ret;
            }
            return true;
        }

其中 上述的调用关系是 ActivityManagerServiceEx -> PowerController -> BackgroundCleanHelper -> judgeAppLaunchAllowed, 故查看 ActivityManagerServiceEx 中的 judgeStartAllowLocked

3.5 查看 ActivityManagerServiceEx.judgeStartAllowLocked 及其被调用关系

  • 搜索 展讯的frameworks中调用关系
root@69959bbb90c6:/home/suhuazhi/8.1/op54_int# grep -irn "judgeStartAllowLocked" vendor/sprd/platform/frameworks/
vendor/sprd/platform/frameworks/base/services/core/java/com/android/server/am/ActivityManagerServiceExAbs.java:44:    protected boolean judgeStartAllowLocked(Intent intent, String targetPkg, int targetUid,

package com.android.server.am;

/**
 * @hide
 */
public abstract class ActivityManagerServiceExAbs extends IActivityManager.Stub {

    protected boolean judgeStartAllowLocked(Intent intent, String targetPkg, int targetUid,
        int callingUid, String callingPackage, String reason){
        return true;
    }
  • 搜索展讯在原生代码中的frameworks中调用关系
root@69959bbb90c6:/home/suhuazhi/8.1/op54_int# grep -irn "judgeStartAllowLocked" frameworks/base/services/
frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java:345:        if(!mService.judgeStartAllowLocked(intent, targetPkg, targetUid, callingUid, callingPackage, "start-activity")){

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:11927:                    if(!judgeStartAllowLocked(null, targetPkg, targetUid, callerUid, callingPackage,"contentprovider")) {

frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java:1204:                skip = skip || !mService.judgeStartAllowLocked(r.intent, info.activityInfo.applicationInfo.packageName,

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java:394:        if(!mAm.judgeStartAllowLocked(service, r.packageName, targetUid, callingUid, callingPackage,"start-service")) {

frameworks/base/services/core/java/com/android/server/am/ActiveServices.java:1311:        if(!mAm.judgeStartAllowLocked(service, targetPkg, targetUid, callingUid, callingPackage,"bind-service")) {

ok 查看了其中在Acitivty、ContentProvider\start-service\bind-service进行拦截, 其中是否拦截的判断函数是 BackgroundCleanHelper.judgeAppLaunchAllowedInternal

3.6 拦截策略

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

public class BackgroundCleanHelper extends PowerSaveHelper {

    // app start reason, should sync with the ActivityManagerService
    // that calling judgeStartAllowLocked
    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. 在ActivityStarter 进行 start-activity 监听,judgeAppLaunchAllowedInternal 判断是否拦截
  2. 在ActivityManagerService 进行 contentprovider 监听,judgeAppLaunchAllowedInternal 判断是否拦截
  3. 在BroadcastQueue 进行 send-broadcast,judgeAppLaunchAllowedInternal 判断是否拦截
  4. 在ActiveServices 进行 start-service 和 bind-service监听,judgeAppLaunchAllowedInternal 判断是否拦截