Kameror i anpassade ROM: Hur utvecklare får hårdvara att fungera utan källkod

Utan källkod, hur får utvecklare hårdvarukomponenter som kameror att fungera i anpassade ROM? Svaret är en BLOB, shim och massor av felsökning.

Med lanseringen av Android Oreo och många enheter som t.ex Xiaomi Redmi Note 3, Google Nexus 5 och andra som inofficiellt tar emot det, det är förmodligen rättvist att undra varför samma funktioner (mest kameran) tenderar att gå sönder när utvecklare portar en Android Open Source Project (AOSP)-baserad ROM. Du har förmodligen sett XDA-forumtrådar med ROM-skivor med en lång lista med trasiga funktioner uppe. "Vad fungerar" följt av en lista över fungerande funktioner, sedan nedanför det ikoniska "Vad fungerar inte? Säg det du!" är två populära refränger på våra forum som praktiskt taget har blivit ett meme på platser som Reddit och Twitter.

Varför är så mycket funktionalitet trasig när en utvecklare försöker porta en AOSP ROM till sin enhet? Det grundläggande svaret är att eftersom funktionerna ändras mellan olika versioner av Android, kommer gamla enhetsdrivrutiner paketerade som BLOB inte att fungera med nyare versioner av Android, eller ens bara med AOSP. För att övervinna det använder sig utvecklare av vad som kallas "shim", men den involverade processen är knepig, tidskrävande och ibland mycket svår att felsöka.

I den här artikeln kommer vi att beskriva hur shims fungerar, särskilt när det gäller att få kameran att fungera korrekt på AOSP-baserade ROM. Vi kommer att använda OnePlus 3T som exempel. Observera att svårigheten att få dessa funktioner att fungera är mycket enhetsspecifik.

OnePlus 3T kör OxygenOS. Även om OnePlus-telefoner är kända för sin anpassade utvecklingsvänlighet, finns det mycket arbete som utvecklare gör bakom kulisserna för att skapa stabila portar av AOSP.


Vad är en shim eller en BLOB?

För att ens börja förstå en del av vad utvecklare gör måste vi först förklara några saker. Även om Android OS är öppen källkod (det kallas Android Open Source Project av en anledning) är det inte programvaran (utan kärnan) som levereras på tusentals Android-enheter. Utvecklare har inte tillgång till källkoden för Samsung Experience, EMUI, OxygenOS, eller någon av de andra varianterna av Android från tredje part.

Nu bryr sig utvecklare som porterar lager AOSP till en icke-Google-enhet förmodligen inte om källkoden för dessa Android-skal eftersom de inte kommer att vara modifiera och bygga dessa ROM. Det skulle vara sant, om inte av en stor, stor anledning: de delar som är nödvändiga för att kameran ska fungera ordentligt, främst de kamera HAL (Hårdvaraabstraktionslager), är även stängd källa.

Problemet med att inte bara ha kamerans HAL utan även ROM-stängd källa är att utvecklare som arbetar med att porta AOSP till sin enhet kommer att vara jobbar blind. OEM-ROM-skivan med stängd källa kan samverka med kamerans HAL bra eftersom OEM-enheten har tillgång till kamerans HAL-källa. Kamerans HAL är det som gör att ROM: en kan "prata med" kamerans hårdvara - utan den skulle kameran inte fungera. Tänk på kameran HAL som bilens ratt och pedaler. Ratten/pedalerna tillåter kontroll av fordonets interna komponenter genom att tillhandahålla ett externt gränssnitt för föraren (ROM) för att använda de interna komponenterna.

Grafik som visar kameraarkitekturen. Källa: Google

När kamerahårdvaran blir mer och mer komplex (den tillkomsten av dubbla kamerort.ex.) att ha tillgång till kamerans HAL-källa skulle göra porteringen av en AOSP ROM med en funktionell kamera mycket enklare.

OEM-tillverkare ger dock inte tillgång till kamerans HAL-källa av olika anledningar. För det första, om de inte har alla äganderättigheter till kamera-HAL (t.ex. när de införlivar immateriella rättigheter från andra företag), kan de inte distribuera källan. För det andra kan frisläppandet av kamerans HAL-källa äventyra deras egna immateriella rättigheter. Slutligen är företag inte skyldiga att tillhandahålla denna källkod (till skillnad från kärnkällkoden som de är skyldig att släppa enligt GPL), så de har inget incitament att släppa det. Så utan tillgång till kamerans HAL-källa, exakt hur får utvecklarna kameran att fungera på AOSP ROM? Svaret är en BLOB, shim och massor av felsökning.

En enhet KLICK (Binary Large OBject) innehåller förpackade binärer som är den kompilerade formen av programvara. I det här fallet kompileras kamerans HAL-källa av OEM och skickas på enheter som binärer. När utvecklare pratar om BLOB hänvisar de till de binärfiler som skickas på live-enheter som de kan extrahera. Nu har ämnet "camera BLOBs". länge plågat OnePlus i många månader, men sanningen är att utvecklare alltid har haft tillgång till kamerans BLOB. De kamera HAL källkoden är den gyllene biljetten för utvecklare här dock, men det kommer aldrig, aldrig släppas på grund av den juridiska faran skulle det sätta företag som OnePlus in.

