מסגרת CAS

המסגרת של מערכות הגישה המותנית של מדיה (Media CAS) מספקת ממשקי API רגילים שמאפשרים להפעיל שירותי גישה מותנית (CA) במגוון חומרות של טלוויזיה דיגיטלית, כולל מערכות כבלים דיגיטליות, מערכות לוויין, מערכות יבשתיות ומערכות IPTV. המסגרת פועלת עם Android TV Input framework ו-Android TV Tuner framework, ומספקת ממשקי Java API שמופעלים מאפליקציית TV Input Service‏ (TIS).

היעדים העיקריים של Media CAS הם:

  • לספק ממשק API ציבורי ל-Java ותשתית פלאגין מקורית שיזמי צד שלישי ויצרני ציוד מקורי (OEM) יוכלו להשתמש בהם כדי לתמוך ב-CAS לטלוויזיה ב-Android.
  • לספק מסגרת CAS ב-Android שמאפשרת ליצרני ציוד מקורי לטלוויזיות חכמות (ATV) לבצע פעולות הדדיות עם מגוון ספקי CAS באופן עקבי.
  • תמיכה במספר ספקי CAS של צד שלישי באמצעות פלאגינים מקומיים. יכול להיות שבתוספים של CAS נעשה שימוש בפרוטוקולים ספציפיים לרשת, בפורמטים של הודעות לניהול הרשאות (EMM) או של הודעות לבקרת הרשאות (ECM) ובמנגנוני דקומפרסיה.
  • תמיכה באבטחת חומרה, כמו סולם מפתחות.
  • תמיכה בסביבות מחשוב מהימנות (TEE), כמו TrustZone.

תצורות נתמכות

הגדרת טיונר חומרה

אם החומרה אחראית לביטול המרובולקס ולפענוח של MPEG transport stream, Tuner framework מספק לאפליקציית TIS נתוני PSI (מידע ספציפי לתוכנית של גישה מותנית) כדי ליצור ממשק עם מקלטי טלוויזיה מבוססי-חומרה.

נתוני PSI של גישה מותנית כוללים מתארי CA, ECM ו-EMM. המבנים האלה מאפשרים לפלאגין CAS לקבל את המפתחות הנדרשים לפענוח של מקורות התוכן.

דיאגרמה של הגדרת המקלט החומרה.

איור 1. הגדרת טיונר חומרה

תצורת החומרה עשויה לכלול שכבת TEE, כמו TrustZone, כפי שמוצג באיור 1. אם אין שכבת TEE, הפלאגין של לקוח CAS יכול לתקשר עם שירותי שרשת מפתחות לחומרה שסופקו על ידי הפלטפורמה. בגלל השינויים הספציפיים למוכר בממשקים האלה, מערכת Media CAS לא סטנדרטיזציה אותם.

הגדרת תוכנה

לפני Android 11, עדיין אפשר היה להשתמש במסגרת Media CAS כדי לעבד תוכן מבוסס-תוכנה, כמו IPTV מ-IP multicast/unicast. אפליקציית TIS אחראית ליצירת אובייקט Java של Media CAS ולהקצאה נכונה שלו.

יכול להיות שהאפליקציה תשתמש ב-MediaExtractor או בניתחים אחרים של MPEG2-TS כדי לחלץ נתוני PSI שקשורים ל-CA, כמו מתארי CA, הודעות ECM והודעות EMM. אם האפליקציה משתמשת במסגרת MediaExtractor, היא יכולה להעביר את ניהול הסשנים של CAS, כמו פתיחת סשן ועיבוד EMM/ECM, למסגרת MediaExtractor. לאחר מכן, MediaExtractor מגדיר את סשן ה-CAS ישירות באמצעות ה-API המקורי.

אחרת, האפליקציה אחראית לחילוץ נתוני ה-PSI שקשורים ל-CA ולהגדרת סשן ה-CAS באמצעות ממשקי ה-API של Media CAS ל-Java (לדוגמה, כשהאפליקציה משתמשת בניתוח MPEG2-TS משלה).

תרשים של הגדרת הטיונר.

איור 2. הגדרת קלט IPTV, CAS ו-descrambler באמצעות המסגרת MediaExtractor

בתרחיש של חילוץ תוכנה, לחלץ נדרש אובייקט של מפרק קוד (descrambler) מבוסס-תוכנה או מבוסס-חומרה לכל טראק מוצפן, ללא קשר לקריאה של הטראק לפענוחים מאובטחים. הסיבה לכך היא:

  • אם הטראק לא דורש פענוח מאובטח, הכלי לחילוץ מבצע פענוח של יחידת הגישה כדי לנקות את המאגרים ומחליץ דגימות כאילו מזרם נקי. כך MediaCodec לא צריך להיות מעורב בפענוח.
  • אם הטראק דורש פענוח מאובטח, יכול להיות שעדיין יהיה צורך במפענח בתוך המחולץ. המצב הזה מתרחש כשזרם התעבורה עבר ערבול ברמת החבילה של התעבורה, שבה עבר ערבול של הכותרת של זרם האלמנטים המנותב (PES). למחולל הנתונים צריכה להיות גישה לכותרת ה-PES כדי לקבל מידע מסוים במורד הזרם (לדוגמה, חותמת הזמן של ההצגה).

    אם מקור הנתונים עבר ערבול ברמת החבילה של ה-PES, כותרת ה-PES נשארת ללא שינוי, והחילוץ לא משתמש במפענח. עם זאת, אי אפשר לאשר מתי מתרחש הערבוב עד שמגיעה החבילה המעורבת בפועל. כדי לפשט את העניין, נניח שמשתמשים במפענח אם נקבע שהטראק מוצפן על סמך טבלת מיפוי התוכניות (PMT).

