เฟรมเวิร์กตัวรับสัญญาณ

สำหรับ Android 11 ขึ้นไป คุณสามารถใช้เฟรมเวิร์ก Android Tuner เพื่อส่งเนื้อหา A/V เฟรมเวิร์กนี้ใช้ไปป์ไลน์ฮาร์ดแวร์จากผู้ให้บริการ จึงเหมาะสำหรับทั้ง SoC ระดับล่างและระดับสูง เฟรมเวิร์กนี้มีวิธีที่ปลอดภัยในการส่งเนื้อหา A/V ที่ได้รับการปกป้องโดย สภาพแวดล้อมการดำเนินการที่เชื่อถือได้ (TEE) และเส้นทางสื่อที่ปลอดภัย (SMP) ซึ่งช่วยให้สามารถ ใช้ในสภาพแวดล้อมการปกป้องเนื้อหาที่มีการจำกัดสูง

อินเทอร์เฟซที่ได้มาตรฐานระหว่างจูนเนอร์กับผลลัพธ์ของ Android CAS ช่วยให้การผสานรวมระหว่างผู้ให้บริการจูนเนอร์กับผู้ให้บริการ CAS เร็วขึ้น อินเทอร์เฟซของจูนเนอร์ทำงานร่วมกับ MediaCodec และ AudioTrack เพื่อสร้างโซลูชันเดียวสำหรับ Android TV อินเทอร์เฟซจูนเนอร์รองรับทั้งทีวีดิจิทัลและทีวีอนาล็อกตามมาตรฐานการออกอากาศหลัก

คอมโพเนนต์

สำหรับ Android 11 มีคอมโพเนนต์ 3 อย่างที่ออกแบบมาสำหรับแพลตฟอร์มทีวีโดยเฉพาะ

  • Tuner HAL: อินเทอร์เฟซระหว่างเฟรมเวิร์กและผู้ให้บริการ
  • Tuner SDK API: อินเทอร์เฟซระหว่างเฟรมเวิร์กกับแอป
  • ตัวจัดการทรัพยากรของจูนเนอร์ (TRM): ประสานงานทรัพยากร HW ของจูนเนอร์

สำหรับ Android 11 เราได้ปรับปรุงคอมโพเนนต์ต่อไปนี้

  • CAS V2
  • TvInputService หรือบริการอินพุตทีวี (TIS)
  • TvInputManagerService หรือบริการตัวจัดการอินพุตทีวี (TIMS)
  • MediaCodec หรือตัวแปลงรหัสสื่อ
  • AudioTrackหรือแทร็กเสียง
  • MediaResourceManager หรือผู้จัดการทรัพยากรสื่อ (MRM)

แผนภาพโฟลว์ของคอมโพเนนต์เฟรมเวิร์ก Tuner

รูปที่ 1 การโต้ตอบระหว่างคอมโพเนนต์ของ Android TV

ฟีเจอร์

ส่วนหน้าของแอปพลิเคชันรองรับมาตรฐาน DTV ด้านล่าง

  • ATSC
  • ATSC3
  • DVB C/S/T
  • ISDB S/S3/T
  • แอนะล็อก

ส่วนหน้าใน Android 12 ที่มี Tuner HAL 1.1 ขึ้นไปรองรับมาตรฐาน DTV ด้านล่าง

  • DTMB

Demux รองรับโปรโตคอลสตรีมด้านล่าง

  • สตรีมการนำส่ง (TS)
  • โปรโตคอลการนำส่งสื่อ MPEG (MMTP)
  • Internet Protocol (IP)
  • ค่าความยาวประเภท (TLV)
  • โปรโตคอลเลเยอร์ลิงก์ ATSC (ALP)

โปรแกรมถอดรหัสรองรับการปกป้องเนื้อหาด้านล่าง

  • เส้นทางสื่อที่ปลอดภัย
  • เส้นทางสื่อที่ชัดเจน
  • บันทึกในเครื่องอย่างปลอดภัย
  • การเล่นในเครื่องอย่างปลอดภัย

Tuner API รองรับกรณีการใช้งานต่อไปนี้

  • สแกน
  • Live
  • การเล่น
  • บันทึก

Tuner, MediaCodec และ AudioTrack รองรับโหมดการไหลของข้อมูลด้านล่าง

  • เพย์โหลด ES ที่มีบัฟเฟอร์หน่วยความจำที่ชัดเจน
  • เพย์โหลด ES ที่มีแฮนเดิลหน่วยความจำที่ปลอดภัย
  • การแสดงภาพ

การออกแบบโดยรวม

HAL ของ Tuner จะกำหนดไว้ระหว่างเฟรมเวิร์ก Android กับฮาร์ดแวร์ของผู้ให้บริการ

  • อธิบายสิ่งที่เฟรมเวิร์กคาดหวังจากผู้ให้บริการและวิธีที่ผู้ให้บริการอาจดำเนินการ
  • ส่งออกฟังก์ชันการทำงานของส่วนหน้า, Demux และ Descrambler ไปยังเฟรมเวิร์กผ่านอินเทอร์เฟซ IFrontend, IDemux, IDescrambler, IFilter, IDvr และ ILnb
  • รวมถึงฟังก์ชันต่างๆ ในการผสานรวม Tuner HAL กับคอมโพเนนต์เฟรมเวิร์กอื่นๆ เช่น MediaCodec และ AudioTrack

ระบบจะสร้างคลาส Java ของ Tuner และคลาสเนทีฟ

  • Tuner Java API ช่วยให้แอปเข้าถึง Tuner HAL ผ่าน API สาธารณะได้
  • คลาสเนทีฟช่วยให้ควบคุมสิทธิ์และจัดการข้อมูลการบันทึกหรือการเล่นจำนวนมากได้ด้วย Tuner HAL
  • โมดูล Native Tuner เป็นตัวเชื่อมระหว่างคลาส Tuner Java กับ Tuner HAL

