Cờ tính năng và chế độ Canary

Media3 giới thiệu các tính năng tối ưu hoá mới, cải tiến hành vi và cải tiến cấu trúc trên các thư viện của mình. Mặc dù những thay đổi này được kiểm thử và xác minh kỹ lưỡng trước khi phát hành, nhưng Media3 có một cơ sở hạ tầng cờ tính năng tập trung (androidx.media3.common.Flags) xoay quanh chế độ Canary để giúp các ứng dụng kiểm soát cách thức và thời điểm áp dụng các hành vi mới.

Trang này giải thích cách hoạt động của chế độ Canary và cờ tính năng, cũng như cách bạn có thể sử dụng các chế độ này trong ứng dụng để giảm rủi ro nâng cấp giữa các bản phát hành, chạy các bản phát hành có kiểm soát và định cấu hình khôi phục khẩn cấp.

Tổng quan

Chế độ Canary nhóm các điểm cải tiến mới được giới thiệu và đã được xác minh của thư viện vào một nút bật/tắt chung, hợp nhất:

  • Bật theo mặc định: Trong các bản phát hành Media3 tiêu chuẩn, chế độ Canary được bật theo mặc định (true). Điều này đảm bảo ứng dụng của bạn tự động hưởng lợi từ các tính năng nâng cao hiệu suất, tối ưu hoá và các tính năng mới an toàn.
  • Khả năng chọn không tham gia và khôi phục: Ứng dụng có thể tắt chế độ Canary trên toàn cầu hoặc ghi đè từng cờ tính năng cụ thể trong thời gian chạy.
  • Không có sự phức tạp về dây nối: Cờ được quản lý thông qua lớp Flags trung tâm trong mô-đun common, giúp loại bỏ nhu cầu về phương thức setter hoặc đối tượng cấu hình riêng biệt trên các thành phần khác nhau.

Tại sao nên sử dụng Cờ trong ứng dụng?

Mặc dù chế độ Canary được bật theo mặc định, nhưng việc tích hợp Flags với cấu hình hoặc khung thử nghiệm của ứng dụng sẽ mang lại một số lợi ích:

1. Giảm thiểu rủi ro khi nâng cấp phiên bản

Việc nâng cấp các phiên bản thư viện chính hoặc phụ trong phiên bản chính thức có thể gây ra các hoạt động tương tác ngoài dự kiến trên các thiết bị OEM cụ thể hoặc quy trình phát nội dung nghe nhìn tuỳ chỉnh. Khi cập nhật Media3, bạn có thể sử dụng chế độ Canary và cấu hình từ xa để có quy trình nâng cấp an toàn hơn trên các bản phát hành:

  1. Phát hành bản cập nhật khi tắt chế độ Canary: Việc phát hành phiên bản Media3 mới khi tắt chế độ Canary sẽ giữ nguyên tập tính chất của bản phát hành trước đó (khi bật Canary), cho phép bạn xác minh độ ổn định của thư viện đường cơ sở và các bản sửa lỗi chung trong phiên bản phát hành công khai trước khi áp dụng các Hành vi mới.
  2. Bật dần chế độ Canary: Sử dụng cấu hình từ xa để bật chế độ Canary theo từng giai đoạn trên các nhóm người dùng (ví dụ: 5% → 25% → 100%) hoặc chạy thử nghiệm A/B để đo lường tác động của chỉ số.
  3. Khôi phục nếu cần: Nếu xảy ra lỗi hồi quy trên một số thiết bị, hãy tắt chế độ Canary hoặc mã nhận dạng cờ cụ thể từ xa mà không cần phát hành ứng dụng khẩn cấp.
  4. Sử dụng làm mặc định: Sau khi xác minh, hãy bật chế độ Canary theo mặc định cho đến lần nâng cấp phiên bản tiếp theo, khi các tính năng Canary đã xác minh trước đó trở thành vĩnh viễn.

Kotlin

// Enable or disable Canary mode globally (defaults to true).
Flags.setCanaryModeEnabled(false)

Java

