前几天在研究怎么非root下杀掉别人的Android进程,在网上搜了下资料,基本上是说调用killPackageProcesses这个方法。自己也试了下,发现有些可以调用成功,有些则失败,有些不解,于是有了这边文章,不足之处望海涵。
killPackageProcesses源码解析
1、killPackageProcesses
public void killBackgroundProcesses(final String packageName) {
if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
!= PackageManager.PERMISSION_GRANTED &&
checkCallingPermission(android.Manifest.permission.RESTART_PACKAGES)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: killBackgroundProcesses() from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
+ " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
int userId = UserId.getCallingUserId();
long callingId = Binder.clearCallingIdentity();
try {
IPackageManager pm = AppGlobals.getPackageManager();
int pkgUid = -1;
synchronized(this) {
try {
pkgUid = pm.getPackageUid(packageName, userId);
} catch (RemoteException e) {
}
if (pkgUid == -1) {
Slog.w(TAG, "Invalid packageName: " + packageName);
return;
}
killPackageProcessesLocked(packageName, pkgUid,
ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
}
} finally {
Binder.restoreCallingIdentity(callingId);
}
}
该函数主要是检查是否申请了相应权限,如果有,则调用killPackageProcessesLocked函数,注意传入的参数ProcessList.SERVICE_ADJ,稍后解释
2、killPackageProcessesLocked
private final boolean killPackageProcessesLocked(String packageName, int uid,
int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
boolean evenPersistent, String reason) {
ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
// Remove all processes this package may have touched: all with the
// same UID (except for the system or root user), and all whose name
// matches the package name.
final String procNamePrefix = packageName + ":";
for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
final int NA = apps.size();
for (int ia=0; ia<NA; ia++) {
ProcessRecord app = apps.valueAt(ia);
if (app.persistent && !evenPersistent) {
// we don't kill persistent processes
continue;
}
if (app.removed) {
if (doit) {
procs.add(app);
}
// If uid is specified and the uid and process name match
// Or, the uid is not specified and the process name matches
} else if (((uid > 0 && uid != Process.SYSTEM_UID && app.info.uid == uid)
|| ((app.processName.equals(packageName)
|| app.processName.startsWith(procNamePrefix))
&& uid < 0))) {
if (app.setAdj >= minOomAdj) {
if (!doit) {
return true;
}
app.removed = true;
procs.add(app);
}
}
}
}
int N = procs.size();
for (int i=0; i<N; i++) {
removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
}
return N > 0;
}
对uid做了一系列判断,过滤掉系统应用,这个我不太关心;重点在下面,app.setAdj >= minOomAdj,比较当前应用的adj和minOomAdj大小,只有大于或等于minOomAdj的应用才能有机会被杀掉。minOomAdj的值也就是上一个函数传入的ProcessList.SERVICE_ADJ。
3、SERVICE_ADJ
在ProcessList.java中SERVICE_ADJ定义如下:
// This is a process holding an application service -- killing it will not
// have much of an impact as far as the user is concerned.
static final int SERVICE_ADJ = 5;
而应用的当前adj值则可以通过adb命令查看。4、其他
所以不是所有service都能够通过killPackageProcesses函数杀掉的,如果service是导出的,可以尝试先stopService后再掉killPackageProcesses函数。