android安全:forceStopPackage对android的Alarm的影响
也许一些使用alarmmanager做定时任务的同学遇到过这样的问题:设定alarm后,进入设置-->应用程序管理-->强行停止app后,定时任务就失效了。
简单的讲就是:force stop会导致alarm失效。
最典型的例子就是我碰到过的一个bug,使用android手机的时钟app设置一个闹钟,然后进入设置-->应用程序管理里面,将时钟这个app force stop掉,结果闹钟就不响了。
其实这不是bug,这是android系统的新加入的机制。下面我来详细分析一下来龙去脉。
1. 在设置的应用程序管理里面强行停止app:
这里会最终会调用到 ActivityManagerService的forceStopPackageLocked()
源代码如下:
<SPAN style="FONT-SIZE: 18px"> private void forceStopPackageLocked(final String packageName, int uid) {
forceStopPackageLocked(packageName, uid, false, false, true, false);
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
if (!mProcessesReady) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
intent.putExtra(Intent.EXTRA_UID, uid);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
false, false, MY_PID, Process.SYSTEM_UID);
}</SPAN>
private void forceStopPackageLocked(final String packageName, int uid) {
forceStopPackageLocked(packageName, uid, false, false, true, false);
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
if (!mProcessesReady) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
}
intent.putExtra(Intent.EXTRA_UID, uid);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
false, false, MY_PID, Process.SYSTEM_UID);
}
代码里面发送了一个广播:ACTION_PACKAGE_RESTARTED,这个广播大有文章。
2. 再看看AlarmManagerService.java的代码,可以看一个内部类UninstallReceiver
源代码如下:
[java]
<SPAN style="FONT-SIZE: 18px">class UninstallReceiver extends BroadcastReceiver {
public UninstallReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
filter.addDataScheme("package");
mContext.registerReceiver(this, filter);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiver(this, sdFilter);
} @Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
String action = intent.getAction();
String pkgList[] = null;
if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
for (String packageName : pkgList) {
if (lookForPackageLocked(packageName)) {
setResultCode(Activity.RESULT_OK);
return;
}
}
return;
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
} else {
if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
&& intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
// This package is being updated; don't kill its alarms.
return;
}
Uri data = intent.getData();
if (data != null) {
String pkg = data.getSchemeSpecificPart();
if (pkg != null) {
pkgList = new String[]{pkg};
}
}
}
if (pkgList != null && (pkgList.length > 0)) {
for (String pkg : pkgList) {
removeLocked(pkg);
mBroadcastStats.remove(pkg);
}
}
}
}
}</SPAN>
class UninstallReceiver extends BroadcastReceiver {
public UninstallReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
filter.addDataScheme("package");
mContext.registerReceiver(this, filter);
// Register for events related to sdcard installation.
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
mContext.registerReceiver(this, sdFilter);
} @Override
public void onReceive(Context context, Intent intent) {
synchronized (mLock) {
String action = intent.getAction();
String pkgList[] = null;
if (Intent.ACTION_QUERY_PACKAGE_RESTART.equals(action)) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
for (String packageName : pkgList) {
if (lookForPackageLocked(packageName)) {
setResultCode(Activity.RESULT_OK);
return;
}
}
return;
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
} else {
if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
&& intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
// This package is being updated; don't kill its alarms.
return;
}
Uri data = intent.getData();
if (data != null) {
String pkg = data.getSchemeSpecificPart();
if (pkg != null) {
pkgList = new String[]{pkg};
}
}
}
if (pkgList != null && (pkgList.length > 0)) {
for (String pkg : pkgList) {
removeLocked(pkg);
mBroadcastStats.remove(pkg);
}
}
}
}
}可见AlarmManagerService接受了ACTION_PACKAGE_RESTARTED广播,而且执行了removeLocked(pkg)
removeLocked()是做什么的呢?继续看源码: [java]
<SPAN style="FONT-SIZE: 18px"> public void removeLocked(String packageName) {
removeLocked(mRtcWakeupAlarms, packageName);
removeLocked(mRtcAlarms, packageName);
removeLocked(mElapsedRealtimeWakeupAlarms, packageName);
removeLocked(mElapsedRealtimeAlarms, packageName);
} private void removeLocked(ArrayList<Alarm> alarmList,
String packageName) {
if (alarmList.size() <= 0) {
return;
} // iterator over the list removing any it where the intent match
Iterator<Alarm> it = alarmList.iterator(); while (it.hasNext()) {
Alarm alarm = it.next();
if (alarm.operation.getTargetPackage().equals(packageName)) {
it.remove();
}
}
}</SPAN>
public void removeLocked(String packageName) {
removeLocked(mRtcWakeupAlarms, packageName);
removeLocked(mRtcAlarms, packageName);
removeLocked(mElapsedRealtimeWakeupAlarms, packageName);
removeLocked(mElapsedRealtimeAlarms, packageName);
}
private void removeLocked(ArrayList<Alarm> alarmList,
String packageName) {
if (alarmList.size() <= 0) {
return;
}
// iterator over the list removing any it where the intent match
Iterator<Alarm> it = alarmList.iterator(); while (it.hasNext()) {
Alarm alarm = it.next();
if (alarm.operation.getTargetPackage().equals(packageName)) {
it.remove();
}
}
}
看到这里,大家应该明白了,removeLocked就是将对应package设置的所有类型的alarm都remove掉。
看到这里大家应该知道为什么自己设置的alarm会不起作用了吧?
思考:
为什么google要加入这样的机制呢?
应该是出于系统安全的考虑,google在4.0系统中在安全方面做了很多努力。
很多病毒程序都不希望自己的进程被用户强行停止,希望自己的病毒程序可以一直运行,而常见的方式就是通过设置alarm,在病毒进程被杀死后,通过定时发送广播来拉起病毒进程,来实现病毒进程的重新启动。
google也正是看到了这个一点,所以加入了forceStopPackage的这一机制,让用户能够有机会干掉病毒进程。
android安全:forceStopPackage对android的Alarm的影响的更多相关文章
- 【Android 应用开发】Android 开发错误集锦
1. eclipse的Device中不显示手机 在eclipse中连接不上手机,出现adb server didn't ACK fail to start daemon 错误. 出现这种原因是因为a ...
- 我的Android进阶之旅------>Android使用AlarmManager全局定时器实现定时更换壁纸
该DEMO将会通过AlarmManager来周期的调用ChangeService,从而让系统实现定时更换壁纸的功能. 更换壁纸的API为android.app.WallpaperManager,它提供 ...
- Android数据存储之Android 6.0运行时权限下文件存储的思考
前言: 在我们做App开发的过程中基本上都会用到文件存储,所以文件存储对于我们来说是相当熟悉了,不过自从Android 6.0发布之后,基于运行时权限机制访问外置sdcard是需要动态申请权限,所以以 ...
- Android权限管理之Android 6.0运行时权限及解决办法
前言: 今天还是围绕着最近面试的一个热门话题Android 6.0权限适配来总结学习,其实Android 6.0权限适配我们公司是在今年5月份才开始做,算是比较晚的吧,不过现在Android 6.0以 ...
- Android应用架构之Android MVP使用
前两篇已经将Retrofit和RxAndroid应用到了项目中,这篇本打算直接将Dagger2引进项目,但是考虑到整个项目结构,就来个结构整理吧,一起来看看网上炒得火热MVP模式. 说到MVP就不得不 ...
- [译]:Xamarin.Android开发入门——Hello,Android Multiscreen深入理解
原文链接:Hello, Android Multiscreen_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android Multiscreen深入理解. 本 ...
- [译]:Xamarin.Android开发入门——Hello,Android Multiscreen快速上手
原文链接:Hello, Android Multiscreen Quickstart. 译文链接:Hello,Android Multiscreen快速上手 本部分介绍利用Xamarin.Androi ...
- [译]:Xamarin.Android开发入门——Hello,Android深入理解
返回索引目录 原文链接:Hello, Android_DeepDive. 译文链接:Xamarin.Android开发入门--Hello,Android深入理解 本部分介绍利用Xamarin开发And ...
- [译]:Xamarin.Android开发入门——Hello,Android快速上手
返回索引目录 原文链接:Hello, Android_Quickstart. 译文链接:Xamarin.Android开发入门--Hello,Android快速上手 本部分介绍利用Xamarin开发A ...
- Android学习第二天-android常用命令
上一篇文章中,我们重点讲解了adb的常用命令,下面我们一起来看看其它常用的命令 2 android 2.1 查看机器上所有已经安装的Android版本和AVD设备 2.1.1查看机器上已经安装的AVD ...
随机推荐
- IoC Service Provier
本文节选自<Spring 揭秘>. 虽然业务对象可以通过IoC方式声明相应的依赖,但是最终仍然需要通过某种角色或者服务将这些相互依赖的对象绑定到一起,而IoC Service Provid ...
- jsoup入门
官网地址:http://jsoup.org/ Jsoup是一个开源的Java库,它可以用于处理实际应用中的HTML.它提供了非常便利的API来进行数据的提取及修改,充分利用了 DOM,CSS以及jqu ...
- Hadoop-- MapReduce简单理解
1.Hadoop和MapReduce概念 Mapreduce是一种模式. Hadoop是一种框架. Hadoop是一个实现了mapreduce模式的开源的分布式并行编程框架. 2.Hadoop框架 ...
- 设计模式 策略-Strategy,装饰-Decorator,观察者-Observer
重温了Head First 3个设计模式.提炼一下思想,笔记如下. 策略-Strategy 当一个类或类族中重复实现某些同类的方法(behavior)时,考虑使用策略模式. 该模式是将Behavior ...
- 关于对javascript 提升概念 的总结与思考。
最近在看一本新买的书叫<你不知道的javascript上卷>..买到这本书也算是个巧合 不过真是物有所值.它对js的几个高级概念都做了非常深刻的描述和通过一些通俗易懂的方式来让我们理解.这 ...
- Quora的技术探索(转)
原文:http://www.cnblogs.com/xiekeli/archive/2012/04/27/2473808.html 关于问答类的应用,最早接触的是stackoverflow和知乎 ,而 ...
- 【OpenOffice+swftools】在线预览环境的搭建和xpdf中文包的配置
[环境参数] Host:Win7 64bit VMware:VMware Workstation11.1.0 Client OS:CentOS release 6.5 (Final) 2.6.32-4 ...
- Awk中调用shell命令
Awk中调用shell命令 需求 在awk中,有时候需要调用linux系统中命令,如计算字符串的MD5值,并保存下来. 方法参考 call a shell command from inside aw ...
- 1.VS2010C++环境设置
一.需要下载的软件 1.visual studio 2010\\xxzx\tools\编程工具\MICROSOFT\VISUAL.STUDIO\VISUAL.STUDIO.201032位cn_visu ...
- rdlc Report Viewer Configuration Error
主要是web.config没有配置 方法参考http://msdn.microsoft.com/zh-cn/library/ms251661.aspx