22 Oktober 2014 10:17

MediaTek kann nicht teilen

Smartphones werden immer günstiger. In China sprießen unzählige Hersteller von günstigen Smartphones aus dem Boden und manch einer glaubt, ein richtig gutes Schnäppchen zu machen. Auf den ersten Blick sehen viele Modelle sowohl von der Ausstattung als auch von der Verarbeitung sehr gut aus. Doch geht man etwas mehr ins Detail, so stolpert man schnell über unschöne Eigenschaften.

Auf ein sehr weit verbreitetes, aber wenig wahrgenommenes Problem möchte ich in diesem Artikel eingehen. Als Entwickler von c:geo wurde ich vor einiger Zeit auf einen Fehler in der App aufmerksam gemacht und schnell war der Schuldige gefunden. Denn alle betroffenen Smartphones besitzen eine CPU von MediaTek – und MediaTek kann nicht teilen!

Das Problem

In c:geo zeigt sich das Problem folgendermaßen: Öffnet man die LiveMap und nutzt man OpenStreetMap, so werden alle Caches (wenn überhaupt) in einer senkrechten Linie angeordnet und von der Karte werden lediglich Teile dargestellt. Die Entfernungen zu Caches springen zufällig.

Auch in einigen anderen Apps kann man ein ähnliches Verhalten beobachten. Entweder stürzt sie ab oder liefert unsinnige Werte. Doch wie kommt es zu diesem Fehler?

Ursache

Kurz: Möchte man bestimmte Zahlen miteinander teilen, berechnet die CPU von MediaTek den Wert unter manchen Bedingungen falsch.

Lang: Das Problem geht vermutlich auf einen recht alten Bug in Android zurück, der aber nur kurze Zeit Anfang 2013 existierte. Bereits nach kurzer Zeit wurde er behoben, aber MediaTek scheint genau diesen Code zu verwenden. Eine Erklärung, wie es zu diesem Fehler kommt, steht in diesem Bugreport.

In short, if two or more 64-bit floating point constants are used in the same basic block, *and* the low 32 bits of the constants were identical, the JIT could mistakenly consider them the same, and optimize away one of them. It failed to consider the upper 32-bits when looking for constant reuse.

Also: Der JIT-Compiler führt eine fehlerhafte Optimierung durch, bei der bei einer Division von zwei ähnlichen double Werten unter Umständen 1 herauskommen kann.

Lösung?

Obwohl der Fehler Upstream schon lange behoben ist, taucht er auch bei KitKat noch auf. Entweder liefert MediaTek weiterhin einen alten JIT-Compiler aus oder hat einen ähnlichen Fehler eingebaut. Um das Problem zuverlässig zu vermeiden, hilft es nur, den JIT-Compiler zu umgehen. Dazu fügt man in den Application-Tag seiner AndroidManifest.xml folgendes Attribut hinzu:

<application … android:vmSafeMode="true">
    …
</application>

Dadurch kann die Ausführung des Programms aber etwas langsamer werden, sodass dies keine ideale Lösung ist.

Kommentare

Hansi, 22.10.2014 10:33
Zur Lösung: Ist es möglich, die MediaTek CPU vom Programm zu erkennen und dementsprechend vmSafeMode zu setzen oder geht das nur global? Im ersten Falle wäre das doch durchaus praktikabel oder übersehe ich da etwas?
SammysHP, 25.10.2014 19:44
@Hansi

Nein, das geht nicht. Der Wert muss in der AndroidManifest.xml stehen. Zwar könnte man ihn über res/values-<version>/… für eine spezifische Version von Android festlegen, nicht aber für andere Merkmale.
Hansi, 30.10.2014 10:55
Alles klar, dann ist das natürlich nicht so schön.
Powered by BetaBlog
Login | RSS Beiträge RSS Kommentare Impressum