Android系统启动篇
4,《Android SystemServer进程启动流程》
Android系统开发准备篇
3,《Android Framework代码IDE加载和调试》
Android系统开发实践篇
4,《android单独编译framework模块并push》
Android系统开发核心知识储备篇
1,《Android编译系统-envsetup和lunch代码篇》
6,《Android中Activity、View和Window关系详解》
11,《android中AMS进程通知Zygote进程fork新进程的通信方式》
Android核心功能详解篇
2,《Android 手势导航(从下往上滑动进入多任务页面)》
3,《android手势分析(应用界面左往右边滑动退出应用)》
———————————————————————————————————————————
目录
一,背景介绍
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" />
重新编译后,酷狗开机自启动问题得以解决。