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

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

我认为这样做的一种可能方法是在Process.java中修改frameworks/base/core/java/android/os
此类具有start函数,该函数接收uid作为输入参数。我认为,通过此参数,我们可以了解正在为哪个应用创建新流程。这是正确的方法吗?

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

最佳答案

通常,当意图可以由应用程序(其活动,服务)处理,并且用户希望该应用程序来处理它时。 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框架需要确定哪些活动/服务可以处理此意图。如果有多个选择,而用户未设置任何首选项,则会出现以下对话框:



因此,可以修改解析过程,让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中的意图未设置标志FLAG_RECEIVER_located_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。处理方式相同。

08-15 19:27
查看更多