Dogłębna analiza SDCardFS, zamiennika FUSE firmy Google, oraz tego, jak jego wdrożenie zmniejszy obciążenie we/wy.
Kilka miesięcy temu Google dodał coś o nazwie „Karta SDFS” do oficjalnych oddziałów AOSP dla jądra Linuksa. W tym czasie ruch został zauważony tylko przez niektórzy programiści jądra, ale poza tym pozostawał poza zasięgiem radaru większości użytkowników. Nie ma w tym nic dziwnego, biorąc pod uwagę fakt, że większość użytkowników, w tym ja, tak naprawdę nie wie, co kryje się pod maską systemu operacyjnego Android i jego jądra.
Jednak najnowszy odcinek Za kulisami programiści Androida podcast odnowiło zainteresowanie tym tematem. Podcast prowadzony przez Cheta Haase’a (starszego inżyniera oprogramowania w Google) omawiał najnowsze i nadchodzące zmiany wprowadzone w jądrze. W programie wystąpił programista jądra Linuksa pracujący w zespole Androida – Rom Lemarchand. Duet omawiał przede wszystkim zmiany wprowadzone w celu uwzględnienia aktualizacji A/B, ale w ostatnich 5 minutach odcinka pan Lemarchand mówił o „następnej wielkiej rzeczy”, nad którą pracował jego zespół –
Karta SDFS.Muszę przyznać, że o istnieniu SDCardFS dowiedziałem się po wysłuchaniu tego podcastu. Oczywiście nie tylko ja zainteresowałem się tym tematem, jako że najnowszy wątek na Reddicie pokazał. Jednak podstawowe wyjaśnienie podane w podcaście nie zadowoliło mnie i chcąc rozwiać niektóre wątpliwości, rozpowszechnianych dezinformacji, przeprowadziłem własne badania i rozmawiałem z kilkoma ekspertami posiadającymi odpowiednią wiedzę na ten temat materiał.
Ogromne podziękowania dla programisty Michała Kowalczyka za wniesienie swojej wiedzy do tego artykułu i poświęcenie czasu na udzielenie odpowiedzi na moje pytania.
„Zewnętrzne” jest tak naprawdę wewnętrzne
Od samego początku z pewnością pojawią się pewne nieporozumienia, które musimy wyjaśnić – w przeciwnym razie reszta artykułu będzie bardzo zagmatwana. Pomocne jest omówienie historii kart SD i telefonów z systemem Android.
W początkach telefonów z Androidem prawie każde urządzenie korzystało z kart microSD do przechowywania danych. Wynikało to z faktu, że telefony były wówczas dostarczane z niewielką pojemnością pamięci wewnętrznej. Jednak karty SD używane do przechowywania aplikacji często nie zapewniają niesamowitych wrażeń użytkownika, przynajmniej w porównaniu z szybkością, z jaką wewnętrzna pamięć flash może odczytywać/zapisywać dane. Dlatego rosnące wykorzystanie kart SD do zewnętrznego przechowywania danych stało się dla Google problemem związanym z komfortem użytkowania.
Ze względu na wczesną popularyzację kart SD jako zewnętrznych urządzeń pamięci masowej, konwencje nazewnictwa pamięci w systemie Android opierały się na fakcie, że każde urządzenie miało rzeczywiste, fizyczne gniazdo karty microSD. Ale nawet na urządzeniach, które nie zawierały gniazda karty SD, etykieta /sdcard była nadal używana do wskazania rzeczywistego układu pamięci wewnętrznej. Bardziej zagmatwany jest fakt, że urządzenia wykorzystujące zarówno fizyczną kartę SD, jak i układ pamięci o dużej pojemności do przechowywania, często nazywają swoje partycje w oparciu o kartę SD. Na przykład w tych urządzeniach punkt podłączenia /sdcard będzie odnosił się do rzeczywistego układu pamięci wewnętrznej, podczas gdy coś takiego jak /storage/sdcard1 będzie odnosić się do fizycznej karty zewnętrznej.
Tak więc, mimo że kartę microSD w praktyce uważa się za pamięć zewnętrzną, konwencja nazewnictwa spowodowała, że nazwa „SDCard” przetrwała długo po faktycznym użyciu karty fizycznej. To zamieszanie z pamięcią masową przysporzyło także twórcom aplikacji pewnego bólu głowy, ponieważ dane aplikacji i ich nośniki zostały oddzielone pomiędzy dwiema partycjami.
Mało miejsca w pierwszych układach pamięci wewnętrznej powodowało, że użytkownicy frustrująco dowiadywali się, że nie mogą już instalować aplikacji (z powodu zapełnienia partycji /data). W międzyczasie ich karty microSD o większej pojemności zostały zdegradowane do przechowywania wyłącznie multimediów (takich jak zdjęcia, muzyka i filmy). Użytkownicy, którzy przeglądali kiedyś nasze fora, mogą pamiętać te nazwy: Link2SD i Apps2SD. Były to rozwiązania (rootowe), które umożliwiały użytkownikom instalowanie aplikacji i znajdujących się w nich danych na fizycznej karcie SD. Nie były to jednak rozwiązania doskonałe, więc Google musiał wkroczyć.
Wiadomo, że Google bardzo wcześnie wycofał karty SD. Nexus One pozostaje jedynym urządzeniem Nexus wyposażonym w gniazdo kart microSD (i tak pozostanie na zawsze, ponieważ marka Nexus faktycznie umarła). W Nexusie S istniała teraz tylko jedna, ujednolicona partycja do przechowywania wszystkich danych aplikacji i multimediów – partycja /data. To, co kiedyś było znane jako punkt podłączenia /sdcard, teraz odnosiło się po prostu do wirtualnego systemu plików (zaimplementowanego w ramach BEZPIECZNIK protokół, jak omówiono poniżej) znajdujący się w partycji danych - /data/media/0.
Aby zachować kompatybilność i zmniejszyć zamieszanie, Google nadal używał tej wirtualnej partycji „sdcard” do przechowywania multimediów. Ale teraz, gdy ta wirtualna partycja „sdcard” faktycznie znajdowała się w katalogu /data, wszystko, co jest w niej przechowywane, będzie wliczane do przestrzeni dyskowej wewnętrznego układu pamięci. Dlatego też do producentów OEM należało rozważenie, ile miejsca przydzielić aplikacjom (/data) w stosunku do multimediów (/data/media).
Google liczył na to, że producenci pójdą za ich przykładem i pozbędą się kart SD. Na szczęście z biegiem czasu producenci telefonów mogli dostarczać te komponenty o większej pojemności, zachowując przy tym opłacalność, więc zapotrzebowanie na karty SD zaczęło się zmniejszać. Jednak konwencje nazewnictwa pozostały niezmienne, aby zmniejszyć wysiłek, jaki programiści i producenci OEM musieliby włożyć w dostosowanie się. Obecnie, gdy mówimy o „pamięci zewnętrznej”, mamy na myśli albo jedna z dwóch rzeczy: rzeczywista wymienna karta microSD lub wirtualna partycja „SDCard” zlokalizowana w /data/media. Ten ostatni z nich, praktycznie mówiąc, jest w rzeczywistości pamięcią wewnętrzną, ale konwencja nazewnictwa Google'a różnicuje je ze względu na fakt, że dane te są dostępne dla użytkownika (np. po podłączeniu do komputera).
Obecnie, gdy mówimy o „pamięci zewnętrznej”, mamy na myśli albo jedna z dwóch rzeczy: rzeczywista wymienna karta microSD lub wirtualna partycja „SDCard” zlokalizowana w /data/media.
Historia wirtualnych systemów plików Androida
Teraz, gdy „sdcard” jest traktowana jako wirtualny system plików, oznaczało to, że można ją sformatować jako dowolny system plików wymagany przez Google. Począwszy od Nexusa S i Androida 2.3, Google zdecydowało się sformatować „sdcard” jako VFAT (wirtualny FAT). To posunięcie miało wówczas sens, ponieważ zamontowanie VFAT umożliwiłoby prawie każdemu komputerowi dostęp do danych przechowywanych w telefonie. Jednakże przy początkowym wdrożeniu wystąpiły dwa główne problemy.
Pierwsza dotyczy przede wszystkim użytkownika końcowego (Ciebie). Aby podłączyć urządzenie do komputera, do przesyłania danych będziesz używać trybu pamięci masowej USB. Wymagało to jednak odmontowania partycji wirtualnej przez urządzenie z systemem Android, zanim komputer mógł uzyskać dostęp do danych. Jeśli użytkownik chciałby korzystać ze swojego urządzenia po podłączeniu do sieci, wiele rzeczy byłoby wyświetlanych jako niedostępne.
The wprowadzenie protokołu przesyłania multimediów (MTP) rozwiązało ten pierwszy problem. Po podłączeniu komputer postrzega urządzenie jako urządzenie do przechowywania multimediów. Żąda listy plików z telefonu, a protokół MTP zwraca listę plików, które komputer może pobrać z urządzenia. W przypadku żądania usunięcia pliku MTP wysyła polecenie usunięcia żądanego pliku z pamięci. W przeciwieństwie do trybu pamięci masowej USB, w którym faktycznie montowana jest karta SD, tryb MTP pozwala użytkownikowi na dalsze korzystanie z urządzenia po podłączeniu. Co więcej, system plików obecny w telefonie z Androidem nie ma już znaczenia, aby komputer mógł rozpoznać pliki na urządzeniu.
Po drugie, VFAT nie zapewniał solidnego zarządzania uprawnieniami, jakiego potrzebował Google. Na początku wielu twórców aplikacji traktowało kartę SD jako wysypisko danych aplikacji, bez jednolitego określenia miejsca przechowywania plików. Wiele aplikacji po prostu tworzy folder z nazwą aplikacji i przechowuje w nim pliki.
Prawie każda aplikacja dostępna w tamtym czasie wymagała ZAPISZ_EXTERNAL_STORAGE pozwolenie na zapisanie plików aplikacji w pamięci zewnętrznej. Jednak bardziej niepokojący był fakt, że prawie każda aplikacja wymagała również ODCZYT_EXTERNAL_STORAGE pozwolenie - tylko do odczytu własnych plików danych! Oznaczało to, że aplikacje mogły łatwo uzyskać dostęp do danych przechowywanych w dowolnym miejscu pamięci zewnętrznej, i takie pozwolenie było często udzielane przez użytkownika, ponieważ było to wymagane przez wiele aplikacji funkcjonować.
Google wyraźnie uznał to za problematyczne. Cała idea zarządzania uprawnieniami polega na segregowaniu tego, do czego aplikacje mogą i nie mogą mieć dostępu. Jeśli prawie każda aplikacja ma dostęp do odczytu potencjalnie wrażliwych danych użytkownika, zezwolenie jest bez znaczenia. Dlatego Google zdecydował, że potrzebuje nowego podejścia. I tu właśnie pojawia się FUSE.
System plików w przestrzeni użytkownika (FUSE)
Począwszy od Androida 4.4, Google zdecydowało się nie montować już wirtualnej partycji „sdcard” jako VFAT. Zamiast tego Google zaczął używać FUSE do emulacji FAT32 na wirtualnej partycji „sdcard”. Podczas wywoływania programu sdcard FUSE do emulacji uprawnień do katalogu w stylu FAT-on-sdcardaplikacje mogą zacząć uzyskiwać dostęp do danych przechowywanych w pamięci zewnętrznej bez konieczności posiadania jakichkolwiek uprawnień. Rzeczywiście, począwszy od poziomu API 19, READ_EXTERNAL_STORAGE nie był już wymagany do uzyskania dostępu do plików znajdujących się na dysku zewnętrznym – pod warunkiem, że folder danych utworzony przez demona FUSE odpowiada nazwie pakietu aplikacji. FUSE sobie poradzi synteza właściciela, grupy i trybów plików w pamięci zewnętrznej gdy aplikacja jest zainstalowana.
FUSE różni się od modułów wbudowanych w jądro tym, że umożliwia nieuprzywilejowanym użytkownikom pisanie wirtualnych systemów plików. Powód, dla którego Google wdrożył FUSE, jest dość prosty – zrobił to, czego chciał i już zrobił dobrze rozumiane i udokumentowane w świecie Linuksa. Cytując A Programista Google w tej sprawie:
„Ponieważ FUSE jest ładnym, stabilnym interfejsem API, przy przechodzeniu między wersjami jądra zasadniczo nie są wymagane żadne prace konserwacyjne. Gdybyśmy przeszli na rozwiązanie wbudowane w jądro, podpisalibyśmy umowę na utrzymywanie zestawu poprawek dla każdej stabilnej wersji jądra.” –Jeff Sharkey, inżynier oprogramowania w Google
Stało się jednak całkiem jasne, że obciążenie FUSE spowodowało między innymi spadek wydajności. Deweloper, z którym rozmawiałem w tej sprawie, Michał Kowalczyk, napisał świetny wpis na blogu ponad rok temu opisując szczegółowo bieżące problemy z FUSE. Więcej szczegółów technicznych można przeczytać na jego blogu, ale opiszę jego ustalenia (za jego zgodą) w sposób bardziej laicki.
Problem z FUSE
W systemie Android demon przestrzeni użytkownika „sdcard” wykorzystuje FUSE do zamontowania /dev/fuse w emulowanym katalogu pamięci zewnętrznej podczas rozruchu. Następnie demon sdcard odpytuje urządzenie FUSE pod kątem wszelkich oczekujących komunikatów z jądra. Jeśli słuchałeś podcastu, być może słyszałeś, jak pan Lemarchand wspomniał o FUSE wprowadzającym obciążenie podczas operacji we/wy - zasadniczo oto, co się dzieje.
W prawdziwym świecie ten hit wydajności wpływa każdy plik zapisany w pamięci zewnętrznej.
Problem nr 1 – Narzut we/wy
Załóżmy, że tworzymy prosty plik tekstowy o nazwie „test.txt” i przechowujemy go w katalogu /sdcard/test.txt (który, niech Przypominam, to właściwie /data/media/0/test.txt przy założeniu, że bieżący użytkownik jest głównym użytkownikiem na urządzenie). Gdybyśmy chcieli przeczytać (polecenie cat) ten plik, spodziewalibyśmy się, że system wyda 3 polecenia: otwórz, przeczytaj, a następnie zamknij. Rzeczywiście, jak pokazuje pan Kowalczyk stosując Strace, tak się dzieje:
Ponieważ jednak plik znajduje się w pamięci zewnętrznej zarządzanej przez demona sdcard, należy wykonać wiele dodatkowych operacji. Według pana Kowalczyka potrzeba w zasadzie 8 dodatkowych kroków każde z tych 3 indywidualnych poleceń:
- Aplikacja przestrzeni użytkownika wywołuje wywołanie systemowe, które będzie obsługiwane przez sterownik FUSE w jądrze (widzimy to w pierwszym wyjściu strace)
- Sterownik FUSE w jądrze powiadamia demona przestrzeni użytkownika (sdcard) o nowym żądaniu
- Demon przestrzeni użytkownika czyta /dev/fuse
- Demon przestrzeni użytkownika analizuje polecenia i rozpoznaje operacje na plikach (np. otwarty)
- Demon przestrzeni użytkownika wywołuje wywołanie systemowe do rzeczywistego systemu plików (EXT4)
- Jądro obsługuje fizyczny dostęp do danych i wysyła je z powrotem do przestrzeni użytkownika
- Przestrzeń użytkownika modyfikuje (lub nie) dane i przekazuje je ponownie przez /dev/fuse do jądra
- Jądro kończy oryginalne wywołanie systemowe i przenosi dane do rzeczywistej aplikacji w przestrzeni użytkownika (w naszym przykładzie cat)
To wygląda bardzo narzutu tylko na pojedyncze polecenie we/wy, które ma zostać uruchomione. I miałbyś rację. Aby to zademonstrować, pan Kowalczyk przeprowadził dwa różne testy wejścia/wyjścia: jeden polegający na kopiowaniu dużego pliku, a drugi na kopiowaniu wielu małych plików. Porównał prędkość FUSE (na partycji wirtualnej zamontowanej jako FAT32) obsługującej te operacje z szybkością jądra (na partycji danych sformatowanej jako EXT4) i odkrył, że FUSE rzeczywiście miał znaczący wkład nad głową.
W pierwszym teście skopiował plik o wielkości 725 MB w obu warunkach testowych. Odkrył, że implementacja FUSE przesyłała duże pliki 17% wolniej.
W drugim teście skopiował 10 000 plików, każdy o rozmiarze 5 KB. W tym scenariuszu wdrożenie FUSE dobiegło końca 40 sekund wolniej aby skopiować w zasadzie 50 MB danych.
W prawdziwym świecie ten hit wydajności wpływa każdy plik zapisany w pamięci zewnętrznej. Oznacza to aplikacje takie jak Mapy przechowujące duże pliki na karcie /sdcard, aplikacje muzyczne przechowujące mnóstwo plików muzycznych, aplikacje aparatu i zdjęcia itp. Na każdą wykonywaną operację we/wy, która obejmuje pamięć zewnętrzną, wpływa obciążenie FUSE. Ale narzut we/wy nie jest jedynym problemem związanym z FUSE.
Problem nr 2 – Podwójne buforowanie
Buforowanie danych jest ważne dla poprawy wydajności dostępu do danych. Przechowując istotne fragmenty danych w pamięci, jądro Linuksa jest w stanie szybko je przywołać, gdy zajdzie taka potrzeba. Jednak ze względu na sposób implementacji FUSE, Android przechowuje dwukrotnie większą ilość potrzebnej pamięci podręcznej.
Jak pokazuje pan Kowalczyk, oczekuje się, że plik o wielkości 10 MB zostanie zapisany w pamięci podręcznej dokładnie tak samo jak 10 MB, ale zamiast tego zostanie zwiększony do rozmiaru pamięci podręcznej o około 20 MB. Jest to problematyczne na urządzeniach z mniejszą ilością pamięci RAM, ponieważ sklepy jądra Linuksa korzystają z pamięci podręcznej stron do przechowywania danych pamięć. Pan Kowalczyk przetestował problem podwójnego buforowania, stosując następujące podejście:
- Utwórz plik o znanym rozmiarze (do testów 10 MB)
- Skopiuj go do /sdcard
- Usuń pamięć podręczną strony
- Zrób migawkę wykorzystania pamięci podręcznej strony
- Przeczytaj plik testowy
- Zrób kolejną migawkę użycia pamięci podręcznej strony
Odkrył, że przed testem jądro wykorzystywało 241 MB na pamięć podręczną stron. Po przeczytaniu pliku testowego spodziewał się, że na pamięć podręczną stron będzie wykorzystywane 251 MB. Zamiast tego odkrył, że to jądro używa 263MB dla pamięci podręcznej strony - o dwa razy więcej niż oczekiwano. Dzieje się tak dlatego, że dane są najpierw buforowane przez aplikację użytkownika, która pierwotnie wykonała wywołanie we/wy (FUSE), a następnie przez demona karty sdcard (EXT4 FS).
Problem nr 3 – Niekompletna implementacja systemu FAT32
Istnieją jeszcze dwa problemy wynikające z użycia FUSE emulującego FAT32, które są mniej znane w społeczności Androida.
Pierwsza polega nieprawidłowe znaczniki czasu. Jeśli kiedykolwiek przesyłałeś plik (np. zdjęcie) i zauważyłeś, że sygnatura czasowa jest niepoprawna, dzieje się tak z powodu implementacji FUSE w systemie Android. Ten problem ma istniał dla lata. Mówiąc ściślej, problem dotyczy czas() wywołanie systemowe umożliwiające zmianę czasu dostępu i modyfikacji pliku. Niestety, wywołania demona sdcard wykonywane przez zwykłego użytkownika nie mają odpowiednich uprawnień do wykonania tego wywołania systemowego. Istnieją obejścia tego problemu, ale są one wymagane mieć dostęp do roota.
Jeśli kiedykolwiek przesyłałeś plik (np. zdjęcie) i zauważyłeś, że sygnatura czasowa jest niepoprawna, dzieje się tak z powodu implementacji FUSE w systemie Android.
Następny problem jest bardziej niepokojący dla firm korzystających z czegoś takiego jak a inteligentna karta SD. Przed FUSE twórcy aplikacji mogli monitorować Flaga O_DIRECT w celu komunikacji z mikrokontrolerem wbudowanym w kartę. Dzięki FUSE programiści mogą uzyskać dostęp jedynie do wersji pliku zapisanej w pamięci podręcznej i nie mogą zobaczyć żadnych poleceń wysyłanych przez mikrokontroler. Jest to problematyczne w przypadku niektórych aplikacji korporacyjnych/rządowych/bankowych, które komunikują się z kartami microSD o wartości dodanej.
Zrzucanie FUSE dla SDCardFS
Niektórzy producenci OEM wcześnie rozpoznali te problemy i zaczęli szukać rozwiązania wbudowanego w jądro, które mogłoby zastąpić FUSE. Samsung opracował na przykład Karta SDFS który jest oparty na WrapFS. To rozwiązanie wbudowane w jądro emuluje FAT32, podobnie jak FUSE, ale rezygnuje z narzutu we/wy, podwójnego buforowania i innych problemów, o których wspomniałem powyżej. (Tak, powtórzę tę kwestię, rozwiązanie, które obecnie wdraża Google, bazuje na pracy Samsunga).
Google w końcu przyznał się do wad związanych z FUSE i dlatego zaczął zmierzać w stronę wbudowanej w jądro warstwy emulacyjnej FAT32 opracowanej przez Samsunga. Spółka, o której mowa w ww Za kulisami programiści Androida podcast, pracuje nad udostępnieniem SDCardFS dla wszystkich urządzeń w nadchodzącej wersji jądra. Aktualnie możesz zobaczyć postęp ich prac pracować w AOSP.
Jak Programista Google wyjaśnił wcześniejnajwiększym wyzwaniem przy wdrażaniu rozwiązania wbudowanego w jądro jest mapowanie nazwy pakietu identyfikator aplikacji niezbędny, aby pakiet mógł uzyskać dostęp do własnych danych w pamięci zewnętrznej bez konieczności ich posiadania uprawnienia. Jednak to stwierdzenie padło rok temu i doszliśmy do punktu, w którym zespół nazywa SDCardFS swoją „kolejną wielką rzeczą”. Potwierdzili już, że straszny błąd znacznika czasu zostało naprawione dzięki odejściu od FUSE, więc możemy się doczekać wszystkich zmian wynikających z porzucenia FUSE.
Błędne przekonania dotyczące sprawdzania faktów
Jeśli dotarłeś tak daleko w artykule, to brawa za nadążanie za wszystkim do tej pory! Chciałem wyjaśnić kilka pytań, które sam sobie zadałem pisząc ten artykuł:
- SDCardFS ma nie ma nic wspólnego z rzeczywistymi kartami SD. Został tak nazwany, ponieważ obsługuje dostęp do wejść/wyjść dla /sdcard. Jak zapewne pamiętasz, /sdcard to przestarzała etykieta odnosząca się do „zewnętrznej” pamięci urządzenia (gdzie aplikacje przechowują swoje multimedia).
- SDCardFS jest a nie tradycyjny system plików jak FAT32, EXT4 lub F2FS. Jest to system plików, który można układać w stosy i przekazuje polecenia do niższych, emulowanych systemów plików (w tym przypadku będzie to FAT32 na karcie /sdcard).
- W kwestii MTP nic się nie zmieni. Będziesz nadal używać protokołu MTP do przesyłania plików do/z komputera (do czasu, gdy Google zdecyduje się na lepszy protokół). Ale przynajmniej błąd znacznika czasu zostanie naprawiony!
- Jak wspomniano wcześniej, gdy Google odnosi się do „pamięci zewnętrznej”, ma na myśli (w każdym razie i celów) wewnętrzna/sdcard wirtualna partycja FAT32 LUB mówią o rzeczywistej, fizycznej, wymiennej karcie microSD karta. Terminologia jest myląca, ale właśnie to nas uderzyło.
Wniosek
Odchodząc od FUSE i wdrażając wbudowaną w jądro warstwę emulacji FAT32 (SDCardFS), Google zmniejszy znaczny narzut we/wy, eliminujący podwójne buforowanie i rozwiązujący pewne niejasne problemy związane z emulacją FUSE FAT32.
Ponieważ zmiany te zostaną wprowadzone w jądrze, można je wdrożyć bez instalowania nowej, głównej wersji Androida. Niektórzy użytkownicy spodziewają się oficjalnego wprowadzenia tych zmian w systemie Android 8, ale jest to możliwe dla każdej przyszłej OTA na urządzeniu Pixel, aby zainstalować jądro Linuksa w wersji 4.1, nad którą pracuje Google NA.
Dla niektórych z Was SDCardFS nie jest nową koncepcją. Tak naprawdę urządzenia Samsunga korzystają z niego od lat (w końcu to oni go opracowali). Odkąd w zeszłym roku w AOSP wprowadzono SDCardFS, niektórzy programiści niestandardowych pamięci ROM i jądra zdecydowali się wdrożyć je w swojej pracy. CyanogenMOD w pewnym momencie rozważał jego wdrożenie, ale wycofał się z niego, gdy użytkownicy napotkali problemy ze swoimi zdjęciami. Miejmy jednak nadzieję, że gdy Google przejmie kontrolę nad tym projektem, użytkownicy Androida na wszystkich przyszłych urządzeniach będą mogli skorzystać z ulepszeń wprowadzonych po rezygnacji z FUSE.