สร้างชั้นเรียน TRM

  • จัดการทรัพยากรจูนเนอร์ที่จำกัด เช่น Frontend, LNB, เซสชัน CAS และอุปกรณ์อินพุตทีวีจาก HAL อินพุตทีวี
  • ใช้กฎเพื่อเรียกคืนทรัพยากรที่ไม่เพียงพอจาก แอป กฎเริ่มต้นคือการชนะในเบื้องหน้า

เราได้ปรับปรุง Media CAS และ CAS HAL ด้วยฟีเจอร์ต่อไปนี้

  • เปิดเซสชัน CAS สำหรับการใช้งานและอัลกอริทึมต่างๆ
  • รองรับระบบ CAS แบบไดนามิก เช่น การนำ CICAM ออกและการแทรก
  • ผสานรวมกับ Tuner HAL โดยการระบุโทเค็นคีย์

MediaCodec และ AudioTrack ได้รับการปรับปรุงด้วยฟีเจอร์ด้านล่าง

  • ใช้หน่วยความจำ A/V ที่ปลอดภัยเป็นอินพุตเนื้อหา
  • กำหนดค่าให้ซิงค์ A/V ของฮาร์ดแวร์ในการเล่นแบบอุโมงค์
  • รองรับ ES_payload และโหมดส่งผ่าน

การออกแบบโดยรวมของ Tuner HAL

รูปที่ 2 แผนภาพของคอมโพเนนต์ภายใน Tuner HAL

เวิร์กโฟลว์โดยรวม

แผนภาพด้านล่างแสดงลำดับการเรียกสำหรับการเล่นการถ่ายทอดสด

ตั้งค่า

ลำดับการตั้งค่าของแผนภาพการเล่นการออกอากาศสด

รูปที่ 3 ลำดับการตั้งค่าสำหรับการเล่นการออกอากาศสด

การจัดการ A/V

แผนภาพการจัดการ A/V สำหรับการเล่นการถ่ายทอดสด

รูปที่ 4 การจัดการ A/V สำหรับการเล่นการถ่ายทอดสด

การจัดการเนื้อหาที่เข้ารหัส

แผนภาพการจัดการเนื้อหาที่เข้ารหัสสำหรับการเล่นการออกอากาศสด

รูปที่ 5 การจัดการเนื้อหาที่เข้ารหัสสำหรับการเล่นการถ่ายทอดสด

การประมวลผลข้อมูลภาพและเสียง

ประมวลผลข้อมูล A/V สำหรับแผนภาพการเล่นการถ่ายทอดสด

รูปที่ 6 กำลังประมวลผล A/V สำหรับการเล่นการถ่ายทอดสด

Tuner SDK API

API ของ Tuner SDK จะจัดการการโต้ตอบกับ Tuner JNI, Tuner HAL และ TunerResourceManager แอป TIS ใช้ Tuner SDK API เพื่อเข้าถึงแหล่งข้อมูลและคอมโพเนนต์ย่อยของจูนเนอร์ เช่น ฟิลเตอร์และตัวถอดรหัส Frontend และ demux เป็นคอมโพเนนต์ภายใน

แผนภาพโฟลว์ของ Tuner SDK API

รูปที่ 7 การโต้ตอบกับ Tuner SDK API

เวอร์ชัน

ตั้งแต่ Android 12 เป็นต้นไป API ของ Tuner SDK จะรองรับฟีเจอร์ใหม่ใน Tuner HAL 1.1 ซึ่ง เป็นการอัปเกรดเวอร์ชัน Tuner 1.0 ที่เข้ากันได้แบบย้อนหลัง

ใช้ API ต่อไปนี้เพื่อตรวจสอบเวอร์ชัน HAL ที่ทำงานอยู่

  • android.media.tv.tuner.TunerVersionChecker.getTunerVersion()

ดูเวอร์ชัน HAL ขั้นต่ำที่จำเป็นได้ในเอกสารประกอบของ API ใหม่ของ Android 12

แพ็กเกจ

API ของ Tuner SDK มีแพ็กเกจ 4 รายการด้านล่าง

  • android.media.tv.tuner
  • android.media.tv.tuner.frontend
  • android.media.tv.tuner.filter
  • android.media.tv.tuner.dvr

แผนภาพโฟลว์ของแพ็กเกจ API ของ Tuner SDK

รูปที่ 8 แพ็กเกจ API ของ Tuner SDK

Android.media.tv.tuner

แพ็กเกจ Tuner เป็นจุดแรกเข้าในการใช้เฟรมเวิร์ก Tuner แอป TIS ใช้แพ็กเกจเพื่อเริ่มต้นและรับอินสแตนซ์ทรัพยากรโดยการระบุ การตั้งค่าเริ่มต้นและการเรียกกลับ

  • tuner(): เริ่มต้นอินสแตนซ์ Tuner โดยระบุพารามิเตอร์ useCase และ sessionId
  • tune(): รับทรัพยากรส่วนหน้าและปรับแต่งโดยการระบุพารามิเตอร์ FrontendSetting
  • openFilter(): รับอินสแตนซ์ตัวกรองโดยการระบุประเภทตัวกรอง
  • openDvrRecorder(): รับอินสแตนซ์การบันทึกโดยการระบุขนาดบัฟเฟอร์
  • openDvrPlayback(): รับอินสแตนซ์การเล่นโดยการระบุขนาดบัฟเฟอร์
  • openDescrambler(): รับอินสแตนซ์การถอดรหัส
  • openLnb(): รับอินสแตนซ์ LNB ภายใน
  • openLnbByName(): รับอินสแตนซ์ LNB ภายนอก
  • openTimeFilter(): รับอินสแตนซ์ตัวกรองเวลา