// Enable or disable Canary mode globally (defaults to true).
Flags.setCanaryModeEnabled(false);

2. Bản phát hành theo giai đoạn có kiểm soát và thử nghiệm A/B

Thay vì cho phép 100% người dùng trải nghiệm các hành vi mới của thư viện cùng một lúc, bạn có thể kết nối Flags với một hệ thống thử nghiệm hoặc cấu hình từ xa.

Bạn có thể bật chế độ Canary theo giai đoạn (ví dụ: 5% người dùng → 25% → 100%) hoặc chạy thử nghiệm A/B để đo lường tác động của các tính năng tối ưu hoá mới đối với các chỉ số phát chính như độ trễ khởi động, tỷ lệ tải lại vào vùng đệm và lỗi phát.

3. Công tắc tắt từ xa và khôi phục nhanh

Nếu xảy ra lỗi hồi quy trong phiên bản chính thức trên một mẫu thiết bị hoặc phiên bản hệ điều hành cụ thể, bạn có thể tắt chế độ Canary từ xa (hoặc mã nhận dạng cờ cụ thể chịu trách nhiệm) bằng cách sử dụng cấu hình phía máy chủ. Thao tác này sẽ ngay lập tức đưa thư viện về hành vi dự phòng ổn định, cũ cho người dùng bị ảnh hưởng mà không cần bản sửa lỗi khẩn cấp cho ứng dụng hoặc bản phát hành nhị phân.

Định cấu hình chế độ và cờ Canary

API Flags cung cấp các phương thức để kiểm soát chế độ Canary chung và ghi đè cờ riêng lẻ.

Chế độ Canary toàn cầu

Cách bật hoặc tắt tất cả các tính năng nâng cao trong chế độ Canary:

Kotlin

// Enable or disable Canary mode globally (defaults to true).
Flags.setCanaryModeEnabled(false)

Java

// Enable or disable Canary mode globally (defaults to true).
Flags.setCanaryModeEnabled(false);

Ghi đè từng cờ

Bạn cũng có thể bật hoặc tắt rõ ràng các cờ cụ thể độc lập với chế độ cài đặt Canary chung:

Kotlin

// Explicitly enable an experimental flag.
Flags.enableFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION)

// Explicitly disable a flag.
Flags.disableFlag(Flags.FLAG_DYNAMIC_SCHEDULING)

Java

// Explicitly enable an experimental flag.
Flags.enableFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION);

// Explicitly disable a flag.
Flags.disableFlag(Flags.FLAG_DYNAMIC_SCHEDULING);

Các chế độ ghi đè rõ ràng luôn được ưu tiên hơn chế độ Canary mặc định chung.

Đang kiểm tra trạng thái gắn cờ

Cách kiểm tra xem chế độ Canary hoặc một cờ cụ thể có đang hoạt động trong mã của bạn hay không:

Kotlin

// Query whether Canary mode is active globally.
val isCanaryActive = Flags.isCanaryModeEnabled()

// Query whether a specific flag is active.
val isFeatureActive = Flags.isEnabled(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION)

Java

// Query whether Canary mode is active globally.
boolean isCanaryActive = Flags.isCanaryModeEnabled();

// Query whether a specific flag is active.
boolean isFeatureActive = Flags.isEnabled(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION);

Thứ tự giải quyết cờ

Khi Media3 kiểm tra xem một tính năng có được bật trong thời gian chạy hay không, Media3 sẽ phân giải trạng thái theo thứ tự sau:

  1. Ghi đè rõ ràng trong thời gian chạy: Nếu enableFlag hoặc disableFlag được gọi cho mã nhận dạng cờ, thì giá trị ghi đè đó sẽ được trả về.
  2. Trạng thái thư viện tĩnh: Nếu cờ bị tắt tĩnh (ví dụ: tính năng phát triển sớm chưa sẵn sàng cho chế độ Canary) hoặc được bật tĩnh (tính năng đã tốt nghiệp từ chế độ Canary giữ lại tính năng dự phòng chọn không tham gia tạm thời), thì giá trị tĩnh đó sẽ được trả về.
  3. Trạng thái chế độ Canary: Nếu không, cờ sẽ tuân theo chế độ cài đặt Canary chung (bật nếu chế độ Canary là true, tắt nếu là false).