Utvecklare som vill överföra AOSP till en enhet har alltså bara BLOBs i kamerans HAL som de inte har tillgång till källkoden för. Sällan om någonsin kan en utvecklare para ihop sin AOSP ROM-kod med kameran HAL BLOB och förvänta sig att den ska fungera, så för att överbrygga gapet mellan de två skapar utvecklare vad som kallas en "shim.”

Att "shimsa" är att "kila (något) eller fylla upp ett utrymme." Detta är faktiskt vad en utvecklare gör när skriva ett shim – de lägger till kod för att BLOB ska kunna samverka med AOSP-källkoden de arbetar med. Shims används för att få BLOBs av alla olika slag att fungera med AOSP, men vanligtvis är det kameran BLOB som kräver mest mellanlägg. Som vi nämnde tidigare krävs shims inte bara för att porta nyare versioner av Android till en enhet (som t.ex. alla dessa inofficiella Android Oreo ROMs) men behövs också när AOSP av samma Android-version portas till den enhet.

Rekommenderad läsning: Från butik till hylla: En djupgående kapitulation om varför MSM8974-enheter är uteslutna från Nougat

OnePlus 2 fick till exempel sin senaste officiella större OS-uppdateringen i form av Android 6.0 Marshmallow. Enheten har dock faktiskt fullt fungerande anpassade AOSP-baserade ROM baserat på Android Nougat, och det är tack vare det hårda arbetet från utvecklare och deras shims. Vi kommer att dela upp några exempel på shims, men först måste vi prata om hur exakt shims fungerar.


Hur fungerar shimsning?

Eftersom utvecklare inte har tillgång till kamerans HAL- eller OEM ROM-källa (och endast de förkompilerade binärfilerna) kan de inte veta vilka funktioner som kamerans HAL förväntar sig. På grund av detta finns det ofta en obalans mellan namnet på funktionen som kameran HAL letar efter och det faktiska namnet på funktionen i AOSP-koden som utvecklaren arbetar med.

För att lösa detta problem skapar utvecklaren helt enkelt en ny funktion som använder samma namn på funktion som kameran HAL BLOB förväntar sig, men denna nya funktion utför bara vad utvecklaren vill ha det till. Denna nya funktion som fungerar som en mellanhand mellan BLOB och AOSP är mellanlägget. Detta speciella scenario där BLOB misslyckas med att hitta funktionen den letar efter är ett av de vanligaste där ett mellanlägg behövs.

Mycket enkelt MS färgdiagram som visar var ett mellanlägg behövs.

Kanske blir det lite mer vettigt med ett hypotetiskt exempel som involverar OnePlus 3T. Vi kommer att skapa ett exempel med OxygenOS och OnePlus-kameran. Om vi ​​använder kamera BLOBs tagna från OxygenOS Nougat för OnePlus 3T för att bygga en AOSP-baserad Nougat ROM kan vi stöta på problem. Detta beror på att kamerans BLOB (som ursprungligen kompilerades av OEM) kommer att kunna referera till alla funktioner den behöver inom OxygenOS, men eftersom kompilerad AOSP ROM kanske inte har dessa funktioner eller kan ha kompilerat dem under ett annat namn (vilket leder till en obalans mellan funktionssymboler), kommer det att finnas en fel. Detta kan fixas genom att skapa en ny funktion i AOSP ROM med det namn som BLOB förväntar sig – vårt shim.

Symboler i ett programmeringssammanhang används för att referera till specifika funktioner i kod. Symboler är nödvändiga eftersom positionen för en funktion kan ändras när koden redigeras, och så för att undvika hårdkodning referenser till funktioner skapar kompilatorn en tabell med symboler som andra funktioner kan använda för att alltid referera till höger fungera. När du ändrar namnet på en funktion innan du kompilerar, ändras dess symbol också, så i princip alla ändringar som OEM gör till kamerans HAL-källa innan kompilering kommer att kräva att utvecklare skapar en ny shim.

Visa en symboltabell med behållare. Källa: Aprioriterat

Förklaringen vi har erbjudit hittills gör att det låter som att det är enkelt att skapa shims. Att ändra några funktionsnamn här och där låter inte så svårt, eller hur? Om det bara vore så enkelt. Verkligheten med shims involverar mer än bara funktionsbyten. Vi pratade med XDA Recognized Developer Sultanxda som kunde ge oss ett exempel på en av de svårare shims han har arbetat med.


Shimming - Inte så lätt som det låter

För de som inte känner till OnePlus 3T var den främre kameran ganska trasig initialt på AOSP-baserade anpassade ROM. Till att börja med skulle ett försök att ta en bild över 8 MP resultera i kraschar. I sitt försök att lösa detta problem gjorde Sultanxda flera shims för att låta OnePlus 3T-kameran på framsidan fungera korrekt.

