อัตราเฟรม

API อัตราเฟรมช่วยให้แอปแจ้งแพลตฟอร์ม Android เกี่ยวกับอัตราเฟรมที่ต้องการได้ และพร้อมให้บริการในแอปที่กำหนดเป้าหมายเป็น Android 11 (ระดับ API 30) ขึ้นไป โดยปกติแล้ว อุปกรณ์ส่วนใหญ่จะรองรับอัตราการรีเฟรชหน้าจอเพียงอัตราเดียว ซึ่งมักอยู่ที่ 60Hz แต่ปัจจุบันมีการเปลี่ยนแปลงแล้ว ปัจจุบันอุปกรณ์หลายรุ่นรองรับอัตราการรีเฟรชเพิ่มเติม เช่น 90Hz หรือ 120Hz อุปกรณ์บางเครื่องรองรับการสลับอัตราการรีเฟรชที่ราบรื่น ขณะที่อุปกรณ์บางเครื่องจะแสดงหน้าจอสีดำเป็นเวลาสั้นๆ ซึ่งมักจะนาน 1 วินาที

วัตถุประสงค์หลักของ API คือการช่วยให้แอปใช้ประโยชน์จากอัตราการรีเฟรชของจอแสดงผลที่รองรับทั้งหมดได้ดียิ่งขึ้น เช่น แอปที่เล่นวิดีโอ 24Hz ซึ่งเรียกใช้ setFrameRate() อาจทำให้อุปกรณ์เปลี่ยนอัตราการรีเฟรช จอแสดงผลจาก 60Hz เป็น 120Hz อัตราการรีเฟรชใหม่นี้ช่วยให้เล่นวิดีโอ 24Hz ได้อย่างราบรื่นโดยไม่มีอาการสั่น และไม่ต้องใช้การแปลง 3:2 เหมือนที่ ต้องใช้ในการเล่นวิดีโอเดียวกันบนจอแสดงผล 60Hz ซึ่งจะช่วยให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดีขึ้น

การใช้งานพื้นฐาน

Android มีวิธีต่างๆ ในการเข้าถึงและควบคุม Surface จึงมี setFrameRate() API หลายเวอร์ชัน API แต่ละเวอร์ชันใช้ พารามิเตอร์เดียวกันและทำงานเหมือนกับเวอร์ชันอื่นๆ ดังนี้

แอปไม่จำเป็นต้องพิจารณากรอบอัตราการรีเฟรชของจอแสดงผลที่รองรับจริง ซึ่งรับได้โดยการเรียก Display.getSupportedModes() เพื่อเรียก setFrameRate() อย่างปลอดภัย เช่น แม้ว่าอุปกรณ์จะรองรับเพียง 60Hz ให้เรียกใช้ setFrameRate() โดยมีอัตราเฟรมที่แอปต้องการ อุปกรณ์ที่ไม่ตรงกับอัตราเฟรมของแอปมากกว่าจะยังคงใช้อัตราการรีเฟรชของจอแสดงผลปัจจุบัน

หากต้องการดูว่าการเรียกใช้ setFrameRate() จะส่งผลต่อการเปลี่ยนแปลงอัตราการรีเฟรชของจอแสดงผลหรือไม่ ให้ลงทะเบียนรับการแจ้งเตือนการเปลี่ยนแปลงจอแสดงผลโดยการเรียกใช้ DisplayManager.registerDisplayListener() หรือ AChoreographer_registerRefreshRateCallback()

เมื่อเรียกใช้ setFrameRate() คุณควรส่งผ่านอัตราเฟรมที่แน่นอนแทนที่จะปัดเศษเป็นจำนวนเต็ม เช่น เมื่อเรนเดอร์วิดีโอที่บันทึกที่ 29.97Hz ให้ส่ง 29.97 แทนที่จะปัดเป็น 30

สำหรับแอปวิดีโอ ควรตั้งค่าพารามิเตอร์ความเข้ากันได้ที่ส่งไปยัง setFrameRate() เป็น Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE เพื่อให้คำแนะนำเพิ่มเติมแก่ แพลตฟอร์ม Android ว่าแอปจะใช้การดึงลงเพื่อปรับให้เข้ากับ อัตราการรีเฟรชจอแสดงผลที่ไม่ตรงกัน (ซึ่งจะทำให้เกิดอาการสั่น)

