"Fungerar som det är tänkt"

Androids tillgänglighetsfunktion är känd för att orsaka fördröjning i användargränssnittet. Är det en bugg eller är det en funktion? Varför uppstår det? Vi på XDA undersöker grundorsaken.

Det fina med Android ligger i de många olika sätt som tredjepartsapplikationer kan interagera med systemet. Lösenordshanterarappar som t.ex LastPass ger möjlighet att automatiskt mata relevant användarnamn/lösenordsdata till nästan vilken inloggningsskärm som helst. Texthjälp låter dig avsevärt förkorta din tid att skicka sms till dina vänner genom att du kan skapa textexpansionsmakro. Native Urklipp minskar besväret med att ofta växla mellan appar för att kopiera stora mängder text genom att du kan dubbelklicka på valfritt inmatningsfält för att få fram ett urklipp. Vem kan glömma Greenify, kanske den #1 mest rekommenderade appen av entusiaster, som håller oseriösa bakgrundsappar i schack och kan därmed förbättra batteritiden? Slutligen, om än mindre bekant med de flesta användare, finns det AutoInmatning

- ett Tasker-plugin-program designat för att automatisera skärmtryck, textinmatning, svepgester och mycket mer. Dessa appar tjänar alla väldigt olika användningsfall, men var och en av dessa appar förlitar sig på en mycket missförstådd del av Androids kärnfunktioner: Tillgänglighet.

För den genomsnittlige Android-användaren kan det tyckas konstigt att många av dessa fantastiska funktioner som används av din favoritapp styrs av en inställning under tillgänglighet undermeny. Att göra en app tillgänglig är vanligtvis tänkt att betyda att en Android-app är användbar för en person med funktionshinder. Så varför i hela friden har LastPass, Native Clipboard, Text Aide, Greenify eller AutoInput en tillgänglighet service? Dessutom, varför verkar det att aktivera en tillgänglighetstjänst orsaka så mycket UI lag? Det verkar inte spela någon roll vilken version av Android du använder – oavsett om det är det Android 5.0 Lollipop eller Android 7.0 Nougat - eftersom fördröjningen orsakad av vissa tillgänglighetstjänster kan påverka din upplevelse. En enkel lösning på detta problem är att bara inaktivera tillgänglighetstjänster som du kanske har aktiverat - men genom att göra det förlorar vi så mycket användbar funktionalitet. En annan lösning är att begära att Google ska "fixa" Androids tillgänglighetsfördröjning, men Google hävdar att Android Accessibility är det fungerar som det är tänkt. Vi har pratat med några utvecklare som är väl förtrogna med tillgänglighetstjänster och har undersökt hur funktionen fungerar, och vi är här för att testa det påståendet: är Androids tillgänglighetsfördröjning ett fel eller är det en funktion?


Förstå Android-tillgänglighet

Som du kanske föreställer dig med namnet, är tillgänglighet främst avsedd för utvecklare för att tillhandahålla ytterligare funktionalitet för alla användare med funktionshinder. Ja, en snabb titt över på officiella dokumentationssidor för tillgänglighet avslöjar att Google har en ganska snäv syn på vilka typer av tjänster som bör tillhandahållas av tillgänglighetstjänster.

Många Android-användare har olika förmågor som kräver att de interagerar med sina Android-enheter på olika sätt. Dessa inkluderar användare som har visuella, fysiska eller åldersrelaterade begränsningar som hindrar dem från att helt se eller med hjälp av en pekskärm, och användare med hörselnedsättning som kanske inte kan uppfatta hörbar information och varningar.

Android tillhandahåller tillgänglighetsfunktioner och tjänster för att hjälpa dessa användare att navigera mer på sina enheter enkelt, inklusive text-till-tal, haptisk feedback, gestnavigering, styrkula och riktningsplatta navigering.

Googles Prata tillbaka, som kommer förinstallerat på alla Android-telefoner, är ett bra exempel på hur den "typiska" tillgänglighetstjänsten är tänkt att se ut. Röståtkomst tar tillgängligheten ett steg längre och möjliggör nästan fullständig kontroll över din telefon med bara din röst. Men det faktum att Google avsåg att tillgänglighetstjänsterna skulle användas på detta sätt hindrar inte utvecklare från att implementera dem på vilket sätt de vill – och det är precis vad utvecklare har Gjort. Det är just på grund av hur tillgänglighet fungerar som gör funktionen otroligt användbar för användare med eller utan funktionshinder.