แพ็กเกจ Tuner มีฟังก์ชันการทำงานที่ไม่ได้ครอบคลุมอยู่ในแพ็กเกจตัวกรอง DVR และส่วนหน้า ฟังก์ชันการทำงานจะแสดงอยู่ด้านล่าง

  • cancelTuning
  • scan / cancelScanning
  • getAvSyncHwId
  • getAvSyncTime
  • connectCiCam1 / disconnectCiCam
  • shareFrontendFromTuner
  • updateResourcePriority
  • setOnTuneEventListener
  • setResourceLostListener

Android.media.tv.tuner.frontend

แพ็กเกจส่วนหน้าประกอบด้วยชุดการตั้งค่า ข้อมูล สถานะ เหตุการณ์ และความสามารถที่เกี่ยวข้องกับส่วนหน้า

ชั้นเรียน

FrontendSettings ได้รับการอนุพันธ์สำหรับมาตรฐาน DTV ที่แตกต่างกันตามคลาสต่อไปนี้

  • AnalogFrontendSettings
  • Atsc3FrontendSettings
  • AtscFrontendSettings
  • DvbcFrontendSettings
  • DvbsFrontendSettings
  • DvbtFrontendSettings
  • Isdbs3FrontendSettings
  • IsdbsFrontendSettings
  • IsdbtFrontendSettings

ตั้งแต่ Android 12 ที่มี Tuner HAL 1.1 ขึ้นไป ระบบจะรองรับมาตรฐาน DTV ต่อไปนี้

  • DtmbFrontendSettings

FrontendCapabilities ได้รับการอนุพันธ์สำหรับมาตรฐาน DTV ที่แตกต่างกันตามคลาส ด้านล่าง

  • AnalogFrontendCapabilities
  • Atsc3FrontendCapabilities
  • AtscFrontendCapabilities
  • DvbcFrontendCapabilities
  • DvbsFrontendCapabilities
  • DvbtFrontendCapabilities
  • Isdbs3FrontendCapabilities
  • IsdbsFrontendCapabilities
  • IsdbtFrontendCapabilities

ตั้งแต่ Android 12 ที่มี Tuner HAL 1.1 ขึ้นไป ระบบจะรองรับมาตรฐาน DTV ต่อไปนี้

  • DtmbFrontendCapabilities

FrontendInfo เรียกข้อมูลของส่วนหน้า FrontendStatus ดึงสถานะปัจจุบันของส่วนหน้า OnTuneEventListener จะรอรับเหตุการณ์ในส่วนหน้า แอป TIS ใช้ ScanCallback เพื่อประมวลผลข้อความที่สแกนจากส่วนหน้า

สแกนช่อง

หากต้องการตั้งค่าทีวี แอปจะสแกนความถี่ที่เป็นไปได้และสร้างรายการช่อง เพื่อให้ผู้ใช้เข้าถึงได้ TIS อาจใช้ Tuner.tune, Tuner.scan(BLIND_SCAN) หรือ Tuner.scan(AUTO_SCAN) เพื่อทำการสแกนช่องให้เสร็จสมบูรณ์

หาก TIS มีข้อมูลการนำส่งที่ถูกต้องสำหรับสัญญาณ เช่น ความถี่ มาตรฐาน (เช่น T/T2, S/S2) และข้อมูลเพิ่มเติมที่จำเป็น (เช่น รหัส PLD) เราขอแนะนำให้ใช้ Tuner.tune เนื่องจากเป็นตัวเลือกที่เร็วกว่า

เมื่อผู้ใช้โทรหา Tuner.tune จะเกิดการดำเนินการต่อไปนี้

  • TIS จะป้อนข้อมูลที่จำเป็นลงใน FrontendSettings โดยใช้ Tuner.tune
  • HAL จะรายงานข้อความปรับ LOCKED หากล็อกสัญญาณ
  • TIS ใช้ Frontend.getStatus เพื่อรวบรวมข้อมูลที่จำเป็น
  • TIS จะเปลี่ยนไปใช้ความถี่ถัดไปที่พร้อมใช้งานในรายการความถี่

TIS จะโทรหา Tuner.tune อีกครั้งจนกว่าจะใช้ความถี่ทั้งหมด

ในระหว่างการปรับ คุณสามารถโทรหา stopTune() หรือ close() เพื่อหยุดชั่วคราวหรือสิ้นสุดการโทร Tuner.tune ได้

Tuner.scan(AUTO_SCAN)

หาก TIS มีข้อมูลไม่เพียงพอที่จะใช้ Tuner.tune แต่มีรายการความถี่และประเภทมาตรฐาน (เช่น DVB T/C/S) ขอแนะนําให้ใช้ Tuner.scan(AUTO_SCAN)

เมื่อผู้ใช้โทรหา Tuner.scan(AUTO_SCAN) จะเกิดการดำเนินการต่อไปนี้

  • TIS ใช้ Tuner.scan(AUTO_SCAN) โดยมี FrontendSettings ที่ระบุความถี่

  • HAL จะรายงานข้อความสแกน LOCKED หากล็อกสัญญาณ นอกจากนี้ HAL อาจรายงานข้อความการสแกนอื่นๆ เพื่อให้ข้อมูลเพิ่มเติมเกี่ยวกับสัญญาณด้วย

  • TIS ใช้ Frontend.getStatus เพื่อรวบรวมข้อมูลที่จำเป็น

  • TIS calls Tuner.scan for the HAL to continue to the next setting on the same frequency. หากโครงสร้าง FrontendSettings ว่างเปล่า HAL จะใช้การตั้งค่าถัดไป ที่พร้อมใช้งาน ไม่เช่นนั้น HAL จะใช้ FrontendSettings สำหรับการสแกนแบบครั้งเดียว และส่ง END เพื่อระบุว่าการดำเนินการสแกนเสร็จสิ้นแล้ว

  • TIS จะทำซ้ำการดำเนินการข้างต้นจนกว่าการตั้งค่าทั้งหมดในความถี่จะ หมด

  • HAL จะส่ง END เพื่อระบุว่าการสแกนเสร็จสิ้นแล้ว

  • TIS จะเปลี่ยนไปใช้ความถี่ถัดไปที่พร้อมใช้งานในรายการความถี่

