I wanted MANAGED INFO to show both IMEIs on dual-SIM devices. AMAPI still gives me a single networkInfo.imei, and the per-SIM telephonyInfos[] entries have carrier and ICCID fields but no IMEI. So I had MANAGED INFO read the modem slots directly. AMAPI device reference
For that to work on a fully managed device or in a company-owned work profile, I delegate CERT_INSTALL to MANAGED INFO. Android lets the certificate delegate read the hardware identifiers available to the device or profile owner. The scope also grants certificate-management privileges. MANAGED INFO checks for the scope and the READ_PHONE_STATE runtime permission before doing the read. Android delegation reference · MANAGED INFO Device identifiers card
In AMAPI I merge this into the app’s existing applications[] entry. The managed configuration switches on the card under Device info. AMAPI application policy
{
"packageName": "org.bayton.managedinfo",
"delegatedScopes": ["CERT_INSTALL"],
"permissionGrants": [{
"permission": "android.permission.READ_PHONE_STATE",
"policy": "GRANT"
}],
"managedConfiguration": {
"device_details_settings": {
"device_details_enable_device_identifiers": true
}
}
}
On Android 11 and later I take the higher of the supported and active modem counts. A phone can support two modems with only one active, so the active count alone can leave a slot unchecked. On Android 8 to 10 the app uses phoneCount. Then it asks Android for the IMEI of each logical slot and keeps the distinct values it gets back. A slot can still return nothing. Android TelephonyManager reference
Here’s the IMEI part of the read, with the permission checks already done.
val slotCount = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
maxOf(1, telephony.supportedModemCount, telephony.activeModemCount)
} else {
@Suppress("DEPRECATION")
maxOf(1, telephony.phoneCount)
}
val imeis = (0 until slotCount).mapNotNull { slot ->
runCatching { telephony.getImei(slot) }.getOrNull()
?.takeIf { it.isNotBlank() }
}.distinct()
The app still has a legacy MEID fallback and uses the first value it finds for its single imei field. When it gets more than one distinct value, the card shows the list and MI can include it as imeiList in its own metadata reporting. The same card shows the hardware serial and Android ID, and attempts the enrolment-specific ID where Android allows it. MANAGED INFO identifier source · Metadata reporting source
As for what AMAPI reports with the only SIM in tray slot 2, AOSP’s no-argument getImei() follows the default subscription’s logical slot. Android 14’s getPrimaryImei() gives you the device-designated primary. I haven’t found a public reference saying which lookup Android Device Policy uses for networkInfo.imei. AOSP slot lookup · Android primary IMEI API
If you’ve seen AMAPI report a different IMEI after moving the same SIM between slots, give me a ping. The handset model, Android version and which slot matched are enough.
#androidenterprise