/* * CDDL HEADER START * * The contents of this file are subject to the terms of the Common Development * and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at * src/com/vodafone360/people/VODAFONE.LICENSE.txt or * http://github.com/360/360-Engine-for-Android * See the License for the specific language governing permissions and * limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each file and * include the License file at src/com/vodafone360/people/VODAFONE.LICENSE.txt. * If applicable, add the following below this CDDL HEADER, with the fields * enclosed by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright 2010 Vodafone Sales & Services Ltd. All rights reserved. * Use is subject to license terms. */ package com.vodafone360.people.utils; import java.util.HashMap; import java.util.Map; import android.content.Context; import android.telephony.TelephonyManager; /** * The SimCard class provides utility methods to access SIM card data. */ public class SimCard { /** * Digits beyond this count will be replaced by 0. */ private static final int ANONYMISED_DIGITS = 4; /** * The Network. */ public enum Network { CH("ch", 41), // Switzerland DE("de", 49), // Germany FR("fr", 33), // France GB("gb", 44), // Great Britain IE("ie", 353), // Ireland IT("it", 39), // Italy NL("nl", 31), // Netherlands SE("se", 46), // Sweden TR("tr", 90), // Turkey TW("tw", 886), // Taiwan US("us", 1), // United States ES("es", 34), // Spain // ZA("za", 260), //Zambia/VodaCom-SA?? UNKNOWN("unknown", 0); private final String mIso; private final int mPrefix; private Network(String iso, int prefix) { mIso = iso; mPrefix = prefix; } private Network() { mIso = null; mPrefix = -1; } public String iso() { return mIso; } protected int prefix() { return mPrefix; } /*** * Returns the SimNetwork of a given ISO if known * * @param iso Country ISO value. * @return SimNetwork or SimNetwork.UNKNOWN if not found. */ public static Network getNetwork(String iso) { for (final Network network : Network.values()) { if (network.iso().equals(iso)) { return network; } } return UNKNOWN; } } /** * SIM card absent state. * @see #getSubscriberId(Context) */ public final static String SIM_CARD_ABSENT = "SimAbsent"; /** * SIM card not readable state. * @see #getSubscriberId(Context) */ public final static String SIM_CARD_NOT_READABLE = "SimNotReadable"; /** * Gets the SIM card state. * * @see TelephonyManager#getSimState() * * @param context the application context * @return the SIM card state */ public static int getState(Context context) { try { final TelephonyManager telephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); return telephonyManager.getSimState(); } catch (final Exception e) { LogUtils.logE("SimCard.getState() - Exception:", e); } return TelephonyManager.SIM_STATE_UNKNOWN; } /** * Tells whether or not the SIM card is present. * * @param context the * @return true if the SIM is ready, false otherwise (not ready or absent) */ public static boolean isSimReady(Context context) { return getState(context) == TelephonyManager.SIM_STATE_READY; } /** * Gets the Subscriber Id. * * @see SIM_CARD_NOT_READABLE * @see SIM_CARD_ABSENT * * @param databaseHelper the DatabaseHelper * @return the Subscriber Id or SIM_CARD_ABSENT or SIM_CARD_NOT_READABLE */ public static String getSubscriberId(Context context) { if (getState(context) == TelephonyManager.SIM_STATE_ABSENT) { return SIM_CARD_ABSENT; } else { try { final TelephonyManager mTelephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); return mTelephonyManager.getSubscriberId(); } catch (final Exception e) { LogUtils.logE("SimCard.getSubscriberId() - Exception: "+e); } } return SIM_CARD_NOT_READABLE; } /** * Logs a MSISDN validation failure event to Flurry. * * @param context Android context. * @param workflow Given work flow (either sign in or sign up). * @param status Current status string. * @param enteredMsisdn User provided MSISDN. */ public static void logMsisdnValidationFail(Context context, String workflow, String status, String enteredMsisdn) { final TelephonyManager telephonyManager = (TelephonyManager)context .getSystemService(Context.TELEPHONY_SERVICE); final Map<String, String> map = new HashMap<String, String>(); map.put("NetworkCountryIso", telephonyManager.getNetworkCountryIso()); map.put("NetworkOperator", telephonyManager.getNetworkOperator()); map.put("NetworkOperatorName", telephonyManager.getNetworkOperatorName()); map.put("SimCountryIso", telephonyManager.getSimCountryIso()); map.put("SimOperator", telephonyManager.getSimOperator()); map.put("SimOperatorName", telephonyManager.getSimOperatorName()); map.put("AnonymisedMsisdn", getAnonymisedMsisdn(telephonyManager.getLine1Number())); map.put("AnonymisedEntereddMsisdn", getAnonymisedMsisdn(enteredMsisdn)); map.put("Workflow", workflow); map.put("Error", status); // FlurryAgent.onEvent("EnterMobileNumberActivity_FAIL", map); LogUtils.logV("SimUtils.logMsisdnValidationFail() enteredMsisdn[" + enteredMsisdn + "]"); } /** * Retrieves the full international MSISDN number from the SIM or NULL if * unavailable or unsure. Note: This functionality is currently part of * SignupEnterMobileNumberActivity so anonymised data can be sent back to * Flurry, in order to verify this program logic on multiple SIMs. * * @param context Android Context * @return Full international MSISDN, or NULL if unsure of conversion. */ public static String getFullMsisdn(Context context) { final TelephonyManager telephonyManager = (TelephonyManager)context .getSystemService(Context.TELEPHONY_SERVICE); final String rawMsisdn = telephonyManager.getLine1Number(); final String verifyedMsisdn = getVerifyedMsisdn(rawMsisdn, telephonyManager .getNetworkCountryIso(), telephonyManager.getNetworkOperatorName(), telephonyManager.getNetworkOperator()); final Map<String, String> map = new HashMap<String, String>(); map.put("NetworkCountryIso", telephonyManager.getNetworkCountryIso()); map.put("NetworkOperator", telephonyManager.getNetworkOperator()); map.put("NetworkOperatorName", telephonyManager.getNetworkOperatorName()); map.put("SimCountryIso", telephonyManager.getSimCountryIso()); map.put("SimOperator", telephonyManager.getSimOperator()); map.put("SimOperatorName", telephonyManager.getSimOperatorName()); map.put("AnonymisedMsisdn", getAnonymisedMsisdn(rawMsisdn)); map.put("AnonymisedVerifyedMsisdn", getAnonymisedMsisdn(verifyedMsisdn)); // FlurryAgent.onEvent("EnterMobileNumberActivity", map); return verifyedMsisdn; } /*** * Convert raw MSISDN to a verified MSISDN with country code. * * @param rawMsisdn Unverified MSISDN. * @param countryIso Country ISO value from the SIM. * @param networkOperatorName Network operator name value from the SIM. * @param networkOperator Network operator value from the SIM. * @return Verified MSISDN, or "" if NULL or unsure of country code. */ public static String getVerifyedMsisdn(String rawMsisdn, String countryIso, String networkOperatorName, String networkOperator) { if (rawMsisdn == null || rawMsisdn.trim().equals("")) { // Reject any NULL or empty values. return ""; } else if (rawMsisdn.substring(0, 1).equals("+")) { // Accept any values starting with "+". return rawMsisdn; // the MTS Russian SIM may have just "8" as a rawNsisdn string } else if (rawMsisdn.length() > 1 && (rawMsisdn.substring(0, 2).equals("00"))) { // Accept any values starting with "00", but at +. return "+" + rawMsisdn.substring(2); } else if (countryIso != null && !countryIso.trim().equals("")) { // Filter known values: try { final Network simNetwork = Network.getNetwork(countryIso); if (simNetwork != Network.UNKNOWN) { return "+" + smartAdd(simNetwork.prefix() + "", dropZero(rawMsisdn)); } else { // Rejected return ""; } } catch (final NumberFormatException e) { // Rejected return ""; } } else { // Rejected return ""; } } /*** * Concatenate the "start" value with the "end" value, except where the * "start" value is already in place. * * @param start First part of String. * @param end Last part of String. * @return "start" + "end". */ private static String smartAdd(String start, String end) { if (end == null || end.trim().equals("")) { return ""; } else if (end.startsWith(start)) { return end; } else { return start + end; } } /*** * Remove the preceding zero, if present. * * @param rawMsisdn Number to alter. * @return Number without the zero. */ private static String dropZero(String rawMsisdn) { if (rawMsisdn == null || rawMsisdn.trim().equals("")) { return ""; } else if (rawMsisdn.startsWith("0")) { return rawMsisdn.substring(1); } else { return rawMsisdn; } } /*** * Converts an identifiable MSISDN value to something that can be sent via a * third party. E.g. "+49123456789" becomes "+49100000000". * * @param input Private MSISDN. * @return Anonymous MSISDN. */ public static String getAnonymisedMsisdn(String input) { if (input == null || input.trim().equals("")) { return ""; } else { final int length = input.length(); final StringBuffer result = new StringBuffer(); for (int i = 0; i < length; i++) { if (i < ANONYMISED_DIGITS) { result.append(input.charAt(i)); } else { result.append("0"); } } return result.toString(); } } }