Widevine is Google's DRM (Digital Rights Management) system for secure video content delivery on Android devices. It applies license rules, blocks screen recording, and decrypts content in secure environments. To integrate Widevine into Android applications, configure ExoPlayer or MediaDrm APIs to request and manage DRM licenses during video playback.
Widevine Security Levels on Android
Android devices use Widevine DRM to protect digital content, employing three security levels (L1, L2, and L3) that offer different degrees of protection based on hardware capabilities. These levels determine how securely a device handles decryption and playback, directly impacting the quality of streaming content available to users.
L1: Hardware-Secured Playback
L1 provides the highest security by performing all DRM operations inside a Trusted Execution Environment (TEE), a hardware-protected zone separate from the main operating system. This ensures that decryption keys and decoded video frames remain secure, preventing unauthorized access. Because of this strong protection, streaming platforms allow L1 devices to play HD and 4K content without restrictions.
L3: Software-Based Decryption
At the lowest security level, L3 relies entirely on software for decryption and playback, with no hardware protection. This makes it easier for attackers to extract decrypted content, as keys and video data remain exposed in system memory. Due to these vulnerabilities, services typically limit L3 devices to standard-definition playback, blocking access to higher-quality streams.
L2: Partial Hardware Security
L2 offers a middle ground, where cryptographic operations run in the TEE, but video decoding happens in regular system memory. While this provides some security for decryption keys, decoded frames remain unprotected, leaving them open to potential extraction. Because of this weakness, most content providers treat L2 similarly to L3, restricting playback to lower resolutions, which is why L2 is rarely seen in practice.
To check the Widevine security level of a device:
val mediaDrm = MediaDrm(WIDEVINE_UUID)val securityLevel = mediaDrm.getPropertyString("securityLevel")Log.d("Widevine", "Security level: $securityLevel")Explanation:
- Apply key rotation if KEY_ROTATION is active in the DRM policy.
- Accepts POST with binary body (challenge from MediaDrm.getKeyRequest()).
- X-Allow-Persistence: true enables persistent license storage on the client.
Integrating Widevine with ExoPlayer
ExoPlayer provides built-in support for Widevine Modular DRM through its DrmSessionManager implementation. This functionality requires three key components to operate correctly: a valid license server URL, a DASH or HLS manifest, and a properly configured MediaItem.DrmConfiguration
val drmConfiguration = MediaItem.DrmConfiguration.Builder(C.WIDEVINE_UUID).setLicenseUri("https://your-license-server.com/license").build()
val mediaItem = MediaItem.Builder().setUri("https://yourcdn.com/video.mpd").setDrmConfiguration(drmConfiguration).build()
val player = ExoPlayer.Builder(context).build()player.setMediaItem(mediaItem)player.prepare()player.play()Explanation:
- License Request Headers: Must include Content-Type: application/octet-stream for PSSH payload.
- Session Initialization: Triggered via player.prepare() using DefaultDrmSessionManager.
- Key Rotation: Requires setKeySetId(byte[]) to persist licenses across sessions.
- Decryption Pipeline: MediaCodec receives clear samples through CryptoInfo.
DASH Manifest Encryption Example
To enable Widevine encryption within a DASH manifest, the <ContentProtection> element specifies the encryption scheme using a UUID assigned to Widevine. The element includes the schemeIdUri attribute and a cenc:pssh tag.
<ContentProtectionschemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"value="Widevine"><cenc:pssh>Base64EncodedPSSH</cenc:pssh></ContentProtection>Explanation:
- schemeIdUri: Identifies Widevine DRM using UUID edef8ba9-79d6-4ace-a3c8-27dcd51d21ed.
- value: Optional label (e.g., "Widevine").
- <cenc:pssh>: Base64-encoded PSSH box containing:
License Server Response Example
A Widevine license server returns a binary license payload after validating the content key request. It may include:
- key_id: Encrypted key identifier
- license_duration: Validity of the license
- allowed_track_types: Resolution or bitrate restrictions
The player applies these rules during playback.
Common Playback Issues on Android
Playback issues on Android stem from device DRM level, incorrect license configurations, or lack of codec support. Each entry maps the issue to its root cause and resolution for debugging and testing.
| Issue | Reason | Resolution |
| Only SD playback available | Device is L3 | Use L1-certified device |
| DRM error during playback | License URL is incorrect or unreachable | Verify URL and network permissions |
| License expired before playback | Short license_duration from server | Use persistent license or extend validity |
| Video not playing on emulator | Emulators are L3 and may lack codec support | Test on real devices with L1 certification |

