killPackageProcesses原理分析

本文探讨如何在非root环境下终止Android进程,主要聚焦于killPackageProcesses方法。作者通过源码分析,发现该方法并非总是有效,并详细解析了相关函数,包括killPackageProcessesLocked和服务调整级别(SERVICE_ADJ),指出非导出服务可能无法直接通过此方法结束,建议先尝试stopService。

前几天在研究怎么非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函数。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值