【Android Monkey源码解析四】- 异常捕获/页面控制

承接上文,在 【Android Monkey源码解析三】- 运行解析 中,有介绍到run方法中的getSystemInterfaces方法是获取所有系统接口对象的。其中异常捕获和页面控制就是通过ActivityManager的setActivityController方法来实现的,如下:

java 复制代码
/**
 * Attach to the required system interfaces.
 *
 * @return Returns true if all system interfaces were available.
 */
private boolean getSystemInterfaces() {
    mAm = ActivityManager.getService();
    if (mAm == null) {
        Logger.err.println("** Error: Unable to connect to activity manager; is the system "
                + "running?");
        return false;
    }
    ...
    try {
        mAm.setActivityController(new ActivityController(), true);
        mNetworkMonitor.register(mAm);
    } catch (RemoteException e) {
        Logger.err.println("** Failed talking with activity manager!");
        return false;
    }
    return true;
}

这里,创建了一个新的ActivityController对象,设置给了ActivityManager的setActivityController的第一个参数。下面看下ActivityController的实现,源码地址:https://android.googlesource.com/platform/development/+/refs/heads/android12-release/cmds/monkey/src/com/android/commands/monkey/Monkey.java#265

java 复制代码
/**
 * Monitor operations happening in the system.
 * ActivityController主要实现处理了如下几个事情:
 * 1. 页面控制(activityStarting)
 * 2. 应用崩溃监控(appCrashed)
 * 3. 应用无响应(appNotResponding)
 * 4. 系统无响应(appNotResponding)
 */
