The photo_id field (ContactsContract.Contacts.PHOTO_ID) is in the main contact record in ContactsContract
.Contacts.CONTENT_URI. I then look for the records in ContactsContract.
Data.CONTENT_URI that have that photo_id (i.e. that table has a photo_id field as well). The actual photo should be in that table in data15 (ContactsContract.
CommonDataKinds.Photo.PHOTO).
Surprisingly enough, there are multiple records in ContactsContract.
Data.CONTENT_URI with the same photo_id; I guess that, since each user has multiple records in that table, they just all have the photo_id of that contact. Even then, there are multiple rows with that photo_id that have a mimetype of vnd.android.cursor.item/photo. As I mentioned before, only a few of my contacts have their photo in the photo blob field (data15).
However, you are right that there are some URls in those records (they are all in the data_sync1 column. However they all point to URLs that imply they are just for synching up the photo with my gmail account. So my guess is that ANY contact that is imported from gmail will have a photo_id, even if there is no current photo, and it will sync up with the URL to get it. But in my case they are all synced up; I guess I still need to find the facebook photo.
So in a nutshell, it looks like the Android contacts app itself does some intelligent things to display an appropriate photo for a user, whereas I had thought this was just a core part of the API. Since I was just trying to make sure I was understanding data providers correctly (I am just starting to learn the API), and not really THAT interested in getting the photos themselves, I think I'll punt and move on.
Hope this post helps some Googlers in the future