/*
* Funambol is a mobile platform developed by Funambol, Inc.
* Copyright (C) 2003 - 2008 Funambol, Inc.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
* WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* 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 Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*
* You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
* 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License version 3.
*
* In accordance with Section 7(b) of the GNU Affero General Public License
* version 3, these Appropriate Legal Notices must retain the display of the
* "Powered by Funambol" logo. If the display of the logo is not reasonably
* feasible for technical reasons, the Appropriate Legal Notices must display
* the words "Powered by Funambol".
*/
package com.funambol.util;
import java.util.Enumeration;
import javax.microedition.io.file.FileSystemRegistry;
import net.rim.device.api.servicebook.ServiceBook;
import net.rim.device.api.servicebook.ServiceRecord;
import net.rim.device.api.system.ApplicationDescriptor;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.system.CoverageInfo;
import net.rim.device.api.system.DeviceInfo;
import net.rim.device.api.system.RadioInfo;
/**
* This class is a wrapper for J2me Funambol Common API. It provides
* informations about Blackberry devices configurations and allow to access some
* system properties that are peculiar of Blackberry devices only. For this
* reason this class has only been implemented into the Blackberry devices
* platform dependent module.
*/
public class BlackberryUtils {
private static final String TAG_LOG = "BlackberryUtils";
private static final String COVERAGE_CARRIER = "Carrier full Coverage";
private static final String COVERAGE_MDS = "BES coverage";
private static final String COVERAGE_NONE = "No coverage";
private static final String NOT_SUPPORTED_WAF = "Not supported by the device";
private static String osVersion = null;
/**
* Access the net.rim.device.api.system.DeviceInfo class in order to
* understand if the running system is a simulator or a real device.
* @return true if the current application is running on a Blackberry
* simulator, false otherwise
*/
public static boolean isSimulator() {
return DeviceInfo.isSimulator();
}
/**
* Give the information about the presence o a wifi bearer on the device
* @return true if the wifi communication interface bearer is supported by
* the device, false otherwise
*/
protected static boolean isWifiAvailable() {
Log.info(TAG_LOG, "Checking WIFI Availability");
boolean isWifiEnabled;
if (RadioInfo.areWAFsSupported(RadioInfo.WAF_WLAN)) {
Log.info(TAG_LOG, "WIFI Supported");
isWifiEnabled = true;
} else {
Log.info(TAG_LOG, "WIFI NOT Supported");
isWifiEnabled = false;
}
return isWifiEnabled;
}
/**
* Give information about the presence of active wifi connections.
* @return true if the device is connected to a wifi network with its wifi
* bearer, false otherwise
*/
protected static boolean isWifiActive() {
Log.info(TAG_LOG, "Checking WIFI Availability");
int active = RadioInfo.getActiveWAFs();
int wifi = RadioInfo.WAF_WLAN;
Log.debug(TAG_LOG, "Active WAFs Found: " + active);
Log.debug(TAG_LOG, "WIFI WAF DEFINITION: " + wifi);
return active >= wifi;
}
protected static boolean isWapGprsDataBearerOffline() {
return RadioInfo.getState()==RadioInfo.STATE_OFF ||
RadioInfo.getSignalLevel() == RadioInfo.LEVEL_NO_COVERAGE;
}
public static String getNetworkCoverageReport() {
StringBuffer sb = new StringBuffer();
sb.append("\nWireless Access Families:");
sb.append("\n3GPP: " + getNetworkCoverage(RadioInfo.WAF_3GPP));
sb.append("\nCDMA: " + getNetworkCoverage(RadioInfo.WAF_CDMA));
sb.append("\nWLAN: " + getNetworkCoverage(RadioInfo.WAF_WLAN));
sb.append("\nCDMA: " + getNetworkCoverage(RadioInfo.NETWORK_CDMA));
sb.append("\nBands:");
sb.append("\nCDMA_800: " + getNetworkCoverage(RadioInfo.BAND_CDMA_800));
sb.append("\nCDMA_1900: " + getNetworkCoverage(RadioInfo.BAND_CDMA_1900));
sb.append("\nNetworks:");
sb.append("\n802_11: " + getNetworkCoverage(RadioInfo.NETWORK_802_11));
sb.append("\nGPRS: " + getNetworkCoverage(RadioInfo.NETWORK_GPRS));
sb.append("\nNetwork services:");
sb.append("\nVOICE: " + getNetworkCoverage(RadioInfo.NETWORK_SERVICE_VOICE));
sb.append("\nUMTS: " + getNetworkCoverage(RadioInfo.NETWORK_SERVICE_UMTS));
sb.append("\nEDGE: " + getNetworkCoverage(RadioInfo.NETWORK_SERVICE_EDGE));
return sb.toString();
}
private static String getNetworkCoverage(int networkType) {
if (RadioInfo.areWAFsSupported(networkType)) {
int status = CoverageInfo.getCoverageStatus(networkType, false);
switch (status) {
case CoverageInfo.COVERAGE_CARRIER:
return COVERAGE_CARRIER;
case CoverageInfo.COVERAGE_MDS:
return COVERAGE_MDS;
case CoverageInfo.COVERAGE_NONE:
return COVERAGE_NONE;
default:
break;
}
}
return NOT_SUPPORTED_WAF;
}
/**
* Validate the given ServiceRecord entry: in order to be validated it must
* be a WAP or WAP2 transport entry
* @param sr is the ServiceRecord to be checked
* @return true if
*/
public static boolean isWapTransportServiceRecord(ServiceRecord sr) {
//TODO: use a table to store this data
return (
// wind, tim & US
(StringUtil.equalsIgnoreCase(sr.getCid(), "WPTCP") && StringUtil.equalsIgnoreCase(sr.getUid(), "WAP2 trans")) ||
// Vodafone it
(StringUtil.equalsIgnoreCase(sr.getCid(), "WAP") && StringUtil.equalsIgnoreCase(sr.getUid(), "vfit WAPtrans")));
}
/**
* Retrieves the WAP/WAP2 Transport APN from service book
* @return the Stirng formatted WAP/WAP2 Transport APN. This entry is
* unique for every ServiceBook.
*/
public static String getServiceBookWapTransportApn() {
//get only active service records
ServiceBook sb = ServiceBook.getSB();
ServiceRecord[] records = sb.findRecordsByType(ServiceRecord.SRT_ACTIVE);
String apn = null;
//Obtain WAP2 ServiceBook Record
for (int i = 0; i <records.length; i++) {
//get the record
ServiceRecord sr = records[i];
//check if CID is WPTCP and UID. UID could be different per carrier.
//TODO: We could build a list.
if (BlackberryUtils.isWapTransportServiceRecord(sr)) {
apn = records[i].getAPN();
}
}
return apn;
}
/**
* Retrieves only ACTIVE ServiceRecords (WAP2 type)from the native device's
* ServiceBook checking if their CID is WPTCP and UID
* @return String[] with the active APN found into the device's ServiceBook
*/
public static String[] getAllActiveServiceBookAPNs() {
ServiceBook sb = ServiceBook.getSB();
ServiceRecord[] records = sb.findRecordsByType(ServiceRecord.SRT_ACTIVE);
String[] apn = new String[records.length];
//Retrieve "WAP2" ServiceBook Record
for (int i = 0; i < records.length; i++) {
//get the record
ServiceRecord sr = records[i];
//check if CID is WPTCP and UID. UID can be different
//per carrier. We could build a list.
apn[i] = sr.getAPN();
}
return apn;
}
/**
* Get the options to use the list of APN included into the device
* ServiceBook
* @return a string that should be added to the url parameters
*/
public static String getServiceBookOptions() {
ServiceBook sb = ServiceBook.getSB();
ServiceRecord[] records = sb.findRecordsByType(ServiceRecord.SRT_ACTIVE);
//Obtain WAP2 ServiceBook Record
for (int i = 0; i < records.length; i++) {
//get the record
ServiceRecord sr = records[i];
//check if CID is WPTCP and UID.
//UID could be different per carrier.
//TODO - We could build a list.
if (StringUtil.equalsIgnoreCase(sr.getCid(), "WPTCP") &&
StringUtil.equalsIgnoreCase(sr.getUid(), "WAP2 trans")) {
if (records[i].getAPN() != null) {
return ";ConnectionUID=" + records[i].getUid();
}
}
}
return "";
}
/**
* Give global information about the data connection bearer activity
* @return true if there is an active bearer including the check for
* WIFI and WAP/GPRS bearer
*/
public static boolean isDataConnectionAvailable() {
boolean ret =
(isWifiAvailable()&&isWifiActive())||
!isWapGprsDataBearerOffline();
Log.debug(TAG_LOG, "Data connection availability: " + ret);
return ret;
}
/**
* Ask the system if the device has an SDCard inserted
* @return boolean true if the SDCard is inserted, false otherwise
*/
public static boolean isSDCardInserted() {
String root = null;
Enumeration e = FileSystemRegistry.listRoots();
while (e.hasMoreElements()) {
root = (String) e.nextElement();
if(StringUtil.equalsIgnoreCase(root, "sdcard/")) {
//device has a microSD inserted
return true;
}
}
//device has NOT a microSD inserted
return false;
}
public static String getOSVersion() {
if(osVersion == null) {
final ApplicationDescriptor[] appDes = ApplicationManager.getApplicationManager()
.getVisibleApplications();
String version = "Unknown";
for (int i = appDes.length - 1; i >= 0; --i) {
if (appDes[i].getModuleName().equals("net_rim_bb_ribbon_app")) {
version = appDes[i].getVersion();
break;
}
}
osVersion = version;
}
return osVersion;
}
public static String[] getSplittedOSVersion() {
Log.trace(TAG_LOG, "getOSVersion");
String os = getOSVersion();
Log.trace(TAG_LOG, "OS version string is: " + os);
if (os == null) {
return new String[0];
}
String[] tokens = StringUtil.split(os, ".");
for(int i=0;i<tokens.length;++i) {
Log.trace(TAG_LOG, "Ver["+i+"]=" + tokens[i]);
}
return tokens;
}
/**
* check OS version
* @param handled OS
* @param high x in x.y.z
* @param mid y in x.y.z
* @param low z in x.y.z
* @return true if OS >= high.mid.low
*/
public static boolean checkOS(String os, int high, int mid, int low)
{
if (os == null || os.length() == 0) {
os = getOSVersion();
}
if (os == null || !(os.length() > 3)) {
return false;
}
try {
final int major = Integer.valueOf(os.substring(0, 1)).intValue();
final int middle = Integer.valueOf(os.substring(2, 3)).intValue();
int minor = 0;
if (os.length() > 4) {
minor = Integer.valueOf(os.substring(4, 5)).intValue();
}
boolean gte = (
(major > high)
||
(major == high && middle > mid)
||
(major == high && middle == mid && minor >= low)
);
return gte;
} catch (Exception e) {
Log.error(TAG_LOG, "Cannot check OS version: " + os, e);
return false;
}
}
/**
* Returns true iff the device has a dedicated key to open the menu. The
* implementation is based on the device model and it works for the models
* currently supported by our APIs (>= 4.2.1)
*/
public static boolean hasDedicatedMenuKey() {
String deviceName = DeviceInfo.getDeviceName();
if (deviceName.startsWith("7130") ||
deviceName.startsWith("8700") ||
deviceName.startsWith("8703") ||
deviceName.startsWith("8705") ||
deviceName.startsWith("8707")) {
return false;
} else {
return true;
}
}
public static boolean isBISEmailAvailable() {
ServiceBook sb = ServiceBook.getSB();
ServiceRecord[] srs = sb.findRecordsByCid("CMIME");
boolean hasEmailConfig = ( srs != null && srs.length > 0 );
return hasEmailConfig;
}
}