TIS จะโทรหา Tuner.scan(AUTO_SCAN) อีกครั้งจนกว่าจะใช้ความถี่ทั้งหมด

ในระหว่างการสแกน คุณสามารถโทรหา stopScan() หรือ close() เพื่อหยุดชั่วคราวหรือสิ้นสุดการสแกนได้

Tuner.scan(BLIND_SCAN)

หาก TIS ไม่มีรายการความถี่และ HAL ของผู้ให้บริการค้นหาความถี่ของส่วนหน้า ที่ผู้ใช้ระบุเพื่อรับทรัพยากรส่วนหน้าไม่ได้ เราขอแนะนำให้ใช้ Tuner.scan(BLIND_SCAN)

  • TIS ใช้ Tuner.scan(BLIND_SCAN) คุณระบุความถี่ได้ใน FrontendSettings สำหรับความถี่เริ่มต้น แต่ TIS จะไม่สนใจการตั้งค่าอื่นๆ ใน FrontendSettings
  • HAL จะรายงานข้อความ LOCKED การสแกนหากล็อกสัญญาณ
  • TIS ใช้ Frontend.getStatus เพื่อรวบรวมข้อมูลที่จำเป็น
  • TIS จะโทรหา Tuner.scan อีกครั้งเพื่อสแกนต่อ (FrontendSettings จะ ไม่สนใจ)
  • TIS จะทำซ้ำการดำเนินการข้างต้นจนกว่าการตั้งค่าทั้งหมดในความถี่จะ หมด HAL จะเพิ่มความถี่โดยที่ TIS ไม่ต้องดำเนินการใดๆ HAL จะรายงาน PROGRESS

TIS จะโทรหา Tuner.scan(AUTO_SCAN) อีกครั้งจนกว่าจะใช้ความถี่ทั้งหมด HAL จะรายงาน END เพื่อระบุว่าการดำเนินการสแกนเสร็จสิ้นแล้ว

ในระหว่างการสแกน คุณสามารถโทรหา stopScan() หรือ close() เพื่อหยุดชั่วคราวหรือสิ้นสุดการสแกน

แผนภาพกระบวนการสแกน TIS

รูปที่ 9 แผนภาพขั้นตอนการสแกน TIS

Android.media.tv.tuner.filter

แพ็กเกจตัวกรองคือชุดของการดำเนินการตัวกรองพร้อมกับการกำหนดค่า การตั้งค่า การเรียกกลับ และเหตุการณ์ แพ็กเกจประกอบด้วยการดำเนินการต่อไปนี้ ดูรายการการดำเนินการทั้งหมดได้ในซอร์สโค้ดของ Android

  • configure()
  • start()
  • stop()
  • flush()
  • read()

ดูรายการทั้งหมดได้ในซอร์สโค้ดของ Android

FilterConfiguration มาจากชั้นเรียนด้านล่าง การกำหนดค่ามีไว้สำหรับประเภทตัวกรองหลัก และระบุโปรโตคอลที่ตัวกรองใช้เพื่อ ดึงข้อมูล

  • AlpFilterConfiguration
  • IpFilterConfiguration
  • MmtpFilterConfiguration
  • TlvFilterConfiguration
  • TsFilterConfiguration

การตั้งค่าได้มาจากคลาสต่อไปนี้ การตั้งค่านี้ใช้กับประเภทย่อยของตัวกรอง และระบุประเภทข้อมูลที่ตัวกรองยกเว้นได้

  • SectionSettings
  • AvSettings
  • PesSettings
  • RecordSettings
  • DownloadSettings

FilterEvent ได้มาจากคลาสต่อไปนี้เพื่อรายงานเหตุการณ์สำหรับข้อมูลประเภทต่างๆ

  • SectionEvent
  • MediaEvent
  • PesEvent
  • TsRecordEvent
  • MmtpRecordEvent
  • TemiEvent
  • DownloadEvent
  • IpPayloadEvent

ตั้งแต่ Android 12 ที่มี Tuner HAL 1.1 ขึ้นไป ระบบจะรองรับเหตุการณ์ต่อไปนี้

  • IpCidChangeEvent
  • RestartEvent
  • ScramblingStatusEvent
