fuck-oems

I personally think that one of the problems with Android ecosystem is Android device manufacturers (OEM’s) altering platform code and implementing hardware in a shitty way.

I believe that the OEM’s intentions are pure: Make the device stand out, give great user experience, make things look pretty and save power. Often times it comes with a cost: Fragmentation: things performing differently on different devices, random ANR crashes and device dependant problems, Services being killed for “power saving”, whitelisting for popular apps, you name it.

It comes with a cost. One of the biggest points of interests I have noticed is the difference between video playback on different devices:

One of the problems with playing video content on android devices is the codec / hardware implementations of devices: Issue 4468 Issue 6899 Issue 6222

Exoplayer, the most popular and stable video / streaming library for Android keeps a list of devices that need a workaround to get around of the device implementation bugs to smoothly play videos:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/**
* Returns whether the codec is known to implement {@link MediaCodec#setOutputSurface(Surface)}
* incorrectly.
*
* <p>If true is returned then we fall back to releasing and re-instantiating the codec instead.
*
* @param name The name of the codec.
* @return True if the device is known to implement {@link MediaCodec#setOutputSurface(Surface)}
* incorrectly.
*/
protected boolean codecNeedsSetOutputSurfaceWorkaround(String name) {
if (name.startsWith("OMX.google")) {
// Google OMX decoders are not known to have this issue on any API level.
return false;
}
synchronized (MediaCodecVideoRenderer.class) {
if (!evaluatedDeviceNeedsSetOutputSurfaceWorkaround) {
if (Util.SDK_INT <= 27 && "dangal".equals(Util.DEVICE)) {
// A small number of devices are affected on API level 27:
// https://github.com/google/ExoPlayer/issues/5169.
deviceNeedsSetOutputSurfaceWorkaround = true;
} else if (Util.SDK_INT >= 27) {
// In general, devices running API level 27 or later should be unaffected. Do nothing.
} else {
// Enable the workaround on a per-device basis. Works around:
// https://github.com/google/ExoPlayer/issues/3236,
// https://github.com/google/ExoPlayer/issues/3355,
// https://github.com/google/ExoPlayer/issues/3439,
// https://github.com/google/ExoPlayer/issues/3724,
// https://github.com/google/ExoPlayer/issues/3835,
// https://github.com/google/ExoPlayer/issues/4006,
// https://github.com/google/ExoPlayer/issues/4084,
// https://github.com/google/ExoPlayer/issues/4104,
// https://github.com/google/ExoPlayer/issues/4134,
// https://github.com/google/ExoPlayer/issues/4315,
// https://github.com/google/ExoPlayer/issues/4419,
// https://github.com/google/ExoPlayer/issues/4460,
// https://github.com/google/ExoPlayer/issues/4468,
// https://github.com/google/ExoPlayer/issues/5312.
switch (Util.DEVICE) {
case "1601":
case "1713":
case "1714":
case "A10-70F":
case "A10-70L":
case "A1601":
case "A2016a40":
case "A7000-a":
case "A7000plus":
case "A7010a48":
case "A7020a48":
case "AquaPowerM":
case "ASUS_X00AD_2":
case "Aura_Note_2":
case "BLACK-1X":
case "BRAVIA_ATV2":
case "BRAVIA_ATV3_4K":
case "C1":
case "ComioS1":
case "CP8676_I02":
case "CPH1609":
case "CPY83_I00":
case "cv1":
case "cv3":
case "deb":
case "E5643":
case "ELUGA_A3_Pro":
case "ELUGA_Note":
case "ELUGA_Prim":
case "ELUGA_Ray_X":
case "EverStar_S":
case "F3111":
case "F3113":
case "F3116":
case "F3211":
case "F3213":
case "F3215":
case "F3311":
case "flo":
case "fugu":
case "GiONEE_CBL7513":
case "GiONEE_GBL7319":
case "GIONEE_GBL7360":
case "GIONEE_SWW1609":
case "GIONEE_SWW1627":
case "GIONEE_SWW1631":
case "GIONEE_WBL5708":
case "GIONEE_WBL7365":
case "GIONEE_WBL7519":
case "griffin":
case "htc_e56ml_dtul":
case "hwALE-H":
case "HWBLN-H":
case "HWCAM-H":
case "HWVNS-H":
case "HWWAS-H":
case "i9031":
case "iball8735_9806":
case "Infinix-X572":
case "iris60":
case "itel_S41":
case "j2xlteins":
case "JGZ":
case "K50a40":
case "kate":
case "le_x6":
case "LS-5017":
case "M5c":
case "manning":
case "marino_f":
case "MEIZU_M5":
case "mh":
case "mido":
case "MX6":
case "namath":
case "nicklaus_f":
case "NX541J":
case "NX573J":
case "OnePlus5T":
case "p212":
case "P681":
case "P85":
case "panell_d":
case "panell_dl":
case "panell_ds":
case "panell_dt":
case "PB2-670M":
case "PGN528":
case "PGN610":
case "PGN611":
case "Phantom6":
case "Pixi4-7_3G":
case "Pixi5-10_4G":
case "PLE":
case "PRO7S":
case "Q350":
case "Q4260":
case "Q427":
case "Q4310":
case "Q5":
case "QM16XE_U":
case "QX1":
case "santoni":
case "Slate_Pro":
case "SVP-DTV15":
case "s905x018":
case "taido_row":
case "TB3-730F":
case "TB3-730X":
case "TB3-850F":
case "TB3-850M":
case "tcl_eu":
case "V1":
case "V23GB":
case "V5":
case "vernee_M5":
case "watson":
case "whyred":
case "woods_f":
case "woods_fn":
case "X3_HK":
case "XE2X":
case "XT1663":
case "Z12_PRO":
case "Z80":
deviceNeedsSetOutputSurfaceWorkaround = true;
break;
default:
// Do nothing.
break;
}
switch (Util.MODEL) {
case "AFTA":
case "AFTN":
deviceNeedsSetOutputSurfaceWorkaround = true;
break;
default:
// Do nothing.
break;
}
}
evaluatedDeviceNeedsSetOutputSurfaceWorkaround = true;
}
}
return deviceNeedsSetOutputSurfaceWorkaround;
}

