如何将应用程序创建的线程视为与应用程序的ContentProvider不同的应用程序?

Jul*_* A. 13 android uid android-contentprovider android-securityexception

我有一个应用程序,当通过ContentObserver对a的更改通知时ContentProvider,尝试在后台线程上查询提供程序.这导致SecurityException抛出:

8-10 15:54:29.577    3057-3200/com.xxxx.mobile.android.xxx W/Binder? Caught a RuntimeException from the binder stub implementation.
  java.lang.SecurityException: Permission Denial: reading com.xxx.mobile.android.mdk.model.customer.ContentProvider uri content://com.xxx.mobile.android.consumer.xxx/vehicle from pid=0, uid=1000 requires the provider be exported, or grantUriPermission()
at android.content.ContentProvider.enforceReadPermissionInner(ContentProvider.java:539)
           at android.content.ContentProvider$Transport.enforceReadPermission(ContentProvider.java:452)
           at android.content.ContentProvider$Transport.query(ContentProvider.java:205)
           at android.content.ContentResolver.query(ContentResolver.java:478)
           at android.content.ContentResolver.query(ContentResolver.java:422)

应用程序创建的线程如何以应用程序的ContentProvider中的不同UID结束?

通过将异常断点在android.content.ContentProvider我看到UserHandle.isSameApp(uid, mMyUid)falseUserHandle.isSameUser(uid, mMyUid)true.我还看到提供者UID是10087.

ade*_*hus 5

uid值1000属于Android系统.Android的许多功能涉及代理对系统线程的请求以进行处理.如果在此期间抛出异常,则错误将包括系统的uid,而不是原始请求者.

对于其他要点:

UserHandle.isSameApp(uid, mMyUid) is false

UserHandle.isSameUser(uid, mMyUid) is true

通过查看来源,这些最容易解释.在具有多用户支持的Android设备上,每个用户都由一系列UID定义.isSameApp是错误的,因为ids的模数不匹配:

 public static final boolean isSameApp(int uid1, int uid2) {
        return getAppId(uid1) == getAppId(uid2);
}

 public static final int getAppId(int uid) {
        return uid % PER_USER_RANGE;
}
Run Code Online (Sandbox Code Playgroud)

同样,这两个id属于同一个用户,因为它们位于相同的范围内:

 public static final boolean isSameUser(int uid1, int uid2) {
        return getUserId(uid1) == getUserId(uid2);
 }

public static final int getUserId(int uid) {
        if (MU_ENABLED) {
            return uid / PER_USER_RANGE;
        } else {
            return 0;
        }
}
Run Code Online (Sandbox Code Playgroud)

请注意,此逻辑存在缺陷,因为这意味着将假定所有Android系统uid(<10000)都"属于"第一个用户.

另请注意,如果第二个用户安装了超过1000个应用程序(!),则可能会将应用程序误认为系统应用程序(两者都uid % PER_USER_RANGE将返回1000).但这并不重要,因为强大的沙盒可以防止任何太糟糕的事情发生.


Lou*_*CAD 3

我在尝试在系统回调 ( ) 中与 ContentProvider 交互时遇到了同样的问题LeScanCallback。问题是回调线程属于 Android 系统,而不是我的应用程序,即使代码位于我的应用程序中。

在尝试与我的 ContentProvider 交互之前,将工作从回调传递到我的应用程序线程之一成功解决了该问题。

为了减少线程创建和回收的样板(需要频繁回调以减少开销),我在委托方法上使用了AndroidAnnotation 的@Background注释(但今天将使用 Kotlin 协程)。