מגבלות של הגדרות תוכנה

כשהטראק מחייב פענוח מאובטח, צריך להפעיל שיקול דעת כשמאפשרים לפעולת פענוח לעבור למאגרים גלויים. מאחר שנדרש פענוח אודיו לא מאובטח, אם פענוח הווידאו מחייב מפענחים מאובטחים, צריך לערבב אותו בסשן אחר מהאודיו. ה-ECM של הסשן צריך להעביר ל-Plugin אות על כך שנדרש מפענח מאובטח.

לחלופין, הפלאגין צריך להיות מסוגל לקשר מפתח למדיניות האבטחה שלו באופן מהימן. אחרת, האפליקציה יכולה לקבל בקלות פריימים של וידאו באמצעות מפענח האודיו.

גם אם הסשן מחייב מפענח מאובטח, יכול להיות שהוא יתבקש להפיק כמות קטנה של נתונים כדי לנקות את המאגרים של המחולץ לצורך עיבוד כותרת ה-PES. כדי למנוע מאפליקציה זדונית לגרום לפלאגין להחזיר את כל יחידת הגישה, הפלאגין צריך לנתח את עומס העבודה של התעבורה כדי לוודא שעומס העבודה מתחיל בכותרת PES מסוג הסטרימינג המתאים. אחרת, הפלאגין צריך לדחות את הבקשה.

רצף כוונון של רשות אישורים

כשמכוונים לערוץ חדש, מודול ה-TIS מתעדכן כדי לקבל מתבניות ה-PSI Tuner מתארי CA,‏ ECM ו-EMM. מתאר של רשות אישורים מכיל את מזהה המערכת של רשות האישורים, שמזהה באופן ייחודי ספק ספציפי של רשות אישורים ונתונים אחרים שספציפיים לספק. מערכת TIS שולחת שאילתה ל-Media CAS כדי לקבוע אם יש פלאגין CAS שיכול לטפל במתאר ה-CA.

תרשים של התאמת התוכן של CAS.

איור 3. התאמת התוכן של CAS

אם מזהה מערכת ה-CA נתמך, נוצרת מופע של Media CAS והנתונים הפרטיים של הספק מתוארת ה-CA מסופקים לתוסף. לאחר מכן, נפתחים סשנים חדשים ב-Media CAS כדי לטפל בזרמי האודיו והווידאו. הסשנים שנפתחים מקבלים הודעות ECM ו-EMM עבור הפלאגין.

תהליך לדוגמה של פלאגין CAS

TIS מעביר את קובצי ה-ECM לתוסף CAS באמצעות ממשקי Media CAS API. קובץ ECM מכיל את מילות הבקרה המוצפנות, שצריך לפענח באמצעות מידע מ-EMM. הפלאגין של CAS קובע איך לקבל EMM לנכס על סמך מידע ספציפי לספק בתיאור ה-CA, שמסופק על ידי השיטה setPrivateData().

ייתכן שה-EMMs יועברו בפס ברוחב פס של שידור התוכן או מחוץ לפס באמצעות בקשת רשת שמופעלת על ידי הפלאגין של CA. TIS משתמשת בשיטה processEMM() כדי להעביר ל-CA plugin את כל ה-EMMs בתחום התדרים.

אם נדרשת בקשת רשת כדי לקבל EMM, הפלאגין של CA אחראי לבצע את העסקה ברשת עם שרת הרישיונות.

דיאגרמה של דוגמה ל-CAS.

איור 4. דוגמה לפלאגין CAS לעיבוד EMM ו-ECM

כשמקבלים את ה-EMM, הפלאגין של CA מנתח אותו כדי לקבל את המפתח המוצפן לצורך פענוח של מילת הבקרה. יכול להיות שמפתח ה-EMM המוצפן ומילה הבקרה המוצפנת ייטענו בסולם מפתחות או בסביבה מהימנה כדי לבצע את פענוח של מילה הבקרה ואת פענוח הנתונים של תוכן השידור.

Media CAS Java API

ממשק ה-API של Media CAS ל-Java מכיל את השיטות הבאות.

  • הצגת רשימה של כל יישומי הפלאגין של 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);
    
  • רושמים מאזין לאירועים ומאפשרים לאפליקציה לציין גורם מטפל שבו נעשה שימוש בלולאה.

    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, מטבלת הגישה המותנית או ממקורות מחוץ לתחום. הערך הזה לא משויך לסשן ספציפי.

    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);
    
  • סוגרים את אובייקט ה-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);