private class ActivityController extends IActivityController.Stub {
    public boolean activityStarting(Intent intent, String pkg) {
        // 当Monkey在执行随机事件时,可能进入任何的应用。这里需要对即将进入的应用进行判断
        // 如果不是目标测试应用,则不允许跳转。
        final boolean allow = isActivityStartingAllowed(intent, pkg);
        if (mVerbose > 0) {
            // StrictMode's disk checks end up catching this on
            // userdebug/eng builds due to PrintStream going to a
            // FileOutputStream in the end (perhaps only when
            // redirected to a file?)  So we allow disk writes
            // around this region for the monkey to minimize
            // harmless dropbox uploads from monkeys.
            StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
            Logger.out.println("    // " + (allow ? "Allowing" : "Rejecting") + " start of "
                    + intent + " in package " + pkg);
            StrictMode.setThreadPolicy(savedPolicy);
        }
        currentPackage = pkg;
        currentIntent = intent;
        return allow;
    }
    // 有三种情况时允许进入目标activity,
    // 1. 如果当前要进入的activity是已指定的测试应用包下的;
    // 2. 如果设置了允许所有启动activity,此标志位(DEBUG_ALLOW_ANY_STARTS )无设置,条件会不满足;
    // 3. 如果启动的activity是启动器的主页面;
    private boolean isActivityStartingAllowed(Intent intent, String pkg) {
        if (MonkeyUtils.getPackageFilter().checkEnteringPackage(pkg)) {
            return true;
        }
        if (DEBUG_ALLOW_ANY_STARTS != 0) {
            return true;
        }
        // In case the activity is launching home and the default launcher
        // package is disabled, allow anyway to prevent ANR (see b/38121026)
        final Set<String> categories = intent.getCategories();
        if (intent.getAction() == Intent.ACTION_MAIN
                && categories != null
                && categories.contains(Intent.CATEGORY_HOME)) {
            try {
                final ResolveInfo resolveInfo =
                        mPm.resolveIntent(intent, intent.getType(), 0,
                                ActivityManager.getCurrentUser());
                final String launcherPackage = resolveInfo.activityInfo.packageName;
                if (pkg.equals(launcherPackage)) {
                    return true;
                }
            } catch (RemoteException e) {
                Logger.err.println("** Failed talking with package manager!");
                return false;
            }
        }
        return false;
    }
    // 当activity进入onResume生命周期时调用
    public boolean activityResuming(String pkg) {
        StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        Logger.out.println("    // activityResuming(" + pkg + ")");
        boolean allow = MonkeyUtils.getPackageFilter().checkEnteringPackage(pkg)
                || (DEBUG_ALLOW_ANY_RESTARTS != 0);
        if (!allow) {
            if (mVerbose > 0) {
                Logger.out.println("    // " + (allow ? "Allowing" : "Rejecting")
                        + " resume of package " + pkg);
            }
        }
        currentPackage = pkg;
        StrictMode.setThreadPolicy(savedPolicy);
        return allow;
    }
    // 当有应用出现崩溃时调用
    public boolean appCrashed(String processName, int pid,
            String shortMsg, String longMsg,
            long timeMillis, String stackTrace) {
        StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        Logger.err.println("// CRASH: " + processName + " (pid " + pid + ")");
        Logger.err.println("// Short Msg: " + shortMsg);
        Logger.err.println("// Long Msg: " + longMsg);
        Logger.err.println("// Build Label: " + Build.FINGERPRINT);
        Logger.err.println("// Build Changelist: " + Build.VERSION.INCREMENTAL);
        Logger.err.println("// Build Time: " + Build.TIME);
        Logger.err.println("// " + stackTrace.replace("\n", "\n// "));
        StrictMode.setThreadPolicy(savedPolicy);
        // 判断是否有设置mMatchDescription,如果没设置,则直接进入第二层if处理
        // 如果有设置mMatchDescription,则通过shortMsg,longMsg,stackTrace进行分别匹配,只要有满足,则进入第二层if处理
        if (mMatchDescription == null
                || shortMsg.contains(mMatchDescription)
                || longMsg.contains(mMatchDescription)
                || stackTrace.contains(mMatchDescription)) {
            // 如果设置mIgnoreCrashes为false或者设置了mRequestBugreport为true
            if (!mIgnoreCrashes || mRequestBugreport) {
                synchronized (Monkey.this) {
                    if (!mIgnoreCrashes) {
                        mAbort = true;
                    }
                    if (mRequestBugreport){
                        mRequestAppCrashBugreport = true;
                        mReportProcessName = processName;
                    }
                }
                return !mKillProcessAfterError;
            }
        }
        return false;
    }
    public int appEarlyNotResponding(String processName, int pid, String annotation) {
        return 0;
    }
    // 出现应用无响应时回调处理
    public int appNotResponding(String processName, int pid, String processStats) {
        StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        Logger.err.println("// NOT RESPONDING: " + processName + " (pid " + pid + ")");
        Logger.err.println(processStats);
        StrictMode.setThreadPolicy(savedPolicy);
        // 同样地,匹配mMatchDescription设置和未设置的条件判断
        if (mMatchDescription == null || processStats.contains(mMatchDescription)) {
            synchronized (Monkey.this) {
                mRequestAnrTraces = true;
                mRequestDumpsysMemInfo = true;
                mRequestProcRank = true;
                if (mRequestBugreport) {
                    mRequestAnrBugreport = true;
                    mReportProcessName = processName;
                }
            }
            if (!mIgnoreTimeouts) {
                synchronized (Monkey.this) {
                    mAbort = true;
                }
            }
        }
        return (mKillProcessAfterError) ? -1 : 1;
    }
    // 出现系统无响应时回调处理
    public int systemNotResponding(String message) {
        StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
        Logger.err.println("// WATCHDOG: " + message);
        StrictMode.setThreadPolicy(savedPolicy);
        synchronized (Monkey.this) {
            if (mMatchDescription == null || message.contains(mMatchDescription)) {
                if (!mIgnoreCrashes) {
                    mAbort = true;
                }
                if (mRequestBugreport) {
                    mRequestWatchdogBugreport = true;
                }
            }
            mWatchdogWaiting = true;
        }
        synchronized (Monkey.this) {
            while (mWatchdogWaiting) {
                try {
                    Monkey.this.wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return (mKillProcessAfterError) ? -1 : 1;
    }
}

本篇主要介绍了ActivityController的异常捕获/页面控制处理,下面会介绍在出现应用崩溃(appCrashed),应用无响应(appNotResponding),系统无响应时的处理分析(systemNotResponding)。

相关推荐
优选资源分享3 小时前
Advanced Renamer v4.20 便携版 批量文件重命名工具
windows·实用工具
_F_y3 小时前
MySQL表的操作
android·数据库·mysql
yngsqq4 小时前
AndroidStudio汉化步骤
android
HyEISN5 小时前
Android 9 开启远程adb
android·adb
2501_944526425 小时前
Flutter for OpenHarmony 万能游戏库App实战 - 抽牌游戏实现
android·开发语言·python·flutter·游戏
大大祥6 小时前
穿山甲广告sdk接入
android·kotlin·音视频·视频播放器·广告sdk
2501_944526426 小时前
Flutter for OpenHarmony 万能游戏库App实战 - 笑话生成器实现
android·javascript·python·flutter·游戏
2501_944526426 小时前
Flutter for OpenHarmony 万能游戏库App实战 - 21点游戏实现
android·javascript·flutter·游戏·harmonyos
Alex老夫子6 小时前
android room数据库增加字段注意事项
android·数据库