ในบางสถานการณ์ พื้นผิววิดีโอจะหยุดส่งเฟรม แต่จะยังคง มองเห็นได้บนหน้าจอเป็นระยะเวลาหนึ่ง สถานการณ์ทั่วไป ได้แก่ เมื่อการเล่น สิ้นสุดวิดีโอ หรือเมื่อผู้ใช้หยุดการเล่นชั่วคราว ในกรณีเหล่านี้ ให้เรียกใช้ setFrameRate() โดยตั้งค่าพารามิเตอร์อัตราเฟรมเป็น 0 เพื่อล้างการตั้งค่าอัตราเฟรมของ Surface กลับเป็นค่าเริ่มต้น ไม่จำเป็นต้องล้างการตั้งค่าอัตราเฟรม เช่นนี้เมื่อทำลาย Surface หรือเมื่อ Surface ถูกซ่อน เนื่องจากผู้ใช้เปลี่ยนไปใช้แอปอื่น ให้ล้างการตั้งค่าอัตราเฟรม เฉพาะเมื่อ Surface ยังคงมองเห็นได้โดยไม่ได้ใช้งาน

การสลับอัตราเฟรมที่ไม่ราบรื่น

ในอุปกรณ์บางรุ่น การสลับอัตราการรีเฟรชอาจทำให้เกิดการหยุดชะงักทางภาพ เช่น หน้าจอสีดำ เป็นเวลา 1-2 วินาที โดยปัญหานี้มักเกิดขึ้นในกล่องรับสัญญาณ แผงทีวี และอุปกรณ์ที่คล้ายกัน โดยค่าเริ่มต้น เฟรมเวิร์ก Android จะไม่เปลี่ยนโหมด เมื่อมีการเรียกใช้ API Surface.setFrameRate() เพื่อหลีกเลี่ยงการหยุดชะงักด้านภาพดังกล่าว

ผู้ใช้บางรายชอบการขัดจังหวะด้วยภาพที่ตอนต้นและ ตอนท้ายของวิดีโอที่ยาวขึ้น ซึ่งจะช่วยให้อัตราการรีเฟรชของจอแสดงผลตรงกับอัตราเฟรมของวิดีโอ และหลีกเลี่ยงอาร์ติแฟกต์การแปลงอัตราเฟรม เช่น การกระตุกแบบ 3:2 Pulldown สำหรับการเล่นภาพยนตร์

ด้วยเหตุนี้ คุณจึงเปิดใช้การสลับอัตราการรีเฟรชแบบไม่ราบรื่นได้หากทั้ง ผู้ใช้และแอปเลือกใช้

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

คำแนะนำเพิ่มเติม

ทำตามคำแนะนำต่อไปนี้สำหรับสถานการณ์ที่พบบ่อย

หลายแพลตฟอร์ม

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

แพลตฟอร์มจะไม่เปลี่ยนเป็นอัตราเฟรมของแอป

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

แอปจะเป็นผู้กำหนดวิธีตอบสนองเมื่ออัตราการรีเฟรชจอแสดงผล ไม่ตรงกับอัตราเฟรมของแอป สำหรับวิดีโอ อัตราเฟรมจะคงที่ตามอัตราเฟรมของ วิดีโอต้นฉบับ และจะต้องใช้การดึงลงเพื่อแสดงเนื้อหาวิดีโอ เกมอาจเลือกที่จะพยายามเรียกใช้ที่อัตราการรีเฟรชของจอแสดงผลแทน การใช้อัตราเฟรมที่ต้องการ แอปไม่ควรเปลี่ยนค่าที่ส่งไปยัง setFrameRate() ตามสิ่งที่แพลตฟอร์มทำ โดยควรตั้งค่าเป็นอัตราเฟรมที่แอปต้องการ ไม่ว่าแอปจะจัดการในกรณีที่แพลตฟอร์มไม่ปรับให้ตรงกับคำขอของแอปอย่างไรก็ตาม ด้วยวิธีนี้ หากเงื่อนไขของอุปกรณ์เปลี่ยนไปจนอนุญาตให้ใช้ อัตราการรีเฟรชการแสดงผลเพิ่มเติมได้ แพลตฟอร์มจะมีข้อมูลที่ถูกต้อง ในการเปลี่ยนไปใช้อัตราเฟรมที่แอปต้องการ

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

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

