阻止Android中的特定应用程序(通过修改源代码)

时间:2013-04-25 18:42:42

标签: android android-intent android-source android-framework

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

我将修改Android源代码。有什么不同的方法呢?欢迎提出建议。

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

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

1 个答案:

答案 0 :(得分:2)

通常,当应用程序(其活动,服务)可以处理意图时,用户更喜欢该应用程序来处理它。 Android框架中的ActivityManagerService(Ams)将首先查看目标活动/服务的相应应用程序是否仍然存在。如果尚未启动或终止,则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框架需要确定哪个活动/服务可以处理此意图。如果有多个选项且用户未设置任何首选项,则会出现以下对话框:

Intent Handling

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

@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,可以轻松地从ResolveInfo获取ApplicationInfo。

对于接收器来说,它更复杂,因为在AndroidManifest.xml和registerReceiver(...)中注册的接收器是不同的。如果broadcastIntent中的intent没有设置标志FLAG_RECEIVER_REGISTERED_ONLY(常见情况),则解析结果将是监听该广播的接收器列表,其可以包含两种接收器。对于那些在AndroidManifest.xml中的人,Ams将调用queryIntentReceiver中的PackageManagerService来获取收听广播的接收者列表。对于registerReciever(...)动态注册的用户,它们由ActivityManagerService而非PackageManagerService管理,因此Ams将直接呼叫mReceiverResolver.queryIntent以获取这些接收者。 mReceiverResolver定义为:

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

因此,您需要做的是覆盖queryIntent方法以过滤掉应用程序中的接收器。对于ContentProvider,该方法在resolveContentProvider中为PackageManagerService。处理它的方式相同。