Yêu cầu về việc khởi chạy

Định cấu hình cờ trước khi tạo thực thể cho bất kỳ thành phần Media3 nào (chẳng hạn như ExoPlayer, Transformer hoặc MediaSession):

  • Thiết lập sớm: Định cấu hình Flags trong quá trình khởi động ứng dụng (ví dụ: bên trong Application.onCreate) hoặc trước khi khởi chạy lớp nội dung nghe nhìn của ứng dụng.
  • An toàn luồng: Các thành phần Media3 đọc cờ trong quá trình tạo thực thể và truyền các giá trị đó đến các luồng xử lý và phát nội dung nội bộ. Hãy đảm bảo rằng việc định cấu hình cờ diễn ra trước khi tạo các thành phần Media3. Không hỗ trợ việc sửa đổi cờ trong khi trình phát hoặc trình biến đổi đang chạy.

Tích hợp với cấu hình từ xa

Cấu trúc được đề xuất là hiển thị 3 tham số trong nền tảng cấu hình từ xa:

  • media3_canary_mode_enabled (Boolean): Nút bật/tắt chung cho chế độ Canary (mặc định là true).
  • media3_force_enable_flags (Danh sách số nguyên): Mã cờ cụ thể để buộc bật cho các bản dùng thử được nhắm mục tiêu.
  • media3_force_disable_flags (Danh sách số nguyên): Mã cờ cụ thể để buộc tắt nếu phát hiện thấy vấn đề.

Áp dụng các giá trị này trong quá trình khởi động trước khi tạo thực thể trình phát:

Kotlin

fun initializeMedia3Flags(
  canaryModeEnabled: Boolean,
  forceEnabledFlags: List<Int>,
  forceDisabledFlags: List<Int>,
) {
  // 1. Set global Canary mode state.
  Flags.setCanaryModeEnabled(canaryModeEnabled)

  // 2. Apply explicit force-enable overrides.
  for (flagId in forceEnabledFlags) {
    Flags.enableFlag(flagId)
  }

  // 3. Apply explicit force-disable overrides (remote kill switch).
  for (flagId in forceDisabledFlags) {
    Flags.disableFlag(flagId)
  }
}

Java

public static void initializeMedia3Flags(
    boolean canaryModeEnabled,
    List<Integer> forceEnabledFlags,
    List<Integer> forceDisabledFlags) {
  // 1. Set global Canary mode state.
  Flags.setCanaryModeEnabled(canaryModeEnabled);

  // 2. Apply explicit force-enable overrides.
  for (int flagId : forceEnabledFlags) {
    Flags.enableFlag(flagId);
  }

  // 3. Apply explicit force-disable overrides (remote kill switch).
  for (int flagId : forceDisabledFlags) {
    Flags.disableFlag(flagId);
  }
}

Kiểm thử bằng cờ

Khi viết mã kiểm thử đơn vị hoặc kiểm thử Robolectric cho các đường dẫn mã chịu ảnh hưởng của cờ tính năng, hãy sử dụng androidx.media3.test.utils.Media3FlagsRule (có trong mô-đun media3-test-utils) để đảm bảo các mã kiểm thử không làm ảnh hưởng đến trạng thái tĩnh của nhau.

Tự động dọn dẹp bằng Media3FlagsRule

Việc thêm Media3FlagsRule đảm bảo rằng tất cả các chế độ ghi đè cờ và sửa đổi chế độ Canary sẽ tự động được đặt lại sau mỗi lần kiểm thử:

Kotlin

class MyPlayerTest {

  @get:Rule val flagsRule = Media3FlagsRule(this)

  @Test
  fun playback_withFeatureFlagEnabled() {
    Flags.enableFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION)
    // Run test with the flag enabled...
  }
}

Java

public static class MyPlayerTest {

  @Rule public final Media3FlagsRule flagsRule = new Media3FlagsRule(this);

