Android12系统源码_获取当前运行在最顶层的Activity方法

前言

在 Android 开发中,由于某些需求常常需要获取当前顶层的 Activity 信息。比如 App 中获取顶层 Activity 界面信息来判断某一个 app 是否在前台运行、统计某一个 app 的使用时长、更有恶意程序通过监听界面伪造 app 进行盗号以及欺诈、自动化开发中通过顶层 Activity 进行页面元素定位点击(比如基于辅助功自动化、uiautomator 自动化)等等操作。 在逆向工程中,获取当前运行 app 运行顶层 activity 也比较常用。通过顶层 Activity 可以快速定位界面中的功能在哪一个页面。

一、获取当前运行的顶层 Activity的几种方式

1、调用ActivityManager的getRunningTasks方法

1)在AndroidManifest文件中添加权限:

<uses-permission  android:name = "android.permission.GET_TASKS"/>

2)获取顶层 activity 参考代码:

    private String getTopActivityByActivityManager() {
        ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningTaskInfo> listTask = activityManager.getRunningTasks(0);
        String activityName = "";
        if (listTask != null && !listTask.isEmpty()) {
            ActivityManager.RunningTaskInfo runningTaskInfo = listTask.get(1);
            activityName = runningTaskInfo.topActivity.getClassName();
        }
       return activityName;
    }

2、调用UsageStatsManager的queryEvents方法:

1)在AndroidManifest文件中添加权限:

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>

2)需要启动授权页面,让用户授权app获取应用使用情况统计权限。:

Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
context.startActivity(intent);

3)获取顶层 activity的参考代码:

    public String getTopActivityByUsageStatsManager() {
        long endTime = System.currentTimeMillis();
        long beginTime = endTime - 10000;

        UsageStatsManager usageStatsManager = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
        String activityInfo = "";
        UsageEvents.Event event = new UsageEvents.Event();
        UsageEvents usageEvents = usageStatsManager.queryEvents(beginTime, endTime);
        while (usageEvents.hasNextEvent()) {
            usageEvents.getNextEvent(event);
            if (event.getEventType() == UsageEvents.Event.MOVE_TO_FOREGROUND) {
                activityInfo = event.getPackageName() + "/" + event.getClassName();
            }
        }
        return activityInfo;
    }

3、使用adb命令
1)输入dumpsys指令

adb shell "dumpsys activity | grep "ResumedActivity:"

2)得到的结果如下所示:

ResumedActivity: ActivityRecord{17ea57d u10 com.example.appcenter/.activity.MainActivity t1000085}

二、ActivityManager的getRunningTasks方法源码分析

1、Android12系统源码中,页面信息ActivityRecord、页面栈Task、页面栈管理者ActivityStarter、ActivityStartController


image.png

1、ActivityManager的getRunningTasks方法如下所示:

frameworks/base/core/java/android/app/ActivityManager.java

@SystemService(Context.ACTIVITY_SERVICE)
public class ActivityManager {
    ...代码省略...
    public List<RunningTaskInfo> getRunningTasks(int maxNum)
            throws SecurityException {
        return ActivityTaskManager.getInstance().getTasks(maxNum);
    }
    ...代码省略...
}

getRunningTasks方法内部直接调用了getTasks方法。

2、ActivityTaskManager的getTasks方法如下所示:

frameworks/base/core/java/android/app/ActivityTaskManager.java

@TestApi
@SystemService(Context.ACTIVITY_TASK_SERVICE)
public class ActivityTaskManager {
    ...代码省略...
    public List<ActivityManager.RunningTaskInfo> getTasks(int maxNum) {
        return getTasks(maxNum, false /* filterForVisibleRecents */);
    }

    public List<ActivityManager.RunningTaskInfo> getTasks(
            int maxNum, boolean filterOnlyVisibleRecents) {
        return getTasks(maxNum, filterOnlyVisibleRecents, false /* keepIntentExtra */);
    }

    public List<ActivityManager.RunningTaskInfo> getTasks(
            int maxNum, boolean filterOnlyVisibleRecents, boolean keepIntentExtra) {
        try {
            return getService().getTasks(maxNum, filterOnlyVisibleRecents, keepIntentExtra);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    ...代码省略...
}

getTasks(int maxNum)方法首先会调用getTasks(int maxNum, boolean filterOnlyVisibleRecents)方法,然后再调用getTasks( int maxNum, boolean filterOnlyVisibleRecents, boolean keepIntentExtra)方法,该方法会调用getService()方法获取IActivityTaskManager实例对象并调用该对象的getTasks方法。

3、ActivityTaskManager的getService方法如下所示:

    public static IActivityTaskManager getService() {
        return IActivityTaskManagerSingleton.get();
    }

    private static final Singleton<IActivityTaskManager> IActivityTaskManagerSingleton =
            new Singleton<IActivityTaskManager>() {
                @Override
                protected IActivityTaskManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE);
                    return IActivityTaskManager.Stub.asInterface(b);
                }
            };

getService方法会返回一个IActivityTaskManager类型的单例对象。

4、在Android12源码中并不存在IActivityTaskManager.java这样一个文件,只能找到 IActivityTaskManager.aidl文件:

frameworks/base/core/java/android/app/IActivityTaskManager.aidl

interface IActivityTaskManager{
    ...代码省略...
  List<ActivityManager.RunningTaskInfo> getTasks(int maxNum, boolean filterOnlyVisibleRecents,boolean keepIntentExtra);
    ...代码省略...
}

