diff options
-rw-r--r-- | Android.mk | 2 | ||||
-rw-r--r-- | res/values-zh-rCN/strings.xml | 13 | ||||
-rw-r--r-- | res/values/strings.xml | 16 | ||||
-rw-r--r-- | src/com/android/contacts/ContactSaveService.java | 246 | ||||
-rw-r--r-- | src/com/android/contacts/activities/ContactEditorBaseActivity.java | 5 | ||||
-rw-r--r-- | src/com/android/contacts/editor/CompactRawContactsEditorView.java | 56 | ||||
-rw-r--r-- | src/com/android/contacts/editor/ContactEditorBaseFragment.java | 96 | ||||
-rw-r--r-- | src/com/android/contacts/editor/ContactEditorFragment.java | 2 | ||||
-rw-r--r-- | src/com/android/contacts/editor/ContactEditorUtils.java | 8 | ||||
-rw-r--r-- | src/com/android/contacts/editor/RawContactEditorView.java | 42 | ||||
-rw-r--r-- | src/com/android/contacts/editor/TextFieldsEditorView.java | 19 | ||||
-rw-r--r-- | src/com/android/contacts/list/ContactPickerFragment.java | 2 | ||||
-rw-r--r-- | src/com/android/contacts/list/JoinContactListAdapter.java | 15 |
13 files changed, 480 insertions, 42 deletions
diff --git a/Android.mk b/Android.mk index 8f34bb902..10178fb01 100644 --- a/Android.mk +++ b/Android.mk @@ -36,8 +36,6 @@ LOCAL_PRIVILEGED_MODULE := true LOCAL_PROGUARD_FLAG_FILES := proguard.flags -LOCAL_SDK_VERSION := current - include $(BUILD_PACKAGE) # Use the folloing include to make our test apk. diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index c3c90e27c..b2bf1caf3 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -101,6 +101,19 @@ <string name="contactSavedToast" msgid="7152589189385441091">"此联系人已保存。"</string> <string name="contactSavedErrorToast" msgid="3207250533172944892">"无法保存联系人更改。"</string> <string name="contactPhotoSavedErrorToast" msgid="4079032272022979114">"无法保存联系人照片更改。"</string> + <string name="contactSavedToSimCardError">"发生错误,正在载入SIM卡联系人。"</string> + <string name="airplane_mode_on">"发生错误,当前处于飞行模式。"</string> + <string name="number_anr_too_long">"发生错误,电话号码过长。"</string> + <string name="email_address_too_long">"发生错误,邮箱地址过长。"</string> + <string name="sim_card_full">"发生错误,SIM卡已满。"</string> + <string name="tag_too_long">"发生错误,联系人姓名过长。"</string> + <string name="no_phone_number">请输入手机号码。</string> + <string name="invalid_phone_number">"发生错误,电话号码不合法。"</string> + <string name="invalid_number_type">"发生错误,号码类型不合法。"</string> + <string name="no_phone_number_or_email">请输入手机号码或者邮箱地址。</string> + <string name="memory_card_full">错误, 内存已满.</string> + <string name="importConfirmation_title" msgid="1418215926447642260">"要导入联系人吗?"</string> + <string name="edit_before_call">"拨号前编辑号码"</string> <string name="groupSavedToast" msgid="1168756874239833756">"群组已保存。"</string> <string name="groupSavedErrorToast" msgid="7984466936615304740">"无法保存所做的群组更改。"</string> <plurals name="listTotalPhoneContacts" formatted="false" msgid="3692277679143308755"> diff --git a/res/values/strings.xml b/res/values/strings.xml index bd9e3412d..f7ad8ed5b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -280,7 +280,21 @@ <!-- Toast displayed when saving a contact photo failed. [CHAR LIMIT=NONE] --> <string name="contactPhotoSavedErrorToast">Couldn\'t save contact photo changes.</string> - + <!-- Toast displayed when saving a contact to sim card failed --> + <string name="contactSavedToSimCardError">Error, Loading Sim Contacts.</string> + <string name="airplane_mode_on">Error, Airplane mode is on.</string> + <string name="number_anr_too_long">Error, Number is too long.</string> + <string name="email_address_too_long">Error, Email Address is too long.</string> + <string name="sim_card_full">Error, Sim Card is full.</string> + <string name="tag_too_long">Error, Contact name is too long.</string> + <string name="no_phone_number">Please insert phone number.</string> + <string name="invalid_phone_number">Error, Number is invalid.</string> + <string name="invalid_number_type">Error, Number type is invalid.</string> + <string name="no_phone_number_or_email">Please insert phone number or email address.</string> + <string name="memory_card_full">Error, Memory is almost full.</string> + <string name="edit_before_call">Edit number before call</string> + <string name="importConfirmation_title">Import contact?</string> + <!-- Toast displayed when a group is saved [CHAR LIMIT=NONE] --> <!-- Toast displayed when a group is saved [CHAR LIMIT=NONE] --> <string name="groupSavedToast">Group saved.</string> diff --git a/src/com/android/contacts/ContactSaveService.java b/src/com/android/contacts/ContactSaveService.java index 6178e9de4..f46e72f57 100644 --- a/src/com/android/contacts/ContactSaveService.java +++ b/src/com/android/contacts/ContactSaveService.java @@ -29,12 +29,14 @@ import android.content.Context; import android.content.Intent; import android.content.OperationApplicationException; import android.database.Cursor; +import android.database.sqlite.SQLiteFullException; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Parcelable; import android.os.RemoteException; +import android.os.ServiceManager; import android.provider.ContactsContract; import android.provider.ContactsContract.AggregationExceptions; import android.provider.ContactsContract.CommonDataKinds.GroupMembership; @@ -46,6 +48,10 @@ import android.provider.ContactsContract.PinnedPositions; import android.provider.ContactsContract.Profile; import android.provider.ContactsContract.RawContacts; import android.provider.ContactsContract.RawContactsEntity; +import android.text.TextUtils; +import android.telephony.PhoneNumberUtils; +import android.telephony.TelephonyManager; +import android.telephony.SubscriptionManager; import android.util.Log; import android.widget.Toast; @@ -56,15 +62,22 @@ import com.android.contacts.common.model.RawContactDeltaList; import com.android.contacts.common.model.RawContactModifier; import com.android.contacts.common.model.account.AccountWithDataSet; import com.android.contacts.common.util.PermissionsUtil; +import com.android.contacts.common.SimContactsConstants; +import com.android.contacts.common.SimContactsOperation; +import com.android.contacts.common.MoreContactUtils; import com.android.contacts.editor.ContactEditorFragment; import com.android.contacts.util.ContactPhotoUtils; +import com.android.internal.telephony.uicc.AdnRecord; +import com.android.internal.telephony.uicc.IccConstants; +import com.android.internal.telephony.IIccPhoneBook; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.HashMap; import java.util.concurrent.CopyOnWriteArrayList; /** @@ -90,6 +103,7 @@ public class ContactSaveService extends IntentService { public static final String EXTRA_SAVE_IS_PROFILE = "saveIsProfile"; public static final String EXTRA_SAVE_SUCCEEDED = "saveSucceeded"; public static final String EXTRA_UPDATED_PHOTOS = "updatedPhotos"; + public static final String SAVE_CONTACT_RESULT = "saveResult"; public static final String ACTION_CREATE_GROUP = "createGroup"; public static final String ACTION_RENAME_GROUP = "renameGroup"; @@ -143,6 +157,33 @@ public class ContactSaveService extends IntentService { ); private static final int PERSIST_TRIES = 3; + private static int count = TelephonyManager.getDefault().getPhoneCount(); + private static int[] mSimMaxCount = new int[count]; + + public static final int RESULT_UNCHANGED = 0; + public static final int RESULT_SUCCESS = 1; + public static final int RESULT_FAILURE = 2; + public static final int RESULT_NO_NUMBER_AND_EMAIL = 3; + public static final int RESULT_SIM_FAILURE = 4; //only for sim operation failure + public static final int RESULT_EMAIL_FAILURE = 5; // only for sim email operation failure + // only for sim failure of number or anr is too long + public static final int RESULT_NUMBER_ANR_FAILURE = 6; + public static final int RESULT_SIM_FULL_FAILURE = 7; // only for sim card is full + public static final int RESULT_TAG_FAILURE = 8; // only for sim failure of name is too long + public static final int RESULT_NUMBER_INVALID = 9; // only for sim failure of number is valid + + public static final int RESULT_MEMORY_FULL_FAILURE = 11; //for memory full exception + public static final int RESULT_NUMBER_TYPE_FAILURE =12; //only for sim failure of number TYPE + + private final int MAX_NUM_LENGTH = 20; + private final int MAX_EMAIL_LENGTH = 40; + private final int MAX_EN_LENGTH = 14; + private final int MAX_CH_LENGTH = 6; + + // Only for request accessing SIM card + // when device is in the "AirPlane" mode. + public static final int RESULT_AIR_PLANE_MODE = 10; + public static SimContactsOperation mSimContactsOperation; private static final int MAX_CONTACTS_PROVIDER_BATCH_SIZE = 499; @@ -183,6 +224,40 @@ public class ContactSaveService extends IntentService { return getApplicationContext().getSystemService(name); } + /** + * when isMultiSimEnabled is true,get the maximum how many contacts can save to sim card + */ + private int getMSimCardMaxCount(int subscription) { + if (0 != mSimMaxCount[subscription]) { + return mSimMaxCount[subscription]; + } + int[] subId = SubscriptionManager.getSubId(subscription); + try { + IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface( + ServiceManager.getService("simphonebook")); + + if (iccIpb != null) { + if (subId != null + && TelephonyManager.getDefault().isMultiSimEnabled()) { + List<AdnRecord> list = iccIpb.getAdnRecordsInEfForSubscriber( + subId[0], IccConstants.EF_ADN); + if (null != list) { + mSimMaxCount[subscription] = list.size(); + } + } else { + List<AdnRecord> list = iccIpb + .getAdnRecordsInEf(IccConstants.EF_ADN); + if (null != list) { + mSimMaxCount[subscription] = list.size(); + } + } + } + } catch (RemoteException ex) { + Log.e(TAG, "Failed to IIccPhoneBookMSim", ex); + } + return mSimMaxCount[subscription]; + } + @Override protected void onHandleIntent(Intent intent) { if (intent == null) { @@ -378,8 +453,28 @@ public class ContactSaveService extends IntentService { long insertedRawContactId = -1; // Attempt to persist changes + Integer result = RESULT_FAILURE; + + ArrayList<Long> rawContactsList = new ArrayList<Long>(); + boolean isCardOperation = false; + for (int i=0; i < state.size(); i++) { + final RawContactDelta entity = state.get(i); + final String accountType = entity.getValues().getAsString(RawContacts.ACCOUNT_TYPE); + final String accountName = entity.getValues().getAsString(RawContacts.ACCOUNT_NAME); + rawContactsList.add(entity.getRawContactId()); + + final int subscription = MoreContactUtils.getSubscription( + accountType, accountName); + isCardOperation = (subscription != SubscriptionManager.INVALID_SUBSCRIPTION_ID) ? + true : false; + if (isCardOperation) { + result = doSaveToSimCard(entity, resolver, subscription); + Log.d(TAG, "doSaveToSimCard result is " + result); + } + } int tries = 0; while (tries++ < PERSIST_TRIES) { + if (result == RESULT_SUCCESS || result == RESULT_FAILURE) { try { // Build operations and try applying final ArrayList<ContentProviderOperation> diff = state.buildDiff(); @@ -449,7 +544,17 @@ public class ContactSaveService extends IntentService { Log.e(TAG, "Problem persisting user edits", e); showToast(R.string.contactSavedErrorToast); break; - + } catch (SQLiteFullException e) { + // Memory is full. don't do any thing + Log.e(TAG, "Memory is full", e); + Intent callbackIntent = intent.getParcelableExtra(EXTRA_CALLBACK_INTENT); + if (callbackIntent != null) { + callbackIntent.putExtra(EXTRA_SAVE_SUCCEEDED, false); + callbackIntent.setData(null); + callbackIntent.putExtra(SAVE_CONTACT_RESULT, RESULT_MEMORY_FULL_FAILURE); + deliverCallback(callbackIntent); + } + return; } catch (OperationApplicationException e) { // Version consistency failed, re-parent change and try again Log.w(TAG, "Version consistency failed, re-parenting: " + e.toString()); @@ -484,6 +589,7 @@ public class ContactSaveService extends IntentService { if (isProfile) { for (RawContactDelta delta : state) { delta.setProfileQueryUri(); + } } } } @@ -518,6 +624,8 @@ public class ContactSaveService extends IntentService { callbackIntent.putExtra(EXTRA_SAVE_SUCCEEDED, true); } callbackIntent.setData(lookupUri); + callbackIntent.putExtra(SAVE_CONTACT_RESULT, result); + deliverCallback(callbackIntent); } } @@ -534,7 +642,124 @@ public class ContactSaveService extends IntentService { return ContactPhotoUtils.savePhotoFromUriToUri(this, photoUri, outputUri, true); } - /** + private Integer doSaveToSimCard(RawContactDelta entity, ContentResolver resolver, + int subscription) { + // Return Error code to indicate caller that device is in + // the "AirPlane" mode and application can't access SIM card. + if (MoreContactUtils.isAPMOnAndSIMPowerDown(this)) { + return RESULT_AIR_PLANE_MODE; + } + + boolean isInsert = entity.isContactInsert(); + Integer result = RESULT_SIM_FAILURE; + mSimContactsOperation = new SimContactsOperation(this); + + ContentValues values = entity.buildSimDiff(); + String tag = null; + String number = null; + String anr = null; + String email = null; + + if(entity.isContactInsert()){ + tag = values.getAsString(SimContactsConstants.STR_TAG); + number = values.getAsString(SimContactsConstants.STR_NUMBER); + anr = values.getAsString(SimContactsConstants.STR_ANRS); + email = values.getAsString(SimContactsConstants.STR_EMAILS); + } else { + tag = values.getAsString(SimContactsConstants.STR_NEW_TAG); + number = values.getAsString(SimContactsConstants.STR_NEW_NUMBER); + anr = values.getAsString(SimContactsConstants.STR_NEW_ANRS); + email = values.getAsString(SimContactsConstants.STR_NEW_EMAILS); + } + + if (TextUtils.isEmpty(number) && TextUtils.isEmpty(anr) && TextUtils.isEmpty(email)) { + return RESULT_NO_NUMBER_AND_EMAIL; + } + + if (!TextUtils.isEmpty(number)) { + if (number.length() > MAX_NUM_LENGTH) { + return RESULT_NUMBER_ANR_FAILURE; + } else if (number.contains(SimContactsConstants.STR_ANRS)) { + return RESULT_NUMBER_TYPE_FAILURE; + } + } + + if (!TextUtils.isEmpty(anr)) { + String[] anrs = anr.split(SimContactsConstants.ANR_SEP); + if (anrs != null) { + if (anrs.length > MoreContactUtils + .getOneSimAnrCount(subscription)) { + return RESULT_NUMBER_TYPE_FAILURE; + } + for (String mAnr : anrs) { + if (mAnr.length() > MAX_NUM_LENGTH) { + return RESULT_NUMBER_ANR_FAILURE; + } + } + } + } + + if (!TextUtils.isEmpty(number) && TextUtils.isEmpty(PhoneNumberUtils + .stripSeparators(number))) { + return RESULT_NUMBER_INVALID; + } + + if (!TextUtils.isEmpty(email)) { + String[] emails = email.split(SimContactsConstants.EMAIL_SEP); + for (String mEmail : emails) { + if (mEmail != null && mEmail.length() > MAX_EMAIL_LENGTH) { + return RESULT_EMAIL_FAILURE; + } + } + } + + if (!TextUtils.isEmpty(tag)) { + if (tag.getBytes().length > MAX_EN_LENGTH) { + return RESULT_TAG_FAILURE; + } + } + + if (entity.isContactInsert()) { + int count = 0; + Cursor c = null; + Uri iccUri; + int[] subId = SubscriptionManager.getSubId(subscription); + if (!TelephonyManager.getDefault().isMultiSimEnabled()) { + iccUri = Uri.parse(SimContactsConstants.SIM_URI); + } else { + iccUri = Uri.parse(SimContactsConstants.SIM_SUB_URI + subId[0]); + } + try { + c = resolver.query(iccUri, null, null, null, null); + if (c != null) { + count = c.getCount(); + } + } finally { + if (c != null) { + c.close(); + } + } + + if (count == getMSimCardMaxCount(subscription)) { + return RESULT_SIM_FULL_FAILURE; + } + } + + if (isInsert) { + Uri resultUri = mSimContactsOperation.insert(values, + subscription); + if (resultUri != null) + result = RESULT_SUCCESS; + } else { + int resultInt = mSimContactsOperation.update(values, + subscription); + if (resultInt == 1) + result = RESULT_SUCCESS; + } + return result; + } + + /** * Find the ID of an existing or newly-inserted raw-contact. If none exists, return -1. */ private long getRawContactId(RawContactDeltaList state, @@ -998,12 +1223,27 @@ public class ContactSaveService extends IntentService { private void deleteContact(Intent intent) { Uri contactUri = intent.getParcelableExtra(EXTRA_CONTACT_URI); + mSimContactsOperation = new SimContactsOperation(this); if (contactUri == null) { Log.e(TAG, "Invalid arguments for deleteContact request"); return; } - getContentResolver().delete(contactUri, null, null); + final List<String> segments = contactUri.getPathSegments(); + // Contains an Id. + final long uriContactId = Long.parseLong(segments.get(3)); + int subscription = mSimContactsOperation + .getSimSubscription(uriContactId); + if (subscription != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + ContentValues values = mSimContactsOperation + .getSimAccountValues(uriContactId); + int result = mSimContactsOperation.delete(values, subscription); + if (result == RESULT_SUCCESS) { + getContentResolver().delete(contactUri, null, null); + } + } else { + getContentResolver().delete(contactUri, null, null); + } } private void deleteMultipleContacts(Intent intent) { diff --git a/src/com/android/contacts/activities/ContactEditorBaseActivity.java b/src/com/android/contacts/activities/ContactEditorBaseActivity.java index 12f1e961b..ac5fe67da 100644 --- a/src/com/android/contacts/activities/ContactEditorBaseActivity.java +++ b/src/com/android/contacts/activities/ContactEditorBaseActivity.java @@ -172,7 +172,7 @@ abstract public class ContactEditorBaseActivity extends ContactsActivity */ void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded, Uri contactLookupUri, Bundle updatedPhotos, boolean backPressed, long photoId, - long nameId); + long nameId, int result); /** * Invoked after the contact is joined. @@ -264,7 +264,8 @@ abstract public class ContactEditorBaseActivity extends ContactsActivity intent.getBooleanExtra(ContactEditorFragment.INTENT_EXTRA_SAVE_BACK_PRESSED, false), intent.getLongExtra(ContactEditorFragment.INTENT_EXTRA_PHOTO_ID, -1), - intent.getLongExtra(ContactEditorFragment.INTENT_EXTRA_NAME_ID, -1)); + intent.getLongExtra(ContactEditorFragment.INTENT_EXTRA_NAME_ID, -1), + intent.getIntExtra(ContactSaveService.SAVE_CONTACT_RESULT, 0)); } else if (ACTION_JOIN_COMPLETED.equals(action)) { mFragment.onJoinCompleted(intent.getData()); } diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java index 6b7df6768..6a4256129 100644 --- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java +++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java @@ -17,6 +17,8 @@ package com.android.contacts.editor; import com.android.contacts.R; +import com.android.contacts.common.model.account.PhoneAccountType; +import com.android.contacts.common.model.account.SimAccountType; import com.android.contacts.common.model.AccountTypeManager; import com.android.contacts.common.model.RawContactDelta; import com.android.contacts.common.model.RawContactDeltaList; @@ -24,14 +26,19 @@ import com.android.contacts.common.model.RawContactModifier; import com.android.contacts.common.model.ValuesDelta; import com.android.contacts.common.model.account.AccountType; import com.android.contacts.common.model.account.AccountType.EditField; +import com.android.contacts.common.model.account.AccountType.EditType; import com.android.contacts.common.model.account.AccountWithDataSet; import com.android.contacts.common.model.dataitem.DataKind; +import com.android.contacts.common.SimContactsConstants; +import com.android.contacts.common.MoreContactUtils; import com.android.contacts.common.util.MaterialColorMapUtils; import com.android.contacts.editor.CompactContactEditorFragment.PhotoHandler; +import com.android.internal.telephony.PhoneConstants; import android.content.Context; import android.graphics.Bitmap; import android.net.Uri; +import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.CommonDataKinds.Email; import android.provider.ContactsContract.CommonDataKinds.GroupMembership; import android.provider.ContactsContract.CommonDataKinds.Nickname; @@ -640,7 +647,7 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O for (RawContactDelta rawContactDelta : rawContactDeltas) { if (!rawContactDelta.isVisible()) continue; final AccountType accountType = rawContactDelta.getAccountType(mAccountTypeManager); - + final String accountName = rawContactDelta.getAccountName(); for (DataKind dataKind : accountType.getSortedDataKinds()) { if (!dataKind.editable) continue; @@ -658,7 +665,7 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O final ValuesDelta valuesDelta = rawContactDelta.getSuperPrimaryEntry( StructuredName.CONTENT_ITEM_TYPE, /* forceSelection =*/ true); if (hasNonEmptyValue(dataKind, valuesDelta)) { - mPhoneticNames.addView(inflatePhoneticNameEditorView( + mPhoneticNames.addView(inflatePhoneticNameEditorView( mPhoneticNames, accountType, valuesDelta, rawContactDelta)); } } else if (Nickname.CONTENT_ITEM_TYPE.equals(mimeType)) { @@ -667,7 +674,7 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O rawContactDelta, Nickname.CONTENT_ITEM_TYPE, dataKind); if (valuesDeltas != null && !valuesDeltas.isEmpty()) { for (ValuesDelta valuesDelta : valuesDeltas) { - mNicknames.addView(inflateNicknameEditorView( + mNicknames.addView(inflateNicknameEditorView( mNicknames, dataKind, valuesDelta, rawContactDelta)); } } @@ -687,6 +694,31 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O updateKindEditorIcons(mPhoneNumbers); } }); + if (SimContactsConstants.ACCOUNT_TYPE_SIM + .equals(accountType.accountType)) { + int sub = PhoneConstants.SUB1; + if (SimContactsConstants.SIM_NAME_2.equals(accountName)) { + sub = PhoneConstants.SUB2; + } + EditType typeHome = new EditType(Phone.TYPE_HOME, + Phone.getTypeLabelResource(Phone.TYPE_HOME)); + if (!MoreContactUtils.canSaveAnr(sub)) { + dataKind.typeOverallMax = 1; + if (null != dataKind.typeList) { + // When the sim card is not 3g the interface should + // remove the TYPE_HOME number view. + dataKind.typeList.remove(typeHome); + } + } else { + dataKind.typeOverallMax = MoreContactUtils.getOneSimAnrCount(sub) + 1; + if (null != dataKind.typeList && !dataKind.typeList.contains( + typeHome)) { + // When the sim card is 3g the interface should + // add the TYPE_HOME number view. + dataKind.typeList.add(typeHome); + } + } + } mPhoneNumbers.addView(kindSectionView); } else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) { final KindSectionView kindSectionView = @@ -704,7 +736,19 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O updateKindEditorIcons(mEmails); } }); - mEmails.addView(kindSectionView); + if (SimContactsConstants.ACCOUNT_TYPE_SIM.equals( + accountType.accountType)) { + int sub = PhoneConstants.SUB1; + if (SimContactsConstants.SIM_NAME_2.equals(accountName)) { + sub = PhoneConstants.SUB2; + } + if (MoreContactUtils.canSaveEmail(sub)) { + dataKind.typeOverallMax = MoreContactUtils.getOneSimEmailCount(sub); + mEmails.addView(kindSectionView); + } + } else { + mEmails.addView(kindSectionView); + } } else if (hasNonEmptyValuesDelta(rawContactDelta, mimeType, dataKind)) { final LinearLayout otherTypeViewGroup; if (mOtherTypesMap.containsKey(mimeType)) { @@ -842,6 +886,10 @@ public class CompactRawContactsEditorView extends LinearLayout implements View.O rawContactDelta, readOnly, mViewIdGenerator); + if (rawContactDelta.getAccountType() != null && rawContactDelta.getAccountType().equals( + SimContactsConstants.ACCOUNT_TYPE_SIM)) { + result.setExpansionViewContainerDisabled(); + } return result; } diff --git a/src/com/android/contacts/editor/ContactEditorBaseFragment.java b/src/com/android/contacts/editor/ContactEditorBaseFragment.java index 18b138190..646bf4fe2 100644 --- a/src/com/android/contacts/editor/ContactEditorBaseFragment.java +++ b/src/com/android/contacts/editor/ContactEditorBaseFragment.java @@ -25,6 +25,7 @@ import com.android.contacts.R; import com.android.contacts.activities.ContactEditorAccountsChangedActivity; import com.android.contacts.activities.ContactEditorBaseActivity; import com.android.contacts.activities.ContactEditorBaseActivity.ContactEditor; +import com.android.contacts.common.SimContactsConstants; import com.android.contacts.common.model.AccountTypeManager; import com.android.contacts.common.model.Contact; import com.android.contacts.common.model.ContactLoader; @@ -35,6 +36,7 @@ import com.android.contacts.common.model.RawContactModifier; import com.android.contacts.common.model.ValuesDelta; import com.android.contacts.common.model.account.AccountType; import com.android.contacts.common.model.account.AccountWithDataSet; +import com.android.contacts.common.model.account.SimAccountType; import com.android.contacts.common.util.ImplicitIntentsUtil; import com.android.contacts.common.util.MaterialColorMapUtils; import com.android.contacts.editor.AggregationSuggestionEngine.Suggestion; @@ -652,6 +654,14 @@ abstract public class ContactEditorBaseFragment extends Fragment implements } @Override + public void onResume() { + super.onResume(); + if (Intent.ACTION_EDIT.equals(mAction)) { + mHasNewContact = false; + } + } + + @Override public void onStop() { super.onStop(); @@ -786,10 +796,18 @@ abstract public class ContactEditorBaseFragment extends Fragment implements // even if they have never added their own information and splitting will create a // name only contact. final boolean isSingleReadOnlyContact = mHasNewContact && mState.size() == 2; + String accountType = null; + if (mState.size() > 0) { + accountType = mState.get(0).getAccountType(); + } splitMenu.setVisible(mState.size() > 1 && !isEditingUserProfile() && !isSingleReadOnlyContact); // Cannot join a user profile - joinMenu.setVisible(!isEditingUserProfile()); + if (accountType != null && SimAccountType.ACCOUNT_TYPE.equals(accountType)) { + joinMenu.setVisible(false); + } else { + joinMenu.setVisible(!isEditingUserProfile()); + } deleteMenu.setVisible(!mDisableDeleteMenuOption); } else { // something else, so don't show the help menu @@ -950,7 +968,9 @@ abstract public class ContactEditorBaseFragment extends Fragment implements } onSaveCompleted(/* hadChanges =*/ false, saveMode, /* saveSucceeded =*/ mLookupUri != null, mLookupUri, - /* updatedPhotos =*/ null, backPressed, mPhotoId, mNameId); + /* updatedPhotos =*/ null, backPressed, mPhotoId, mNameId, + getActivity().getIntent().getIntExtra( + ContactSaveService.SAVE_CONTACT_RESULT, 0)); return true; } @@ -1275,7 +1295,8 @@ abstract public class ContactEditorBaseFragment extends Fragment implements // For profile contacts, we need a different query URI rawContactDelta.setProfileQueryUri(); // Try to find a local profile contact - if (rawContactDelta.getValues().getAsString(RawContacts.ACCOUNT_TYPE) == null) { + if (SimContactsConstants.ACCOUNT_TYPE_PHONE + .equals(rawContactDelta.getAccountType())) { localProfileExists = true; } } @@ -1401,20 +1422,81 @@ abstract public class ContactEditorBaseFragment extends Fragment implements @Override public void onJoinCompleted(Uri uri) { onSaveCompleted(false, SaveMode.RELOAD, uri != null, uri, /* updatedPhotos =*/ null, - /* backPressed =*/ false, mPhotoId, mNameId); + /* backPressed =*/ false, mPhotoId, mNameId, + getActivity().getIntent().getIntExtra(ContactSaveService.SAVE_CONTACT_RESULT, + 0)); } @Override public void onSaveCompleted(boolean hadChanges, int saveMode, boolean saveSucceeded, Uri contactLookupUri, Bundle updatedPhotos, boolean backPressed, long photoId, - long nameId) { + long nameId, int result) { + Log.d(TAG, "onSaveCompleted(" + saveMode + ", " + contactLookupUri + ", saveResult:" + + result); if (hadChanges) { if (saveSucceeded) { if (saveMode != SaveMode.JOIN) { - Toast.makeText(mContext, R.string.contactSavedToast, Toast.LENGTH_SHORT).show(); + if (null != contactLookupUri) { + Toast.makeText(mContext, R.string.contactSavedToast, + Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(mContext, R.string.contacts_deleted_toast, + Toast.LENGTH_SHORT).show(); + } } } else { - Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG).show(); + if (result == ContactSaveService.RESULT_AIR_PLANE_MODE) { + // Access SIM card in the "AirPlane" + // mode prompt a toast to alert user. + Toast.makeText(mContext, R.string.airplane_mode_on, Toast.LENGTH_LONG).show(); + } else if (result == ContactSaveService.RESULT_SIM_FAILURE) { + Toast.makeText(mContext, R.string.contactSavedToSimCardError, + Toast.LENGTH_LONG).show(); + } else if (result == ContactSaveService.RESULT_NUMBER_ANR_FAILURE) { + Toast.makeText(mContext, R.string.number_anr_too_long, Toast.LENGTH_LONG) + .show(); + mStatus = Status.EDITING; + setEnabled(true); + bindEditors(); + return; + } else if (result == ContactSaveService.RESULT_EMAIL_FAILURE) { + Toast.makeText(mContext, R.string.email_address_too_long, Toast.LENGTH_LONG) + .show(); + mStatus = Status.EDITING; + setEnabled(true); + bindEditors(); + return; + } else if (result == ContactSaveService.RESULT_SIM_FULL_FAILURE) { + Toast.makeText(mContext, R.string.sim_card_full, Toast.LENGTH_LONG).show(); + } else if (result == ContactSaveService.RESULT_TAG_FAILURE) { + Toast.makeText(mContext, R.string.tag_too_long, Toast.LENGTH_SHORT).show(); + mStatus = Status.EDITING; + setEnabled(true); + bindEditors(); + return; + } else if (result == ContactSaveService.RESULT_NO_NUMBER_AND_EMAIL) { + Toast.makeText(mContext, R.string.no_phone_number_or_email, Toast.LENGTH_SHORT) + .show(); + mStatus = Status.EDITING; + setEnabled(true); + bindEditors(); + return; + } else if (result == ContactSaveService.RESULT_NUMBER_INVALID) { + Toast.makeText(mContext, R.string.invalid_phone_number, Toast.LENGTH_SHORT) + .show(); + mStatus = Status.EDITING; + setEnabled(true); + return; + } else if (result == ContactSaveService.RESULT_MEMORY_FULL_FAILURE) { + Toast.makeText(mContext, R.string.memory_card_full, Toast.LENGTH_SHORT) + .show(); + } else if(result == ContactSaveService.RESULT_NUMBER_TYPE_FAILURE) { + Toast.makeText(mContext, R.string.invalid_number_type, Toast.LENGTH_SHORT) + .show(); + } else { + Toast.makeText(mContext, R.string.contactSavedErrorToast, Toast.LENGTH_LONG) + .show(); + } } } switch (saveMode) { diff --git a/src/com/android/contacts/editor/ContactEditorFragment.java b/src/com/android/contacts/editor/ContactEditorFragment.java index 4da17faf2..31e8d5155 100644 --- a/src/com/android/contacts/editor/ContactEditorFragment.java +++ b/src/com/android/contacts/editor/ContactEditorFragment.java @@ -380,7 +380,7 @@ public class ContactEditorFragment extends ContactEditorBaseFragment implements final RawContactEditorView rawContactEditorView = (RawContactEditorView) view; final PhoneticNameEditorView phoneticNameEditorView = (PhoneticNameEditorView) rawContactEditorView.getPhoneticNameEditor(); - if (phoneticNameEditorView != null) { + if (phoneticNameEditorView != null && phoneticNameEditorView.getEntry() != null) { final String phoneticName = phoneticNameEditorView.getPhoneticName(); if (!TextUtils.isEmpty(phoneticName)) { return phoneticName; diff --git a/src/com/android/contacts/editor/ContactEditorUtils.java b/src/com/android/contacts/editor/ContactEditorUtils.java index 105b88552..2f00a2894 100644 --- a/src/com/android/contacts/editor/ContactEditorUtils.java +++ b/src/com/android/contacts/editor/ContactEditorUtils.java @@ -30,6 +30,7 @@ import com.android.contacts.common.testing.NeededForTesting; import com.android.contacts.common.model.AccountTypeManager; import com.android.contacts.common.model.account.AccountType; import com.android.contacts.common.model.account.AccountWithDataSet; +import com.android.contacts.common.SimContactsConstants; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; @@ -242,7 +243,12 @@ public class ContactEditorUtils { String[] getWritableAccountTypeStrings() { final Set<String> types = Sets.newHashSet(); for (AccountType type : mAccountTypes.getAccountTypes(true)) { - types.add(type.accountType); + if (type.accountType.equals(SimContactsConstants.ACCOUNT_TYPE_SIM) + || type.accountType.equals(SimContactsConstants.ACCOUNT_TYPE_PHONE)) { + continue; + } else { + types.add(type.accountType); + } } return types.toArray(new String[types.size()]); } diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java index eeba401de..917a0680b 100644 --- a/src/com/android/contacts/editor/RawContactEditorView.java +++ b/src/com/android/contacts/editor/RawContactEditorView.java @@ -42,6 +42,7 @@ import com.android.contacts.common.model.dataitem.DataKind; import com.android.contacts.common.model.RawContactDelta; import com.android.contacts.common.model.ValuesDelta; import com.android.contacts.common.model.RawContactModifier; +import com.android.contacts.common.SimContactsConstants; import com.google.common.base.Objects; @@ -249,23 +250,34 @@ public class RawContactEditorView extends BaseRawContactEditorView { mName.setValues( type.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_DISPLAY_NAME), primary, state, false, vig); - mPhoneticName.setValues( - type.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME), - primary, state, false, vig); - // It is useful to use Nickname outside of a KindSectionView so that we can treat it - // as a part of StructuredName's fake KindSectionView, even though it uses a - // different CP2 mime-type. We do a bit of extra work below to make this possible. - final DataKind nickNameKind = type.getKindForMimetype(Nickname.CONTENT_ITEM_TYPE); - if (nickNameKind != null) { - ValuesDelta primaryNickNameEntry = state.getPrimaryEntry(nickNameKind.mimeType); - if (primaryNickNameEntry == null) { - primaryNickNameEntry = RawContactModifier.insertChild(state, nickNameKind); + if (!(SimContactsConstants.ACCOUNT_TYPE_SIM).equals(type.accountType)) { + mPhoneticName.setValues( + type.getKindForMimetype(DataKind.PSEUDO_MIME_TYPE_PHONETIC_NAME), + primary, state, false, vig); + // It is useful to use Nickname outside of a KindSectionView so that we can + // treat it as a part of StructuredName's fake KindSectionView, even though + // it uses adifferent CP2 mime-type. We do a bit of extra work below to make + // this possible. + final DataKind nickNameKind = type + .getKindForMimetype(Nickname.CONTENT_ITEM_TYPE); + if (nickNameKind != null) { + ValuesDelta primaryNickNameEntry = state + .getPrimaryEntry(nickNameKind.mimeType); + if (primaryNickNameEntry == null) { + primaryNickNameEntry = RawContactModifier + .insertChild(state, nickNameKind); + } + mNickName.setValues(nickNameKind, primaryNickNameEntry, state, false, vig); + mNickName.setDeletable(false); + } else { + mPhoneticName.setPadding(0, 0, 0, (int) getResources().getDimension( + R.dimen.editor_padding_between_editor_views)); + mNickName.setVisibility(View.GONE); } - mNickName.setValues(nickNameKind, primaryNickNameEntry, state, false, vig); - mNickName.setDeletable(false); } else { - mPhoneticName.setPadding(0, 0, 0, (int) getResources().getDimension( - R.dimen.editor_padding_between_editor_views)); + //sim card can't store expand fields,so set it disabled. + mName.setExpansionViewContainerDisabled(); + mPhoneticName.setVisibility(View.GONE); mNickName.setVisibility(View.GONE); } } else if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) { diff --git a/src/com/android/contacts/editor/TextFieldsEditorView.java b/src/com/android/contacts/editor/TextFieldsEditorView.java index fe476ed01..88a8e30ee 100644 --- a/src/com/android/contacts/editor/TextFieldsEditorView.java +++ b/src/com/android/contacts/editor/TextFieldsEditorView.java @@ -377,10 +377,12 @@ public class TextFieldsEditorView extends LabeledEditorView { mHideOptional = ss.mHideOptional; - int numChildren = Math.min(mFieldEditTexts == null ? 0 : mFieldEditTexts.length, - ss.mVisibilities == null ? 0 : ss.mVisibilities.length); - for (int i = 0; i < numChildren; i++) { - mFieldEditTexts[i].setVisibility(ss.mVisibilities[i]); + if (mFieldEditTexts != null) { + int numChildren = Math.min(mFieldEditTexts == null ? 0 : mFieldEditTexts.length, + ss.mVisibilities == null ? 0 : ss.mVisibilities.length); + for (int i = 0; i < numChildren; i++) { + mFieldEditTexts[i].setVisibility(ss.mVisibilities[i]); + } } } @@ -429,4 +431,13 @@ public class TextFieldsEditorView extends LabeledEditorView { } } } + /** + * use for account type is ACCOUNT_TYPE_SIM only because that sim card + * can not store expand fields. + */ + + public void setExpansionViewContainerDisabled() { + mExpansionViewContainer.setEnabled(false); + mExpansionView.setVisibility(View.INVISIBLE); + } } diff --git a/src/com/android/contacts/list/ContactPickerFragment.java b/src/com/android/contacts/list/ContactPickerFragment.java index 4e8138916..fa1d2679c 100644 --- a/src/com/android/contacts/list/ContactPickerFragment.java +++ b/src/com/android/contacts/list/ContactPickerFragment.java @@ -165,7 +165,7 @@ public class ContactPickerFragment extends ContactEntryListFragment<ContactEntry HeaderEntryContactListAdapter adapter = new HeaderEntryContactListAdapter(getActivity()); adapter.setFilter(ContactListFilter.createFilterWithType( - ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS)); + ContactListFilter.FILTER_TYPE_ALL_WITHOUT_SIM)); adapter.setSectionHeaderDisplayEnabled(true); adapter.setDisplayPhotos(true); adapter.setQuickContactEnabled(false); diff --git a/src/com/android/contacts/list/JoinContactListAdapter.java b/src/com/android/contacts/list/JoinContactListAdapter.java index f08fcbbe3..553993702 100644 --- a/src/com/android/contacts/list/JoinContactListAdapter.java +++ b/src/com/android/contacts/list/JoinContactListAdapter.java @@ -24,6 +24,7 @@ import android.provider.ContactsContract; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Contacts.AggregationSuggestions; import android.provider.ContactsContract.Directory; +import android.provider.ContactsContract.RawContacts; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -34,6 +35,7 @@ import com.android.contacts.R; import com.android.contacts.common.list.ContactListAdapter; import com.android.contacts.common.list.ContactListItemView; import com.android.contacts.common.list.DirectoryListLoader; +import com.android.contacts.common.SimContactsConstants; import com.android.contacts.common.preference.ContactsPreferences; public class JoinContactListAdapter extends ContactListAdapter { @@ -81,7 +83,10 @@ public class JoinContactListAdapter extends ContactListAdapter { } builder.appendQueryParameter("limit", String.valueOf(MAX_SUGGESTIONS)); - + builder.appendQueryParameter(RawContacts.ACCOUNT_TYPE, + SimContactsConstants.ACCOUNT_TYPE_SIM); + builder.appendQueryParameter(SimContactsConstants.WITHOUT_SIM_FLAG, + "true"); loader.setSuggestionUri(builder.build()); // TODO simplify projection @@ -92,11 +97,19 @@ public class JoinContactListAdapter extends ContactListAdapter { .appendEncodedPath(Uri.encode(filter)) .appendQueryParameter( ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT)) + .appendQueryParameter(RawContacts.ACCOUNT_TYPE, + SimContactsConstants.ACCOUNT_TYPE_SIM) + .appendQueryParameter( + SimContactsConstants.WITHOUT_SIM_FLAG, "true") .build(); } else { allContactsUri = buildSectionIndexerUri(Contacts.CONTENT_URI).buildUpon() .appendQueryParameter( ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(Directory.DEFAULT)) + .appendQueryParameter(RawContacts.ACCOUNT_TYPE, + SimContactsConstants.ACCOUNT_TYPE_SIM) + .appendQueryParameter( + SimContactsConstants.WITHOUT_SIM_FLAG, "true") .build(); } loader.setUri(allContactsUri); |