2

该项目涉及修改 Android 以阻止/拒绝启动特定应用程序。因此,如果用户尝试以任何方式启动任何预先列出的应用程序,则不应启动该应用程序。

我将修改 Android 源代码。有哪些不同的方法可以做到这一点?欢迎提出建议。

我认为其中一种可能的方法是Process.javaframeworks/base/core/java/android/os. 此类具有start接收uid作为输入参数的功能。我认为从这个参数我们可以知道正在为哪个应用程序创建新进程。这是正确的方法吗?

此外,由于应用程序是使用意图启动的,是否可以(通过修改任何类)删除特定意图?

4

1 回答 1

2

通常,当应用程序(其活动、服务)可以处理意图并且用户更喜欢该应用程序来处理它时。在ActivityManagerService(Ams)Android框架中会先看目标activity/service对应的应用是否还活着。如果尚未启动或终止,则 Ams 将通过调用startProcessLocked方法启动该应用程序。

final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            String hostingType, ComponentName hostingName, boolean allowWhileBooting,
            boolean isolated) {
    //you can get the uid from ApplicationInfo.uid
    ...
    startProcessLocked(app, hostingType, hostingNameStr);
    ...
}

private final void startProcessLocked(ProcessRecord app,
            String hostingType, String hostingNameStr) {
    //prepare its uid, gid, gids for starting that process
    ...
    Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, null, null);
    ...
}

所以在那个方法中,它开始了一个新的过程。这Process.start就是您在问题中提到的,它最终调用 Zygote 来分叉一个新进程。

我觉得在ams中截取应用程序启动过程是比较好的方法。您可以获得有关此应用程序的更多信息,它也是您Process.start方法的上游。

更新:

刚刚注意到您正在考虑限制意图。一个意图可以由多个应用程序处理,因此我们不能限制应用程序发送特定的意图。但是我们可以修改解析过程。Resolving意味着 Android 框架需要确定哪个活动/服务可以处理这个意图。如果有多个选择并且用户没有设置任何偏好,则会出现以下对话框:

意图处理

因此,可以修改解析过程,让 Android 框架放弃您的特定应用程序能够处理该意图的事实。我认为这也是一种完成工作的方式,但它更加复杂,因为 Android 以不同的方式解析活动、服务和接收者的意图。对于活动,Ams 将调用resolveIntentPackageManagerService获取要开始的活动。对于服务,它是get调用的resolveService方法。PackageManagerService所以你需要以不同的方式处理它们。但是因为他们都会在他们的实现中得到一个 ResolveInfo 的列表,所以你可以很容易地过滤掉你的应用程序。例如,在resolveIntentPackageManagerService

@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
        int flags, int userId) {
    if (!sUserManager.exists(userId)) return null;
    enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent");
    List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);
    //filter out here!!!!
    return chooseBestActivity(intent, resolvedType, flags, query, userId);
}

如果您查看ResolveInfo.java.

对于receiver来说就更复杂了,因为AndroidManifest.xml中注册的receiver和byregisterReceiver(...)是不同的。如果broadcastIntent 中的intent 没有设置标志FLAG_RECEIVER_REGISTERED_ONLY(常见情况),那么解析结果将是一个收听该广播的接收者列表,其中可能包含两种接收者。对于 AndroidManifest.xml 中的那些,Ams 将调用queryIntentReceiverPackageManagerService获取收听广播的接收者列表。对于由 动态注册的registerReciever(...),它们是由ActivityManagerServicenot管理的PackageManagerService,所以 Ams 会直接调用mReceiverResolver.queryIntent来获取那些接收者。mReceiverResolver定义为:

final IntentResolver<BroadcastFilter, BroadcastFilter> mReceiverResolver
        = new IntentResolver<BroadcastFilter, BroadcastFilter>() {
        ...
}

因此,您需要做的是重写 queryIntent 方法以过滤掉应用程序中的接收者。对于 ContentProvider,该方法resolveContentProvider位于PackageManagerService. 同样的处理方式。

于 2013-04-26T01:31:01.547 回答