Android Question "ContentProviderHelper.checkAssociationAndPermissionLocked". Say What?

drgottjr

Expert
Licensed User
Longtime User
here's a strange exception: ContentProviderHelper.checkAssociationAndPermissionLocked
the method referred to is easily found in com.android.server.am.ContentProviderHelper. instances of the exception are not so easy to find.

below please find the exception that was logged by my app, as well as 3 other examples found on the internet. finding those 3 took some time.

my log:
ALL EXTRAS: Bundle[{job=receiving, android.intent.extra.STREAM=Supplier{VAL_PARCELABLE@104+180}}]
error: android.os.RemoteException: Remote stack trace:
at com.android.server.am.ContentProviderHelper.checkAssociationAndPermissionLocked(ContentProviderHelper.java:651)
at com.android.server.am.ContentProviderHelper.getContentProviderImpl(ContentProviderHelper.java:264)
at com.android.server.am.ContentProviderHelper.getContentProvider(ContentProviderHelper.java:140)
at com.android.server.am.ActivityManagerService.getContentProvider(ActivityManagerService.java:6474)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2395)


similar. some as late as aug, 2022
found here: https://github.com/GrapheneOS/os-issue-tracker/issues/1179
05-08 03:20:39.160 22814 22814 E AndroidRuntime: Caused by: android.os.RemoteException: Remote stack trace:
05-08 03:20:39.160 22814 22814 E AndroidRuntime: at com.android.server.am.ContentProviderHelper.checkAssociationAndPermissionLocked(ContentProviderHelper.java:611)
05-08 03:20:39.160 22814 22814 E AndroidRuntime: at com.android.server.am.ContentProviderHelper.getContentProviderImpl(ContentProviderHelper.java:235)
05-08 03:20:39.160 22814 22814 E AndroidRuntime: at com.android.server.am.ContentProviderHelper.getContentProvider(ContentProviderHelper.java:125)
05-08 03:20:39.160 22814 22814 E AndroidRuntime: at com.android.server.am.ActivityManagerService.getContentProvider(ActivityManagerService.java:6047)
05-08 03:20:39.160 22814 22814 E AndroidRuntime: at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2463)

and here: https://github.com/ankidroid/Anki-Android/issues/12675
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.am.ContentProviderHelper.checkAssociationAndPermissionLocked(ContentProviderHelper.java:744)
at com.android.server.am.ContentProviderHelper.getContentProviderImpl(ContentProviderHelper.java:307)
at com.android.server.am.ContentProviderHelper.getContentProviderImpl(ContentProviderHelper.java:168)
at com.android.server.am.ContentProviderHelper.getContentProvider(ContentProviderHelper.java:142)
at com.android.server.am.ActivityManagerService.getContentProvider(ActivityManagerService.java:7630)


and here: https://codeberg.org/Freeyourgadget/Gadgetbridge/pulls/2577
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.am.ContentProviderHelper.checkAssociationAndPermissionLocked(ContentProviderHelper.java:796)
at com.android.server.am.ContentProviderHelper.getContentProviderImpl(ContentProviderHelper.java:329)
at com.android.server.am.ContentProviderHelper.getContentProviderImpl(ContentProviderHelper.java:168)
at com.android.server.am.ContentProviderHelper.getContentProvider(ContentProviderHelper.java:142)
at com.android.server.am.ActivityManagerService.getContentProvider(ActivityManagerService.java:7550)

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
here's the story:
app 1 ("sender") sends a bitmap to app 2 ("receiver") using startactivityforresult and the fileprovider. app 2 ("receiver") receives the bitmap,
manipulates it and sends the manipulated bitmap back to app 1 ("sender") using setresult and an intent with the bitmap's uri as determined by fileprovider.

in reality, both apps are very large, so, for simplicity's sake, i built 2 simple apps to handle sending, receiving and returning the bitmap. "sender" sends the
bitmap, "receiver" receives it, saves it, loads it back in and returns it to "sender". both apps are found attached below. the exception occurs in both the
full versions and the simplified versions. not surprising, presumably, since the code was copied from the full versions.

"sender" has no problem sending the bitmap to "receiver", and "receiver" has no problem receiving it. "receiver" has no (evident) problem returning
the bitmap using fileprovider. "sender" has no problem receiving the intent as returned by "receiver". it can read the intent's extras. what it cannot do
is obtain the bitmap at the uri specified in the intent. it throws the exception above.

i've tried in using b4a 12.2, java 11 and 2 devices running android 12 and 13, respectively.

in addition to the attached examples, i also attach the full log showing program flow between the 2 apps.

