Bộ nhớ có giới hạn

Bộ nhớ có giới hạn hạn chế quyền truy cập của ứng dụng vào bộ nhớ ngoài. Trong Android 11 trở lên, các ứng dụng nhắm đến API 30 trở lên phải sử dụng bộ nhớ có giới hạn. Trước đây, trong Android 10, các ứng dụng có thể chọn không sử dụng bộ nhớ có giới hạn.

Hạn chế quyền truy cập vào ứng dụng

Mục tiêu của bộ nhớ có giới hạn là bảo vệ quyền riêng tư của dữ liệu ứng dụng và người dùng. Điều này bao gồm việc bảo vệ thông tin người dùng (chẳng hạn như siêu dữ liệu ảnh), ngăn ứng dụng sửa đổi hoặc xoá tệp người dùng mà không có quyền rõ ràng và bảo vệ các tài liệu nhạy cảm của người dùng được tải xuống thư mục Tải xuống hoặc các thư mục khác.

Các ứng dụng sử dụng bộ nhớ có phạm vi có thể có các cấp truy cập sau (quyền truy cập thực tế là dành riêng cho việc triển khai).

  • Quyền đọcghi đối với các tệp của riêng họ mà không cần có quyền
  • Quyền đọc đối với tệp nội dung nghe nhìn của các ứng dụng khác bằng quyền READ_EXTERNAL_STORAGE
  • Bạn chỉ được phép ghi vào tệp nội dung nghe nhìn của các ứng dụng khác khi có sự đồng ý trực tiếp của người dùng (trừ Thư viện hệ thống và những ứng dụng đủ điều kiện có quyền truy cập vào Mọi tệp)
  • Không có quyền đọc hoặc ghi đối với các thư mục dữ liệu ứng dụng bên ngoài của ứng dụng khác

Sử dụng bộ nhớ có giới hạn với FUSE

Android 11 trở lên hỗ trợ Hệ thống tệp trong không gian người dùng (FUSE), cho phép mô-đun MediaProvider kiểm tra các thao tác trên tệp trong không gian người dùng và hạn chế quyền truy cập vào các tệp dựa trên chính sách cho phép, từ chối hoặc chỉnh sửa quyền truy cập. Các ứng dụng trong bộ nhớ có giới hạn sử dụng FUSE sẽ có các tính năng bảo mật của bộ nhớ có giới hạn và khả năng truy cập vào các tệp bằng đường dẫn tệp trực tiếp (giúp các API Tệp hoạt động trong ứng dụng).

Android 10 đã thực thi các quy tắc về bộ nhớ có giới hạn đối với quyền truy cập vào tệp của MediaProvider, nhưng không thực thi đối với quyền truy cập trực tiếp vào đường dẫn tệp (ví dụ: sử dụng File API và NDK API) do cần phải nỗ lực chặn các lệnh gọi của nhân. Do đó, các ứng dụng trong bộ nhớ có giới hạn không thể truy cập vào các tệp bằng đường dẫn tệp trực tiếp. Hạn chế này ảnh hưởng đến khả năng thích ứng của nhà phát triển ứng dụng vì họ phải thay đổi đáng kể mã để viết lại quyền truy cập File API thành MediaProvider API.

FUSE và SDCardFS

Việc Android 11 hỗ trợ FUSE không liên quan đến việc ngừng sử dụng SDCardFS, nhưng có cung cấp một giải pháp thay thế cho Thư viện đa phương tiện đối với những thiết bị từng dùng SDCardFS. Thiết bị:

  • Khi khởi chạy bằng Android 11 trở lên bằng cách sử dụng nhân 5.4 trở lên, bạn không thể sử dụng SDCardFS.
  • Việc nâng cấp lên Android 11 trở lên có thể lưu trữ FUSE trên SDCardFS để chặn các thao tác trên tệp và đáp ứng các mục tiêu về quyền riêng tư.

Điều chỉnh hiệu suất FUSE

Trước đây, Android hỗ trợ FUSE trong Android 7 trở xuống, trong đó bộ nhớ ngoài được gắn dưới dạng FUSE. Do các vấn đề về hiệu suất và bế tắc với việc triển khai FUSE đó, Android 8 đã giới thiệu SDCardFS. Android 11 hỗ trợ lại FUSE bằng cách sử dụng một quy trình triển khai libfuse được cải thiện và kiểm thử kỹ lưỡng hơn. Quy trình này có thể được điều chỉnh để giải quyết các vấn đề về hiệu suất trong Android 7 trở xuống.

Quy trình điều chỉnh FUSE bao gồm các điểm điều chỉnh sau:

  • Bỏ qua FUSE cho các thư mục Android/dataAndroid/obb để cải thiện hiệu suất cho các ứng dụng trò chơi dựa vào những thư mục này.
  • Tối ưu hoá (chẳng hạn như điều chỉnh tỷ lệ đọc trước và tỷ lệ bẩn của hệ thống tệp FUSE) để duy trì hiệu suất đọc và phát nội dung nghe nhìn mượt mà.
  • Sử dụng bộ nhớ đệm ghi lại của FUSE.
  • Lưu quyền vào bộ nhớ đệm để giảm IPC cho máy chủ hệ thống.
  • Tối ưu hoá cho các ứng dụng có quyền truy cập vào Tất cả tệp để thực hiện các thao tác hàng loạt nhanh hơn.

