如何验证 Android DevicePolicyManager#isAdminActive 与激活设备管理器失败的结果

How to validate results of Android DevicePolicyManager#isAdminActive vs failure to activate device manager

我面临一个有趣的情况,但我不知道如何解决。当用户作为 Android for Work 用户首次登录我的应用程序时,我有义务确保该应用程序已注册为设备管理器。我通过调用 DevicePolicyManager#isAdminActive 检查是否是这种情况,如果是 returns false,那么我启动 Intentaction=DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN,以便启动Android 启用设备管理的控件。一旦发生这种情况,当我的应用程序再次启动时(或者当它从设备管理流程 returns 时),将再次检查 DevicePolicyManager#isAdminActive 的值。如果用户启用了设备管理,那么一切都很好,应用程序会继续运行。

有趣的是,这在用户第一次浏览我们的流程时完全符合预期。不幸的是,重启后,当用户启动我的应用程序时,它会通过 DevicePolicyManager#isAdminActive 检查以确保设备管理仍然处于打开状态,这很有趣。 DevicePolicyManager#isAdminActive 将报告 false,这是通过查看设备安全设置来验证的。然而,更糟糕的是,尝试启用设备管理将导致以下异常:

W/DeviceAdminAdd: Exception trying to activate admin ComponentInfo{com.mysoft.myapp/com.mysoft.core.receivers.MyAppAdminReceiver} java.lang.IllegalArgumentException: Admin is already added at android.os.Parcel.readException(Parcel.java:1550) at android.os.Parcel.readException(Parcel.java:1499) at android.app.enterprise.IEnterpriseDeviceManager$Stub$Proxy.setActiveAdmin(IEnterpriseDeviceManager.java:867) at android.app.enterprise.EnterpriseDeviceManager.setActiveAdmin(EnterpriseDeviceManager.java:720) at com.android.settings.DeviceAdminAdd.addAndFinish(DeviceAdminAdd.java:346) at com.android.settings.DeviceAdminAdd.onClick(DeviceAdminAdd.java:313) at android.view.View.performClick(View.java:5242) at android.widget.TextView.performClick(TextView.java:10571) at android.view.View$PerformClick.run(View.java:21196) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:145) at android.app.ActivityThread.main(ActivityThread.java:6938) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at ...

即使我尝试通过系统安全设置页面手动启用设备管理,我的 logcat 控制台也会出现这个异常,所以我认为原始 Intent 没有格式错误。

所以,这是我的问题:对 Android 设备管理 API 的一次调用告诉我我的设备管理员未激活,但对同一 API 的另一个调用告诉我这是。我相信第二个实际上是错误的,但无法激活管理,我的用户陷入循环,无法使用我的应用程序。

有没有其他人遇到过这个错误,如果遇到过,你是如何解决这个问题的?

我分析了DevicePolicyManagerService.java的AOSP源码。功能 在这种情况下失败的是 setActiveAdmin(),它抛出一个 异常,因为它声称我们的应用程序已被添加为设备 行政人员。调用后从 setActiveAdmin 抛出此异常 到 getActiveAdminUncheckedLocked() returns 一个有效的对象,表明 请求的设备管理员处于活动状态:

final ActiveAdmin existingAdmin
    = getActiveAdminUncheckedLocked(adminReceiver, userHandle);
if (!refreshing && existingAdmin != null) {
    throw new IllegalArgumentException("Admin is already added");
}
if (policy.mRemovingAdmins.contains(adminReceiver)) {
    throw new IllegalArgumentException(
            "Trying to set an admin which is being removed");
}

不过,在此之前,我们已经调用了DevicePolicyManager.isAdminActive, 其中包含以下逻辑:

return getActiveAdminUncheckedLocked(adminReceiver, userHandle) != null;

这很好;这正是我们想要的。但是,这是 AOSP 代码。我推测受影响的可能有不同的实现 设备,其中存在逻辑错误 DevicePolicyManager#isAdminActive(),因此调用在 returning 时为 false 应该 return 是真的。

在生产中部署检测工具来捕捉这种情况后,我已经验证了这个假设是正确的。从我的指标推断,Android 设备群体中存在实现,因此 isAdminActive(X) 编辑的值 return 将 return 为假, 即使 [=30] =] X 将在 return 由 getActiveAdmins() 编辑的枚举活动管理员列表中找到。幸运的是,这种情况并不常见,但确实存在。我会建议任何依赖这些调用的编码人员针对这种情况强化他们的代码。