after failing with fileprovider, i also tried converting the bitmap to bytes and returning it that way, but there is a limit to what you can stuff in the transaction
buffer, and the bitmaps i use are generally at or over the limit (fyi: android.os.TransactionTooLargeException is the exception thrown when overflowing the buffer.)

there are potentially a couple workarounds, but they ruin the flow, and, in any case, fileprovider is supposed to work, no?

since the test bitmap is on the small side, i've set up the examples so that they can handle a bitmap or a byte array. in "receiver" there is a a flag to set/unset to toggle
which version to use. "sender" can accept either. since the bitmap is small, there shouldn't be any problem transferring a byte array. you'll see the length of the byte
array returned in the log. but when you try to return a bitmap, you should get the exception. so even returning a small bitmap will trigger the exception.

is anyone familiar with this exception?
 

Attachments

  • sender.zip
    14.2 KB · Views: 63
  • receiver.zip
    10.4 KB · Views: 58
  • log.txt
    2.8 KB · Views: 59

JohnC

Expert
Licensed User
Longtime User
I have not dived deep into this issue too much (or looked at the code), but I have a quick quesiton - are you using the same filename as the original and returned modified file?

If so, maybe try renaming the file that is returned to something else to see if the error goes away.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
different names. thanks for reaching out.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
OK, I just spent some time on this, and I think I know where the problem is.

I changed the code in the Sender to this:

B4X:
If res = -1 Then      ' success
        Log("ALL EXTRAS: " & i.ExtrasToString)

        If i.Action = i.ACTION_SEND Then        ' shared image from some other app
            Dim in As JavaObject = i
            Dim uri As String = in.RunMethod("getParcelableExtra", Array("android.intent.extra.STREAM"))

            Try
                Log("Loading bitmap from: " & uri)
                Dim bmp As Bitmap = LoadBitmapResize("ContentDir", uri, imageview.width, imageview.Height,True)
                imageview.Bitmap = bmp
                imageview.Gravity = Gravity.CENTER

            Catch
                Log(LastException)
                Log("failed to load shared image")
                MsgboxAsync("There was a problem opening that image.", "Sorry")
                Wait For MsgBox_Result (Result As Int)
                Activity.Finish
            End Try
        End If

And then I noticed there is a difference in the contents of the Intent that the Receiver gets:

B4X:
starting by intent: (Intent) Intent { act=android.intent.action.SEND typ=image/* flg=0x1 cmp=com.georgieapps.receiver/.main clip={image/* U:content://com.georgieapps.sender.provider/name/b4x.jpg} (has extras) }

And the Intent that the Sender gets back:
B4X:
ALL EXTRAS: Bundle[{job=receiving, android.intent.extra.STREAM=content://com.georgieapps.receiver.provider/name/newb4x.jpg}]

As you can see, then second intent contains a lot less info than the first intent.

So, my hunch is that the "Intent" that is provided to the "Ion_Event" (Args(1)) does not have enough info in it for the file provider to fetch the image properly.

Also, my changes to the code resulted in giving a different error:

B4X:
ALL EXTRAS: Bundle[{job=receiving, android.intent.extra.STREAM=content://com.georgieapps.receiver.provider/name/newb4x.jpg}]
Loading bitmap from: content://com.georgieapps.receiver.provider/name/newb4x.jpg
(RemoteException) android.os.RemoteException: Remote stack trace:
    at com.android.server.am.ActivityManagerService.getContentProviderImpl(ActivityManagerService.java:6827)
    at com.android.server.am.ActivityManagerService.getContentProvider(ActivityManagerService.java:7247)
    at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2078)
    at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2741)
    at android.os.Binder.execTransactInternal(Binder.java:1021)
failed to load shared image
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
yep, i see the difference. your interpretation could be right. i set the mime type for the return, yet it doesn't appear in the return intent's extras. unclear whether that's the reason for the exception.

i've been searching to see if a setresult intent is, somehow, different from the intent that startsactivityforresult. one would think that having a uri in the hands of a fileprovider would be enough.

what i see is that i'm complying with the rules regarding using a fileprovider for file sharing. it fails. either i'm not complying correctly or there is an issue with fileprovider.

thanks again.
 
Upvote 0

JohnC

Expert
Licensed User
Longtime User
What about just skipping the whole use of the Ion event method, and just catch the starting intent in the sender main Create_Activity just like you do in the receiver?

This way it should be a "real" intent.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
yeah, it's a possibility. one of the workarounds i mentioned initially. i use startactivityforresult and setresult in a lot of apps without a problem. i'm comfortable with the flow. i would like to know if i'm using fileprovider incorrectly. i use it a lot also, so knowing of if i'm not using it correctly would be important.
 
Upvote 0
Top