ในบางกรณี แพลตฟอร์มอาจเปลี่ยนไปใช้หลายเท่าของอัตราเฟรมที่แอป ระบุไว้ใน setFrameRate() เช่น แอปอาจเรียกใช้ setFrameRate() ที่ 60Hz และอุปกรณ์อาจเปลี่ยนจอแสดงผลเป็น 120Hz สาเหตุหนึ่งที่อาจเกิดปัญหานี้คือแอปอื่นมี Surface ที่มีการตั้งค่าอัตราเฟรมเป็น 24Hz ใน กรณีดังกล่าว การแสดงผลที่ 120Hz จะช่วยให้ทั้งพื้นผิว 60Hz และ พื้นผิว 24Hz ทำงานได้โดยไม่ต้องใช้พุลดาวน์

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

setFrameRate() เทียบกับ preferredDisplayModeId

WindowManager.LayoutParams.preferredDisplayModeId เป็นอีกวิธีที่แอปสามารถระบุอัตราเฟรมต่อแพลตฟอร์ม แอปบางแอปต้องการเปลี่ยนอัตราการรีเฟรชของจอแสดงผลเท่านั้น ไม่ต้องการเปลี่ยนการตั้งค่าโหมดการแสดงผลอื่นๆ เช่น ความละเอียดของจอแสดงผล โดยทั่วไป ให้ใช้ setFrameRate() แทน preferredDisplayModeId ฟังก์ชัน setFrameRate() ใช้งานง่ายกว่าเนื่องจากแอปไม่จำเป็นต้องค้นหาใน รายการโหมดการแสดงผลเพื่อหาโหมดที่มีอัตราเฟรมที่เฉพาะเจาะจง

setFrameRate() ช่วยให้แพลตฟอร์มมีโอกาสมากขึ้นในการเลือกอัตราเฟรมที่เข้ากันได้ ในสถานการณ์ที่มีแพลตฟอร์มหลายรายการที่ทำงานที่ อัตราเฟรมที่แตกต่างกัน ตัวอย่างเช่น ลองพิจารณาสถานการณ์ที่แอป 2 แอป ทํางานในโหมดแยกหน้าจอใน Pixel 4 โดยแอปหนึ่งเล่นวิดีโอ 24Hz และอีกแอปแสดงรายการที่เลื่อนได้ให้ผู้ใช้ Pixel 4 รองรับอัตราการรีเฟรชหน้าจอ 2 แบบ ได้แก่ 60Hz และ 90Hz การใช้ preferredDisplayModeId API ระบบจะบังคับให้พื้นผิววิดีโอเลือก 60Hz หรือ 90Hz การเรียกใช้ setFrameRate() ที่ 24Hz จะทำให้แพลตฟอร์มได้รับข้อมูลเพิ่มเติมเกี่ยวกับอัตราเฟรมของวิดีโอต้นฉบับ ซึ่งช่วยให้แพลตฟอร์ม เลือก 90Hz สำหรับอัตราการรีเฟรชของจอแสดงผลได้ ซึ่งดีกว่า 60Hz ในสถานการณ์นี้

อย่างไรก็ตาม มีบางสถานการณ์ที่ควรใช้ preferredDisplayModeId แทน setFrameRate() เช่น สถานการณ์ต่อไปนี้

  • หากแอปต้องการเปลี่ยนความละเอียดหรือการตั้งค่าโหมดการแสดงผลอื่นๆ ให้ใช้ preferredDisplayModeId
  • แพลตฟอร์มจะเปลี่ยนโหมดการแสดงผลเมื่อตอบสนองต่อการเรียกใช้ setFrameRate() เท่านั้น หากการเปลี่ยนโหมดมีขนาดเล็กและผู้ใช้ไม่น่าจะสังเกตเห็น หากแอปต้องการเปลี่ยนอัตราการรีเฟรชของจอแสดงผล แม้ว่าจะต้องเปลี่ยนโหมดอย่างหนัก (เช่น ในอุปกรณ์ Android TV ) ให้ใช้ preferredDisplayModeId
  • แอปที่ไม่สามารถจัดการการแสดงผลที่ทำงานที่อัตราเฟรมของแอปหลายรายการ ซึ่งต้องตั้งค่าการประทับเวลาการนำเสนอในแต่ละเฟรม ควรใช้ preferredDisplayModeId