  @Test
  public void playback_withFeatureFlagEnabled() {
    Flags.enableFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION);
    // Run test with the flag enabled...
  }
}

Kiểm thử có tham số

Bạn có thể kết hợp Media3FlagsRule với chú thích @BindFlag và @BindCanaryMode để chạy kiểm thử có tham số trên các trạng thái cờ:

Kotlin

class MyParameterizedPlayerTest {

  @BindCanaryMode var canaryMode: Boolean = false

  @BindFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION) var perStreamProgression: Boolean = false

  @get:Rule val flagsRule = Media3FlagsRule(this)

  @Test
  fun playback() {
    // Flags are automatically set for each test parameter combination.
  }
}

Java

public static class MyParameterizedPlayerTest {

  @BindCanaryMode public boolean canaryMode;

  @BindFlag(Flags.FLAG_PER_STREAM_MEDIA_PROGRESSION)
  public boolean perStreamProgression;

  @Rule public final Media3FlagsRule flagsRule = new Media3FlagsRule(this);

  @Test
  public void playback() {
    // Flags are automatically set for each test parameter combination.
  }
}

Chẩn đoán và ghi nhật ký

Media3 cung cấp các công cụ chẩn đoán để xác minh cờ đang hoạt động và trạng thái chế độ Canary trong quá trình khởi chạy và trong thời gian chạy.

Nhật ký khởi chạy

Khi một thực thể ExoPlayer được khởi chạy, thực thể đó sẽ in trạng thái Canary đang hoạt động và mọi cơ chế ghi đè rõ ràng vào logcat cùng với phiên bản thư viện:

ExoPlayerImpl: Init 59a18ab [AndroidXMedia3/1.10.1] [flame, Pixel 4, Google, 33] [Canary:ON]

Nếu các chế độ ghi đè đang hoạt động, thì chỉ những độ lệch so với trạng thái mặc định mới được liệt kê:

ExoPlayerImpl: Init 59a18ab [AndroidXMedia3/1.10.1] [flame, Pixel 4, Google, 33] [Canary:ON, Overrides: enabled=[1], disabled=[3]]

Kiểm tra có lập trình

Bạn có thể truy xuất chuỗi chẩn đoán được định dạng hoặc danh sách ghi đè truy vấn theo phương thức lập trình (ví dụ: để đưa trạng thái cờ vào báo cáo sự cố hoặc số liệu phân tích của ứng dụng):

Kotlin

// Get formatted string representing active Canary state and overrides.
val flagLogString = Flags.getLogString()

// Query explicit override IDs if needed.
val enabledFlags = Flags.getEnabledOverrides()
val disabledFlags = Flags.getDisabledOverrides()

Java

// Get formatted string representing active Canary state and overrides.
String flagLogString = Flags.getLogString();

// Query explicit override IDs if needed.
int[] enabledFlags = Flags.getEnabledOverrides();
int[] disabledFlags = Flags.getDisabledOverrides();

Vòng đời của cờ

Cờ trong Media3 được thiết kế để tạm thời:

  1. Phát triển: Một tính năng hoặc hoạt động tối ưu hoá mới được thêm vào sau mã nhận dạng cờ trong Flags.java.
  2. Chế độ Canary: Sau khi được xác minh và sẵn sàng cho mục đích sử dụng chung, tính năng này sẽ hoạt động ở chế độ Canary trên các bản phát hành.
  3. Quảng bá và dọn dẹp: Sau một khoảng thời gian thử nghiệm chứng minh được độ ổn định trong môi trường thực tế, tính năng này sẽ được quảng bá để bật vĩnh viễn trong thư viện, đồng thời hằng số cờ, đường dẫn mã dự phòng và các bước kiểm tra có điều kiện sẽ bị xoá.

Nếu bạn gặp vấn đề với cờ tính năng, vui lòng gửi báo cáo trên Trình theo dõi sự cố AndroidX Media3 trên GitHub để nhóm có thể giải quyết vấn đề trước khi quảng bá vĩnh viễn.