För att förenkla lite, här är en grundläggande genomgång av hur Androids tillgänglighet fungerar. En utvecklare skapar en Tillgänglighetstjänst som prenumererar på olika Tillgänglighetsevenemang som skickas av systemet till Tjänsten beroende på om vissa kriterier är uppfyllda eller inte. När alla tjänster är inaktiverade under Inställningar --> Tillgänglighet, samlar eller skickar inte Android några tillgänglighetshändelser. Men när användaren börjar aktivera tillgänglighetstjänster kommer Android att börja övervaka och samla in endast de tillgänglighetshändelser som tillgänglighetstjänsten begär. Till exempel en tillgänglighetstjänst som prenumererar på tillgänglighetsevenemanget TYPE_WINDOW_CONTENT_CHANGED kommer att meddelas av systemet varje gång att en ändring i det aktuella fönstret sker. Ännu ett tillgänglighetsevenemang kallas TYPE_VIEW_CLICKED eldar av varje gång användaren klickar på en knapp av något slag.

Android-tillgänglighetsdemonstration. I den här videon har jag aktiverat appen Tasker att övervaka ändringar i fönstrets titel. Detta kräver att Tasker's Accessibility Service aktiveras. Du kan replikera detta genom att skapa en ny profil i Tasker med 'Event'-kontexten inställd på 'Variable Set' och välja %WIN som variabel att övervaka. Totalt togs denna cirka 1 minuts video 107 ändringar i det aktuella fönstret.

Den här typen av tillgänglighetshändelser inträffar med stor frekvens under normal användarinteraktion. Så föreställ dig vad som händer när en användare möjliggör flera tillgänglighetstjänster som begär att högfrekventa tillgänglighetsevenemang avskedas. Det är rätt - eftersläpning. För att mildra detta kan utvecklare snävare definiera vilka typer av tillgänglighetsevenemang deras Tjänsten ska reagera på och i vilket sammanhang, såsom möjligheten att begränsa Tjänsten till att endast reagera när i vissa appar eller för att begränsa valperiod mellan evenemang. Men förutom att mängden omkostnader som genereras av en tillgänglighetstjänst beror mest på vilka typer av tillgänglighetsevenemang den prenumererar på. I huvudsak kommer inte alla tillgänglighetstjänster att orsaka fördröjning. En enskild tillgänglighetstjänst som kräver en högfrekvent händelse kan orsaka fördröjning, särskilt om nämnda tjänst är kopplad till en annan tjänst som kräver en annan högfrekvent händelse övervakas.


Dyk djupt in i tillgänglighet med APK Teardowns

Som du kunde se från videon som publicerades ovan kan en tillgänglighetstjänst som övervakar ändringar i fönstrets innehåll resultera i ganska märkbara förändringar i användargränssnittets prestanda på grund av den stora mängden fångade tillgänglighetshändelser som avfyras av systemet. Det är dock ganska svårt att avgöra exakt hur mycket omkostnader som orsakas av en viss tillgänglighetstjänst. Övervakning av LogCat kommer i allmänhet inte att ta dig någonstans, eftersom tillgänglighetshändelser endast skrivs ut till LogCat om utvecklaren av tillgänglighetstjänsten väljer att göra det. Tack och lov, pappa till alla Android Accessibility Services, AutoInmatning, gör precis det. Och LogCat-utgången är exakt så rörig som du kan föreställa dig.

AutoInput döljer inte sanningen för oss. Omkostnaderna som orsakas av appen kan vara ganska enorma beroende på vilka händelser du övervakar. Men denna omkostnad är nödvändig för att appen ska fungera. För att AutoInput ska fånga upp varje knapptryckning, varje skärmgest, varje UI-uppdatering och varje knapptryckning, behov för att övervaka respektive tillgänglighetshändelser. Utan dessa händelser kan AutoInput inte koppla in i systemet och tillhandahålla den nästan obegränsade UI-automatisering som den för närvarande tillåter. Således är alla AutoInputs funktioner helt vettiga inom ramen för tillgänglighet. Men för andra appar måste vi titta lite djupare för att förstå hur deras tillgänglighetstjänster hanteras.

