เฟรมเวิร์กระบบการเข้าถึงแบบมีเงื่อนไขของสื่อ (Media CAS) มี API มาตรฐานเพื่อให้เปิดใช้บริการการเข้าถึงแบบมีเงื่อนไข (CA) ในฮาร์ดแวร์ทีวีดิจิทัลหลากหลายประเภท ซึ่งรวมถึงระบบเคเบิลดิจิทัล ดาวเทียม ภาคพื้นดิน และ IPTV เฟรมเวิร์กนี้ทำงานร่วมกับ เฟรมเวิร์กอินพุตของ Android TV และ เฟรมเวิร์กจูนเนอร์ของ Android TV, โดยมี Java API ที่เรียกใช้จากแอปบริการอินพุตของทีวี (TIS)
วัตถุประสงค์หลักของ Media CAS มีดังนี้
- จัดเตรียม Java API สาธารณะและเฟรมเวิร์กปลั๊กอินดั้งเดิมที่นักพัฒนาแอปของบุคคลที่สามและ OEM สามารถใช้เพื่อรองรับ CAS สำหรับทีวีที่ออกอากาศใน Android
- จัดเตรียมเฟรมเวิร์ก CAS ภายใน Android ที่ช่วยให้ OEM ของ ATV ทำงานร่วมกับผู้ให้บริการ CAS ที่หลากหลายได้อย่างสอดคล้องกัน
- รองรับผู้ให้บริการ CAS ของบุคคลที่สามหลายรายโดยใช้ปลั๊กอินดั้งเดิม ปลั๊กอิน CAS อาจใช้โปรโตคอลเครือข่ายเฉพาะของผู้ให้บริการ รูปแบบข้อความการจัดการสิทธิ์ (EMM)/ข้อความการควบคุมสิทธิ์ (ECM) และตัวถอดรหัส
- รองรับการรักษาความปลอดภัยของฮาร์ดแวร์ เช่น คีย์แลดเดอร์
- รองรับสภาพแวดล้อมการดำเนินการที่เชื่อถือได้ (TEE) เช่น TrustZone
การกำหนดค่าที่รองรับ
การกำหนดค่าจูนเนอร์ฮาร์ดแวร์
หากฮาร์ดแวร์มีหน้าที่รับผิดชอบในการแยกสัญญาณมัลติเพล็กซ์ของสตรีมการขนส่ง MPEG และการถอดรหัส เฟรมเวิร์กจูนเนอร์ จะให้ข้อมูลเฉพาะของโปรแกรมการเข้าถึงแบบมีเงื่อนไข (PSI) แก่ แอป TIS เพื่อเชื่อมต่อกับจูนเนอร์ทีวีที่ใช้ฮาร์ดแวร์
ข้อมูล PSI การเข้าถึงแบบมีเงื่อนไขประกอบด้วยตัวอธิบาย CA, ECM และ EMM โครงสร้างเหล่านี้ช่วยให้ปลั๊กอิน CAS ได้รับคีย์ที่จำเป็นในการถอดรหัสสตรีมเนื้อหา
รูปที่ 1 การกำหนดค่าจูนเนอร์ฮาร์ดแวร์
การกำหนดค่าฮาร์ดแวร์อาจมีเลเยอร์ TEE เช่น TrustZone ซึ่งแสดงไว้ในรูปที่ 1 หากไม่มีเลเยอร์ TEE ปลั๊กอินไคลเอ็นต์ CAS จะสื่อสารกับบริการคีย์แลดเดอร์ฮาร์ดแวร์ที่แพลตฟอร์มจัดเตรียมไว้ให้ได้ Media CAS ไม่ได้กำหนดมาตรฐานอินเทอร์เฟซเหล่านี้เนื่องจากมีความแตกต่างกันไปตามผู้ให้บริการ
การกำหนดค่าซอฟต์แวร์
ก่อน Android 11 เฟรมเวิร์ก Media CAS ยังคงใช้เพื่อประมวลผลเนื้อหาที่ใช้ซอฟต์แวร์ เช่น IPTV จาก IP มัลติแคสต์/ยูนิแคสต์ แอป TIS มีหน้าที่รับผิดชอบในการสร้างอินสแตนซ์และจัดเตรียมออบเจ็กต์ Media CAS Java อย่างเหมาะสม
แอปอาจใช้ MediaExtractor หรือตัวแยกวิเคราะห์ MPEG2-TS อื่นๆ เพื่อแยกข้อมูล PSI ที่เกี่ยวข้องกับ CA เช่น ตัวอธิบาย CA, ECM และ EMM หากแอปใช้เฟรมเวิร์ก MediaExtractor แอปจะมอบหมายการจัดการเซสชัน CAS เช่น การเปิดเซสชันและการประมวลผล EMM/ECM ให้กับเฟรมเวิร์ก MediaExtractor ได้ จากนั้น MediaExtractor จะกำหนดค่าเซสชัน CAS โดยใช้ Native API โดยตรง
มิเช่นนั้น แอปจะมีหน้าที่รับผิดชอบในการแยกข้อมูล PSI ที่เกี่ยวข้องกับ CA และกำหนดค่าเซสชัน CAS โดยใช้ Media CAS Java API (เช่น เมื่อแอปใช้ตัวแยกวิเคราะห์ MPEG2-TS ของตัวเอง)
รูปที่ 2 การกำหนดค่าอินพุต IPTV, CAS และตัวถอดรหัสโดยใช้เฟรมเวิร์ก MediaExtractor
ในสถานการณ์ตัวแยกวิเคราะห์ซอฟต์แวร์ ตัวแยกวิเคราะห์ต้องใช้ออบเจ็กต์ตัวถอดรหัสที่ใช้ซอฟต์แวร์หรือฮาร์ดแวร์สำหรับแทร็กที่เข้ารหัสแต่ละแทร็ก ไม่ว่าแทร็กจะเรียกใช้ตัวถอดรหัสที่ปลอดภัยหรือไม่ก็ตาม ทั้งนี้เป็นไปตามเหตุผลต่อไปนี้
- หากแทร็กไม่จำเป็นต้องถอดรหัสอย่างปลอดภัย ตัวแยกวิเคราะห์จะถอดรหัสหน่วยการเข้าถึงเพื่อล้างบัฟเฟอร์และแยกตัวอย่างราวกับว่ามาจากสตรีมที่ชัดเจน วิธีนี้ช่วยให้
MediaCodecไม่จำเป็นต้องมีส่วนร่วมในการถอดรหัส หากแทร็กจำเป็นต้องถอดรหัสอย่างปลอดภัย ตัวแยกวิเคราะห์อาจยังคงต้องใช้ตัวถอดรหัส ซึ่งจะเกิดขึ้นเมื่อสตรีมการขนส่งถูกเข้ารหัสที่ระดับแพ็กเก็ตการขนส่ง โดยที่ส่วนหัวของแพ็กเก็ตสตรีมพื้นฐาน (PES) ถูกเข้ารหัส ตัวแยกวิเคราะห์ต้องเข้าถึงส่วนหัวของ PES เพื่อส่งข้อมูลบางอย่างไปยังปลายทาง (เช่น การประทับเวลาการนำเสนอ)
ตัวแยกวิเคราะห์จะไม่ใช้ตัวถอดรหัสหากสตรีมการขนส่งถูกเข้ารหัสที่ระดับแพ็กเก็ต PES โดยที่ส่วนหัวของ PES ยังคงชัดเจน อย่างไรก็ตาม คุณจะยืนยันไม่ได้ว่าการเข้ารหัสเกิดขึ้นเมื่อใดจนกว่าแพ็กเก็ตที่เข้ารหัสจริงจะมาถึง เพื่อความเรียบง่าย ให้ถือว่ามีการใช้ตัวถอดรหัสหากระบบพิจารณาว่าแทร็กถูกเข้ารหัสตามตารางการแมปโปรแกรม (PMT)
ข้อจำกัดของการกำหนดค่าซอฟต์แวร์
เมื่อแทร็กจำเป็นต้องถอดรหัสอย่างปลอดภัย ตัวถอดรหัสต้องระมัดระวังเมื่ออนุญาตให้ดำเนินการถอดรหัสลงในบัฟเฟอร์ที่ชัดเจน เนื่องจากจำเป็นต้องถอดรหัสเสียงอย่างไม่ปลอดภัย หากการถอดรหัสวิดีโอจำเป็นต้องใช้ตัวถอดรหัสที่ปลอดภัย ระบบควรเข้ารหัสวิดีโอในเซสชันอื่นจากเสียง ECM สำหรับเซสชันต้องส่งสัญญาณไปยังปลั๊กอินว่าจำเป็นต้องใช้ตัวถอดรหัสที่ปลอดภัย
หรือปลั๊กอินต้องสามารถเชื่อมโยงคีย์กับนโยบายการรักษาความปลอดภัยได้อย่างน่าเชื่อถือ มิเช่นนั้น แอปจะรับเฟรมวิดีโอด้วยตัวถอดรหัสเสียงได้อย่างง่ายดาย
แม้ว่าเซสชันจะจำเป็นต้องใช้ตัวถอดรหัสที่ปลอดภัย แต่ตัวแยกวิเคราะห์อาจขอให้ส่งข้อมูลจำนวนเล็กน้อยไปยังบัฟเฟอร์ที่ชัดเจนเพื่อประมวลผลส่วนหัวของ PES เพื่อป้องกันไม่ให้แอปที่เป็นอันตรายทำให้ปลั๊กอินส่งคืนหน่วยการเข้าถึงทั้งหมด ปลั๊กอินต้องแยกวิเคราะห์เพย์โหลดการขนส่งเพื่อให้แน่ใจว่าเพย์โหลดเริ่มต้นด้วยส่วนหัวของ PES ที่มีประเภทสตรีมที่เหมาะสม มิเช่นนั้น ปลั๊กอินควรปฏิเสธคำขอ
ลำดับการปรับแต่ง CA
เมื่อปรับแต่งไปยังช่องใหม่ โมดูล TIS จะลงทะเบียนเพื่อรับตัวอธิบาย CA, ECM และ EMM จากเฟรมเวิร์ก PSI Tuner ตัวอธิบาย CA มีรหัสระบบ CA ซึ่งระบุผู้ให้บริการ CA ที่เฉพาะเจาะจงและข้อมูลอื่นๆ ที่เฉพาะของผู้ให้บริการ TIS จะค้นหา Media CAS เพื่อดูว่ามีปลั๊กอิน CAS ที่จัดการตัวอธิบาย CA ได้หรือไม่
รูปที่ 3 การปรับแต่งเนื้อหา CAS
หากระบบรองรับรหัสระบบ CA ระบบจะสร้างอินสแตนซ์ของ Media CAS และส่งข้อมูลส่วนตัวของผู้ให้บริการจากตัวอธิบาย CA ไปยังปลั๊กอิน จากนั้น ระบบจะเปิดเซสชันใหม่ใน Media CAS เพื่อจัดการสตรีมเสียงและวิดีโอ เซสชันที่เปิดใหม่จะได้รับ ECM และ EMM สำหรับปลั๊กอิน
โฟลว์ปลั๊กอิน CAS ตัวอย่าง
TIS จะส่ง ECM ไปยังปลั๊กอิน CAS โดยใช้ Media CAS API ECM มีคำควบคุมที่เข้ารหัส ซึ่งต้องถอดรหัสโดยใช้ข้อมูลจาก EMM ปลั๊กอิน CAS จะกำหนดวิธีรับ EMM สำหรับชิ้นงานตามข้อมูลเฉพาะของผู้ให้บริการในตัวอธิบาย CA ซึ่งจัดเตรียมไว้ให้โดยเมธอด setPrivateData()
ระบบอาจส่ง EMM ในแบนด์ในสตรีมเนื้อหาหรือนอกแบนด์โดยใช้คำขอเครือข่ายที่ปลั๊กอิน CA เริ่มต้น TIS ใช้เมธอด processEMM() เพื่อส่ง EMM ในแบนด์ไปยังปลั๊กอิน CA
หากต้องใช้คำขอเครือข่ายเพื่อรับ EMM ปลั๊กอิน CA จะมีหน้าที่รับผิดชอบในการทำธุรกรรมเครือข่ายกับเซิร์ฟเวอร์ใบอนุญาต
รูปที่ 4 ปลั๊กอิน CAS ตัวอย่างสำหรับการประมวลผล EMM และ ECM
เมื่อได้รับ EMM แล้ว ปลั๊กอิน CA จะแยกวิเคราะห์ EMM เพื่อรับคีย์ที่เข้ารหัสเพื่อถอดรหัสคำควบคุม ระบบอาจโหลดคีย์ EMM ที่เข้ารหัสและคำควบคุมที่เข้ารหัสลงในคีย์แลดเดอร์หรือสภาพแวดล้อมที่เชื่อถือได้เพื่อดำเนินการถอดรหัสคำควบคุมและถอดรหัสสตรีมเนื้อหาในภายหลัง
Media CAS Java API
Media CAS Java API มีเมธอดต่อไปนี้
แสดงรายการปลั๊กอิน CA ทั้งหมดที่พร้อมใช้งานในอุปกรณ์
class MediaCas.PluginDescriptor { public String getName(); public int getSystemId(); } static PluginDescriptor[] enumeratePlugins();สร้างอินสแตนซ์ Media CAS สำหรับระบบ CA ที่ระบุ ซึ่งหมายความว่าเฟรมเวิร์ก Media CAS สามารถจัดการระบบ CAS หลายระบบพร้อมกันได้
MediaCas(int CA_system_id); MediaCas(@NonNull Context context, int casSystemId, @Nullable String tvInputServiceSessionId, @PriorityHintUseCaseType int priorityHint);ลงทะเบียน Listener เหตุการณ์และอนุญาตให้แอประบุแฮนเดิลอร์ที่จะใช้ Looper
interface MediaCas.EventListener { void onEvent(MediaCas, int event, int arg, byte[] data); void onSessionEvent(@NonNull MediaCas mediaCas, @NonNull Session session, int event, int arg, @Nullable byte[] data); void onPluginStatusUpdate(@NonNull MediaCas mediaCas, @PluginStatus int status, int arg); void onResourceLost(@NonNull MediaCas mediaCas); } void setEventListener(MediaCas.EventListener listener, Handler handler);ส่งข้อมูลส่วนตัวสำหรับระบบ CA ข้อมูลส่วนตัวอาจมาจากตัวอธิบาย CA, ตารางการเข้าถึงแบบมีเงื่อนไข หรือแหล่งที่มานอกแบนด์ ข้อมูลนี้ไม่ได้เชื่อมโยงกับเซสชันใดเซสชันหนึ่ง
void setPrivateData(@NonNull byte[] data);ประมวลผลแพ็กเก็ต EMM
void processEmm(@NonNull byte[] data, int offset, int length);ส่งเหตุการณ์ไปยังระบบ CA รูปแบบของเหตุการณ์จะเฉพาะเจาะจงกับสคีมาและเฟรมเวิร์กจะไม่ทราบ
void sendEvent(int event, int arg, @Nullable byte[] data);เริ่มการดำเนินการจัดเตรียมประเภทที่ระบุสำหรับระบบ CA เมื่ออุปกรณ์ลงชื่อสมัครใช้บริการทีวีแบบชำระเงินเป็นครั้งแรก อุปกรณ์จะต้องได้รับการจัดเตรียมไปยังเซิร์ฟเวอร์ CAS ก่อน ระบุชุดพารามิเตอร์ที่เกี่ยวข้องให้กับอุปกรณ์สำหรับการจัดเตรียม
void provision(String provisionString);ทริกเกอร์การรีเฟรชสิทธิ์ เมื่อผู้ใช้สมัครใช้บริการช่องใหม่ (เช่น โดยการตอบสนองต่อโฆษณาหรือเพิ่มช่องในคู่มือรายการทีวี (EPG)) แอปควรบอกไคลเอ็นต์ CA ให้รีเฟรชคีย์สิทธิ์ได้
void refreshEntitlements(int refreshType);ปิดออบเจ็กต์ Media CAS
void close();เปิดเซสชัน
Session openSession(); Session openSession(@SessionUsage int sessionUsage, @ScramblingMode int scramblingMode);ปิดเซสชันที่เปิดไว้ก่อนหน้านี้
void Session#close();ระบุข้อมูลส่วนตัวของ CA จากตัวอธิบาย CA ใน PMT ซึ่งอาจมาจากส่วนข้อมูลโปรแกรมหรือส่วนข้อมูล ES ไปยังเซสชัน CAS
void Session#setPrivateData(@NonNull byte[] sessionId, @NonNull byte[] data);ประมวลผลแพ็กเก็ต ECM สำหรับเซสชัน
void Session#processEcm(@NonNull byte[] data, int offset, int length);รับรหัสเซสชัน
byte[] Session#getSessionId();ส่งเหตุการณ์เซสชันไปยังระบบ CA รูปแบบของเหตุการณ์จะเฉพาะเจาะจงกับสคีมาและเฟรมเวิร์กจะไม่ทราบ
void Session#sendSessionEvent(int event, int arg, @Nullable byte[] data);