// Copyright 2021 Google LLC. All rights reserved. import static java.nio.charset.StandardCharsets.UTF_8; import com.google.video.widevine.sdk.wvpl.WvPLCASProxyEnvironment; import com.google.video.widevine.sdk.wvpl.WvPLCASProxySession; import com.google.video.widevine.sdk.wvpl.WvPLCasKey; import com.google.video.widevine.sdk.wvpl.WvPLClientCapabilities; import com.google.video.widevine.sdk.wvpl.WvPLClientInfo; import com.google.video.widevine.sdk.wvpl.WvPLDeviceInfo; import com.google.video.widevine.sdk.wvpl.WvPLHdcp; import com.google.video.widevine.sdk.wvpl.WvPLKeyCategory; import com.google.video.widevine.sdk.wvpl.WvPLKeyCategorySpec; import com.google.video.widevine.sdk.wvpl.WvPLKeyType; import com.google.video.widevine.sdk.wvpl.WvPLLicenseCategory; import com.google.video.widevine.sdk.wvpl.WvPLLicenseCategorySpec; import com.google.video.widevine.sdk.wvpl.WvPLMessageType; import com.google.video.widevine.sdk.wvpl.WvPLOutputProtection; import com.google.video.widevine.sdk.wvpl.WvPLPlaybackPolicy; import com.google.video.widevine.sdk.wvpl.WvPLRequestType; import com.google.video.widevine.sdk.wvpl.WvPLSessionInit; import com.google.video.widevine.sdk.wvpl.WvPLStatus; import com.google.video.widevine.sdk.wvpl.WvPLStatusException; import com.google.video.widevine.sdk.wvpl.WvPLTrackType; import com.google.video.widevine.sdk.wvpl.WvPLWidevinePsshData; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.Base64; import java.util.HashMap; import java.util.List; import java.util.Map; public class WvPLCASProxyUsingMultiContentLicenseExample { static final String B64_DRM_SERVICE_CERTIFICATE_WITH_CAS_PROXY_TYPE = "CrwCCAMSELBFY1_OQaWD87swUMHQjTMY0Ont7AUijgIwggEKAoIBAQCUNggP3JYvTaepEoHfiG32zOEbimIPtzmjTsu-" + "3mOyXn3iA_d-aL6PnCqB0ORWvHld-xkRGHUUCSMAX0stvi-vTAd7e5fdMTXVtDbmj4o2fYDfp0klk3qj3OS7-X" + "H-z2musgRkbzZTzpH8MzUnLRHz97TMx46bwYyL8SskrvnaWwyPBhkDfmAoNQKSVuLZNc6snfOAE4hNCdB4Qq-H" + "TgC3FIl-1Kt4svUUPL4LYAzpKG5xH2r6ol0PQGSIKQ2qhJ-dyXLgDZcFLYdKd7hnKD1yUpvv8tGdHwcXawq7B-" + "eLitKy0gRJx1nyMmLQ-RG31FBEfR6Gtatzcs2OTyoZuktzAgMBAAE6DXdpZGV2aW5lX3Rlc3RABBKAAwtMdfh-" + "yBur-Ivq7rz_00RR8vA4MPJOPR3sZXDVFRQsATRvqUVPCTP88hh6Y7Y3IdHTEfXgcjiz2GZqEOvXzl3iuWkSjN" + "QjNl5ghk955VIryOdzkIYBZJIv4_eEon2RRflExbv4y2GuWxTxHxMmIrFKXF-w2fLSvpiy1qT5daHPIcdvRBDH" + "wIAVbmNmfv2EXoAqbvBWLhOdA8IRd5Lylqa8SWsUgkuyt9mglUdno6h_WCXZBm99eTfuN66ls-rJrlDgUNO3OU" + "OXpMYMI8jE4Neo4GF8AKXoyt0lcckHwynzdlSYa04V6vbPMNycO-u1wpnUAPqkXYbnoYnbjm5gJ7Vav5wJtUM4" + "wFAREefRmS_Dz_kqspC1CxQXo10KZQm3b4QXc_S0cqNXM_R9NGct0qjUdKec_k1RfC1j7MckdZMg4oU-mnqmwO" + "ZS7jTNIaHS4ASTuicsDUsfX1Ac4eqGv1L3qEY4pipCOps-5mRJ3sCjz87cX8QnPsArgtFYSYPgAg=="; static final String B64_PRIVATE_KEY_WITH_CAS_PROXY_TYPE = "MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQI5Qd3AH24lskCAggAMB0GCWCGSAFlAwQBKgQQ9X4D3HPW" + "x35HsgzSgMWCzASCBNBDZGDdRs_hyeRTrca0H4UERbrKRYFsoce9n6-cghmLtIzAn8pYdGH_jfj5Hc3HTo9aXx" + "fJJz9Juckh9teStzVmA-8y2Qj7W8W243DjbyNyKKDzk9esQme5sVvNugEb8wiqraZ0q4KxfjcK60HsZrOK1Ise" + "0TglQMvudrDzV3vTxtgP5LTer6wEnUjfGixzhL120X48me-1stTPeG2ji9zlsgmMCjYCEbe4ovMCZmVOaHnbQ3" + "WNVVnMnVQCqCAmBg_0AKgYB9wvvy7vdRaFHv0EtmyCOegLToNE0I7L5LMcL4-HQ--bwQMHjVkDmIqB3s3XWyhN" + "U_nneES3qpgAbKpObfPGs814BqjbKwGj6z8jrNJ9Lmlaj_7msphYCuOAEjc26CEmxMYG1dTe-XiluHGIVunau6" + "iL7OguAdgbhkc2MQ7XJISjQ8j2sYuryUW33Pn2JSoKa4vVCWxTwg2t86Mc3FJ_daLM_z_kqTh5zel6o05tGXgH" + "hn2UGRTjAs3PgxzExUX6M2_-6uSmdnS4oWxAqVd9ZREMjZaSBY6qPdXyM-Wd2RmUfLNSO3aazLxWu8uH2nbud_" + "3vLyMSj_7lLjtAATqDKrcr1PyNlrn0MTQWIUZ4S5rsHHtprPB_v-7Ufh4OVPdyWfapBGJLx8Eg0Xscoxc_DpwA" + "D9KoA62GGg2CPu4NvvHiFIvEkpsxNFGTEAbZfoXXw78GP370doSguKvbTI3INcguKM35pbpe7-gbU8BjSednsl" + "bQMk4QKFg0YIQmTPDVXAC7FVnyP_dlNf2RXQRObGBGvA_oWv62iz8d3UhpIJOFHeyNic-qoQTj6wRFcxdFR61J" + "hvqZ8rM_KHJl_pvazrhMJ4JAQJXWhQzOvp4rqAJ7Jfx1u_pF_ZRZ6AX2Rjec-xep4EaqRZPdfEUydKKlr10IIc" + "_kNQwU15m0UEE_40wDJ3XqrhKuUnPfHpm4cziFYsQPrfuI36MCKklPvjdWS6VdSA-evN6KBZwD3RQh4jdzTxWf" + "zN-0p9612jIwzUzZj8Zax-TRRaOaN-0-nuPsmR88Ps4Y8AE2-CocYykAD8jh5WbuZKJDEtrNsIfz6keNZVk5ji" + "1JWcpwzbPk9L_A8MdZh5XBA7X-BLe2F6EIVgI3mwTUPSC8wpoGsc4Hu2VeePzOuuZ59IGSmDkyi68usMQzsVeq" + "2VJyz4UpDgy5dC5EOcBHLf3_oiAoxuYu6MIXLk-srrO8-mikdRcey9EzmK9uqMV1e4b7Ts7hdIglBij1QwIKbD" + "mMDMnmnPGX9X5KJojYuxkboe4WWwUgloyRkwxqKWIuEhLirO7E9eS-OOeqtz0idkcMNWziJRiUkVh768T4yfOf" + "Z8ZvOCx59YN8bL390OZIIdaxSvj5mGeQX2-DTDspxDLpiluDJzTQmH7UZsSQ9DlQiXBtJwuaiFoRsyr0b1hh6n" + "yE1TibcD_mWuwMOanUnvGF7OzRyneki4aB-v_PwpvplIDQuRqmkjn9i5P7tl6msEMUhp0yBE2tQIYPbQlIw57n" + "3wRcGOz9ymOrREzEW1UhZQBibr8ZFNoWzRt-k0EVLYzNt96NDtHfHc7AlxJv8ERIDOZ4ai_nNeLgtV76-ybXnT" + "RqRO9TXwqZhHQ_7gEs4Y01IJxvEQ=="; static final String PASSPHRASE = "encryptallthekitties"; static final String PROVIDER_IV = "d58ce954203b7c9a9a9d467f59839249"; static final String PROVIDER_KEY = "1ae8ccd0e7985cc0b6203a55855a1034afc252980e970ca90e5202689f9" + "47ab9"; static final String B64_LICENSE_REQUEST = "CAcSuQsKhAsIARLtCQquAggCEhCLiDL7eSGz5lQZxhEvltHOGOTt1OEFIo4CMIIBCgKCAQEApynnDkNRVwiBn-bGL5_C" + "bqnyMAvVzKeRMbRpl8woIqhHmljqKHt9zq2mt3KQzQ3z96mL1OkZB2Mb_EBlr-k7CPlaV5n3ORJS3mo9Cg5QLc" + "EWwOCFPIdeXr_4Q4WMMi8sBgF9QjmBp6QQcP-OrgwqwTVJEYfrInkHsRhey3bNPybrAlmj5sF3w1reLAeqJD0p" + "WZ4lGmq027m-oAESe9OXZb1AobsjuIOxCrgprd4XMRuQKVBZVwk28O5exr2roL4Hrb_zBQVTfGfxAE2vRp5tdg" + "Ak9vBwlWh_3jWmJlG1BL7qynkoLOgwAakU_dnvrOfm0VlZq-5TazxMtT5XOzkSjQIDAQABKJkgEoACMjGvs7ZD" + "6n2zCV_co_6N9J4pnSsZ_p2nq18obvIXoIImvQ1TDpaD-7eO3syn2Lw_H5rAOlOo1IApwPSQpq8wG9onMW5ZIE" + "CaWoiay6SVOdHZLAt4SxgdoRTzu0XtvHu6fN36blmVAOkvjA3RHs6-u4D-xzJz1cYgvzCzDAvhqQ8bhuqRNJc5" + "2WG1ic4bG4PTHhNeSJt1KjJDGtG9botphtvQyYBzhytTSRH8jr-lKMYvaWm21LUHmmQLAvpZiczKxwjUEw5Ghg" + "IPi1D56jj4JCQpNVX4L8kgrTP0E5i1Mv4B4otQ9201NJg1MocUlpurZ_aOs8wwqsXScf_z4bHJYhq2BQqwAggB" + "EhAITWC8ZZN9tqx_mStB7PXyGKLTiowFIo4CMIIBCgKCAQEAmRs1e7cU3srB5w6qNtHQg03ySj0QNp-Qoic0o6" + "1K68z8JDK91tzR_9dWmbpWCMRFeXLSfEerz_jIjNmQCTgmC4yFeVMnsq7zodsn6LliA5KE1gLGp0xqFDpnvmSh" + "ahyPRPr62sJCzrbYrenE1FQuvT7p0qCnHrekzPkW4C8meTsME6SSHD7tScXJbNRVWY7eBAzkcrAVqa882oLEl5" + "Kqf2u_v0ZnKTtE7HQpw5oDiRHOH-Riw16VwmTTYzQ8OtuUT6KqvboPthxAJ5dYXz37eW9s4dzzt5yYh76YFHDs" + "vLBI5Z5WT8OtLEuGD3CqRo-2bEooR-7HVa3om9YiV0DJpQIDAQABKJkgMAESgAMhLeFBwTBXwZhyGN1_vC3J-E" + "yC-R9bFj0DcMcGk4fHDJDDBg8FBFc8bgvTrLmE_Dq3siGnfTczMk1nCppe6mRpHVZmqbZ902eAPNV1O9depyOb" + "7AwAgpdpV3HOIDxgiY1PJkrVXT0ByW9m1vtsU9GSimCtBA19SOnIPWhJwkjkXA-Vu7jNCx_u5EWMXGCrDVLh-w" + "-O6Ydmr5z5MwdXhlfoAPGk7T9qAOiVGyFY9Fz8wvfl5cw9fwTqK-NKqN1J69eMYYwUBOMIJX5QKqyN8A1SqJhT" + "Ab_l5ueE13sLxSyTWosYP7Wv7SWlhVp3_PJxXJB2EWJKWLA32BmFe6uSa-5NVgJ3CJ77Bw-z9ThdHd4eSG2PMt" + "JT3oaS4wmONbMZJkfnlUTPD7KLNiEz6UKXeBzz9olgUxZn7nTnAmvXITfrHd0FeDTPHavo1wafiKy0t6QCRw8o" + "ASZLtJw7_uJPxkCkY3TWwQvH0rlgeS0R2lCGq4zP9GGAwkPDldIvGp5PawIaEwoMY29tcGFueV9uYW1lEgN3d3" + "caEQoKbW9kZWxfbmFtZRIDd3d3GiAKDHByb2R1Y3RfbmFtZRIQV2lkZXZpbmVDYXNUZXN0cxomChFhcmNoaXRl" + "Y3R1cmVfbmFtZRIRYXJjaGl0ZWN0dXJlX25hbWUaGgoLZGV2aWNlX25hbWUSC2RldmljZV9uYW1lMgIoDhIgCh" + "4KHBoNd2lkZXZpbmVfdGVzdCIJQ2FzVHNGYWtlWAIYASDk7dThBTAVONOi-_4CGoACBXDXgJopfGQLxWI0z-o2" + "h-dH3L-ObMMm3moRAv7MQ-xnTALlyNMRCaGsfyy1L0SmsrQQptJjK7hB6tZDe-UQ76fIpQLeHnNOBXuaxl7sY2" + "Gvrztx8HT_N0KFgAZ9hW1L--zvFw0R1ctjG88xGTpmFWsGoWEZ0NGTgc1XyssK62tuWz5CfIEXvhN7ZiMyoagP" + "SOWZZ1Mltbiv1AEPeFC6My-njq8N3u9whokMzhlGMePSBctFmn4f8RtUeR7zlLdPuKcp0BBLAOF7ngXF1C-skj" + "-Y1DrtxwqwczA56yLzXGlh5FhwhaFMSprOHbAFCIQ-ee66aDIbVZ-9_fBMiIE83Q=="; public static String loadCertificateStatusListFromFile(String certificateStatusListFile) throws IOException { BufferedReader br = Files.newBufferedReader(Paths.get(certificateStatusListFile), UTF_8); StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append(System.lineSeparator()); line = br.readLine(); } br.close(); return sb.toString(); } public static void multiContentLicenseRequestGeneration(WvPLCASProxySession session) { WvPLPlaybackPolicy policy = new WvPLPlaybackPolicy(); policy.setLicenseDurationSeconds(604800); policy.setPlaybackDurationSeconds(86400); session.setPolicy(policy); System.out.println( "License Duration Seconds = " + session.getPolicy().getLicenseDurationSeconds()); System.out.println( "Playback duration Seconds = " + session.getPolicy().getPlaybackDurationSeconds()); // Add keys for each single content shown in this multi content license. // Assume key1 and key2 are entitlement keys created for single content. WvPLCasKey key1 = new WvPLCasKey(); byte[] oddKeyId = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; key1.setOddKeyId(oddKeyId); byte[] oddKeyBytes = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; key1.setOddKeyBytes(oddKeyBytes); byte[] evenKeyId = {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0}; key1.setEvenKeyId(evenKeyId); byte[] evenKeyBytes = {16, 15, 14, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; key1.setEvenKeyBytes(evenKeyBytes); key1.setTrackType(WvPLTrackType.TrackType.VIDEO_HD); key1.setKeyType(WvPLKeyType.KeyType.ENTITLEMENT); WvPLOutputProtection requiredOutputProtection = new WvPLOutputProtection(); // Set required output protection fields. requiredOutputProtection.setSecuredataPath(true); requiredOutputProtection.setDisableAnalogOutput(true); // Set output protection on the Cas key. key1.setOutputProtection(requiredOutputProtection); // Config key for one single content. WvPLKeyCategorySpec keyCategorySpec = new WvPLKeyCategorySpec(); keyCategorySpec.setKeyCategory(WvPLKeyCategory.KeyCategory.SINGLE_CONTENT_KEY_DEFAULT); // Content id instead of group id needs to fill in since this is a key for // SINGLE_CONTENT_KEY_DEFAULT. String contentId1 = "content_1"; keyCategorySpec.setContentOrGroupId(contentId1.getBytes(UTF_8)); key1.setKeyCategorySpec(keyCategorySpec); // Add WvPLCasKey to WvPLSession. WvPLStatus status = session.addKey(key1); // Add key for another single content. // Adding a TrackType.VIDEO_SD with even key and even keyId. WvPLCasKey key2 = new WvPLCasKey(); evenKeyId = new byte[] {10, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; evenKeyBytes = new byte[] {10, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 10, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; key2.setEvenKeyId(evenKeyId); key2.setEvenKeyBytes(evenKeyBytes); key2.setTrackType(WvPLTrackType.TrackType.VIDEO_SD); WvPLKeyCategorySpec keyCategorySpec2 = new WvPLKeyCategorySpec(); keyCategorySpec2.setKeyCategory(WvPLKeyCategory.KeyCategory.SINGLE_CONTENT_KEY_DEFAULT); // Content id instead of group id needs to fill in since this is a key for // SINGLE_CONTENT_KEY_DEFAULT. String contentId2 = "content_2"; keyCategorySpec2.setContentOrGroupId(contentId2.getBytes(UTF_8)); key2.setKeyCategorySpec(keyCategorySpec2); status = session.addKey(key2); List wvplCasKeys = session.getKeys(); // Validate setting/getting sessionInit values. WvPLSessionInit sessionInit = new WvPLSessionInit(); String testSessionId = "TestSessionId"; String testPurchaseId = "TestPurchaseId"; String testProviderClientToken = "TestProviderClientToken"; byte[] testMasterSigningKeys = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; boolean testOverrideProviderClientToken = true; sessionInit.setSessionId(testSessionId); sessionInit.setPurchaseId(testPurchaseId); sessionInit.setMasterSigningKey(testMasterSigningKeys); sessionInit.setProviderClientToken(testProviderClientToken); sessionInit.setOverrideProviderClientToken(testOverrideProviderClientToken); // Set licenseCategorySpec in sessionInit where License Category should be // MULTI_CONTENT_LICENSE. WvPLLicenseCategorySpec licenseCategorySpec = new WvPLLicenseCategorySpec(); licenseCategorySpec .setLicenseCategory(WvPLLicenseCategory.LicenseCategory.MULTI_CONTENT_LICENSE); String groupId = "user_group_1"; licenseCategorySpec.setContentOrGroupId(groupId.getBytes(UTF_8)); sessionInit.setLicenseCategorySpec(licenseCategorySpec); session.setSessionInit(sessionInit); WvPLSessionInit retrievedSessionInit = session.getSessionInit(); System.out.println( "retrieved session init fields: sessionId = " + retrievedSessionInit.getSessionId() + ", purchaseId = " + retrievedSessionInit.getPurchaseId() + ", masterSigningKey = " + Arrays.toString(retrievedSessionInit.getMasterSigningKey()) + ", providerClientToken = " + retrievedSessionInit.getProviderClientToken() + ", overrideProviderClientToken = " + retrievedSessionInit.getOverrideProviderClientToken() + ", licenseCategorySpec= " + retrievedSessionInit.getLicenseCategorySpec().toString()); } public static void main(String[] argv) throws Exception { byte[] passphraseBytes = PASSPHRASE.getBytes(UTF_8); byte[] decodedDrmServiceCertificate = Base64.getUrlDecoder().decode(B64_DRM_SERVICE_CERTIFICATE_WITH_CAS_PROXY_TYPE); byte[] decodedPrivateKey = Base64.getUrlDecoder().decode(B64_PRIVATE_KEY_WITH_CAS_PROXY_TYPE); byte[] decodedLicenseRequest = Base64.getUrlDecoder().decode(B64_LICENSE_REQUEST); java.util.Map configValues = new HashMap<>(); // Define the configuration that is to be used for WvPLCASEnvironment. configValues.put("drm_certificate_type", "dev"); configValues.put("provider", "widevine_test"); configValues.put("provider_iv", PROVIDER_IV); configValues.put("provider_key", PROVIDER_KEY); // Set the device certificate expiration to 10 years (10 * 365 * 24 * 3600). // Note that in practice, the expiration should not be 10 years long. Certificate status list // should be updated periodically. configValues.put("device_certificate_expiration", "315360000"); // Construct WvPLCASProxyEnvironment. WvPLCASProxyEnvironment environment = new WvPLCASProxyEnvironment(configValues); WvPLStatus status = environment.setServiceCertificate( decodedDrmServiceCertificate, decodedPrivateKey, passphraseBytes); if (status.getStatusCode() != WvPLStatus.StatusCode.OK) { System.out.println("setServiceCertificate status = " + status.getStatusCode() + ", message = " + status.getMessage()); } else { System.out.println("Successfully loaded service certificate"); } // Get Device Certificate Status List Request. try { byte[] deviceCertificateStatusListRequest = environment.generateDeviceStatusListRequest(); System.out.println( "generateDeviceStatusListRequest = " + Arrays.toString(deviceCertificateStatusListRequest)); } catch (WvPLStatusException e) { status = e.getStatus(); System.out.println("GenerateDeviceStatusListRequest exception: code = " + status.getStatusCode() + ", message = " + status.getMessage()); } // Get service certificate response. byte[] serviceCertificateResponse = environment.generateDrmServiceCertificateResponse(); System.out.println( "Service certificate response = " + Arrays.toString(serviceCertificateResponse)); // Set device certificate statusList. String certificateStatusListFile = "sdk/testing/sampleTestCertificateStatusList.json"; String certList = ""; try { certList = loadCertificateStatusListFromFile(certificateStatusListFile); } catch (FileNotFoundException e) { System.out.println("FileNotFoundException in reading input cert list."); } catch (IOException e) { System.out.println("IOException in reading input cert list."); } status = environment.setDeviceCertificateStatusList(certList.getBytes(UTF_8)); if (status.getStatusCode() != WvPLStatus.StatusCode.OK) { System.out.println("setServiceCertificate status = " + status.getStatusCode() + ", message = " + status.getMessage()); } else { System.out .println("Successfully set DeviceCertificateStatusList in WvPLCASProxyEnvironment."); } // Construct a WVPLCASProxySession for a license request. WvPLCASProxySession session = null; try { session = environment.createSession(decodedLicenseRequest); } catch (WvPLStatusException e) { System.out.println("Message: " + e.getMessage()); System.out.println("Status message: " + e.getStatus().getMessage()); } System.out.println("Successful create WvPLCASProxySession in WvPLCASProxyEnvironment."); System.out.println("Version of Cas Proxy SDK library: " + WvPLCASProxySession.getVersionString()); WvPLRequestType requestType = session.getRequestType(); System.out.println("Message type : " + requestType.getMessageType()); System.out.println("License type : " + requestType.getLicenseType()); System.out.println("LicenseRequest type : " + requestType.getLicenseRequestType()); // Examine the license request by retrieving WvPLClientInfo. try { WvPLClientInfo clientInfo = session.getClientInfo(); WvPLHdcp.HDCP maxHdcpVersion = clientInfo.getMaxHdcpVersion(); System.out.println("WvPLClientInfo, max hdcp version = " + maxHdcpVersion.getHDCP() + ", oem crypto api version = " + clientInfo.getOemCryptoApiVersion() + ", provider client token = " + clientInfo.getProviderClientToken()); Map namesValues = clientInfo.getNamesValues(); for (Map.Entry nameValue : namesValues.entrySet()) { System.out.println("Key = " + nameValue.getKey() + ", Value = " + nameValue.getValue()); } } catch (WvPLStatusException e) { status = e.getStatus(); System.out.println("GetClientInfo WvPLStatus: code = " + status.getStatusCode() + ", message = " + status.getMessage()); } // Retrieve the content ID byte[] contentId = session.getContentId(); System.out.println("Content ID: " + Arrays.toString(contentId)); // Examine the license request by retrieving WvPLDeviceInfo. try { WvPLDeviceInfo deviceInfo = session.getDeviceInfo(); System.out.println("soc = " + deviceInfo.getSoc() + ", manufacturer = " + deviceInfo.getManufacturer() + ", model = " + deviceInfo.getModel() + ", device_type = " + deviceInfo.getDeviceType() + ", system_id = " + deviceInfo.getSystemId()); // Retrieve DRM Device Certificate serial number. byte[] drmDeviceCertificateSerialNumber = deviceInfo.getDrmCertificateSerialNumber(); System.out.println("DrmDeviceCertificateSerialNumber = " + Arrays.toString(drmDeviceCertificateSerialNumber)); } catch (WvPLStatusException e) { status = e.getStatus(); System.out.println("GetDeviceInfo WvPLStatus: code = " + status.getStatusCode() + ", message = " + status.getMessage()); } // Insert policy and keys for multi_content_license. multiContentLicenseRequestGeneration(session); // Retrieve session pssh data. try { WvPLWidevinePsshData widevinePsshData = session.getPsshData(); System.out.println("ContentId from Widevine Pssh = " + Arrays.toString(widevinePsshData.getContentId())); if (!widevinePsshData.getKeyIds().isEmpty()) { for (byte[] keyId : widevinePsshData.getKeyIds()) { System.out.println("keyId from Widevine Pssh = " + Arrays.toString(keyId)); } } else { System.out.println("KeyIds from Widevine Pssh is empty"); } } catch (WvPLStatusException e) { status = e.getStatus(); System.out.println("Get WvPLStatus: code = " + status.getStatusCode() + ", message = " + status.getMessage()); } // Retrieve a CAS License request that is to be sent to Widevine License Service using HTTP(s) // POST. String licenseRequest = session.generateLicenseRequestAsJSON(); System.out.println("License request is: " + licenseRequest); try { WvPLClientCapabilities wvplClientCapabilities = session.getClientCapabilities(); System.out.println("WvPLClientCapabilities = " + wvplClientCapabilities); } catch (WvPLStatusException e) { status = e.getStatus(); System.out.println("GetClientInfo WvPLStatus: code = " + status.getStatusCode() + ", message = " + status.getMessage()); } // Destroy the created session. environment.destroySession(session); // Tear down the environment object. environment.close(); } }