The READ_CONTACTS permission is required if you look up a contact (using the code below) on a pre-Marshmallow device (API 23). But, on Marshmallow or above, you don’t seem to need READ_CONTACTS even though READ_CONTACTS is a dangerous permission.

I don’t see why these two cases should be different.

In particular, if you launch the user’s contacts app with this:

val intent = Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI)
startActivityForResult(intent, RC_CONTACT_LOOKUP)

and then read the contact’s phone number with this in onActivityResult:

RC_CONTACT_LOOKUP -> if (resultCode == RESULT_OK) {
    lateinit var cursor: Cursor
    if (data != null) {
        try {
            cursor =  applicationContext.contentResolver.query(data.data,
                    null, null, null, null)
            cursor.moveToFirst()
            val column = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
            val phoneNumber = cursor.getString(column)
            contactButton.text = phoneNumber
            errorTextView.text = ""
        } catch (exception: Exception) {
            Log.e(tag, "Could not query column db", exception)
        } finally {
            cursor.close()
        }
    }
}

it won’t work in the pre-Marshmallow case unless you’ve required the READ_CONTACTS permission in the manifest. But, for the Marshmallow case, you don’t need to request it (which you would do, of course, at runtime on an as-needed basis because it’s Marshmallow).