package com.android.contacts.ui; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.accounts.Account; import android.app.ProgressDialog; import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.content.OperationApplicationException; import android.database.Cursor; import android.net.Uri; import android.os.RemoteException; import android.os.ServiceManager; import android.provider.ContactsContract; import android.provider.Settings; import android.provider.ContactsContract.CommonDataKinds.Email; import android.provider.ContactsContract.CommonDataKinds.GroupMembership; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.Groups; import android.provider.ContactsContract.RawContacts; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; import android.widget.Toast; import com.android.contacts.PinYin; import com.android.contacts.R; import com.android.contacts.RecentCallsListActivity; import com.android.contacts.util.CommonUtil; import com.android.contacts.util.Config; import com.android.contacts.util.Constants; import com.android.internal.telephony.AdnRecord; import com.android.internal.telephony.EncodeException; import com.android.internal.telephony.GsmAlphabet; import com.android.internal.telephony.IIccPhoneBook; import com.android.internal.telephony.IccConstants; import com.android.internal.telephony.PhoneFactory; public class SimUtils { private static final String LOG_TAG = "SimUtils"; protected static final int NAME_COLUMN = 0; protected static final int NUMBER_COLUMN = 1; protected static final int EMAILS_COLUMN = 2; private static final String ACCOUNT_TYPE_GOOGLE = "com.google"; private static final String GOOGLE_MY_CONTACTS_GROUP = "System Group: My Contacts"; private static final ContentValues sEmptyContentValues = new ContentValues(); private static final int [] SIM_NAME_LENGTH = { 0, 0}; private static final int[] SIM_LENGTH = { -1, -1 }; private static final int[] USIM_EMAIL_LENGTH = {0, 0}; public static final Uri SIM_URI = Uri.parse("content://icc/adn"); public static final Uri SIM1_URI = Uri.parse("content://icc0/adn"); public static final Uri SIM2_URI = Uri.parse("content://icc1/adn"); private SimUtils() { }; /** * show toast. * * @param context * @param message */ public static void showToast(Context context, String message) { Toast.makeText(context, message, Toast.LENGTH_LONG).show(); } /* * @param context * @param uri * @param ArrayList<ContactEntity> */ public static void querySimContact(Context context, Uri uri, ArrayList<HashMap<String, String>> simContactsList) { Cursor cur = null; String[] projection = new String[] { "name", "number", "anr", "email" }; try { TelephonyManager t = (TelephonyManager) context.getSystemService(PhoneFactory .getServiceName(Context.TELEPHONY_SERVICE, 0)); TelephonyManager t2 = (TelephonyManager) context.getSystemService(PhoneFactory .getServiceName(Context.TELEPHONY_SERVICE, 1)); final boolean hasSim1 = (null != t) ? t.hasIccCard() : false; final boolean hasSim2 = (null != t2) ? t2.hasIccCard() : false; // add sim card state judge by phone_03 start boolean isStandby1 = Settings.System.getInt(context.getContentResolver(), PhoneFactory.getSetting(Settings.System.SIM_STANDBY, 0), 1) == 1; boolean isStandby2 = Settings.System.getInt(context.getContentResolver(), PhoneFactory.getSetting(Settings.System.SIM_STANDBY, 1), 1) == 1; // add sim card state judge by phone_03 end if (hasSim1 && isStandby1 && uri.equals(SimUtils.SIM1_URI)) { Log.i(LOG_TAG, "querySimContact : ...... query one start"); cur = context.getContentResolver().query(uri, projection, null, null, null); // modify // by // dory.zheng // for // usim Log.i(LOG_TAG, "querySimContact : ...... query one end"); if (null != cur && 0 == cur.getCount()) { cur.close(); cur = null; return; } if (null != cur && 0 < cur.getCount()) { if (cur.moveToFirst()) { do { HashMap<String, String> oneRecord = new HashMap<String, String>(); String number = cur.getString(1); if (null == number) continue; String name = (null != cur.getString(0)) ? cur.getString(0) : number; // modify by dory.zheng for usim begin String anr = cur.getString(cur.getColumnIndex("anr")); String email = cur.getString(cur.getColumnIndex("email")); // modify by dory.zheng for usim end oneRecord.put("name", name); oneRecord.put("number", number); // modify by dory.zheng for usim begin oneRecord.put("anr", anr); oneRecord.put("email", email); // modify by dory.zheng for usim end simContactsList.add(oneRecord); } while (cur.moveToNext()); cur.close(); cur = null; return; } } } if (hasSim2 && isStandby2 && uri.equals(SimUtils.SIM2_URI)) { Log.i("querySimContact :", " ...... query two start"); cur = context.getContentResolver().query(uri, projection, null, null, null); // modify // by // dory.zheng // for // usim Log.i("querySimContact :", " ...... query two start"); if (null != cur && 0 == cur.getCount()) { cur.close(); cur = null; return; } if (null != cur && 0 < cur.getCount()) { if (cur.moveToFirst()) { do { HashMap<String, String> oneRecord = new HashMap<String, String>(); String number = cur.getString(1); if (null == number) continue; String name = (null != cur.getString(0)) ? cur.getString(0) : number; // modify by dory.zheng for usim begin String anr = cur.getString(cur.getColumnIndex("anr")); String email = cur.getString(cur.getColumnIndex("email")); // modify by dory.zheng for usim end oneRecord.put("name", name); oneRecord.put("number", number); // modify by dory.zheng for usim begin oneRecord.put("anr", anr); oneRecord.put("email", email); // modify by dory.zheng for usim end simContactsList.add(oneRecord); } while (cur.moveToNext()); cur.close(); cur = null; return; } } } } catch (Exception e) { e.printStackTrace(); } finally { if (null != cur && !cur.isClosed()) { cur.close(); cur = null; } } } public static void newPhoneContact(Account account, final ContentResolver resolver, String name, String number) { final NamePhoneTypePair namePhoneTypePair = new NamePhoneTypePair(name); final String realname = namePhoneTypePair.name; final int phoneType = namePhoneTypePair.phoneType; final ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>(); ContentProviderOperation.Builder builder = ContentProviderOperation .newInsert(RawContacts.CONTENT_URI); String myGroupsId = null; if (account != null) { builder.withValue(RawContacts.ACCOUNT_NAME, account.name); builder.withValue(RawContacts.ACCOUNT_TYPE, account.type); // TODO: temporal fix for "My Groups" issue. Need to be refactored. if (ACCOUNT_TYPE_GOOGLE.equals(account.type)) { final Cursor tmpCursor = resolver.query(Groups.CONTENT_URI, new String[] { Groups.SOURCE_ID }, Groups.TITLE + "=?", new String[] { GOOGLE_MY_CONTACTS_GROUP }, null); try { if (tmpCursor != null && tmpCursor.moveToFirst()) { myGroupsId = tmpCursor.getString(0); } } finally { if (tmpCursor != null) { tmpCursor.close(); } } } } else { builder.withValues(sEmptyContentValues); } operationList.add(builder.build()); builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); builder.withValueBackReference(StructuredName.RAW_CONTACT_ID, 0); builder.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); builder.withValue(StructuredName.DISPLAY_NAME, realname); operationList.add(builder.build()); builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); builder.withValueBackReference(Phone.RAW_CONTACT_ID, 0); builder.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); builder.withValue(Phone.TYPE, phoneType); builder.withValue(Phone.NUMBER, number); builder.withValue(Data.IS_PRIMARY, 1); operationList.add(builder.build()); if (myGroupsId != null) { builder = ContentProviderOperation.newInsert(Data.CONTENT_URI); builder.withValueBackReference(GroupMembership.RAW_CONTACT_ID, 0); builder.withValue(Data.MIMETYPE, GroupMembership.CONTENT_ITEM_TYPE); builder.withValue(GroupMembership.GROUP_SOURCE_ID, myGroupsId); operationList.add(builder.build()); } try { resolver.applyBatch(ContactsContract.AUTHORITY, operationList); } catch (RemoteException e) { Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage())); } catch (OperationApplicationException e) { Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage())); } } private static class NamePhoneTypePair { final String name; final int phoneType; public NamePhoneTypePair(String nameWithPhoneType) { // Look for /W /H /M or /O at the end of the name signifying the // type int nameLen = nameWithPhoneType.length(); if (nameLen - 2 >= 0 && nameWithPhoneType.charAt(nameLen - 2) == '/') { char c = Character.toUpperCase(nameWithPhoneType.charAt(nameLen - 1)); if (c == 'W') { phoneType = Phone.TYPE_WORK; } else if (c == 'M' || c == 'O') { phoneType = Phone.TYPE_MOBILE; } else if (c == 'H') { phoneType = Phone.TYPE_HOME; } else { phoneType = Phone.TYPE_OTHER; } name = nameWithPhoneType.substring(0, nameLen - 2); } else { phoneType = Phone.TYPE_OTHER; name = nameWithPhoneType; } } } public static String changeName(String name, int phoneId) { int NmLen = getSimContactorNameLength(phoneId); while(true){ byte[] bytes = getSimRecordBytes(name); if (bytes != null && bytes.length > NmLen) { int end = name.length() > 1 ? name.length() - 1 : 0; name = name.substring(0, end); } else { break; } } return name; } public static String changeEmail(String email, int phoneId){ int emailRecordSize = getSimContactEmailLength(phoneId); byte[] bytes = getSimRecordBytes(email); while(bytes != null && bytes.length > emailRecordSize){ int end = email.length() > 1 ? email.length() - 1 : 0; email = email.substring(0, end); bytes = getSimRecordBytes(email); } return email; } /** * Get capacity of SIM card * * @param phoneId * @return */ public static int getSimCardLength(int phoneId) { if (SIM_LENGTH[phoneId] < 1) { try { IIccPhoneBook iccIpb = getIccPhoneBook(phoneId); if (iccIpb != null) { int[] sizes = iccIpb.getAdnRecordsSize(IccConstants.EF_ADN); int size = -1; if(sizes != null){ if (sizes.length == 3){ size = sizes[2]; } else if(sizes.length == 2){ size = sizes[1] / sizes[0]; } } SIM_LENGTH[phoneId] = size; } } catch (RemoteException ex) { // ignore it } catch (SecurityException ex) { // ignore it } } return SIM_LENGTH[phoneId]; } /** * Get number of contactor in Sim card * * @param context * @param phoneId * @return */ public static int getSimContactorNum(Context context, int phoneId) { Uri uri = Config.isMSMS ? SimUtils.SIM1_URI : SimUtils.SIM_URI; if (phoneId == 1) { uri = SimUtils.SIM2_URI; } Cursor cur = null; try { cur = context.getContentResolver().query(uri, new String[] { "name", "number", "anr", "email"}, null, null, null); //modify by dory.zheng for usim return null == cur ? -1 : cur.getCount(); } finally { if(cur != null){ cur.close(); cur = null; } } } /** * Get remain size in sim card * * @param context * @param phoneId * @return */ public static int getSimRemain(Context context, int phoneId) { int total = getSimCardLength(phoneId); int ContactorNum = getSimContactorNum(context, phoneId); int remain = total - ContactorNum; return remain < 0 ? -1 : remain; } public static int getSimContactorNameLength(int phoneId){ if (SIM_NAME_LENGTH[phoneId] < 1) { try { IIccPhoneBook iccIpb = getIccPhoneBook(phoneId); if (iccIpb != null) { int[] sizes = iccIpb.getAdnRecordsSize(IccConstants.EF_ADN); int size = -1; if(sizes != null){ size = sizes[0] - 14; if(size < 0){ //get length of sim contactor's Name fail return 12; } } else { return 12; } SIM_NAME_LENGTH[phoneId] = size - 1; } else { return 12; } } catch (RemoteException ex) { return 12; } catch (SecurityException ex) { return 12; } } return SIM_NAME_LENGTH[phoneId]; } private static IIccPhoneBook getIccPhoneBook(int phoneId){ return IIccPhoneBook.Stub.asInterface(ServiceManager .getService(PhoneFactory.getServiceName("simphonebook", phoneId))); } public static int getSimContactEmailLength(int phoneId){ if(USIM_EMAIL_LENGTH[phoneId] <= 0){ int[] sizes = null; IIccPhoneBook iccIpb = getIccPhoneBook(phoneId); if (iccIpb != null) { try { sizes = iccIpb.getEmailRecordsSize(); } catch (RemoteException e) { Log.e(LOG_TAG, "get email record size fial", e); } } int size = 0; if(sizes != null){ size = sizes[0] - 2; } USIM_EMAIL_LENGTH[phoneId] = size > 0 ? size : 0; } return USIM_EMAIL_LENGTH[phoneId]; } public static byte[] getSimRecordBytes(String record){ byte[] bytes = null; if (record == null) { record = ""; } try { bytes = GsmAlphabet.isAsciiStringToGsm8BitUnpackedField(record); } catch (EncodeException e) { // TODO Auto-generated catch block try { bytes = record.getBytes("utf-16be"); } catch (UnsupportedEncodingException e1) { // TODO Auto-generated catch block Log.w(LOG_TAG, "record convert byte exception : " + record,e1); } } return bytes; } public static String getDisplayNameFromPhoneNumber(String number){ if (number != null){ return number.replace(";", "W").replace(",", "P"); } else { return ""; } } /** * add by dory.zheng for splitString * * @param source * @return */ public static String[] splitString(String source) { String[] result = new String[3]; if (source == null || source.equals("")) { return result; } Integer pos; String strSource = source; Integer times = 0; //while ((pos = strSource.indexOf(AdnRecord.ANR_SPLIT_FLG)) >= 0) { while ((pos = strSource.indexOf(":")) >= 0) { result[times] = strSource.substring(0, pos); strSource = strSource.substring(pos + 1); times++; } if (strSource.length() > 0) { result[times] = strSource; } return result; } public static String getFistAnrNumber(String anr) { if (anr != null) { //String[] anrStr = anr.split(AdnRecord.ANR_SPLIT_FLG); String[] anrStr = anr.split(":"); for (String anrNumber : anrStr) { if (!TextUtils.isEmpty(anrNumber)) { return anrNumber; } } } return null; } /** * check sim card state and fdn state and and state * @param context * @param justCheckSimStateReady flag for just check sim state is ready or not * @param phoneId not -1 if phone is dual sim * @return true if sim state is ready and fdn is not edable and adn has ready, else false */ public static boolean checkSimState(Context context, boolean justCheckSimStateReady, int phoneId) { final Context ctx = context; TelephonyManager tm = null; context = null; if (-1 != phoneId) { tm = (TelephonyManager) ctx.getSystemService(PhoneFactory.getServiceName( Context.TELEPHONY_SERVICE, phoneId)); } else { tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE); } int simState = tm.getSimState(); int adnCacheState = tm.getAdnCachestate(); if (TelephonyManager.SIM_STATE_READY == simState) { Log.v(LOG_TAG, "sim ready"); if (justCheckSimStateReady) { return true; } if (CommonUtil.isFdnEnable(ctx)) { Log.d(LOG_TAG, "FDN has enable"); return false; } if (adnCacheState == Constants.ADNCACHE_STATE_NOT_READY) { Log.v(LOG_TAG, "adn cache not ready"); return false; } return true; } else { Log.v(LOG_TAG, "sim state not ready"); return false; } } }