Các tinh chỉnh ở trên có thể mang lại hiệu suất tương đương giữa các thiết bị FUSE và không phải FUSE. Ví dụ: việc kiểm thử một chiếc Pixel 2 đã được điều chỉnh bằng FUSE và một chiếc Pixel 2 bằng Kho lưu trữ nội dung nghe nhìn cho thấy hiệu suất đọc tuần tự tương đương (ví dụ: phát video) giữa quyền truy cập vào đường dẫn tệp và Kho lưu trữ nội dung nghe nhìn. Tuy nhiên, các thao tác ghi tuần tự kém hơn một chút với FUSE, còn các thao tác đọc và ghi ngẫu nhiên có thể chậm hơn gấp đôi.

Các phép đo hiệu suất có thể thay đổi tuỳ theo thiết bị và giữa các trường hợp sử dụng cụ thể. Vì MediaProvider API mang lại hiệu suất ổn định nhất, nên các nhà phát triển ứng dụng lo ngại về hiệu suất nên sử dụng MediaProvider API cho ứng dụng của họ.

Giảm thiểu tác động của FUSE đến hiệu suất

Tác động của FUSE đến hiệu suất chỉ giới hạn ở những người dùng thường xuyên sử dụng các tệp được lưu trữ trên bộ nhớ dùng chung bên ngoài. FUSE bỏ qua bộ nhớ riêng tư bên ngoài (bao gồm cả thư mục android/dataandroid/obb), trong khi bộ nhớ trong (chẳng hạn như /data/data, nơi nhiều ứng dụng lưu trữ dữ liệu để giữ cho dữ liệu được mã hoá và an toàn) không được FUSE gắn kết.

  • Các ứng dụng có ít người dùng bộ nhớ ngoài dùng chung thường tương tác với một số lượng tệp hạn chế (thường ít hơn 100 tệp). Những ứng dụng này được hưởng lợi từ các hoạt động tối ưu hoá hiện có đối với các thao tác đọc và ghi thông thường, đồng thời không gặp phải bất kỳ tác động nào đến hiệu suất liên quan đến FUSE trong Android 11.

  • Các ứng dụng sử dụng nhiều bộ nhớ ngoài dùng chung thường thực hiện các thao tác hàng loạt đối với tệp, chẳng hạn như liệt kê hoặc xoá một thư mục có 1.000 tệp, hoặc tạo hoặc xoá một thư mục có 1 triệu tệp trên hệ thống tệp. Các thao tác hàng loạt trên tệp có thể chịu ảnh hưởng của FUSE trên Android 11, nhưng nếu các ứng dụng đó đủ điều kiện để có quyền MANAGE_EXTERNAL_STORAGE, thì chúng sẽ được hưởng lợi từ các hoạt động tối ưu hoá hiệu suất có trong bản cập nhật tháng 10 năm 2020.

Để tránh hao tổn hiệu suất FUSE, các ứng dụng có thể lưu trữ dữ liệu trong bộ nhớ riêng bên ngoài hoặc dùng các API hàng loạt trong lớp ContentProvider để bỏ qua FUSE và nhận được một đường dẫn được tối ưu hoá hiệu suất. Ngoài ra, bản cập nhật tháng 10 năm 2020 cho thành phần hệ thống MediaProvider còn có các điểm tối ưu hoá hiệu suất cho trình quản lý tệp và các ứng dụng tương tự (chẳng hạn như sao lưu/khôi phục, chống vi-rút) có quyền MANAGE_EXTERNAL_STORAGE.

Quyền riêng tư quan trọng hơn hiệu suất

Trên các thiết bị đã được điều chỉnh cho FUSE, hầu hết các hành trình quan trọng của người dùng đều có hiệu suất tương đương giữa Android 10 và Android 11. Tuy nhiên, khi kiểm thử điểm chuẩn trên một tập hợp các thao tác với tệp, Android 11 có thể hoạt động kém hơn Android 10. Đối với những mẫu truy cập tệp có hiệu suất kém hơn trong Android 11 (ví dụ: lượt đọc hoặc ghi ngẫu nhiên), bạn nên sử dụng API MediaProvider để cung cấp cho ứng dụng một chế độ truy cập không phải FUSE, đây là lựa chọn tốt nhất và có hiệu suất ổn định.

Thông tin cập nhật về MediaProvider và FUSE

Hành vi của thành phần hệ thống MediaProvider khác nhau giữa các bản phát hành Android.

  • Trong Android 10 trở xuống, SDCardFS là hệ thống tệp và MediaProvider cung cấp một giao diện cho các bộ sưu tập tệp (ví dụ: hình ảnh, video, tệp nhạc, v.v.). Khi tạo một tệp bằng File API, ứng dụng có thể yêu cầu MediaProvider quét tệp đó và ghi lại trong cơ sở dữ liệu.

  • Trong Android 11 trở lên, SDCardFS không được dùng nữa và MediaProvider trở thành trình xử lý hệ thống tệp (cho FUSE) cho bộ nhớ ngoài, giúp hệ thống tệp trên bộ nhớ ngoài và cơ sở dữ liệu MediaProvider nhất quán. Là trình xử lý không gian người dùng cho hệ thống tệp FUSE, MediaProvider có thể chặn các lệnh gọi của nhân và đảm bảo các thao tác trên tệp đều an toàn về quyền riêng tư.

Trong Android 11 trở lên, MediaProvider cũng là một thành phần hệ thống mô-đun (một mô-đun Mainline) có thể được cập nhật bên ngoài các bản phát hành Android. Điều này có nghĩa là các vấn đề về hiệu suất, quyền riêng tư hoặc bảo mật được phát hiện trong MediaProvider có thể được khắc phục và cung cấp qua mạng từ Cửa hàng Google Play hoặc các cơ chế khác do đối tác cung cấp. Mọi thứ trong phạm vi những gì được mong đợi từ trình xử lý FUSE cũng có thể cập nhật, cho phép cập nhật để khắc phục các lỗi và sự hồi quy hiệu suất FUSE.