* #32381: added proper screenlock (based on CSipSimple mechanism)
diff --git a/src/org/sflphone/utils/Compatibility.java b/src/org/sflphone/utils/Compatibility.java
new file mode 100644
index 0000000..7a4a800
--- /dev/null
+++ b/src/org/sflphone/utils/Compatibility.java
@@ -0,0 +1,528 @@
+/*
+ * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr)
+ * Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
+ *
+ * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Additional permission under GNU GPL version 3 section 7:
+ *
+ * If you modify this program, or any covered work, by linking or
+ * combining it with the OpenSSL project's OpenSSL library (or a
+ * modified version of that library), containing parts covered by the
+ * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ * grants you additional permission to convey the resulting work.
+ * Corresponding Source for a non-source form of such a combination
+ * shall include the source code for the parts of OpenSSL used as well
+ * as that of the covered work.
+ */
+
+package org.sflphone.utils;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.lang.reflect.Field;
+import java.util.regex.Pattern;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Configuration;
+import android.media.AudioManager;
+import android.media.MediaRecorder.AudioSource;
+import android.net.Uri;
+import android.os.Environment;
+import android.provider.Contacts;
+import android.util.Log;
+
+@SuppressWarnings("deprecation")
+public final class Compatibility {
+
+ private Compatibility() {
+ }
+
+ private static final String THIS_FILE = "Compat";
+
+ public static int getApiLevel() {
+ return android.os.Build.VERSION.SDK_INT;
+ }
+
+ public static boolean isCompatible(int apiLevel) {
+ return android.os.Build.VERSION.SDK_INT >= apiLevel;
+ }
+
+ /**
+ * Get the stream id for in call track. Can differ on some devices. Current
+ * device for which it's different :
+ *
+ * @return
+ */
+ public static int getInCallStream(boolean requestBluetooth) {
+ /* Archos 5IT */
+ if (android.os.Build.BRAND.equalsIgnoreCase("archos")
+ && android.os.Build.DEVICE.equalsIgnoreCase("g7a")) {
+ // Since archos has no voice call capabilities, voice call stream is
+ // not implemented
+ // So we have to choose the good stream tag, which is by default
+ // falled back to music
+ return AudioManager.STREAM_MUSIC;
+ }
+ if (requestBluetooth) {
+ return 6; /* STREAM_BLUETOOTH_SCO -- Thx @Stefan for the contrib */
+ }
+
+ // return AudioManager.STREAM_MUSIC;
+ return AudioManager.STREAM_VOICE_CALL;
+ }
+
+ public static boolean shouldUseRoutingApi() {
+ Log.d(THIS_FILE, "Current device " + android.os.Build.BRAND + " - "
+ + android.os.Build.DEVICE);
+
+ // HTC evo 4G
+ if (android.os.Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
+ return true;
+ }
+
+ // ZTE joe
+ if (android.os.Build.DEVICE.equalsIgnoreCase("joe")) {
+ return true;
+ }
+
+ // Samsung GT-S5830
+ if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-S")) {
+ return true;
+ }
+
+ if (!isCompatible(4)) {
+ // If android 1.5, force routing api use
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static boolean shouldUseModeApi() {
+
+ // ZTE blade et joe
+ if (android.os.Build.DEVICE.equalsIgnoreCase("blade")
+ || android.os.Build.DEVICE.equalsIgnoreCase("joe")) {
+ return true;
+ }
+ // Samsung GT-S5360 GT-S5830 GT-S6102 ... probably all..
+ if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-") ||
+ android.os.Build.PRODUCT.toUpperCase().startsWith("GT-") ||
+ android.os.Build.DEVICE.toUpperCase().startsWith("YP-")) {
+ return true;
+ }
+
+ // HTC evo 4G
+ if (android.os.Build.PRODUCT.equalsIgnoreCase("htc_supersonic")) {
+ return true;
+ }
+ // LG P500, Optimus V
+ if (android.os.Build.DEVICE.toLowerCase().startsWith("thunder")) {
+ return true;
+ }
+ // LG-E720(b)
+ if (android.os.Build.MODEL.toUpperCase().startsWith("LG-E720")
+ && !Compatibility.isCompatible(9)) {
+ return true;
+ }
+ // LG-LS840
+ if (android.os.Build.DEVICE.toLowerCase().startsWith("cayman")) {
+ return true;
+ }
+
+ // Huawei
+ if (android.os.Build.DEVICE.equalsIgnoreCase("U8150") ||
+ android.os.Build.DEVICE.equalsIgnoreCase("U8110") ||
+ android.os.Build.DEVICE.equalsIgnoreCase("U8120") ||
+ android.os.Build.DEVICE.equalsIgnoreCase("U8100") ||
+ android.os.Build.PRODUCT.equalsIgnoreCase("U8655")) {
+ return true;
+ }
+
+ // Moto defy mini
+ if (android.os.Build.MODEL.equalsIgnoreCase("XT320")) {
+ return true;
+ }
+
+ // Alcatel
+ if (android.os.Build.DEVICE.toUpperCase().startsWith("ONE_TOUCH_993D")) {
+ return true;
+ }
+
+ // N4
+ if (android.os.Build.DEVICE.toUpperCase().startsWith("MAKO")) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public static String guessInCallMode() {
+ // New api for 2.3.3 is not available on galaxy S II :(
+ if (!isCompatible(11) && android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9100")) {
+ return Integer.toString(AudioManager.MODE_NORMAL);
+ }
+
+ if (android.os.Build.BRAND.equalsIgnoreCase("sdg") || isCompatible(10)) {
+ // Note that in APIs this is only available from level 11.
+ return "3";
+ }
+ if (android.os.Build.DEVICE.equalsIgnoreCase("blade")) {
+ return Integer.toString(AudioManager.MODE_IN_CALL);
+ }
+
+ if (!isCompatible(5)) {
+ return Integer.toString(AudioManager.MODE_IN_CALL);
+ }
+
+ return Integer.toString(AudioManager.MODE_NORMAL);
+ }
+
+ public static String getDefaultMicroSource() {
+ // Except for galaxy S II :(
+ if (!isCompatible(11) && android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9100")) {
+ return Integer.toString(AudioSource.MIC);
+ }
+
+ if (isCompatible(10)) {
+ // Note that in APIs this is only available from level 11.
+ // VOICE_COMMUNICATION
+ return Integer.toString(0x7);
+ }
+ /*
+ * Too risky in terms of regressions else if (isCompatible(4)) { //
+ * VOICE_CALL return 0x4; }
+ */
+ /*
+ * if(android.os.Build.MODEL.equalsIgnoreCase("X10i")) { // VOICE_CALL
+ * return Integer.toString(0x4); }
+ */
+ /*
+ * Not relevant anymore, atrix I tested sounds fine with that
+ * if(android.os.Build.DEVICE.equalsIgnoreCase("olympus")) { //Motorola
+ * atrix bug // CAMCORDER return Integer.toString(0x5); }
+ */
+
+ return Integer.toString(AudioSource.DEFAULT);
+ }
+
+ public static String getDefaultFrequency() {
+ if (android.os.Build.DEVICE.equalsIgnoreCase("olympus")) {
+ // Atrix bug
+ return "32000";
+ }
+ if (android.os.Build.DEVICE.toUpperCase().equals("GT-P1010")) {
+ // Galaxy tab see issue 932
+ return "32000";
+ }
+
+ return isCompatible(4) ? "16000" : "8000";
+ }
+
+ public static String getCpuAbi() {
+ if (isCompatible(4)) {
+ Field field;
+ try {
+ field = android.os.Build.class.getField("CPU_ABI");
+ return field.get(null).toString();
+ } catch (Exception e) {
+ Log.w(THIS_FILE, "Announce to be android 1.6 but no CPU ABI field", e);
+ }
+
+ }
+ return "armeabi";
+ }
+
+ public final static int getNumCores() {
+ // Private Class to display only CPU devices in the directory listing
+ class CpuFilter implements FileFilter {
+ @Override
+ public boolean accept(File pathname) {
+ // Check if filename is "cpu", followed by a single digit number
+ if (Pattern.matches("cpu[0-9]", pathname.getName())) {
+ return true;
+ }
+ return false;
+ }
+ }
+ try {
+ // Get directory containing CPU info
+ File dir = new File("/sys/devices/system/cpu/");
+ // Filter to only list the devices we care about
+ File[] files = dir.listFiles(new CpuFilter());
+ // Return the number of cores (virtual CPU devices)
+ return files.length;
+ } catch (Exception e) {
+ return Runtime.getRuntime().availableProcessors();
+ }
+ }
+
+ private static boolean needPspWorkaround() {
+ // New api for 2.3 does not work on Incredible S
+ if (android.os.Build.DEVICE.equalsIgnoreCase("vivo")) {
+ return true;
+ }
+
+ // New API for android 2.3 should be able to manage this but do only for
+ // honeycomb cause seems not correctly supported by all yet
+ if (isCompatible(11)) {
+ return false;
+ }
+
+ // All htc except....
+ if (android.os.Build.PRODUCT.toLowerCase().startsWith("htc")
+ || android.os.Build.BRAND.toLowerCase().startsWith("htc")
+ || android.os.Build.PRODUCT.toLowerCase().equalsIgnoreCase("inc") /*
+ * For
+ * Incredible
+ */
+ || android.os.Build.DEVICE.equalsIgnoreCase("passion") /* N1 */) {
+ if (android.os.Build.DEVICE.equalsIgnoreCase("hero") /* HTC HERO */
+ || android.os.Build.DEVICE.equalsIgnoreCase("magic") /*
+ * Magic
+ * Aka
+ * Dev
+ * G2
+ */
+ || android.os.Build.DEVICE.equalsIgnoreCase("tatoo") /* Tatoo */
+ || android.os.Build.DEVICE.equalsIgnoreCase("dream") /*
+ * Dream
+ * Aka
+ * Dev
+ * G1
+ */
+ || android.os.Build.DEVICE.equalsIgnoreCase("legend") /* Legend */
+
+ ) {
+ return false;
+ }
+
+ // Older than 2.3 has no chance to have the new full perf wifi mode
+ // working since does not exists
+ if (!isCompatible(9)) {
+ return true;
+ } else {
+ // N1 is fine with that
+ if (android.os.Build.DEVICE.equalsIgnoreCase("passion")) {
+ return false;
+ }
+ return true;
+ }
+
+ }
+ // Dell streak
+ if (android.os.Build.BRAND.toLowerCase().startsWith("dell") &&
+ android.os.Build.DEVICE.equalsIgnoreCase("streak")) {
+ return true;
+ }
+ // Motorola milestone 1 and 2 & motorola droid & defy not under 2.3
+ if ((android.os.Build.DEVICE.toLowerCase().contains("milestone2") ||
+ android.os.Build.BOARD.toLowerCase().contains("sholes") ||
+ android.os.Build.PRODUCT.toLowerCase().contains("sholes") ||
+ android.os.Build.DEVICE.equalsIgnoreCase("olympus") ||
+ android.os.Build.DEVICE.toLowerCase().contains("umts_jordan")) && !isCompatible(9)) {
+ return true;
+ }
+ // Moto defy mini
+ if (android.os.Build.MODEL.equalsIgnoreCase("XT320")) {
+ return true;
+ }
+
+ // Alcatel ONE touch
+ if (android.os.Build.DEVICE.startsWith("one_touch_990")) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private static boolean needToneWorkaround() {
+ if (android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i5800") ||
+ android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i5801") ||
+ android.os.Build.PRODUCT.toLowerCase().startsWith("gt-i9003")) {
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean needSGSWorkaround() {
+ if (isCompatible(9)) {
+ return false;
+ }
+ if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-I9000") ||
+ android.os.Build.DEVICE.toUpperCase().startsWith("GT-P1000")) {
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean needWebRTCImplementation() {
+ if (android.os.Build.DEVICE.toLowerCase().contains("droid2")) {
+ return true;
+ }
+ if (android.os.Build.MODEL.toLowerCase().contains("droid bionic")) {
+ return true;
+ }
+ if (android.os.Build.DEVICE.toLowerCase().contains("sunfire")) {
+ return true;
+ }
+ // Huawei Y300
+ if (android.os.Build.DEVICE.equalsIgnoreCase("U8833")) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean shouldSetupAudioBeforeInit() {
+ // Setup for GT / GS samsung devices.
+ if (android.os.Build.DEVICE.toLowerCase().startsWith("gt-")
+ || android.os.Build.PRODUCT.toLowerCase().startsWith("gt-")) {
+ return true;
+ }
+ return false;
+ }
+
+ private static boolean shouldFocusAudio() {
+ /* HTC One X */
+ if (android.os.Build.DEVICE.toLowerCase().startsWith("endeavoru") ||
+ android.os.Build.DEVICE.toLowerCase().startsWith("evita")) {
+ return false;
+ }
+
+ if (android.os.Build.DEVICE.toUpperCase().startsWith("GT-P7510") && isCompatible(15)) {
+ return false;
+ }
+ return true;
+ }
+
+// private static int getDefaultAudioImplementation() {
+// // Acer A510
+// if (android.os.Build.DEVICE.toLowerCase().startsWith("picasso")) {
+// return SipConfigManager.AUDIO_IMPLEMENTATION_JAVA;
+// }
+// if (Compatibility.isCompatible(11)) {
+// return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
+// }
+// if (android.os.Build.DEVICE.equalsIgnoreCase("ST25i") && Compatibility.isCompatible(10)) {
+// return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
+// }
+// if (android.os.Build.DEVICE.equalsIgnoreCase("u8510") && Compatibility.isCompatible(10)) {
+// return SipConfigManager.AUDIO_IMPLEMENTATION_OPENSLES;
+// }
+// return SipConfigManager.AUDIO_IMPLEMENTATION_JAVA;
+// }
+
+
+
+ public static boolean useFlipAnimation() {
+ if (android.os.Build.BRAND.equalsIgnoreCase("archos")
+ && android.os.Build.DEVICE.equalsIgnoreCase("g7a")) {
+ return false;
+ }
+ return true;
+ }
+
+
+ public static Intent getContactPhoneIntent() {
+ Intent intent = new Intent(Intent.ACTION_PICK);
+ /*
+ * intent.setAction(Intent.ACTION_GET_CONTENT);
+ * intent.setType(Contacts.Phones.CONTENT_ITEM_TYPE);
+ */
+ if (isCompatible(5)) {
+ // Don't use constant to allow backward compat simply
+ intent.setData(Uri.parse("content://com.android.contacts/contacts"));
+ } else {
+ // Fallback for android 4
+ intent.setData(Contacts.People.CONTENT_URI);
+ }
+
+ return intent;
+
+ }
+
+
+ public static boolean isTabletScreen(Context ctxt) {
+ boolean isTablet = false;
+ if (!isCompatible(4)) {
+ return false;
+ }
+ Configuration cfg = ctxt.getResources().getConfiguration();
+ int screenLayoutVal = 0;
+ try {
+ Field f = Configuration.class.getDeclaredField("screenLayout");
+ screenLayoutVal = (Integer) f.get(cfg);
+ } catch (Exception e) {
+ return false;
+ }
+ int screenLayout = (screenLayoutVal & 0xF);
+ // 0xF = SCREENLAYOUT_SIZE_MASK but avoid 1.5 incompat doing that
+ if (screenLayout == 0x3 || screenLayout == 0x4) {
+ // 0x3 = SCREENLAYOUT_SIZE_LARGE but avoid 1.5 incompat doing that
+ // 0x4 = SCREENLAYOUT_SIZE_XLARGE but avoid 1.5 incompat doing that
+ isTablet = true;
+ }
+
+ return isTablet;
+ }
+
+ public static int getHomeMenuId() {
+ return 0x0102002c;
+ // return android.R.id.home;
+ }
+
+ public static boolean isInstalledOnSdCard(Context context) {
+ // check for API level 8 and higher
+ if (Compatibility.isCompatible(8)) {
+ PackageManager pm = context.getPackageManager();
+ try {
+ PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
+ ApplicationInfo ai = pi.applicationInfo;
+ return (ai.flags & 0x00040000 /*
+ * ApplicationInfo.
+ * FLAG_EXTERNAL_STORAGE
+ */) == 0x00040000 /*
+ * ApplicationInfo.
+ * FLAG_EXTERNAL_STORAGE
+ */;
+ } catch (NameNotFoundException e) {
+ // ignore
+ }
+ }
+
+ // check for API level 7 - check files dir
+ try {
+ String filesDir = context.getFilesDir().getAbsolutePath();
+ if (filesDir.startsWith("/data/")) {
+ return false;
+ } else if (filesDir.contains(Environment.getExternalStorageDirectory().getPath())) {
+ return true;
+ }
+ } catch (Throwable e) {
+ // ignore
+ }
+
+ return false;
+ }
+
+}
\ No newline at end of file