Shim #1 - Ändra kamerapaketets namn

För att förhindra att den främre kameran kraschar när användaren tog en bild över 8 MP, tvingade Sultanxda kameran HAL att identifiera alla kameror som OnePlus-kameran. Detta görs eftersom OnePlus beslutat att dedikera en hjälpfunktion till vissa applikationer (isOnePlusCamera, isFacebookCameraetc.) av någon anledning. Sultanxda fixade detta genom att shimsa kamerans HAL så att den pekar på en ny funktion som alltid returnerar "sant" som om användaren använder OnePlus-kameran – även när de inte är det.

Shim #2 - Inaktivera QuadraCfa

För sin nästa shim var han tvungen att inaktivera QuadraCfa som förmodligen är en proprietär Qualcomm-teknik relaterad till kameran. Vi säger förmodligen för att varken jag själv eller Sultanxda är exakt säker på vad QuadraCfa är, men Sultanxda vet att den gick sönder den främre kameran när den var aktiverad.

Han observerade att QuadraCfa på något sätt skulle aktivera sig själv, men han var inte säker på varför eller hur det gjorde det. Att lösa detta krävde en ganska okonventionell modifiering från hans sida. I ett konventionellt shim tillhandahåller shim-funktionen, när den är kompilerad, den saknade symbolen som BLOB letar efter. I det här fallet hade BLOB redan de symboler den behövde – de som förmodligen representerade funktionerna som startade QuadraCfa.

Välsigna Hex Editor. Programmet Sultanxda använde.

Därför behövde han åsidosätta symbolerna som används av kameran HAL och i huvudsak göra att de "saknas" så hans shims skulle ge de "saknade" symbolerna. Det enda sättet att göra det är via hex-redigera själva kamerans HAL. Hexredigering är i grunden att titta igenom ett gäng oorganiserat skratt i form av binär data för att hitta en nål i höstacken – antingen en funktion eller en sträng som du vill redigera.

Hexredigering av en funktion är betydligt svårare än hexredigering av en sträng, men lyckligtvis kunde Sultanxda undvika att behöva hexredigera funktionerna bakom QuadraCfa genom att istället hex-redigera symbolnamnen för att ogiltigförklara dessa symboler.

Shim #3 - Bright Light Crash Fix

Därefter upptäckte Sultanxda att ta en bild från den främre kameran under starkt ljus skulle få kameran att krascha. För att reproducera denna bugg på sin egen enhet, Sultanxda faktiskt slog på ficklampsfunktionen på sin OnePlus One och lyste ljuset framför OnePlus 3T: s främre kamera för att få den att krascha och producera användbara loggar! När han upptäckte vilken funktion som orsakade kraschen skapade han ett shim för att tvinga enheten att använda lågljusläge hela tiden för den framåtvända kameran.

Shim #4 - Lågupplösta framvända kamerabilder

Efter att ha fixat kraschen i starkt ljus med det tidigare mellanlägget, upptäckte Sultanxda en annan bugg som faktiskt uppstod som ett direkt resultat av det mellanlägget: lågupplösta framåtvända kamerabilder. Istället för att ta bilder med den upplösning som användaren begärde (t.ex. 16 MP), skulle den resulterande bilden tas med 4 MP.

Att lösa detta krävde att han shimsade funktionerna handleSuperResolution och isSuperResolution för att alltid returnera sant, men ENDAST när den framåtvända kameran är aktiv (för annars skulle kameran krascha när man tar bilder från den bakre sensorn).


Lärdom - Shimming kan vara svårt

Sultanxda erkänner att de shims han var tvungen att skapa för att få OnePlus 3T-frontkameran att fungera inte representerar ditt typiska exempel på ett shim. Han är ganska stolt över sitt shim med tanke på dess komplexitet och den sällsynta nödvändigheten att hexredigera själva BLOB. Men det här exemplet visar bara hur svårt det kan vara att få kamerahårdvaran att fungera på vissa enheter.

Må dina äventyr med kamerashims vara mindre smärtsamma än mina. -Sultanxda

Loggar, loggar och mer loggar. Utan ett konsekvent sätt att reproducera en krasch och utan loggar, har utvecklarna lite hopp om att hitta källan till problemet. Även om de hittar vad som orsakar problemet är det inte alltid en enkel lösning. Hela processen att hitta och krossa dessa buggar kan ta dagar eller veckor och är anledningen till att fixa kameran på AOSP ROMs är en av de svårare uppgifterna.

Om din enhet har en AOSP ROM portad till den med fullt fungerande hårdvara, förhoppningsvis kan du börja med det uppskattar den kamp som dessa utvecklare kan ha gått igenom för att ge dig dessa Funktioner. Uppskatta dem för deras arbete, för det är inte lätt. Det är mycket arbete som de allra flesta användare inte ens kommer att lägga märke till, eftersom duktiga utvecklare på våra forum tar hand om de många osynliga delarna av Android.

Vi vill rikta ett särskilt tack till Sultanxda för de många bidrag han föreslog när han skapade den här artikeln.