Android系统层面限制应用开机自启动详解

 Android系统启动篇

1,《android系统启动流程简介》

2,《android init进程启动流程》

3,《android zygote进程启动流程》

4,《Android SystemServer进程启动流程》

5,《android launcher启动流程》

6,《Android Activity启动过程详解》

Android系统开发准备篇

1,《Android 源码下载和编译》

2,《android 11源码编译和pixel3 刷机》

3,《Android Framework代码IDE加载和调试》

Android系统开发实践篇

1,《android设置默认输入法》

2,《android framework预制APK应用》

3,《Android系统层面限制应用开机自启动详解》

4,《android单独编译framework模块并push》

5,《Android Framework开发系统问题分析》

Android系统开发核心知识储备篇

1,《Android编译系统-envsetup和lunch代码篇》

2,《Android编译系统-概念篇》

3,《android日志系统详解》

4,《Android系统Handler详解》

5,《Android系统Binder详解》

6,《Android中Activity、View和Window关系详解》

7,《android view绘制流程详解》

8,《Android读取系统属性详解》

9,《android 窗口管理机制详解》

10,《初识Android系统》

11,《android中AMS进程通知Zygote进程fork新进程的通信方式》

Android核心功能详解篇

1,《android应用市场点击下载APK安装详解》

2,《Android 手势导航(从下往上滑动进入多任务页面)》

3,《android手势分析(应用界面左往右边滑动退出应用)》

4,《android应用安装流程详解》

5,《android11安装应用触发桌面图标刷新流程》

6,《Android系统多任务Recents详解》

7,《android系统导航栏视图分析》

———————————————————————————————————————————

目录

一,背景介绍

二,问题分析

2.1 问题定位

2.2 问题分析

三,解决方案


一,背景介绍

        android系统开发过程中,在集成第三方应用为系统应用时,时常遇到第三方应用开机自启动问题。如何从系统层面限制应用开机自启动?接下来以酷狗应用为例,来讲解说明。

二,问题分析

2.1 问题定位

        通过开机日志分析,酷狗监听广播启动了AutoStartReceiver服务,日志如下,

ActivityManager( 1488): Start proc 4690:com.kugou.android.auto/u0a98 for broadcast {com.kugou.android.auto/com.kugou.android.auto.receiver.AutoStartReceiver}

监听的系统广播具体是啥?需要反编译酷狗apk,反编译后查看manifest文件,

<receiver android:name="com.kugou.android.auto.receiver.AutoStartReceiver">
            <intent-filter android:priority="1000">
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <action android:name="android.media.AUDIO_BECOMING_NOISY"/>
                <action android:name="android.intent.action.ACTION_SHUTDOWN"/>
            </intent-filter>
        </receiver>

可以得出,酷狗监听了系统开机广播android.intent.action.BOOT_COMPLETED

2.2 问题分析

        既然酷狗监听系统广播,从源头处理,对酷狗屏蔽系统开机广播。问题重新定义为,如何从系统层面屏蔽特定应用的特定系统广播?

三,解决方案

        修改广播处理逻辑,frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中做处理,代码片段如下,

final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage,
            @Nullable String callerFeatureId, Intent intent, String resolvedType,
            IIntentReceiver resultTo, int resultCode, String resultData,
            Bundle resultExtras, String[] requiredPermissions, int appOp, Bundle bOptions,
            boolean ordered, boolean sticky, int callingPid, int callingUid, int realCallingUid,
            int realCallingPid, int userId, boolean allowBackgroundActivityStarts,
            @Nullable int[] broadcastWhitelist) {


......................................


            String skipPackages[] = null;
            if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())
                    || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())
                    || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
                Uri data = intent.getData();
                if (data != null) {
                    String pkgName = data.getSchemeSpecificPart();
                    if (pkgName != null) {
                        skipPackages = new String[] { pkgName };
                    }
                }
            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
                skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
            }else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
                Resources res = mContext.getResources();
                String[] blacklist = res.getStringArray(com.android.internal.R.array.blacklist_boot_receiver);
                Set<String> pkgs = new ArraySet();
                for (int i = 0, j = receivers.size(); i < j; i++) {
                    ResolveInfo curt = (ResolveInfo) receivers.get(i);
                    if (ArrayUtils.contains(blacklist, curt.activityInfo.packageName)) {
                        pkgs.add(curt.activityInfo.packageName);
                    }
                }
                if (!pkgs.isEmpty()) {
                    skipPackages = pkgs.stream().toArray(String[]::new);
                }
                Slog.w(TAG, "array blacklist:"+Arrays.toString(blacklist)+",array skipPackages:"+Arrays.toString(skipPackages));
            }
            if (skipPackages != null && (skipPackages.length > 0)) {
                for (String skipPackage : skipPackages) {
                    if (skipPackage != null) {
                        int NT = receivers.size();
                        for (int it=0; it<NT; it++) {
                            ResolveInfo curt = (ResolveInfo)receivers.get(it);
                            if (curt.activityInfo.packageName.equals(skipPackage)) {
                                receivers.remove(it);
                                it--;
                                NT--;
                            }
                        }
                    }
                }
            }

.....................................



}
        其中,R.array.blacklist_boot_receiver资源文件定义,见frameworks/base/core/res/res/values/arrays.xml文件,com.kugou.android.auto为酷狗应用包名,
   <string-array name="blacklist_boot_receiver">
        <item>com.kugou.android.auto</item>
    </string-array>

        系统中的资源,需要在symbols.xml中定义,文件路径:frameworks/base/core/res/res/values/symbols.xml,

<java-symbol type="array" name="blacklist_boot_receiver" />

        重新编译后,酷狗开机自启动问题得以解决。

猜你喜欢

转载自blog.csdn.net/allen_xu_2012_new/article/details/131011532