In Android 7.0 wurde die Radio Interface Layer (RIL) mit einer Reihe von Funktionen neu strukturiert, um die RIL-Funktionen zu verbessern. Für die Implementierung dieser Funktionen sind Änderungen am Partnercode erforderlich. Sie sind optional, werden aber empfohlen. Refactoring-Änderungen sind abwärtskompatibel, sodass frühere Implementierungen der überarbeiteten Funktionen weiterhin funktionieren.
Das RIL-Refactoring umfasst die folgenden Verbesserungen:
- RIL-Fehlercodes Ermöglicht neben dem vorhandenen
GENERIC_FAILURE
-Code bestimmte Fehlercodes. So können Sie Fehler leichter beheben, da Sie genauere Informationen zur Ursache erhalten. - RIL-Version Sie erhalten genauere und einfacher zu konfigurierende Versionsinformationen.
- RIL-Kommunikation mit Wakelocks Verbessert die Akkuleistung des Geräts.
Sie können eine oder mehrere der oben genannten Verbesserungen implementieren. Weitere Informationen finden Sie in den Codekommentaren zur RIL-Versionierung in https://android.googlesource.com/platform/hardware/ril/+/main/include/telephony/ril.h
.
Erweiterte RIL-Fehlercodes implementieren
Fast alle RIL-Anfrageaufrufe können als Antwort auf einen Fehler den Fehlercode GENERIC_FAILURE
zurückgeben. Dieses Problem betrifft alle angeforderten Antworten, die von den OEMs zurückgegeben werden. Dies kann die Fehlerbehebung anhand des Fehlerberichts erschweren, wenn derselbe GENERIC_FAILURE
-Fehlercode aus verschiedenen Gründen von RIL-Aufrufen zurückgegeben wird. Es kann viel Zeit in Anspruch nehmen, bis Anbieter herausfinden, welcher Teil des Codes einen GENERIC_FAILURE
-Code zurückgegeben haben könnte.
Unter Android 7.x und höher können OEMs für jeden Fehler, der derzeit als GENERIC_FAILURE
kategorisiert ist, einen eindeutigen Fehlercode zurückgeben. OEMs, die ihre benutzerdefinierten Fehlercodes nicht öffentlich bekannt geben möchten, können Fehler als eine Reihe von Ganzzahlen (z. B. 1 bis x) zurückgeben, die als OEM_ERROR_1
bis OEM_ERROR_X
zugeordnet sind. Anbieter müssen dafür sorgen, dass jeder solche maskierte Fehlercode einem eindeutigen Fehlergrund im Code zugeordnet ist. Die Verwendung bestimmter Fehlercodes kann die RIL-Fehlerbehebung beschleunigen, wenn vom OEM allgemeine Fehler zurückgegeben werden, da es oft zu lange dauert, die genaue Ursache eines GENERIC_FAILURE
-Fehlercodes zu ermitteln (manchmal ist es sogar unmöglich).
Außerdem werden mit ril.h
weitere Fehlercodes für die Enumerationen RIL_LastCallFailCause
und RIL_DataCallFailCause
hinzugefügt, damit Anbietercodes keine allgemeinen Fehler wie CALL_FAIL_ERROR_UNSPECIFIED
und PDP_FAIL_ERROR_UNSPECIFIED
zurückgeben.
Erweiterte RIL-Fehlercodes prüfen
Nachdem Sie neue Fehlercodes hinzugefügt haben, um den Code GENERIC_FAILURE
zu ersetzen, prüfen Sie, ob die neuen Fehlercodes vom RIL-Aufruf anstelle von GENERIC_FAILURE
zurückgegeben werden.
Erweiterte RIL-Versionierung implementieren
Die RIL-Versionierung in älteren Android-Releases war problematisch: Die Version selbst war ungenau, der Mechanismus zur Meldung einer RIL-Version war unklar (was dazu führte, dass einige Anbieter eine falsche Version meldeten) und die Umgehung zur Schätzung der Version war anfällig für Ungenauigkeiten.
Unter Android 7.x und höher werden in ril.h
alle RIL-Versionswerte dokumentiert, die entsprechende RIL-Version beschrieben und alle Änderungen für diese Version aufgeführt. Wenn Anbieter Änderungen vornehmen, die einer RIL-Version entsprechen, müssen sie ihre Version im Code aktualisieren und diese Version in RIL_REGISTER
zurückgeben.
Erweiterte RIL-Versionen prüfen
Prüfen Sie, ob die RIL-Version, die Ihrem RIL-Code entspricht, während RIL_REGISTER
zurückgegeben wird (und nicht die in ril.h
definierte RIL_VERSION
).
RIL-Kommunikation mit Wakelocks implementieren
Zeitlich begrenzte Wakelocks werden in der RIL-Kommunikation ungenau verwendet, was sich negativ auf die Akkuleistung auswirkt. Unter Android 7.x und höher können Sie die Leistung verbessern, indem Sie RIL-Anfragen klassifizieren und den Code so aktualisieren, dass Wakelocks für verschiedene Anfragetypen unterschiedlich behandelt werden.
RIL-Anfragen klassifizieren
RIL-Anfragen können entweder angefordert oder unaufgefordert sein. Anbieter sollten angeforderte Anfragen in eine der folgenden Kategorien einordnen:
- synchron. Anfragen, auf die nicht viel Zeit für eine Antwort benötigt wird. Beispiel:
RIL_REQUEST_GET_SIM_STATUS
. - asynchron. Anfragen, auf die es sehr lange dauert, bis eine Antwort erfolgt. Beispiel:
RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
.
Asynchron angeforderte RIL-Anfragen können sehr lange dauern. Nachdem RIL Java eine Bestätigung vom Anbietercode erhalten hat, wird der Wakelock freigegeben, was dazu führen kann, dass der App-Prozessor vom Inaktivitätsstatus in den Ruhemodus wechselt. Wenn die Antwort aus dem Anbietercode verfügbar ist, holt RIL Java (der App-Prozessor) den Wakelock wieder ab, verarbeitet die Antwort und kehrt dann in den Ruhemodus zurück. Solche Übergänge vom Inaktivitätsmodus in den Ruhemodus und wieder zurück können viel Strom verbrauchen.
Wenn die Reaktionszeit nicht lang genug ist, kann es energieeffizienter sein, den Wakelock zu halten und während der gesamten Zeit, die für die Antwort benötigt wird, im Ruhemodus zu bleiben, als in den Ruhemodus zu wechseln, indem der Wakelock aufgehoben und das Gerät wieder aktiviert wird, wenn die Antwort eingeht. Anbieter sollten plattformspezifische Leistungsmessungen verwenden, um den Grenzwert für die Zeit T zu bestimmen, bei der der Stromverbrauch im Leerlauf während der gesamten Zeit T höher ist als der Stromverbrauch, der durch die Umstellung vom Leerlauf in den Ruhemodus und zurück in den Leerlauf in derselben Zeit T entsteht. Wenn die Zeit T bekannt ist, können RIL-Befehle, die länger als T dauern, als asynchron und die verbleibenden Befehle als synchron klassifiziert werden.
RIL-Kommunikationsszenarien
Die folgenden Diagramme veranschaulichen gängige RIL-Kommunikationsszenarien und bieten Lösungen zum Ändern des Codes, um angeforderte und unaufgeforderte RIL-Anfragen zu verarbeiten.
Hinweis:Implementierungsdetails zu den in den folgenden Diagrammen verwendeten Funktionen finden Sie in den Methoden acquireWakeLock()
, decrementWakeLock()
und clearWakeLock(
in ril.cpp
.
Szenario: RIL-Anfrage und angeforderte asynchrone Antwort
Wenn in diesem Szenario die von der RIL angeforderte Antwort voraussichtlich viel Zeit in Anspruch nimmt (z.B. eine Antwort auf RIL_REQUEST_GET_AVAILABLE_NETWORKS
), wird der Wakelock auf der Seite des App-Prozessors für lange Zeit gehalten. Auch Modemprobleme können zu langen Wartezeiten führen.
Lösung 1:Das Modem hält den Wakelock für die RIL-Anfrage und die asynchrone Antwort.
- Die RIL-Anfrage wird gesendet und das Modem holt sich den Wakelock, um diese Anfrage zu verarbeiten.
- Das Modem sendet eine Bestätigung, die dazu führt, dass die Java-Seite den Wakelock-Zähler dekrementiert und ihn freigibt, wenn der Zählerwert 0 ist.
Hinweis:Die Zeitüberschreitung für den Wakelock für die Anfrage-/Bestätigungssequenz sollte kürzer sein als die derzeit verwendete Zeitüberschreitung, da die Bestätigung relativ schnell empfangen werden sollte.
- Nach der Verarbeitung der Anfrage sendet das Modem einen Interrupt an den Anbietercode, der den Wakelock erwirbt und eine Antwort an ril.cpp sendet, die wiederum den Wakelock erwirbt und eine Antwort an die Java-Seite sendet.
- Wenn die Antwort die Java-Seite erreicht, wird der Wakelock erworben und eine Antwort an den Aufrufer zurückgegeben.
- Nachdem die Antwort von allen Modulen verarbeitet wurde, wird eine Bestätigung (über einen Socket) an
ril.cpp
zurückgesendet, wodurch der in Schritt 3 erworbene Wakelock freigegeben wird.
Lösung 2:Das Modem hält den Wakelock nicht und die Antwort ist schnell (synchrone RIL-Anfrage und ‑Antwort). Das synchrone oder asynchrone Verhalten ist für einen bestimmten RIL-Befehl hartcodiert und wird auf Anrufbasis entschieden.
- Die RIL-Anfrage wird gesendet, indem
acquireWakeLock()
auf Java-Seite aufgerufen wird. - Der Anbietercode muss keinen Wakelock erwerben und kann die Anfrage verarbeiten und schnell reagieren.
- Wenn die Antwort von der Java-Seite empfangen wird, wird
decrementWakeLock()
aufgerufen, wodurch der Wakelock-Zähler verringert und der Wakelock freigegeben wird, wenn der Zählerwert 0 ist.
Szenario: Unbestellte Antwort von RIL
In diesem Szenario haben nicht angeforderte RIL-Antworten ein Flag vom Typ „Wakelock“, das angibt, ob für die Antwort des Anbieters ein Wakelock erworben werden muss. Wenn das Flag gesetzt ist, wird ein zeitgesteuerter Wakelock festgelegt und die Antwort wird über einen Socket an die Java-Seite gesendet. Wenn der Timer abläuft, wird der Wakelock freigegeben. Die sitzungsbasierte Sperre kann für verschiedene unaufgeforderte RIL-Antworten zu lang oder zu kurz sein.
Lösung:Eine Bestätigung wird vom Java-Code an die native Seite (ril.cpp
) gesendet, anstatt ein zeitgesteuertes Wakelock auf der nativen Seite aufrechtzuerhalten, während eine unaufgeforderte Antwort gesendet wird.
Neu gestaltete Wakelocks prüfen
Prüfen Sie, ob RIL-Anrufe als synchron oder asynchron gekennzeichnet sind. Da der Akkuverbrauch von der Hardware/Plattform abhängen kann, sollten Anbieter einige interne Tests durchführen, um herauszufinden, ob die Verwendung der neuen Wakelock-Semantik für asynchrone Aufrufe zu einer Akkueinsparung führt.