blob: 7a4a800d9bd80e4cbf29429f46dedbe5184fafe8 [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 /**
71 * Get the stream id for in call track. Can differ on some devices. Current
72 * device for which it's different :
73 *
74 * @return
75 */
76 public static int getInCallStream(boolean requestBluetooth) {
77 /* Archos 5IT */
78 if (android.os.Build.BRAND.equalsIgnoreCase("archos")
79 && android.os.Build.DEVICE.equalsIgnoreCase("g7a")) {
80 // Since archos has no voice call capabilities, voice call stream is
81 // not implemented
82 // So we have to choose the good stream tag, which is by default
83 // falled back to music
84 return AudioManager.STREAM_MUSIC;
85 }
86 if (requestBluetooth) {
87 return 6; /* STREAM_BLUETOOTH_SCO -- Thx @Stefan for the contrib */
88 }
89
90 // return AudioManager.STREAM_MUSIC;
91 return AudioManager.STREAM_VOICE_CALL;
92 }
93
94 public static boolean shouldUseRoutingApi() {
95 Log.d(THIS_FILE, "Current device " + android.os.Build.BRAND + " - "
96 + android.os.Build.DEVICE);
97
98 // HTC evo 4G
99 if (android.os.Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
100 return true;
101 }
102
103 // ZTE joe
104 if (android.os.Build.DEVICE.equalsIgnoreCase("joe")) {
105 return true;
106 }
107
108 // Samsung GT-S5830
109 if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-S")) {
110 return true;
111 }
112
113 if (!isCompatible(4)) {
114 // If android 1.5, force routing api use
115 return true;
116 } else {
117 return false;
118 }
119 }
120
121 public static boolean shouldUseModeApi() {
122
123 // ZTE blade et joe
124 if (android.os.Build.DEVICE.equalsIgnoreCase("blade")
125 || android.os.Build.DEVICE.equalsIgnoreCase("joe")) {
126 return true;
127 }
128 // Samsung GT-S5360 GT-S5830 GT-S6102 ... probably all..
129 if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-") ||
130 android.os.Build.PRODUCT.toUpperCase().startsWith("GT-") ||
131 android.os.Build.DEVICE.toUpperCase().startsWith("YP-")) {
132 return true;
133 }
134
135 // HTC evo 4G
136 if (android.os.Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
137 return true;
138 }
139 // LG P500, Optimus V
140 if (android.os.Build.DEVICE.toLowerCase().startsWith("thunder")) {
141 return true;
142 }
143 // LG-E720(b)
144 if (android.os.Build.MODEL.toUpperCase().startsWith("LG-E720")
145 && !Compatibility.isCompatible(9)) {
146 return true;
147 }
148 // LG-LS840
149 if (android.os.Build.DEVICE.toLowerCase().startsWith("cayman")) {
150 return true;
151 }
152
153 // Huawei
154 if (android.os.Build.DEVICE.equalsIgnoreCase("U8150") ||
155 android.os.Build.DEVICE.equalsIgnoreCase("U8110") ||
156 android.os.Build.DEVICE.equalsIgnoreCase("U8120") ||
157 android.os.Build.DEVICE.equalsIgnoreCase("U8100") ||
158 android.os.Build.PRODUCT.equalsIgnoreCase("U8655")) {
159 return true;
160 }
161
162 // Moto defy mini
163 if (android.os.Build.MODEL.equalsIgnoreCase("XT320")) {
164 return true;
165 }
166
167 // Alcatel
168 if (android.os.Build.DEVICE.toUpperCase().startsWith("ONE_TOUCH_993D")) {
169 return true;
170 }
171
172 // N4
173 if (android.os.Build.DEVICE.toUpperCase().startsWith("MAKO")) {
174 return true;
175 }
176
177 return false;
178 }
179
180 public static String guessInCallMode() {
181 // New api for 2.3.3 is not available on galaxy S II :(
182 if (!isCompatible(11) && android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9100")) {
183 return Integer.toString(AudioManager.MODE_NORMAL);
184 }
185
186 if (android.os.Build.BRAND.equalsIgnoreCase("sdg") || isCompatible(10)) {
187 // Note that in APIs this is only available from level 11.
188 return "3";
189 }
190 if (android.os.Build.DEVICE.equalsIgnoreCase("blade")) {
191 return Integer.toString(AudioManager.MODE_IN_CALL);
192 }
193
194 if (!isCompatible(5)) {
195 return Integer.toString(AudioManager.MODE_IN_CALL);
196 }
197
198 return Integer.toString(AudioManager.MODE_NORMAL);
199 }
200
201 public static String getDefaultMicroSource() {
202 // Except for galaxy S II :(
203 if (!isCompatible(11) && android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9100")) {
204 return Integer.toString(AudioSource.MIC);
205 }
206
207 if (isCompatible(10)) {
208 // Note that in APIs this is only available from level 11.
209 // VOICE_COMMUNICATION
210 return Integer.toString(0x7);
211 }
212 /*
213 * Too risky in terms of regressions else if (isCompatible(4)) { //
214 * VOICE_CALL return 0x4; }
215 */
216 /*
217 * if(android.os.Build.MODEL.equalsIgnoreCase("X10i")) { // VOICE_CALL
218 * return Integer.toString(0x4); }
219 */
220 /*
221 * Not relevant anymore, atrix I tested sounds fine with that
222 * if(android.os.Build.DEVICE.equalsIgnoreCase("olympus")) { //Motorola
223 * atrix bug // CAMCORDER return Integer.toString(0x5); }
224 */
225
226 return Integer.toString(AudioSource.DEFAULT);
227 }
228
229 public static String getDefaultFrequency() {
230 if (android.os.Build.DEVICE.equalsIgnoreCase("olympus")) {
231 // Atrix bug
232 return "32000";
233 }
234 if (android.os.Build.DEVICE.toUpperCase().equals("GT-P1010")) {
235 // Galaxy tab see issue 932
236 return "32000";
237 }
238
239 return isCompatible(4) ? "16000" : "8000";
240 }
241
242 public static String getCpuAbi() {
243 if (isCompatible(4)) {
244 Field field;
245 try {
246 field = android.os.Build.class.getField("CPU_ABI");
247 return field.get(null).toString();
248 } catch (Exception e) {
249 Log.w(THIS_FILE, "Announce to be android 1.6 but no CPU ABI field", e);
250 }
251
252 }
253 return "armeabi";
254 }
255
256 public final static int getNumCores() {
257 // Private Class to display only CPU devices in the directory listing
258 class CpuFilter implements FileFilter {
259 @Override
260 public boolean accept(File pathname) {
261 // Check if filename is "cpu", followed by a single digit number
262 if (Pattern.matches("cpu[0-9]", pathname.getName())) {
263 return true;
264 }
265 return false;
266 }
267 }
268 try {
269 // Get directory containing CPU info
270 File dir = new File("/sys/devices/system/cpu/");
271 // Filter to only list the devices we care about
272 File[] files = dir.listFiles(new CpuFilter());
273 // Return the number of cores (virtual CPU devices)
274 return files.length;
275 } catch (Exception e) {
276 return Runtime.getRuntime().availableProcessors();
277 }
278 }
279
280 private static boolean needPspWorkaround() {
281 // New api for 2.3 does not work on Incredible S
282 if (android.os.Build.DEVICE.equalsIgnoreCase("vivo")) {
283 return true;
284 }
285
286 // New API for android 2.3 should be able to manage this but do only for
287 // honeycomb cause seems not correctly supported by all yet
288 if (isCompatible(11)) {
289 return false;
290 }
291
292 // All htc except....
293 if (android.os.Build.PRODUCT.toLowerCase().startsWith("htc")
294 || android.os.Build.BRAND.toLowerCase().startsWith("htc")
295 || android.os.Build.PRODUCT.toLowerCase().equalsIgnoreCase("inc") /*
296 * For
297 * Incredible
298 */
299 || android.os.Build.DEVICE.equalsIgnoreCase("passion") /* N1 */) {
300 if (android.os.Build.DEVICE.equalsIgnoreCase("hero") /* HTC HERO */
301 || android.os.Build.DEVICE.equalsIgnoreCase("magic") /*
302 * Magic
303 * Aka
304 * Dev
305 * G2
306 */
307 || android.os.Build.DEVICE.equalsIgnoreCase("tatoo") /* Tatoo */
308 || android.os.Build.DEVICE.equalsIgnoreCase("dream") /*
309 * Dream
310 * Aka
311 * Dev
312 * G1
313 */
314 || android.os.Build.DEVICE.equalsIgnoreCase("legend") /* Legend */
315
316 ) {
317 return false;
318 }
319
320 // Older than 2.3 has no chance to have the new full perf wifi mode
321 // working since does not exists
322 if (!isCompatible(9)) {
323 return true;
324 } else {
325 // N1 is fine with that
326 if (android.os.Build.DEVICE.equalsIgnoreCase("passion")) {
327 return false;
328 }
329 return true;
330 }
331
332 }
333 // Dell streak
334 if (android.os.Build.BRAND.toLowerCase().startsWith("dell") &&
335 android.os.Build.DEVICE.equalsIgnoreCase("streak")) {
336 return true;
337 }
338 // Motorola milestone 1 and 2 & motorola droid & defy not under 2.3
339 if ((android.os.Build.DEVICE.toLowerCase().contains("milestone2") ||
340 android.os.Build.BOARD.toLowerCase().contains("sholes") ||
341 android.os.Build.PRODUCT.toLowerCase().contains("sholes") ||
342 android.os.Build.DEVICE.equalsIgnoreCase("olympus") ||
343 android.os.Build.DEVICE.toLowerCase().contains("umts_jordan")) && !isCompatible(9)) {
344 return true;
345 }
346 // Moto defy mini
347 if (android.os.Build.MODEL.equalsIgnoreCase("XT320")) {
348 return true;
349 }
350
351 // Alcatel ONE touch
352 if (android.os.Build.DEVICE.startsWith("one_touch_990")) {
353 return true;
354 }
355
356 return false;
357 }
358
359 private static boolean needToneWorkaround() {
360 if (android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i5800") ||
361 android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i5801") ||
362 android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i9003")) {
363 return true;
364 }
365 return false;
366 }
367
368 private static boolean needSGSWorkaround() {
369 if (isCompatible(9)) {
370 return false;
371 }
372 if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9000") ||
373 android.os.Build.DEVICE.toUpperCase().startsWith("GT-P1000")) {
374 return true;
375 }
376 return false;
377 }
378
379 private static boolean needWebRTCImplementation() {
380 if (android.os.Build.DEVICE.toLowerCase().contains("droid2")) {
381 return true;
382 }
383 if (android.os.Build.MODEL.toLowerCase().contains("droid bionic")) {
384 return true;
385 }
386 if (android.os.Build.DEVICE.toLowerCase().contains("sunfire")) {
387 return true;
388 }
389 // Huawei Y300
390 if (android.os.Build.DEVICE.equalsIgnoreCase("U8833")) {
391 return true;
392 }
393 return false;
394 }
395
396 public static boolean shouldSetupAudioBeforeInit() {
397 // Setup for GT / GS samsung devices.
398 if (android.os.Build.DEVICE.toLowerCase().startsWith("gt-")
399 || android.os.Build.PRODUCT.toLowerCase().startsWith("gt-")) {
400 return true;
401 }
402 return false;
403 }
404
405 private static boolean shouldFocusAudio() {
406 /* HTC One X */
407 if (android.os.Build.DEVICE.toLowerCase().startsWith("endeavoru") ||
408 android.os.Build.DEVICE.toLowerCase().startsWith("evita")) {
409 return false;
410 }
411
412 if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-P7510") && isCompatible(15)) {
413 return false;
414 }
415 return true;
416 }
417
418// private static int getDefaultAudioImplementation() {
419// // Acer A510
420// if (android.os.Build.DEVICE.toLowerCase().startsWith("picasso")) {
421// return SipConfigManager.AUDIO_IMPLEMENTATION_JAVA;
422// }
423// if (Compatibility.isCompatible(11)) {
424// return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
425// }
426// if (android.os.Build.DEVICE.equalsIgnoreCase("ST25i") && Compatibility.isCompatible(10)) {
427// return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
428// }
429// if (android.os.Build.DEVICE.equalsIgnoreCase("u8510") && Compatibility.isCompatible(10)) {
430// return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
431// }
432// return SipConfigManager.AUDIO_IMPLEMENTATION_JAVA;
433// }
434
435
436
437 public static boolean useFlipAnimation() {
438 if (android.os.Build.BRAND.equalsIgnoreCase("archos")
439 && android.os.Build.DEVICE.equalsIgnoreCase("g7a")) {
440 return false;
441 }
442 return true;
443 }
444
445
446 public static Intent getContactPhoneIntent() {
447 Intent intent = new Intent(Intent.ACTION_PICK);
448 /*
449 * intent.setAction(Intent.ACTION_GET_CONTENT);
450 * intent.setType(Contacts.Phones.CONTENT_ITEM_TYPE);
451 */
452 if (isCompatible(5)) {
453 // Don't use constant to allow backward compat simply
454 intent.setData(Uri.parse("content://com.android.contacts/contacts"));
455 } else {
456 // Fallback for android 4
457 intent.setData(Contacts.People.CONTENT_URI);
458 }
459
460 return intent;
461
462 }
463
464
465 public static boolean isTabletScreen(Context ctxt) {
466 boolean isTablet = false;
467 if (!isCompatible(4)) {
468 return false;
469 }
470 Configuration cfg = ctxt.getResources().getConfiguration();
471 int screenLayoutVal = 0;
472 try {
473 Field f = Configuration.class.getDeclaredField("screenLayout");
474 screenLayoutVal = (Integer) f.get(cfg);
475 } catch (Exception e) {
476 return false;
477 }
478 int screenLayout = (screenLayoutVal & 0xF);
479 // 0xF = SCREENLAYOUT_SIZE_MASK but avoid 1.5 incompat doing that
480 if (screenLayout == 0x3 || screenLayout == 0x4) {
481 // 0x3 = SCREENLAYOUT_SIZE_LARGE but avoid 1.5 incompat doing that
482 // 0x4 = SCREENLAYOUT_SIZE_XLARGE but avoid 1.5 incompat doing that
483 isTablet = true;
484 }
485
486 return isTablet;
487 }
488
489 public static int getHomeMenuId() {
490 return 0x0102002c;
491 // return android.R.id.home;
492 }
493
494 public static boolean isInstalledOnSdCard(Context context) {
495 // check for API level 8 and higher
496 if (Compatibility.isCompatible(8)) {
497 PackageManager pm = context.getPackageManager();
498 try {
499 PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
500 ApplicationInfo ai = pi.applicationInfo;
501 return (ai.flags & 0x00040000 /*
502 * ApplicationInfo.
503 * FLAG_EXTERNAL_STORAGE
504 */) == 0x00040000 /*
505 * ApplicationInfo.
506 * FLAG_EXTERNAL_STORAGE
507 */;
508 } catch (NameNotFoundException e) {
509 // ignore
510 }
511 }
512
513 // check for API level 7 - check files dir
514 try {
515 String filesDir = context.getFilesDir().getAbsolutePath();
516 if (filesDir.startsWith("/data/")) {
517 return false;
518 } else if (filesDir.contains(Environment.getExternalStorageDirectory().getPath())) {
519 return true;
520 }
521 } catch (Throwable e) {
522 // ignore
523 }
524
525 return false;
526 }
527
528}