Search code examples
androiddrmwidevinehdcp

Detect Widevine DRM HDCP protection level


I am currently in the process of switching to ExoPlayer with Dash/Widevine DRM. Through testing, I encountered a high percentage of devices that have no HDCP protection enabled. Due to contractual agreements, this is a problem. I have to detect this and log it BEFORE allowing playback.

I took inspiration that this was even a possibility from the App DRM Info WideVineScreenShot

My first thought was to use DrmManagerClient

I scrapped that because I wasn't getting results and tried to use MediaDrm

val mediaDrm = MediaDrm(WIDEVINE_UUID)

val vendor = mediaDrm.getPropertyString(MediaDrm.PROPERTY_VENDOR)
val version = mediaDrm.getPropertyString(MediaDrm.PROPERTY_VERSION)
val description = mediaDrm.getPropertyString(MediaDrm.PROPERTY_DESCRIPTION)
val algorithms = mediaDrm.getPropertyString(MediaDrm.PROPERTY_ALGORITHMS)

var hdcp: String? = null

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
   hdcp = mediaDrm.connectedHdcpLevel.toString()
}

Log.i("WideVine", "$vendor $version $description $algorithms $hdcp")

Which works! Amazing Problem solved!

...Except as you can see it will only work on Pie and up... This is a no go. DrmInfo will work on every version of Android I tried. I just have no idea how to use DrmManagerClient and the Docs are practically nonexistent.

Any info will be valued, thank you.


Solution

  • Ok, so after taking cracks at this all-day, I was starting to think it wouldn't be possible. My best attempts were failing and the one StackOverflow post even remotely related this topic had a hint but it didn't work.

    val algorithms = mediaDrm.getPropertyString("maxHdcpLevel")
    

    But as you can see here this wont get past the compiler and requires a MediaDrm.Property* Compiler Error

    val stringProperties = arrayOf(
                    MediaDrm.PROPERTY_VENDOR,
                    MediaDrm.PROPERTY_VERSION,
                    MediaDrm.PROPERTY_DESCRIPTION,
                    MediaDrm.PROPERTY_ALGORITHMS,
                    "maxHdcpLevel")
    
    val widevinePropertiesMap = mutableMapOf<String, String>()
    
    for (prop in stringProperties) {
         widevinePropertiesMap[prop] = mediaDrm.getPropertyString(prop)
         Log.i(prop, mediaDrm.getPropertyString(prop))
         }
    
    Log.i("maxHdcpLevel:", "${widevinePropertiesMap["maxHdcpLevel"]}")
    
    

    Alternatively, if you just want to get one thing you can just...

    @SupressLint("WrongConstant")
    

    THIS WORKS!.

    I am not really sure why you can exploit the method this way, however, it gets the job done!

    Here are some additional properties that we can obtain:

      val securityLevel = mediaDrm.getPropertyString("securityLevel")
      val systemId = mediaDrm.getPropertyString("systemId")
      val hdcpLevel = mediaDrm.getPropertyString("hdcpLevel")
      val maxHdcpLevel = mediaDrm.getPropertyString("maxHdcpLevel")
      val usageReportingSupport = mediaDrm.getPropertyString("usageReportingSupport")
      val maxNumberOfSessions = mediaDrm.getPropertyString("maxNumberOfSessions")
      val numberOfOpenSessions = mediaDrm.getPropertyString("numberOfOpenSessions")