อัตราเฟรม

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

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

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

Android นำเสนอวิธีต่างๆ ในการเข้าถึงและควบคุมแพลตฟอร์ม 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 เพื่อล้างพื้นผิว การตั้งค่าอัตราเฟรมกลับไปเป็นค่าเริ่มต้น คุณไม่จำเป็นต้องล้างการตั้งค่าอัตราเฟรมเช่นนี้เมื่อทำลายแพลตฟอร์มหรือเมื่อแพลตฟอร์มซ่อนอยู่เนื่องจากผู้ใช้เปลี่ยนไปใช้แอปอื่น ให้ล้างการตั้งค่าอัตราเฟรมเฉพาะในกรณีที่แพลตฟอร์มยังคงมองเห็นได้อยู่แต่ไม่มีการใช้งาน

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

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

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

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

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

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

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

หลายพื้นผิว

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

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

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

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

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

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

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

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

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

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

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

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

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