Richard Dapice
Richard Dapice

Reputation: 885

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.

Upvotes: 3

Views: 4759

Answers (2)

Halil Ozel
Halil Ozel

Reputation: 3332

I access and use many features as follows. It might work for you.

try {
            val mediaDrm = MediaDrm(WIDEVINE_UUID)
            securityLevel = mediaDrm.getPropertyString("securityLevel")
            bundle.apply {
                putString("vendor", mediaDrm.getPropertyString(MediaDrm.PROPERTY_VENDOR))
                putString("version", mediaDrm.getPropertyString(MediaDrm.PROPERTY_VERSION))
                putString("description", mediaDrm.getPropertyString(MediaDrm.PROPERTY_DESCRIPTION))
                putString("algorithms", mediaDrm.getPropertyString(MediaDrm.PROPERTY_ALGORITHMS))
                putString("securityLevel", mediaDrm.getPropertyString("securityLevel"))
                putString("systemId", mediaDrm.getPropertyString("systemId"))
                putString("hdcpLevel", mediaDrm.getPropertyString("hdcpLevel"))
                putString("maxHdcpLevel", mediaDrm.getPropertyString("maxHdcpLevel"))
                putString("usageReportingSupport", mediaDrm.getPropertyString("usageReportingSupport"))
                putString("maxNumberOfSessions", mediaDrm.getPropertyString("maxNumberOfSessions"))
                putString("numberOfOpenSessions", mediaDrm.getPropertyString("numberOfOpenSessions"))
            }
            if (Build.VERSION.SDK_INT >= 28) {
                mediaDrm.close()
            } else {
                mediaDrm.release()
            }
        } catch (e: Exception) {
            bundle.putString("error", e.toString())
        }

Upvotes: 0

Richard Dapice
Richard Dapice

Reputation: 885

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")

Upvotes: 6

Related Questions