รูปแบบเหตุการณ์และข้อมูลจากตัวกรอง
ประเภทตัวกรอง ธง กิจกรรม การดำเนินการกับข้อมูล รูปแบบข้อมูล
TS.SECTION
MMTP.SECTION
IP.SECTION
TLV.SECTION
ALP.SECTION
isRaw:
true
ต้องระบุ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
เรียกใช้
Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้ง ตามกิจกรรมและกำหนดการภายใน

ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
แพ็กเกจเซสชันที่ประกอบขึ้น 1 รายการจะได้รับการส่งใน FMQ โดยแพ็กเกจเซสชันอื่น
isRaw:
false
ต้องระบุ:
DemuxFilterEvent::DemuxFilterSectionEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ไม่บังคับ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterSectionEven[i].size)


ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
TS.PES isRaw:
true
ต้องระบุ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
เรียกใช้
Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้ง ตามกิจกรรมและกำหนดการภายใน

ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
แพ็กเกจ PES ที่ประกอบแล้ว 1 แพ็กเกจจะได้รับการเติมใน FMQ โดยแพ็กเกจ PES อื่น ๆ
isRaw:
false
ต้องระบุ:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ไม่บังคับ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
MMTP.PES isRaw:
true
ต้องระบุ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
เรียกใช้
Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้ง ตามกิจกรรมและกำหนดการภายใน

ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
แพ็กเกจ MFU ที่ประกอบแล้ว 1 แพ็กเกจจะได้รับการเติมใน FMQ โดยแพ็กเกจ MFU อื่น
isRaw:
false
ต้องระบุ:
DemuxFilterEvent::DemuxFilterPesEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ไม่บังคับ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
Filter.read(buffer, offset, DemuxFilterPesEven[i].size)


ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
TS.TS
ไม่มี ต้องระบุ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
เรียกใช้
Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้ง ตามกิจกรรมและกำหนดการภายใน

ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
tsที่กรองออก
จะได้รับการกรอกใน FMQts
TS.Audio
TS.Video
MMTP.Audio
MMTP.Video
isPassthrough:
true
ไม่บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
ไคลเอ็นต์จะเริ่ม MediaCodec ได้หลังจากได้รับ DemuxFilterStatus::DATA_READY
ไคลเอ็นต์สามารถเรียกใช้ Filter.flush หลังจากได้รับ DemuxFilterStatus::DATA_OVERFLOW
ไม่มี
isPassthrough:
false
ต้องระบุ:
DemuxFilterEvent::DemuxFilterMediaEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ไม่บังคับ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
วิธีใช้MediaCodec
for i=0; i<n; i++
linearblock = MediaEvent[i].getLinearBlock();
codec.startQueueLinearBlock(linearblock)
linearblock.recycle()


วิธีใช้เสียงโดยตรงของAudioTrack
for i=0; i<n; i++
audioHandle = MediaEvent[i].getAudioHandle();
audiotrack.write(encapsulated(audiohandle))
ข้อมูล ES หรือ ES บางส่วนในหน่วยความจำ ION
TS.PCR
IP.NTP
ALP.PTP
ไม่มี ต้องระบุ: ไม่มี
ไม่บังคับ: ไม่มี
ไม่มี ไม่มีข้อมูล
TS.RECORD ไม่มี ต้องระบุ:
DemuxFilterEvent::DemuxFilterTsRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

ไม่บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
สำหรับข้อมูลดัชนี
for i=0; i<n; i++
DemuxFilterTsRecordEvent[i];


สำหรับเนื้อหาที่บันทึกไว้ ตามRecordStatus::*และกำหนดการภายใน ให้ทำ อย่างใดอย่างหนึ่งต่อไปนี้
  • เรียกใช้ DvrRecord.write(adustedSize) อย่างน้อย 1 ครั้งไปยังที่เก็บข้อมูล
    ระบบจะโอนข้อมูลจาก MQ ของ HAL ไปยังที่เก็บข้อมูล
  • เรียกใช้ DvrRecord.write(buffer, adustedSize) อย่างน้อย 1 ครั้งเพื่อบัฟเฟอร์
    ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
สำหรับข้อมูลดัชนี: อยู่ในเพย์โหลดของเหตุการณ์

สำหรับเนื้อหาที่บันทึกไว้: สตรีม TS แบบมัลติเพล็กซ์ที่กรอกใน FMQ
TS.TEMI ไม่มี ต้องระบุ:
DemuxFilterEvent::DemuxFilterTemiEvent[n]

ไม่บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++
DemuxFilterTemiEvent[i];
ไม่มี
MMTP.MMTP ไม่มี ต้องระบุ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
เรียกใช้
Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้ง ตามกิจกรรมและกำหนดการภายใน

ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
mmtpที่กรองออก
จะได้รับการกรอกใน FMQmmtp
MMTP.RECORD ไม่มี ต้องระบุ:
DemuxFilterEvent::DemuxFilterMmtpRecordEvent[n]
RecordStatus::DATA_READY
RecordStatus::DATA_OVERFLOW
RecordStatus::LOW_WATER
RecordStatus::HIGH_WATER

ไม่บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
สำหรับข้อมูลดัชนี for i=0; i<n; i++
DemuxFilterMmtpRecordEvent[i];


สำหรับเนื้อหาที่บันทึกไว้ ตาม RecordStatus::* และกำหนดการภายใน ให้ทำอย่างใดอย่างหนึ่งต่อไปนี้
  • เรียกใช้ DvrRecord.write(adjustedSize) อย่างน้อย 1 ครั้ง ไปยังที่เก็บข้อมูล
    ระบบจะโอนข้อมูลจาก MQ ของ HAL ไปยังที่เก็บข้อมูล
  • เรียกใช้ DvrRecord.write(buffer, adjustedSize)อย่างน้อย 1 ครั้งเพื่อบัฟเฟอร์
    ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
สำหรับข้อมูลดัชนี: อยู่ในเพย์โหลดของเหตุการณ์

สำหรับเนื้อหาที่บันทึกไว้: สตรีมที่บันทึกไว้ซึ่งมัลติเพล็กซ์แล้ว FMQ

หากแหล่งที่มาของตัวกรองสำหรับการบันทึกคือ TLV.TLV ถึง IP.IP ที่มีการส่งผ่าน สตรีมที่บันทึกจะมี TLV และส่วนหัว IP
MMTP.DOWNLOAD ไม่มี ต้องระบุ:
DemuxFilterEvent::DemuxFilterDownloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ไม่บังคับ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterDownloadEvent[i].size)

ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
แพ็กเกจดาวน์โหลดจะได้รับการเติมเต็มใน FMQ โดยแพ็กเกจดาวน์โหลด IP อื่น
IP.IP_PAYLOAD ไม่มี ต้องระบุ:
DemuxFilterEvent::DemuxFilterIpPayloadEvent[n]
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

