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

Bộ nhớ có giới hạn giới hạn quyền truy cập của ứng dụng vào bộ nhớ ngoài. Trên 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 ứng dụng và dữ liệu 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 của người dùng mà không có sự cho phép rõ ràng, cũng như bảo vệ 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.

Ứng dụng sử dụng bộ nhớ có giới hạn có thể có các cấp truy cập sau (quyền truy cập thực tế là tuỳ thuộc vào cách triển khai).

  • Quyền đọcghi vào tệp của riêng ứng dụng mà không cần quyền
  • Quyền Đọc tệp nội dung nghe nhìn của các ứng dụng khác bằng quyền READ_EXTERNAL_STORAGE
  • Chỉ được phép cấp quyền 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 (các trường hợp ngoại lệ được cấp cho Thư viện hệ thống và các ứng dụng đủ điều kiện để truy cập vào Mọi tệp)
  • Không có quyền đọc hoặc ghi vào thư mục dữ liệu ứng dụng bên ngoài của các ứ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). Hệ thống này cho phép mô-đun MediaProvider kiểm tra các thao tác tệp trong không gian người dùng và kiểm soát quyền truy cập vào tệp dựa trên chính sách cho phép, từ chối hoặc cắt bớt 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 tệp bằng đường dẫn tệp trực tiếp (giúp 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 tệp của MediaProvider, nhưng không áp dụng cho quyền truy cập đường dẫn tệp trực tiếp (ví dụ: sử dụng API Tệp và API NDK) do cần phải chặn các lệnh gọi hạt nhân. Do đó, các ứng dụng trong bộ nhớ có giới hạn không thể truy cập vào tệp bằng đường dẫn tệp trực tiếp. Quy định 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ì cần phải thay đổi đáng kể mã để viết lại quyền truy cập API Tệp vào API MediaProvider.

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 cung cấp một giải pháp thay thế cho Media Store cho các thiết bị trước đây sử dụng SDCardFS. Thiết bị:

  • Khi khởi chạy bằng Android 11 trở lên bằ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 đầu SDCardFS để chặn các hoạt động của 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

Android trước đây 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à tắc nghẽn khi triển khai FUSE đó, Android 8 đã ra mắt SDCardFS. Android 11 giới thiệu lại tính năng hỗ trợ cho FUSE bằng cách sử dụng phương thức triển khai libfuse được cải tiến và kiểm thử tốt hơn, 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.

Tính năng điều chỉnh FUSE bao gồm các tinh chỉnh sau:

  • Bỏ qua FUSE cho 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 các thư mục này.
  • Các hoạt động tối ưu hoá (chẳng hạn như điều chỉnh tỷ lệ đọc trước và sửa đổi của hệ thống tệp FUSE) để đảm bảo hoạt động đọc và phát nội dung nghe nhìn diễn ra mượt mà.
  • Sử dụng bộ nhớ đệm ghi lại FUSE.
  • Lưu quyền vào bộ nhớ đệm để giảm IPC đến máy chủ hệ thống.
  • Các tính năng tối ưu hoá cho ứ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 tuỳ chọn điều chỉnh nêu trên có thể tạo ra hiệu suất tương đương giữa thiết bị FUSE và thiết bị không phải FUSE. Ví dụ: khi kiểm thử Pixel 2 được điều chỉnh bằng FUSE và Pixel 2 bằng Media Store, bạn sẽ nhận thấy hiệu suất đọc tuần tự tương đương (chẳng hạn như phát video) giữa quyền truy cập vào đường dẫn tệp và Media Store. Tuy nhiên, các hoạt động ghi tuần tự kém hơn một chút so với FUSE, còn các hoạt động đọc và ghi ngẫu nhiên có thể chậm hơn gấp đôi.

Kết quả đo lường 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ì các API MediaProvider mang lại hiệu suất nhất quán nhất, nên các nhà phát triển ứng dụng quan tâm đến hiệu suất nên sử dụng các API MediaProvider cho ứng dụng của họ.

Giảm thiểu tác động của FUSE đối với hiệu suất

Mức tác động đến hiệu suất của FUSE chỉ giới hạn ở những người dùng thường xuyên các tệp được lưu trữ trên bộ nhớ ngoài dùng chung. Bộ nhớ riêng tư bên ngoài (bao gồm cả các thư mục android/dataandroid/obb) bị FUSE bỏ qua, 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 để đảm bảo dữ liệu được mã hoá và bảo mật) không được gắn FUSE.

  • Các ứng dụng ít dùng bộ nhớ ngoài dùng chung thường tương tác với một nhóm tệp giới hạn (thường dưới 100 tệp). Những ứng dụng này được hưởng lợi từ các biện pháp tối ưu hoá hiện có cho các thao tác đọc và ghi phổ biến và sẽ không thấy 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 có nhiều người dùng 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á thư mục có 1.000 tệp hoặc tạo/xoá một thư mục có hàng triệu tệp trên hệ thống tệp. Các hoạt động của tệp hàng loạt có thể chịu ảnh hưởng của FUSE trên Android 11. Tuy nhiên, nếu các ứng dụng đó đủ điều kiện để cấp quyền MANAGE_EXTERNAL_STORAGE, thì các ứng dụng đó sẽ được hưởng lợi từ các tính nă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 của FUSE, ứng dụng có thể lưu trữ dữ liệu trong bộ nhớ riêng tư bên ngoài hoặc sử dụng các API hàng loạt trong lớp ContentProvider để bỏ qua FUSE và nhận đườ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 bao gồm các tính năng 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, diệt vi-rút) có quyền MANAGE_EXTERNAL_STORAGE.

Quyền riêng tư 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 như nhau 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 các mẫu truy cập tệp hoạt động kém hơn trong Android 11 (ví dụ: đọc hoặc ghi ngẫu nhiên), bạn nên sử dụng API MediaProvider để cung cấp cho ứng dụng chế độ truy cập không phải FUSE. Đây là lựa chọn hiệu quả nhất và nhất quán nhất.

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 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 một ứng dụng 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òn được dùng nữa và MediaProvider trở thành trình xử lý hệ thống tệp (dành 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 hạt nhân và đảm bảo các thao tác với tệp đảm bảo 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ô-đ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 phát hiện được trong MediaProvider có thể được khắc phục và phân phối qua mạng không dây 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 dự kiến của 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à hồi quy về hiệu suất của FUSE.