我们知道源码编译的时候会将aidl文件转化为 java 文件,IActivityTaskManager的getTasks方法的调用最终是通过binder来实现跨进程通信的。而IActivityTaskManager.aidl中getTasks方法的具体实现类,其实是ActivityTaskManagerService。

5、ActivityTaskManagerService的getTasks方法如下所示:

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    ...代码省略...
    RootWindowContainer mRootWindowContainer;
    ...代码省略...
    @Override
    public List<ActivityManager.RunningTaskInfo> getTasks(int maxNum,
            boolean filterOnlyVisibleRecents, boolean keepIntentExtra) {
        final int callingUid = Binder.getCallingUid();
        final int callingPid = Binder.getCallingPid();

        int flags = filterOnlyVisibleRecents ? RunningTasks.FLAG_FILTER_ONLY_VISIBLE_RECENTS : 0;
        flags |= (keepIntentExtra ? RunningTasks.FLAG_KEEP_INTENT_EXTRA : 0);
        final boolean crossUser = isCrossUserAllowed(callingPid, callingUid);
        flags |= (crossUser ? RunningTasks.FLAG_CROSS_USERS : 0);
        final int[] profileIds = getUserManager().getProfileIds(
                UserHandle.getUserId(callingUid), true);
        ArraySet<Integer> callingProfileIds = new ArraySet<>();
        for (int i = 0; i < profileIds.length; i++) {
            callingProfileIds.add(profileIds[i]);
        }
        ArrayList<ActivityManager.RunningTaskInfo> list = new ArrayList<>();

        synchronized (mGlobalLock) {
            if (DEBUG_ALL) Slog.v(TAG, "getTasks: max=" + maxNum);

            final boolean allowed = isGetTasksAllowed("getTasks", callingPid, callingUid);
            flags |= (allowed ? RunningTasks.FLAG_ALLOWED : 0);
            mRootWindowContainer.getRunningTasks(
                    maxNum, list, flags, callingUid, callingProfileIds);
        }

        return list;
    }
    ...代码省略...
}

ActivityTaskManagerService的getTasks在进行一系列判断之后,会调用RootWindowContainer的getRunningTasks方法。

6、RootWindowContainer的getRunningTasks方法如下所示:

class RootWindowContainer extends WindowContainer<DisplayContent>
        implements DisplayManager.DisplayListener {
    ...代码省略...
    ActivityTaskSupervisor mTaskSupervisor;
    ...代码省略...
    void getRunningTasks(int maxNum, List<ActivityManager.RunningTaskInfo> list,
            int flags, int callingUid, ArraySet<Integer> profileIds) {
        mTaskSupervisor.getRunningTasks().getTasks(maxNum, list, flags, this, callingUid,
                profileIds);
    ...代码省略...
    }

该方法内部直接调用了ActivityTaskSupervisor的getRunningTasks方法获取RunningTasks实例对象,然后调用RunningTasks的getTasks方法。
7、先来看下ActivityTaskSupervisor的getRunningTasks方法:

public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
    ...代码省略...
    private RunningTasks mRunningTasks;
    ...代码省略...
    RunningTasks getRunningTasks() {
        return mRunningTasks;
    }
    ...代码省略...
}

8、再来看下RunningTasks的getTasks方法:

class RunningTasks {
    ...代码省略...
    void getTasks(int maxNum, List<RunningTaskInfo> list, int flags,
            RootWindowContainer root, int callingUid, ArraySet<Integer> profileIds) {
        // Return early if there are no tasks to fetch
        if (maxNum <= 0) {
            return;
        }

        // Gather all of the tasks across all of the tasks, and add them to the sorted set
        mTmpSortedSet.clear();
        mCallingUid = callingUid;
        mUserId = UserHandle.getUserId(callingUid);
        mCrossUser = (flags & FLAG_CROSS_USERS) == FLAG_CROSS_USERS;
        mProfileIds = profileIds;
        mAllowed = (flags & FLAG_ALLOWED) == FLAG_ALLOWED;
        mFilterOnlyVisibleRecents =
                (flags & FLAG_FILTER_ONLY_VISIBLE_RECENTS) == FLAG_FILTER_ONLY_VISIBLE_RECENTS;
        mTopDisplayFocusRootTask = root.getTopDisplayFocusedRootTask();
        mRecentTasks = root.mService.getRecentTasks();
        mKeepIntentExtra = (flags & FLAG_KEEP_INTENT_EXTRA) == FLAG_KEEP_INTENT_EXTRA;

        if (mTopDisplayFocusRootTask.getAdjacentTaskFragment() != null) {
            mTopDisplayAdjacentTask = mTopDisplayFocusRootTask.getAdjacentTaskFragment().asTask();
        } else {
            mTopDisplayAdjacentTask = null;
        }

        final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
                PooledLambda.__(Task.class));
        root.forAllLeafTasks(c, false);
        c.recycle();

        // Take the first {@param maxNum} tasks and create running task infos for them
        final Iterator<Task> iter = mTmpSortedSet.iterator();
        while (iter.hasNext()) {
            if (maxNum == 0) {
                break;
            }

            final Task task = iter.next();
            list.add(createRunningTaskInfo(task));
            maxNum--;
        }
    }
    ...代码省略...
    private RunningTaskInfo createRunningTaskInfo(Task task) {
        final RunningTaskInfo rti = new RunningTaskInfo();
        task.fillTaskInfo(rti, !mKeepIntentExtra);
        // Fill in some deprecated values
        rti.id = rti.taskId;
        return rti;
    }
    ...代码省略...
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容