setFrameRate() เทียบกับ preferredRefreshRate

WindowManager.LayoutParams#preferredRefreshRate กำหนดอัตราเฟรมที่ต้องการในหน้าต่างของแอป และอัตราดังกล่าวจะมีผล กับพื้นผิวทั้งหมดภายในหน้าต่าง แอปควรกำหนดอัตราเฟรมที่ต้องการโดยไม่คำนึงถึงอัตราการรีเฟรชที่อุปกรณ์รองรับ ซึ่งคล้ายกับ setFrameRate() เพื่อให้ตัวจัดตารางเวลาทราบอัตราเฟรมที่แอปต้องการได้ดียิ่งขึ้น

ระบบจะไม่สนใจ preferredRefreshRate สำหรับ Surface ที่ใช้ setFrameRate() โดยทั่วไป ให้ใช้ setFrameRate() หากเป็นไปได้

preferredRefreshRate เทียบกับ preferredDisplayModeId

หากแอปต้องการเปลี่ยนเฉพาะอัตราการรีเฟรชที่ต้องการ เราขอแนะนำให้ใช้ preferredRefreshRate แทน preferredDisplayModeId

หลีกเลี่ยงการเรียกใช้ setFrameRate() บ่อยเกินไป

แม้ว่าการเรียกใช้ setFrameRate() จะไม่ส่งผลต่อประสิทธิภาพมากนัก แต่แอปควรหลีกเลี่ยงการเรียกใช้ setFrameRate() ทุกเฟรมหรือหลายครั้งต่อวินาที การเรียกใช้ setFrameRate() มีแนวโน้มที่จะส่งผลให้มีการเปลี่ยนแปลง อัตราการรีเฟรชของจอแสดงผล ซึ่งอาจส่งผลให้เฟรมหลุดระหว่างการเปลี่ยน คุณควรหาอัตราเฟรมที่ถูกต้องล่วงหน้าและเรียกใช้ setFrameRate() เพียงครั้งเดียว

การใช้งานสำหรับเกมหรือแอปอื่นๆ ที่ไม่ใช่แอปวิดีโอ

แม้ว่าวิดีโอจะเป็น Use Case หลักสำหรับ setFrameRate() API แต่ก็สามารถใช้กับแอปอื่นๆ ได้ ตัวอย่างเช่น เกมที่ต้องการไม่ให้ทำงานสูงกว่า 60Hz (เพื่อลดการใช้พลังงานและเล่นได้นานขึ้น) สามารถเรียกใช้ Surface.setFrameRate(60, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT) ได้ ด้วยวิธีนี้ อุปกรณ์ที่ทำงานที่ 90Hz โดยค่าเริ่มต้นจะทำงานที่ 60Hz แทนในขณะที่เกมทำงานอยู่ ซึ่งจะหลีกเลี่ยงการสั่นที่อาจเกิดขึ้นหากเกมทำงานที่ 60Hz ในขณะที่จอแสดงผลทำงานที่ 90Hz

การใช้ FRAME_RATE_COMPATIBILITY_FIXED_SOURCE

FRAME_RATE_COMPATIBILITY_FIXED_SOURCE มีไว้สำหรับแอปวิดีโอเท่านั้น สำหรับการใช้งานที่ไม่ใช่วิดีโอ ให้ใช้ FRAME_RATE_COMPATIBILITY_DEFAULT

การเลือกกลยุทธ์ในการเปลี่ยนอัตราเฟรม

  • เราขอแนะนำเป็นอย่างยิ่งว่าเมื่อแอปแสดงวิดีโอที่เล่นเป็นเวลานาน เช่น ภาพยนตร์ แอปควรเรียกใช้ setFrameRate(fps, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS) โดยที่ fps คืออัตราเฟรมของวิดีโอ
  • เราขอแนะนำอย่างยิ่งไม่ให้แอปเรียกใช้ setFrameRate() ด้วย CHANGE_FRAME_RATE_ALWAYS เมื่อคุณคาดหวังให้การเล่นวิดีโอใช้เวลาหลายนาทีหรือน้อยกว่านั้น

ตัวอย่างการผสานรวมสำหรับแอปเล่นวิดีโอ