This sounds like a problem from the past, but I have seen an increase of problems coming from Huawei devices regarding of this issue. Also specific AndroidTV devices have been affected.

This problem also extends to playing DRM content on devices. Because of buggy implementations of DRM / bad certificates, sometimes the only way to reliably play DRM content on Android device is using software decoding for DRM (level 3), which causes horrible lag, performance problems and decrease in quality.

source1 source2 source3

What is even worse, imo, is the problems with native views such as VideoView, working differently on different devices.

Playing a simple video (mp4) causes certain Huawei devices to crash:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#00  pc 000000000006fd98  /system/lib64/libc.so (__ioctl+4)
#01 pc 0000000000029e34 /system/lib64/libc.so (ioctl+136)
#02 pc 000000000006b4f0 /system/lib64/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+256)
#03 pc 000000000006c7f4 /system/lib64/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+60)
#04 pc 000000000006c470 /system/lib64/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+240)
#05 pc 0000000000061e74 /system/lib64/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+72)
#06 pc 00000000000771fc /system/lib64/libmedia.so (android::BpMediaPlayer::setDataSource(int, long, long)+300)
#07 pc 0000000000065ebc /system/lib64/libmedia.so (android::MediaPlayer::setDataSource(int, long, long)+592)
#08 pc 00000000000461a0 /system/lib64/libmedia_jni.so (android_media_MediaPlayer_setDataSourceFD(_JNIEnv*, _jobject*, _jobject*, long, long)+180)
at android.media.MediaPlayer._setDataSource (MediaPlayer.java)
at android.media.MediaPlayer.setDataSource (MediaPlayer.java:1382)
at android.media.MediaPlayer.setDataSource (MediaPlayer.java:1349)
at android.media.MediaPlayer.attemptDataSource (MediaPlayer.java:1177)
at android.media.MediaPlayer.setDataSource (MediaPlayer.java:1148)
at android.media.MediaPlayer.setDataSource (MediaPlayer.java:1172)
at android.widget.VideoView.openVideo (VideoView.java:402)
at android.widget.VideoView.setVideoURI (VideoView.java:274)
at android.widget.VideoView.setVideoURI (VideoView.java:257)
at XXXX
at android.os.Handler.handleCallback (Handler.java:907)
at android.os.Handler.dispatchMessage (Handler.java:105)
at android.os.Looper.loop (Looper.java:216)
at android.app.ActivityThread.main (ActivityThread.java:7625)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:987)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
By device
P20 Pro (HWCLT) 27
Honor 10 (HWCOL) 16
HUAWEI P smart 2019 (HWPOT-H) 10
P20 (HWEML) 9
Others 23
P20 Pro (HWCLT) 27 31.8%
Honor 10 (HWCOL) 16 18.8%
HUAWEI P smart 2019 (HWPOT-H) 10 11.8%
P20 (HWEML) 9 10.6%
Mate 10 Pro (HWBLA) 6 7.1%
Honor Play (HWCOR) 5 5.9%
honor 10 Lite (HWHRY-H) 5 5.9%
HUAWEI P30 lite (HWMAR) 4 4.7%
HONOR 10i (HWHRY-HF) 2 2.4%
HUAWEI Y9 Prime 2019 (HWSTK-HF) 1 1.2%

Unless Google is playing some kind of crazy sleight of hand towards Huawei (its not impossible), it seems to be that some device OEM’s are in the right of blame in here.

- Zudoku