En tillgänglighetstjänst attribut definieras i en XML-resursfil inom APK. Därför kan vi utföra en APK rivning på en app med en tillgänglighetstjänst för att ta reda på tjänstens attribut. Varje app fungerar på olika sätt, så jag ska försöka förklara hur deras tjänsts attribut relaterar till den specifika funktionen den utför.

Native Urklipp

Native Clipboard är min favorit när det kommer till urklippshanterare. Om du letar efter en mycket anpassningsbar urklippshanterare är Native Clipboard en ganska bra app. Den har till och med en Xposed Module-komponent så att du kan trycka länge på "Klistra in"-knappen för att ta fram urklippshanteraren! Tyvärr, om du inte har tillgång till Xposed Framework (som alla användare på Nougat) måste du lösa för att aktivera tillgänglighetstjänsten som låter dig dubbelklicka på valfri textinmatning för att få fram urklipp chef. Här är vad det innebär.


"@string/access_decs"
android: accessibilityEventTypes="typeViewClicked|typeViewFocused|typeViewLongClicked|typeWindowStateChanged"
android: accessibilityFeedbackType="feedbackGeneric"
android: notificationTimeout="100"
android: accessibilityFlags="flagReportViewIds|flagRetrieveInteractiveWindows"
android: canRetrieveWindowContent="true"
xmlns: andro />

Native Clipboards tillgänglighetstjänst begär att en tillgänglighetshändelse ska aktiveras varje gång som en vy klickas, långklickas, fokuseras eller om det sker en förändring i fönstrets tillstånd. Utan att ha tillgång till källkoden kan jag inte säga exakt hur Native Clipboard fungerar, men det är troligt att Native Clipboard väntar på att fönstret ska indikera att det mjuka tangentbordet för närvarande är öppet, och sedan övervakar det efter tryck på ingången fält. Appen har en pollingperiod på 100 ms, så det är definitivt tillräckligt snabbt för att reagera i princip omedelbart på förändringar i det mjuka tangentbordets synlighet samt dubbla tryck. Detta kan resultera i vissa UI-overhead när användaren använder det mjuka tangentbordet för att skriva text, vilket kan leda till fördröjning.

Greenify

Nästa är allas favoritbatterisparare, Greenify. Greenify använder Accessibility Events för att driva sina icke-root-funktioner.


"@string/accessibility_service_description"
android: settingsActivity="com.oasisfeng.greenify.accessibility.AccessibilitySettings"
android: accessibilityEventTypes="typeAnnouncement|typeNotificationStateChanged|typeWindowStateChanged"
android: accessibilityFeedbackType="feedbackGeneric" android: notificationTimeout="0"
android: accessibilityFlags="flagReportViewIds"
android: canRetrieveWindowContent="true"
xmlns: andro />

Den använder ändringar i Window State för att avgöra när telefonens skärm har stängts av, och det kräver att du försenar aktiveringen av låsskärmen genom att ändra ett alternativ i säkerhetsinställningarna. Greenify kommer också att ta emot händelser av typen Announcement eller Notification State ändrad, det senare som är onödigt på Android 5.0+-enheter tack vare funktionen Notification Access. Det kommer dock fortfarande att ta emot dessa händelser oavsett detta. Greenify borde inte orsaka mycket omkostnader i sig, men möjligheten kvarstår.

Nova Launcher

Förmodligen den mest populära lanseringsappen från tredje part på marknaden, Nova Launcher är ett utmärkt exempel på en app som använder en tillgänglighetstjänst med minimal eller ingen omkostnad. Den enda anledningen till tjänstens existens är att hjälpa vissa enheter att utföra gester.


"@string/accessibility_service_description"
android: accessibilityEventTypes=""
android: packageNames="com.teslacoilsw.launcher"
android: accessibilityFeedbackType=""
android: notificationTimeout="10000"
android: canRetrieveWindowContent="false"
xmlns: andro />