เราขอแนะนำให้ทำตามขั้นตอนต่อไปนี้เพื่อผสานรวมการสลับอัตรารีเฟรชในแอปเล่นวิดีโอ

  1. ตัดสินใจเกี่ยวกับchangeFrameRateStrategy:
    1. หากเล่นวิดีโอที่ยาว เช่น ภาพยนตร์ ให้ใช้ MATCH_CONTENT_FRAMERATE_ALWAYS
    2. หากเล่นวิดีโอสั้น เช่น ตัวอย่างภาพยนตร์ ให้ใช้ CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS
  2. หาก changeFrameRateStrategy เป็น CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS ให้ไปที่ขั้นตอนที่ 4
  3. ตรวจหาว่ากำลังจะมีการสลับอัตราการรีเฟรชที่ไม่ราบรื่นโดยตรวจสอบ ว่าข้อเท็จจริงทั้ง 2 ข้อต่อไปนี้เป็นจริง
    1. การเปลี่ยนโหมดอย่างราบรื่นจากอัตราการรีเฟรชปัจจุบัน (เราจะเรียกว่า C) เป็นอัตราเฟรมของวิดีโอ (เราจะเรียกว่า V) เป็นไปไม่ได้ กรณีนี้จะเกิดขึ้นหาก C และ V แตกต่างกันและ Display.getMode().getAlternativeRefreshRates ไม่มีค่าที่เป็นผลคูณของ V
    2. ผู้ใช้เลือกใช้การเปลี่ยนแปลงอัตราการรีเฟรชที่ไม่ราบรื่น คุณตรวจหา ได้โดยตรวจสอบว่า DisplayManager.getMatchContentFrameRateUserPreference แสดงผลเป็น MATCH_CONTENT_FRAMERATE_ALWAYS หรือไม่
  4. หากต้องการเปลี่ยนอย่างราบรื่น ให้ทำดังนี้
    1. เรียกใช้ setFrameRate และส่ง fps, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE และ changeFrameRateStrategy โดยที่ fps คืออัตราเฟรมของวิดีโอ
    2. เริ่มเล่นวิดีโอ
  5. หากกำลังจะมีการเปลี่ยนโหมดที่ไม่ราบรื่น ให้ทำดังนี้
    1. แสดง UX เพื่อแจ้งให้ผู้ใช้ทราบ โปรดทราบว่าเราขอแนะนำให้คุณใช้วิธีที่ ผู้ใช้สามารถปิด UX นี้และข้ามการหน่วงเวลาเพิ่มเติมในขั้นตอนที่ 5.ง. เนื่องจากดีเลย์ที่เราแนะนำนั้นมากกว่าที่จำเป็นบนจอแสดงผลที่ มีเวลาการสลับที่เร็วกว่า
    2. เรียกใช้ setFrameRate และส่ง fps, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, และ CHANGE_FRAME_RATE_ALWAYS โดยที่ fps คืออัตราเฟรมของวิดีโอ
    3. รอ onDisplayChanged การโทรกลับ
    4. รอ 2 วินาทีเพื่อให้การสลับโหมดเสร็จสมบูรณ์
    5. เริ่มเล่นวิดีโอ

รหัสเทียมที่รองรับเท่านั้นสำหรับการเปลี่ยนอัตโนมัติมีดังนี้

SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
transaction.setFrameRate(surfaceControl,
    contentFrameRate,
    FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
    CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
transaction.apply();
beginPlayback();

รหัสเทียมเพื่อรองรับการสลับที่ราบรื่นและไม่ราบรื่นตามที่อธิบายไว้ข้างต้นมีดังนี้

SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
if (isSeamlessSwitch(contentFrameRate)) {
  transaction.setFrameRate(surfaceControl,
      contentFrameRate,
      FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
      CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
  transaction.apply();
  beginPlayback();
} else if (displayManager.getMatchContentFrameRateUserPreference()
      == MATCH_CONTENT_FRAMERATE_ALWAYS) {
  showRefreshRateSwitchUI();
  sleep(shortDelaySoUserSeesUi);
  displayManager.registerDisplayListener();
  transaction.setFrameRate(surfaceControl,
      contentFrameRate,
      FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
      CHANGE_FRAME_RATE_ALWAYS);
  transaction.apply();
  waitForOnDisplayChanged();
  sleep(twoSeconds);
  hideRefreshRateSwitchUI();
  beginPlayback();
}