ไม่บังคับ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
for i=0; i<n; i++ Filter.read(buffer, offset, DemuxFilterIpPayloadEvent[i].size)

ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
แพ็กเกจเพย์โหลด IP จะได้รับการเติมใน FMQ โดยแพ็กเกจเพย์โหลด IP อื่น
IP.IP
TLV.TLV
ALP.ALP
isPassthrough:
true
ไม่บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
สตรีมย่อยของโปรโตคอลที่กรองแล้วจะป้อนตัวกรองถัดไปในเชน filter ไม่มี
isPassthrough:
false
ต้องระบุ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW

แนะนำ:
DemuxFilterStatus::LOW_WATER
DemuxFilterStatus::HIGH_WATER
เรียกใช้
Filter.read(buffer, offset, adjustedSize) อย่างน้อย 1 ครั้ง ตามกิจกรรมและกำหนดการภายใน

ระบบจะคัดลอกข้อมูลจาก MQ ของ HAL ไปยังบัฟเฟอร์ไคลเอ็นต์
กรองสตรีมย่อยของโปรโตคอลออกและกรอกส่วนหัวของโปรโตคอล FMQ
IP.PAYLOAD_THROUGH
TLV.PAYLOAD_THROUGH
ALP.PAYLOAD_THROUGH
ไม่มี ไม่บังคับ:
DemuxFilterStatus::DATA_READY
DemuxFilterStatus::DATA_OVERFLOW
ฟีดเพย์โหลดของโปรโตคอลที่กรองออกจะส่งไปยังตัวกรองถัดไปในเชน filter ไม่มี
ตัวอย่างโฟลว์ในการใช้ตัวกรองเพื่อสร้าง PSI/SI

ตัวอย่างโฟลว์สำหรับการใช้ตัวกรองเพื่อสร้าง PSI/SI

รูปที่ 10 ขั้นตอนการสร้าง PSI/SI

  1. เปิดตัวกรอง

    Filter filter = tuner.openFilter(
      Filter.TYPE_TS,
      Filter.SUBTYPE_SECTION,
      /* bufferSize */1000,
      executor,
      filterCallback
    );
    
  2. กำหนดค่าและเริ่มตัวกรอง

    Settings settings = SectionSettingsWithTableInfo
        .builder(Filter.TYPE_TS)
        .setTableId(2)
        .setVersion(1)
        .setCrcEnabled(true)
        .setRaw(false)
        .setRepeat(false)
        .build();
      FilterConfiguration config = TsFilterConfiguration
        .builder()
        .setTpid(10)
        .setSettings(settings)
        .build();
      filter.configure(config);
      filter.start();
    
  3. กระบวนการ SectionEvent

    FilterCallback filterCallback = new FilterCallback() {
      @Override
      public void onFilterEvent(Filter filter, FilterEvent[] events) {
        for (FilterEvent event : events) {
          if (event instanceof SectionEvent) {
            SectionEvent sectionEvent = (SectionEvent) event;
            int tableId = sectionEvent.getTableId();
            int version = sectionEvent.getVersion();
            int dataLength = sectionEvent.getDataLength();
            int sectionNumber = sectionEvent.getSectionNumber();
            filter.read(buffer, 0, dataLength); }
          }
        }
    };
    
ตัวอย่างโฟลว์ในการใช้ MediaEvent จากตัวกรอง

ตัวอย่างโฟลว์ในการใช้ MediaEvent จากตัวกรอง

รูปที่ 11 Flow ในการใช้ MediaEvent จากตัวกรอง

  1. เปิด กำหนดค่า และเริ่มใช้ตัวกรอง A/V
  2. กระบวนการ MediaEvent
  3. รับ MediaEvent
  4. จัดคิวบล็อกเชิงเส้นไปยัง codec
  5. ปล่อยแฮนเดิล A/V เมื่อใช้ข้อมูลแล้ว

Android.media.tv.tuner.dvr

DvrRecorder มีวิธีการบันทึกต่อไปนี้

  • configure
  • attachFilter
  • detachFilter
  • start
  • flush
  • stop
  • setFileDescriptor
  • write

DvrPlayback มีวิธีการเล่นดังนี้

  • configure
  • start
  • flush
  • stop
  • setFileDescriptor
  • read

ใช้ DvrSettings เพื่อกำหนดค่า DvrRecorder และ DvrPlayback OnPlaybackStatusChangedListener และ OnRecordStatusChangedListener ใช้เพื่อรายงานสถานะของอินสแตนซ์ DVR

ตัวอย่างขั้นตอนการเริ่มบันทึก

ตัวอย่างขั้นตอนการเริ่มบันทึก