Som du kan se finns det ingen tillgänglighetshändelse definierad i XML-filen. Allt som nämns är namnet på ett paket - Nova Launcher. Det som händer här är en lösning för vissa enheter för vilka Nova Launchers gester inte fungerar. Den här tjänsten ger Nova Launcher alla tillgänglighetshändelser som avfyras från endast inom Nova Launcher. Det låter konstigt, men det är tydligen ett sätt att fixa Novas hemskärmsgester om din enhet inte fungerar med dem. Eftersom detta bara begär händelser från Nova själv, innebär tjänsten väldigt lite omkostnader.

LastPass

Slutligen, kanske den mest ökända tillgänglighetstjänsten som orsakar fördröjning (förmodligen på grund av dess enorma popularitet) - LastPass. Frågan om eftersläpning inom LastPass är så märkbart att företaget har en tjänsteman FAQ-sida som beskriver problemet. Som det står i FAQen finns det inget du kan göra åt fördröjningen förutom att inaktivera tjänsten. Varför verkar LastPasss tjänst så extrem när det kommer till eftersläpning? Låt oss ta en titt på tjänstens attribut.


"@string/accessibility_service_description"
android: accessibilityEventTypes="typeViewFocused|typeWindowContentChanged"
android: accessibilityFeedbackType="feedbackGeneric"
android: notificationTimeout="200"
android: accessibilityFlags="flagReportViewIds"
android: canRetrieveWindowContent="true"
android: canRequestEnhancedWebAccessibility="true"
xmlns: andro />

Sanningen är att det inte finns något utöver det vanliga med LastPass tjänst. Den begär bara två händelsetyper att övervaka - TYPE_VIEW_FOCUSED och TYPE_WINDOW_CONTENT_CHANGED. Den gör detta eftersom den behöver veta när en app/webbsidas innehåll ändras/kommer i fokus, och sedan hämtar den det aktuella fönstrets innehåll för att leta efter eventuella lösenordsinmatningsfält. Men eftersom tjänsten ständigt gör detta på två extremt ofta skjutande tillgänglighetshändelser, resulterar det i eftersläpning. Det är den olyckliga sanningen.


Att leva med fördröjningen

När vi först läste att Google stängde felrapporter om tillgänglighetsfördröjning eftersom funktionen "fungerade som avsett", var vi lika förbryllade och upprörda som många av er. Men i stället för att acceptera förklaringen till nominellt värde, bestämde vi oss för att själva undersöka saken för att fastställa sanningen. Så när Googlern på felrapportsidan sa detta:

Hej det här problemet är beständigt över Android-utgåvor. Det kommer alltid att finnas en ytterligare fördröjning när en tillgänglighetstjänst är aktiverad. Det beror på att enheten, förutom standardgränssnittet, tillhandahåller mycket information till tillgänglighetstjänster så att de kan ge en alternativ användarupplevelse till dessa användare.

Vi har kommit att förstå Varför detta är avsett beteende. Appar som använder tillgänglighetstjänster på ett sätt som var oavsiktligt av Google kommer alltid att medföra vissa prestandakostnader; denna kostnad är helt enkelt nödvändig för att tillhandahålla tjänster med den mängd information som Android Accessibility avfyras i bakgrunden. Androids eftersläpning med tillgänglighetstjänster är inte en bugg, utan en funktion. En funktion som vi måste leva med om inte hela systemet omarbetas, och jag kan inte föreställa mig hur det skulle göras för att rymma så många olika funktionsuppsättningar från så många olika appar.

Åtminstone skulle LastPass-utvecklarna inte ta detta sittande. Deras utvecklare har arbetat med Chromium-utvecklarna för att optimera tillgänglighetsstödet, kanske genom att aktivera LastPass-stöd genom användning av API: er istället för att aktivera en tillgänglighetstjänst. Att optimera kring de omkostnader som Accessibility Services ådrar är en möjlighet, men som många utvecklare implicit har noterat på Chromium-forumen är det helt enkelt ett plåster som inte kommer att lösa det faktum att oavsiktlig användning av tillgänglighetstjänster kan leda till eftersläpning.


Speciellt tack till utvecklaren av AutoInput, joaomgcd, för att du svarade på många av mina frågor angående tillgänglighet!