blob: fb3ab00a3bd9398319731998b5ee71f72881cda5 [file] [log] [blame]
Alexandre Lisionb8add812013-10-24 11:42:42 -04001/*
2 * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
3 * Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
4 *
5 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 * Additional permission under GNU GPL version 3 section 7:
22 *
23 * If you modify this program, or any covered work, by linking or
24 * combining it with the OpenSSL project's OpenSSL library (or a
25 * modified version of that library), containing parts covered by the
26 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
27 * grants you additional permission to convey the resulting work.
28 * Corresponding Source for a non-source form of such a combination
29 * shall include the source code for the parts of OpenSSL used as well
30 * as that of the covered work.
31 */
32
33package org.sflphone.utils;
34
35import java.io.File;
36import java.io.FileFilter;
37import java.lang.reflect.Field;
38import java.util.regex.Pattern;
39
40import android.content.Context;
41import android.content.Intent;
42import android.content.pm.ApplicationInfo;
43import android.content.pm.PackageInfo;
44import android.content.pm.PackageManager;
45import android.content.pm.PackageManager.NameNotFoundException;
46import android.content.res.Configuration;
47import android.media.AudioManager;
48import android.media.MediaRecorder.AudioSource;
49import android.net.Uri;
50import android.os.Environment;
51import android.provider.Contacts;
52import android.util.Log;
53
54@SuppressWarnings("deprecation")
55public final class Compatibility {
56
57 private Compatibility() {
58 }
59
60 private static final String THIS_FILE = "Compat";
61
62 public static int getApiLevel() {
63 return android.os.Build.VERSION.SDK_INT;
64 }
65
66 public static boolean isCompatible(int apiLevel) {
67 return android.os.Build.VERSION.SDK_INT >= apiLevel;
68 }
69
70 /**
Alexandre Lision35577132013-12-06 15:21:15 -050071 * Get the stream id for in call track. Can differ on some devices. Current device for which it's different :
Alexandre Lisionb8add812013-10-24 11:42:42 -040072 *
73 * @return
74 */
75 public static int getInCallStream(boolean requestBluetooth) {
76 /* Archos 5IT */
Alexandre Lision35577132013-12-06 15:21:15 -050077 if (android.os.Build.BRAND.equalsIgnoreCase("archos") && android.os.Build.DEVICE.equalsIgnoreCase("g7a")) {
Alexandre Lisionb8add812013-10-24 11:42:42 -040078 // Since archos has no voice call capabilities, voice call stream is
79 // not implemented
80 // So we have to choose the good stream tag, which is by default
81 // falled back to music
82 return AudioManager.STREAM_MUSIC;
83 }
84 if (requestBluetooth) {
85 return 6; /* STREAM_BLUETOOTH_SCO -- Thx @Stefan for the contrib */
86 }
87
88 // return AudioManager.STREAM_MUSIC;
89 return AudioManager.STREAM_VOICE_CALL;
90 }
91
92 public static boolean shouldUseRoutingApi() {
Alexandre Lision35577132013-12-06 15:21:15 -050093 Log.d(THIS_FILE, "Current device " + android.os.Build.BRAND + " - " + android.os.Build.DEVICE);
Alexandre Lisionb8add812013-10-24 11:42:42 -040094
95 // HTC evo 4G
96 if (android.os.Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
97 return true;
98 }
99
100 // ZTE joe
101 if (android.os.Build.DEVICE.equalsIgnoreCase("joe")) {
102 return true;
103 }
104
105 // Samsung GT-S5830
106 if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-S")) {
107 return true;
108 }
109
110 if (!isCompatible(4)) {
111 // If android 1.5, force routing api use
112 return true;
113 } else {
114 return false;
115 }
116 }
117
118 public static boolean shouldUseModeApi() {
119
120 // ZTE blade et joe
Alexandre Lision35577132013-12-06 15:21:15 -0500121 if (android.os.Build.DEVICE.equalsIgnoreCase("blade") || android.os.Build.DEVICE.equalsIgnoreCase("joe")) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400122 return true;
123 }
124 // Samsung GT-S5360 GT-S5830 GT-S6102 ... probably all..
Alexandre Lision35577132013-12-06 15:21:15 -0500125 if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-") || android.os.Build.PRODUCT.toUpperCase().startsWith("GT-")
126 || android.os.Build.DEVICE.toUpperCase().startsWith("YP-")) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400127 return true;
128 }
129
130 // HTC evo 4G
131 if (android.os.Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
132 return true;
133 }
134 // LG P500, Optimus V
135 if (android.os.Build.DEVICE.toLowerCase().startsWith("thunder")) {
136 return true;
137 }
138 // LG-E720(b)
Alexandre Lision35577132013-12-06 15:21:15 -0500139 if (android.os.Build.MODEL.toUpperCase().startsWith("LG-E720") && !Compatibility.isCompatible(9)) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400140 return true;
141 }
142 // LG-LS840
143 if (android.os.Build.DEVICE.toLowerCase().startsWith("cayman")) {
144 return true;
145 }
146
147 // Huawei
Alexandre Lision35577132013-12-06 15:21:15 -0500148 if (android.os.Build.DEVICE.equalsIgnoreCase("U8150") || android.os.Build.DEVICE.equalsIgnoreCase("U8110")
149 || android.os.Build.DEVICE.equalsIgnoreCase("U8120") || android.os.Build.DEVICE.equalsIgnoreCase("U8100")
150 || android.os.Build.PRODUCT.equalsIgnoreCase("U8655")) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400151 return true;
152 }
153
154 // Moto defy mini
155 if (android.os.Build.MODEL.equalsIgnoreCase("XT320")) {
156 return true;
157 }
158
159 // Alcatel
160 if (android.os.Build.DEVICE.toUpperCase().startsWith("ONE_TOUCH_993D")) {
161 return true;
162 }
163
164 // N4
165 if (android.os.Build.DEVICE.toUpperCase().startsWith("MAKO")) {
166 return true;
167 }
168
169 return false;
170 }
171
172 public static String guessInCallMode() {
173 // New api for 2.3.3 is not available on galaxy S II :(
174 if (!isCompatible(11) && android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9100")) {
175 return Integer.toString(AudioManager.MODE_NORMAL);
176 }
177
178 if (android.os.Build.BRAND.equalsIgnoreCase("sdg") || isCompatible(10)) {
179 // Note that in APIs this is only available from level 11.
180 return "3";
181 }
182 if (android.os.Build.DEVICE.equalsIgnoreCase("blade")) {
183 return Integer.toString(AudioManager.MODE_IN_CALL);
184 }
185
186 if (!isCompatible(5)) {
187 return Integer.toString(AudioManager.MODE_IN_CALL);
188 }
189
190 return Integer.toString(AudioManager.MODE_NORMAL);
191 }
192
193 public static String getDefaultMicroSource() {
194 // Except for galaxy S II :(
195 if (!isCompatible(11) && android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9100")) {
196 return Integer.toString(AudioSource.MIC);
197 }
198
199 if (isCompatible(10)) {
200 // Note that in APIs this is only available from level 11.
201 // VOICE_COMMUNICATION
202 return Integer.toString(0x7);
203 }
204 /*
Alexandre Lision35577132013-12-06 15:21:15 -0500205 * Too risky in terms of regressions else if (isCompatible(4)) { // VOICE_CALL return 0x4; }
Alexandre Lisionb8add812013-10-24 11:42:42 -0400206 */
207 /*
Alexandre Lision35577132013-12-06 15:21:15 -0500208 * if(android.os.Build.MODEL.equalsIgnoreCase("X10i")) { // VOICE_CALL return Integer.toString(0x4); }
Alexandre Lisionb8add812013-10-24 11:42:42 -0400209 */
210 /*
Alexandre Lision35577132013-12-06 15:21:15 -0500211 * Not relevant anymore, atrix I tested sounds fine with that if(android.os.Build.DEVICE.equalsIgnoreCase("olympus")) { //Motorola atrix bug
212 * // CAMCORDER return Integer.toString(0x5); }
Alexandre Lisionb8add812013-10-24 11:42:42 -0400213 */
214
215 return Integer.toString(AudioSource.DEFAULT);
216 }
217
218 public static String getDefaultFrequency() {
219 if (android.os.Build.DEVICE.equalsIgnoreCase("olympus")) {
220 // Atrix bug
221 return "32000";
222 }
223 if (android.os.Build.DEVICE.toUpperCase().equals("GT-P1010")) {
224 // Galaxy tab see issue 932
225 return "32000";
226 }
227
228 return isCompatible(4) ? "16000" : "8000";
229 }
230
231 public static String getCpuAbi() {
232 if (isCompatible(4)) {
233 Field field;
234 try {
235 field = android.os.Build.class.getField("CPU_ABI");
236 return field.get(null).toString();
237 } catch (Exception e) {
238 Log.w(THIS_FILE, "Announce to be android 1.6 but no CPU ABI field", e);
239 }
240
241 }
242 return "armeabi";
243 }
244
245 public final static int getNumCores() {
246 // Private Class to display only CPU devices in the directory listing
247 class CpuFilter implements FileFilter {
248 @Override
249 public boolean accept(File pathname) {
250 // Check if filename is "cpu", followed by a single digit number
251 if (Pattern.matches("cpu[0-9]", pathname.getName())) {
252 return true;
253 }
254 return false;
255 }
256 }
257 try {
258 // Get directory containing CPU info
259 File dir = new File("/sys/devices/system/cpu/");
260 // Filter to only list the devices we care about
261 File[] files = dir.listFiles(new CpuFilter());
262 // Return the number of cores (virtual CPU devices)
263 return files.length;
264 } catch (Exception e) {
265 return Runtime.getRuntime().availableProcessors();
266 }
267 }
268
269 private static boolean needPspWorkaround() {
270 // New api for 2.3 does not work on Incredible S
271 if (android.os.Build.DEVICE.equalsIgnoreCase("vivo")) {
272 return true;
273 }
274
275 // New API for android 2.3 should be able to manage this but do only for
276 // honeycomb cause seems not correctly supported by all yet
277 if (isCompatible(11)) {
278 return false;
279 }
280
281 // All htc except....
Alexandre Lision35577132013-12-06 15:21:15 -0500282 if (android.os.Build.PRODUCT.toLowerCase().startsWith("htc") || android.os.Build.BRAND.toLowerCase().startsWith("htc")
Alexandre Lisionb8add812013-10-24 11:42:42 -0400283 || android.os.Build.PRODUCT.toLowerCase().equalsIgnoreCase("inc") /*
Alexandre Lision35577132013-12-06 15:21:15 -0500284 * For Incredible
Alexandre Lisionb8add812013-10-24 11:42:42 -0400285 */
286 || android.os.Build.DEVICE.equalsIgnoreCase("passion") /* N1 */) {
287 if (android.os.Build.DEVICE.equalsIgnoreCase("hero") /* HTC HERO */
288 || android.os.Build.DEVICE.equalsIgnoreCase("magic") /*
Alexandre Lision35577132013-12-06 15:21:15 -0500289 * Magic Aka Dev G2
Alexandre Lisionb8add812013-10-24 11:42:42 -0400290 */
291 || android.os.Build.DEVICE.equalsIgnoreCase("tatoo") /* Tatoo */
292 || android.os.Build.DEVICE.equalsIgnoreCase("dream") /*
Alexandre Lision35577132013-12-06 15:21:15 -0500293 * Dream Aka Dev G1
Alexandre Lisionb8add812013-10-24 11:42:42 -0400294 */
295 || android.os.Build.DEVICE.equalsIgnoreCase("legend") /* Legend */
296
297 ) {
298 return false;
299 }
300
301 // Older than 2.3 has no chance to have the new full perf wifi mode
302 // working since does not exists
303 if (!isCompatible(9)) {
304 return true;
305 } else {
306 // N1 is fine with that
307 if (android.os.Build.DEVICE.equalsIgnoreCase("passion")) {
308 return false;
309 }
310 return true;
311 }
312
313 }
314 // Dell streak
Alexandre Lision35577132013-12-06 15:21:15 -0500315 if (android.os.Build.BRAND.toLowerCase().startsWith("dell") && android.os.Build.DEVICE.equalsIgnoreCase("streak")) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400316 return true;
317 }
318 // Motorola milestone 1 and 2 & motorola droid & defy not under 2.3
Alexandre Lision35577132013-12-06 15:21:15 -0500319 if ((android.os.Build.DEVICE.toLowerCase().contains("milestone2") || android.os.Build.BOARD.toLowerCase().contains("sholes")
320 || android.os.Build.PRODUCT.toLowerCase().contains("sholes") || android.os.Build.DEVICE.equalsIgnoreCase("olympus") || android.os.Build.DEVICE
321 .toLowerCase().contains("umts_jordan")) && !isCompatible(9)) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400322 return true;
323 }
324 // Moto defy mini
325 if (android.os.Build.MODEL.equalsIgnoreCase("XT320")) {
326 return true;
327 }
328
329 // Alcatel ONE touch
330 if (android.os.Build.DEVICE.startsWith("one_touch_990")) {
331 return true;
332 }
333
334 return false;
335 }
336
337 private static boolean needToneWorkaround() {
Alexandre Lision35577132013-12-06 15:21:15 -0500338 if (android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i5800") || android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i5801")
339 || android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i9003")) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400340 return true;
341 }
342 return false;
343 }
344
345 private static boolean needSGSWorkaround() {
346 if (isCompatible(9)) {
347 return false;
348 }
Alexandre Lision35577132013-12-06 15:21:15 -0500349 if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9000") || android.os.Build.DEVICE.toUpperCase().startsWith("GT-P1000")) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400350 return true;
351 }
352 return false;
353 }
354
355 private static boolean needWebRTCImplementation() {
356 if (android.os.Build.DEVICE.toLowerCase().contains("droid2")) {
357 return true;
358 }
359 if (android.os.Build.MODEL.toLowerCase().contains("droid bionic")) {
360 return true;
361 }
362 if (android.os.Build.DEVICE.toLowerCase().contains("sunfire")) {
363 return true;
364 }
365 // Huawei Y300
366 if (android.os.Build.DEVICE.equalsIgnoreCase("U8833")) {
367 return true;
368 }
369 return false;
370 }
371
372 public static boolean shouldSetupAudioBeforeInit() {
373 // Setup for GT / GS samsung devices.
Alexandre Lision35577132013-12-06 15:21:15 -0500374 if (android.os.Build.DEVICE.toLowerCase().startsWith("gt-") || android.os.Build.PRODUCT.toLowerCase().startsWith("gt-")) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400375 return true;
376 }
377 return false;
378 }
379
380 private static boolean shouldFocusAudio() {
381 /* HTC One X */
Alexandre Lision35577132013-12-06 15:21:15 -0500382 if (android.os.Build.DEVICE.toLowerCase().startsWith("endeavoru") || android.os.Build.DEVICE.toLowerCase().startsWith("evita")) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400383 return false;
384 }
385
386 if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-P7510") && isCompatible(15)) {
387 return false;
388 }
389 return true;
390 }
391
Alexandre Lision35577132013-12-06 15:21:15 -0500392 // private static int getDefaultAudioImplementation() {
393 // // Acer A510
394 // if (android.os.Build.DEVICE.toLowerCase().startsWith("picasso")) {
395 // return SipConfigManager.AUDIO_IMPLEMENTATION_JAVA;
396 // }
397 // if (Compatibility.isCompatible(11)) {
398 // return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
399 // }
400 // if (android.os.Build.DEVICE.equalsIgnoreCase("ST25i") && Compatibility.isCompatible(10)) {
401 // return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
402 // }
403 // if (android.os.Build.DEVICE.equalsIgnoreCase("u8510") && Compatibility.isCompatible(10)) {
404 // return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
405 // }
406 // return SipConfigManager.AUDIO_IMPLEMENTATION_JAVA;
407 // }
Alexandre Lisionb8add812013-10-24 11:42:42 -0400408
409 public static boolean useFlipAnimation() {
Alexandre Lision35577132013-12-06 15:21:15 -0500410 if (android.os.Build.BRAND.equalsIgnoreCase("archos") && android.os.Build.DEVICE.equalsIgnoreCase("g7a")) {
Alexandre Lisionb8add812013-10-24 11:42:42 -0400411 return false;
412 }
413 return true;
414 }
415
Alexandre Lisionb8add812013-10-24 11:42:42 -0400416 public static Intent getContactPhoneIntent() {
417 Intent intent = new Intent(Intent.ACTION_PICK);
418 /*
Alexandre Lision35577132013-12-06 15:21:15 -0500419 * intent.setAction(Intent.ACTION_GET_CONTENT); intent.setType(Contacts.Phones.CONTENT_ITEM_TYPE);
Alexandre Lisionb8add812013-10-24 11:42:42 -0400420 */
421 if (isCompatible(5)) {
422 // Don't use constant to allow backward compat simply
423 intent.setData(Uri.parse("content://com.android.contacts/contacts"));
424 } else {
425 // Fallback for android 4
426 intent.setData(Contacts.People.CONTENT_URI);
427 }
428
429 return intent;
430
431 }
Alexandre Lisionb8add812013-10-24 11:42:42 -0400432
433 public static boolean isTabletScreen(Context ctxt) {
434 boolean isTablet = false;
435 if (!isCompatible(4)) {
436 return false;
437 }
438 Configuration cfg = ctxt.getResources().getConfiguration();
439 int screenLayoutVal = 0;
440 try {
441 Field f = Configuration.class.getDeclaredField("screenLayout");
442 screenLayoutVal = (Integer) f.get(cfg);
443 } catch (Exception e) {
444 return false;
445 }
446 int screenLayout = (screenLayoutVal & 0xF);
447 // 0xF = SCREENLAYOUT_SIZE_MASK but avoid 1.5 incompat doing that
448 if (screenLayout == 0x3 || screenLayout == 0x4) {
449 // 0x3 = SCREENLAYOUT_SIZE_LARGE but avoid 1.5 incompat doing that
450 // 0x4 = SCREENLAYOUT_SIZE_XLARGE but avoid 1.5 incompat doing that
451 isTablet = true;
452 }
453
454 return isTablet;
455 }
456
457 public static int getHomeMenuId() {
458 return 0x0102002c;
459 // return android.R.id.home;
460 }
461
462 public static boolean isInstalledOnSdCard(Context context) {
463 // check for API level 8 and higher
464 if (Compatibility.isCompatible(8)) {
465 PackageManager pm = context.getPackageManager();
466 try {
467 PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
468 ApplicationInfo ai = pi.applicationInfo;
469 return (ai.flags & 0x00040000 /*
Alexandre Lision35577132013-12-06 15:21:15 -0500470 * ApplicationInfo. FLAG_EXTERNAL_STORAGE
Alexandre Lisionb8add812013-10-24 11:42:42 -0400471 */) == 0x00040000 /*
Alexandre Lision35577132013-12-06 15:21:15 -0500472 * ApplicationInfo. FLAG_EXTERNAL_STORAGE
Alexandre Lisionb8add812013-10-24 11:42:42 -0400473 */;
474 } catch (NameNotFoundException e) {
475 // ignore
476 }
477 }
478
479 // check for API level 7 - check files dir
480 try {
481 String filesDir = context.getFilesDir().getAbsolutePath();
482 if (filesDir.startsWith("/data/")) {
483 return false;
484 } else if (filesDir.contains(Environment.getExternalStorageDirectory().getPath())) {
485 return true;
486 }
487 } catch (Throwable e) {
488 // ignore
489 }
490
491 return false;
492 }
493
494}