รูปที่ 12 ขั้นตอนการเริ่มบันทึก

  1. เปิด กำหนดค่า และเริ่ม DvrRecorder

    DvrRecorder recorder = openDvrRecorder(/* bufferSize */ 1000, executor, listener);
    DvrSettings dvrSettings = DvrSettings
    .builder()
    .setDataFormat(DvrSettings.DATA_FORMAT_TS)
    .setLowThreshold(100)
    .setHighThreshold(900)
    .setPacketSize(188)
    .build();
    recorder.configure(dvrSettings);
    recorder.attachFilter(filter);
    recorder.setFileDescriptor(fd);
    recorder.start();
    
  2. รับ RecordEvent และดึงข้อมูลดัชนี

    FilterCallback filterCallback = new FilterCallback() {
      @Override
      public void onFilterEvent(Filter filter, FilterEvent[] events) {
        for (FilterEvent event : events) {
          if (event instanceof TsRecordEvent) {
            TsRecordEvent recordEvent = (TsRecordEvent) event;
            int tsMask = recordEvent.getTsIndexMask();
            int scMask = recordEvent.getScIndexMask();
            int packetId = recordEvent.getPacketId();
            long dataLength = recordEvent.getDataLength();
            // handle the masks etc. }
          }
        }
    };
    
  3. เริ่มต้น OnRecordStatusChangedListener และจัดเก็บข้อมูลบันทึก

      OnRecordStatusChangedListener listener = new OnRecordStatusChangedListener() {
        @Override
        public void onRecordStatusChanged(int status) {
          // a customized way to consume data efficiently by using status as a hint.
          if (status == Filter.STATUS_DATA_READY) {
            recorder.write(size);
          }
        }
      };
    

HAL ของตัวรับสัญญาณ

Tuner HAL เป็นไปตาม HIDL และกำหนดอินเทอร์เฟซระหว่างเฟรมเวิร์กกับ ฮาร์ดแวร์ของผู้ให้บริการ ผู้ให้บริการใช้อินเทอร์เฟซเพื่อติดตั้งใช้งาน Tuner HAL และ เฟรมเวิร์กจะใช้อินเทอร์เฟซนี้เพื่อสื่อสารกับการติดตั้งใช้งาน Tuner HAL

โมดูล

Tuner HAL 1.0

โมดูล การควบคุมพื้นฐาน การควบคุมเฉพาะโมดูล ไฟล์ HAL
ITuner ไม่มี frontend(open, getIds, getInfo), openDemux, openDescrambler, openLnb, getDemuxCaps ITuner.hal
IFrontend setCallback, getStatus, close tune, stopTune, scan, stopScan, setLnb IFrontend.hal
IFrontendCallback.hal
IDemux close setFrontendDataSource, openFilter, openDvr, getAvSyncHwId, getAvSyncTime, connect / disconnectCiCam IDemux.hal
IDvr close, start, stop, configure attach/detachFilters, flush, getQueueDesc IDvr.hal
IDvrCallback.hal
IFilter close, start, stop, configure, getId flush, getQueueDesc, releaseAvHandle, setDataSource IFilter.hal
IFilterCallback.hal
ILnb close, setCallback setVoltage, setTone, setSatellitePosition, sendDiseqcMessage ILnb.hal
ILnbCallback.hal
IDescrambler close setDemuxSource, setKeyToken, addPid, removePid IDescrambler.hal

Tuner HAL 1.1 (มาจาก Tuner HAL 1.0)

โมดูล การควบคุมพื้นฐาน การควบคุมเฉพาะโมดูล ไฟล์ HAL
ITuner ไม่มี getFrontendDtmbCapabilities @1.1::ITuner.hal
IFrontend tune_1_1, scan_1_1, getStatusExt1_1 link/unlinkCiCam @1.1::IFrontend.hal
@1.1::IFrontendCallback.hal
IFilter getStatusExt1_1 configureIpCid, configureAvStreamType, getAvSharedHandle, configureMonitorEvent @1.1::IFilter.hal
@1.1::IFilterCallback.hal

แผนภาพโฟลว์ของการโต้ตอบระหว่างโมดูลของ Tuner HAL

รูปที่ 13 แผนภาพการโต้ตอบระหว่างโมดูล HAL ของจูนเนอร์

การเชื่อมโยงตัวกรอง

Tuner HAL รองรับการเชื่อมโยงตัวกรองเพื่อให้ตัวกรองลิงก์กับตัวกรองอื่นๆ สำหรับหลายเลเยอร์ได้ ตัวกรองจะทำตามกฎต่อไปนี้

  • ตัวกรองจะลิงก์เป็นโครงสร้างแบบต้นไม้ และไม่อนุญาตให้ใช้เส้นทางที่ปิด
  • โหนดรากคือ demux
  • ฟิลเตอร์จะทำงานแยกกัน
  • ตัวกรองทั้งหมดเริ่มรับข้อมูล
  • การเชื่อมโยงตัวกรองจะล้างในตัวกรองสุดท้าย

บล็อกโค้ดด้านล่างและรูปที่ 14 แสดงตัวอย่างการกรองเลเยอร์หลายรายการ

demuxCaps = ITuner.getDemuxCap;
If (demuxCaps[IP][MMTP] == true) {
        ipFilter = ITuner.openFilter(<IP, ..>)
        mmtpFilter1 = ITuner.openFilter(<MMTP ..>)
        mmtpFilter2 = ITuner.openFilter(<MMTP ..>)
        mmtpFilter1.setDataSource(<ipFilter>)
        mmtpFilter2.setDataSource(<ipFilter>)
}

แผนภาพตัวอย่างการเชื่อมโยงตัวกรอง

รูปที่ 14 แผนภาพโฟลว์ของการเชื่อมโยงตัวกรองสำหรับหลายเลเยอร์

ตัวจัดการทรัพยากรของตัวรับสัญญาณ

ก่อน Tuner Resource Manager (TRM) การสลับระหว่าง 2 แอปต้องใช้ฮาร์ดแวร์จูนเนอร์เดียวกัน TV Input Framework (TIF) ใช้กลไก "ใครได้ก่อนชนะ" ซึ่งหมายความว่าแอปใดก็ตามที่ได้รับทรัพยากรก่อนจะเก็บทรัพยากรนั้นไว้ อย่างไรก็ตาม กลไกนี้อาจไม่เหมาะกับ Use Case ที่ซับซ้อนบางอย่าง

TRM ทำงานเป็นบริการของระบบเพื่อจัดการฮาร์ดแวร์จูนเนอร์ TVInput และ CAS สำหรับแอป TRM ใช้กลไก "ชนะในเบื้องหน้า" ซึ่ง คำนวณลำดับความสำคัญของแอปตามสถานะเบื้องหน้าหรือเบื้องหลังของแอป และประเภทกรณีการใช้งาน TRM จะให้หรือเพิกถอนทรัพยากรตาม ลำดับความสำคัญ TRM รวมการจัดการทรัพยากร ATV สำหรับการออกอากาศ, OTT และ DVR ไว้ในที่เดียว

อินเทอร์เฟซ TRM

TRM จะแสดงอินเทอร์เฟซ AIDL ใน ITunerResourceManager.aidl สำหรับเฟรมเวิร์ก Tuner MediaCas และ TvInputHardwareManager เพื่อลงทะเบียน ขอ หรือ ปล่อยทรัพยากร

อินเทอร์เฟซสำหรับการจัดการไคลเอ็นต์แสดงอยู่ด้านล่าง

  • registerClientProfile(in ResourceClientProfile profile, IResourcesReclaimListener listener, out int[] clientId)
  • unregisterClientProfile(in int clientId)

อินเทอร์เฟซสำหรับขอและปล่อยทรัพยากรแสดงอยู่ด้านล่าง

  • requestFrontend(TunerFrontendRequest request, int[] frontendHandle) / releaseFrontend
  • requestDemux(TunerDemuxRequest request, int[] demuxHandle) / releaseDemux
  • requestDescrambler(TunerDescramblerRequest request, int[] descramblerHandle) / releaseDescrambler
  • requestCasSession(CasSessionRequest request, int[] casSessionHandle) / releaseCasSession
  • requestLnb(TunerLnbRequest request, int[] lnbHandle) / releaseLnb

คลาสไคลเอ็นต์และคำขอแสดงอยู่ด้านล่าง

  • ResourceClientProfile
  • ResourcesReclaimListener
  • TunerFrontendRequest
  • TunerDemuxRequest
  • TunerDescramblerRequest
  • CasSessionRequest
  • TunerLnbRequest

ลำดับความสำคัญของไคลเอ็นต์

TRM จะคำนวณลำดับความสำคัญของไคลเอ็นต์โดยใช้พารามิเตอร์จากโปรไฟล์ของไคลเอ็นต์ และค่าลำดับความสำคัญจากไฟล์การกำหนดค่า ไคลเอ็นต์อาจอัปเดตลำดับความสำคัญด้วยค่าลำดับความสำคัญที่กำหนดเองได้ด้วย

พารามิเตอร์ในโปรไฟล์ของลูกค้า

TRM จะดึงรหัสกระบวนการจาก mTvInputSessionId เพื่อพิจารณาว่าแอป เป็นแอปที่ทำงานอยู่เบื้องหน้าหรือเบื้องหลัง ในการสร้าง mTvInputSessionId TvInputService.onCreateSession หรือ TvInputService.onCreateRecordingSession จะเริ่มต้นเซสชัน TIS

mUseCase ระบุกรณีการใช้งานของเซสชัน Use Case ที่กำหนดไว้ล่วงหน้ามีดังนี้

TvInputService.PriorityHintUseCaseType  {
  PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK
  PRIORITY_HINT_USE_CASE_TYPE_LIVE
  PRIORITY_HINT_USE_CASE_TYPE_RECORD,
  PRIORITY_HINT_USE_CASE_TYPE_SCAN,
  PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND
}

ไฟล์การกำหนดค่า

ไฟล์การกำหนดค่าเริ่มต้น

ไฟล์การกำหนดค่าเริ่มต้นด้านล่างระบุค่าลำดับความสำคัญสำหรับกรณีการใช้งานที่กำหนดไว้ล่วงหน้า ผู้ใช้สามารถเปลี่ยนค่าได้โดยใช้ไฟล์การกำหนดค่าที่กำหนดเอง

กรณีการใช้งาน เบื้องหน้า ฉากหลัง
LIVE 490 400
PLAYBACK 480 300
RECORD 600 500
SCAN 450 200
BACKGROUND 180 100
ไฟล์การกำหนดค่าที่กำหนดเอง

ผู้ให้บริการสามารถปรับแต่งไฟล์การกำหนดค่า /vendor/etc/tunerResourceManagerUseCaseConfig.xmlได้ ไฟล์นี้ใช้สำหรับ เพิ่ม นำออก หรืออัปเดตประเภท Use Case และค่าลำดับความสำคัญของ Use Case ไฟล์ที่ปรับแต่งแล้วสามารถใช้ platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml เป็นเทมเพลตได้

ตัวอย่างเช่น กรณีการใช้งานผู้ให้บริการรายใหม่คือ VENDOR_USE_CASE__[A-Z0-9]+, [0 - 1000] รูปแบบควรเป็นไปตาม platform/hardware/interfaces/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd

ค่าลำดับความสำคัญที่กำหนดเองและค่า nice

TRM มี updateClientPriority ให้ไคลเอ็นต์อัปเดตค่าลำดับความสำคัญที่กำหนดเองและค่า nice ค่าลำดับความสำคัญที่กำหนดเองจะเขียนทับค่าลำดับความสำคัญที่คำนวณ จากประเภทกรณีการใช้งานและรหัสเซสชัน

ค่าความเหมาะสมจะระบุว่าพฤติกรรมของไคลเอ็นต์มีความยืดหยุ่นเพียงใดเมื่อขัดแย้งกับไคลเอ็นต์อื่น ค่า nice จะลดค่าลำดับความสำคัญของไคลเอ็นต์ ก่อนที่จะเปรียบเทียบค่าลำดับความสำคัญกับไคลเอ็นต์ที่ท้าทาย

กลไกการเรียกคืน

แผนภาพด้านล่างแสดงวิธีเรียกคืนและกำหนดทรัพยากรใหม่เมื่อ เกิดความขัดแย้งของทรัพยากร

แผนภาพกระบวนการกลไกการเรียกคืน

รูปที่ 15 แผนภาพของกลไกการเรียกคืนสำหรับความขัดแย้งระหว่างทรัพยากรของจูนเนอร์