summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk2
-rw-r--r--TestCommon/src/com/android/contacts/common/test/mocks/MockAccountTypeManager.java5
-rw-r--r--TestCommon/src/com/android/contacts/common/test/mocks/MockContactPhotoManager.java20
-rw-r--r--res/drawable-hdpi/ic_action_call.pngbin0 -> 1094 bytes
-rw-r--r--res/drawable-hdpi/ic_check_wht_24dp.pngbin0 -> 341 bytes
-rwxr-xr-xres/drawable-hdpi/ic_contact_picture_sim.pngbin0 -> 1533 bytes
-rwxr-xr-xres/drawable-hdpi/ic_contact_picture_sim_1.pngbin0 -> 1447 bytes
-rwxr-xr-xres/drawable-hdpi/ic_contact_picture_sim_2.pngbin0 -> 1718 bytes
-rwxr-xr-xres/drawable-hdpi/ic_contact_picture_sim_business.pngbin0 -> 1690 bytes
-rwxr-xr-xres/drawable-hdpi/ic_contact_picture_sim_personal.pngbin0 -> 2010 bytes
-rwxr-xr-xres/drawable-hdpi/ic_contact_picture_sim_primary.pngbin0 -> 2288 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-hdpi/ic_menu_settings_holo_light.pngbin1219 -> 1374 bytes
-rw-r--r--res/drawable-hdpi/ic_rx_videocam.pngbin0 -> 413 bytes
-rw-r--r--res/drawable-hdpi/ic_tx_videocam.pngbin0 -> 370 bytes
-rwxr-xr-xres/drawable-hdpi/phone_account.pngbin0 -> 1150 bytes
-rwxr-xr-xres/drawable-hdpi/sim1_account.pngbin0 -> 1236 bytes
-rwxr-xr-xres/drawable-hdpi/sim2_account.pngbin0 -> 1414 bytes
-rwxr-xr-xres/drawable-hdpi/simcard_account.pngbin0 -> 1207 bytes
-rw-r--r--res/drawable-mdpi/ic_action_call.pngbin0 -> 741 bytes
-rw-r--r--res/drawable-mdpi/ic_check_wht_24dp.pngbin0 -> 295 bytes
-rwxr-xr-xres/drawable-mdpi/ic_contact_picture_sim.pngbin0 -> 1365 bytes
-rwxr-xr-xres/drawable-mdpi/ic_contact_picture_sim_1.pngbin0 -> 1260 bytes
-rwxr-xr-xres/drawable-mdpi/ic_contact_picture_sim_2.pngbin0 -> 1429 bytes
-rwxr-xr-xres/drawable-mdpi/ic_contact_picture_sim_business.pngbin0 -> 1400 bytes
-rwxr-xr-xres/drawable-mdpi/ic_contact_picture_sim_personal.pngbin0 -> 1559 bytes
-rwxr-xr-xres/drawable-mdpi/ic_contact_picture_sim_primary.pngbin0 -> 1690 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-mdpi/ic_menu_settings_holo_light.pngbin850 -> 1233 bytes
-rwxr-xr-xres/drawable-mdpi/ic_rx_videocam.pngbin0 -> 299 bytes
-rwxr-xr-xres/drawable-mdpi/ic_tx_videocam.pngbin0 -> 265 bytes
-rwxr-xr-xres/drawable-mdpi/phone_account.pngbin0 -> 1098 bytes
-rwxr-xr-xres/drawable-mdpi/sim1_account.pngbin0 -> 1159 bytes
-rwxr-xr-xres/drawable-mdpi/sim2_account.pngbin0 -> 1289 bytes
-rwxr-xr-xres/drawable-mdpi/simcard_account.pngbin0 -> 1369 bytes
-rw-r--r--res/drawable-xhdpi/ic_action_call.pngbin0 -> 1489 bytes
-rw-r--r--res/drawable-xhdpi/ic_check_wht_24dp.pngbin0 -> 402 bytes
-rwxr-xr-xres/drawable-xhdpi/ic_contact_picture_sim.pngbin0 -> 1734 bytes
-rwxr-xr-xres/drawable-xhdpi/ic_contact_picture_sim_1.pngbin0 -> 1566 bytes
-rwxr-xr-xres/drawable-xhdpi/ic_contact_picture_sim_2.pngbin0 -> 1871 bytes
-rwxr-xr-xres/drawable-xhdpi/ic_contact_picture_sim_business.pngbin0 -> 1961 bytes
-rwxr-xr-xres/drawable-xhdpi/ic_contact_picture_sim_personal.pngbin0 -> 2365 bytes
-rwxr-xr-xres/drawable-xhdpi/ic_contact_picture_sim_primary.pngbin0 -> 2834 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xhdpi/ic_menu_settings_holo_light.pngbin1638 -> 1503 bytes
-rwxr-xr-xres/drawable-xhdpi/ic_rx_videocam.pngbin0 -> 439 bytes
-rwxr-xr-xres/drawable-xhdpi/ic_tx_videocam.pngbin0 -> 405 bytes
-rwxr-xr-xres/drawable-xhdpi/phone_account.pngbin0 -> 1187 bytes
-rwxr-xr-xres/drawable-xhdpi/sim1_account.pngbin0 -> 1352 bytes
-rwxr-xr-xres/drawable-xhdpi/sim2_account.pngbin0 -> 1539 bytes
-rwxr-xr-xres/drawable-xhdpi/simcard_account.pngbin0 -> 1281 bytes
-rw-r--r--res/drawable-xxhdpi/ic_action_call.pngbin0 -> 2245 bytes
-rw-r--r--res/drawable-xxhdpi/ic_check_wht_24dp.pngbin0 -> 449 bytes
-rwxr-xr-x[-rw-r--r--]res/drawable-xxhdpi/ic_menu_settings_holo_light.pngbin2506 -> 1727 bytes
-rwxr-xr-xres/drawable-xxhdpi/ic_rx_videocam.pngbin0 -> 603 bytes
-rwxr-xr-xres/drawable-xxhdpi/ic_tx_videocam.pngbin0 -> 551 bytes
-rwxr-xr-xres/drawable-xxhdpi/phone_account.pngbin0 -> 1317 bytes
-rwxr-xr-xres/drawable-xxhdpi/sim1_account.pngbin0 -> 1519 bytes
-rwxr-xr-xres/drawable-xxhdpi/sim2_account.pngbin0 -> 1826 bytes
-rwxr-xr-xres/drawable-xxhdpi/simcard_account.pngbin0 -> 1431 bytes
-rwxr-xr-xres/drawable-xxxhdpi/ic_menu_settings_holo_light.pngbin0 -> 2064 bytes
-rwxr-xr-xres/drawable-xxxhdpi/ic_rx_videocam.pngbin0 -> 753 bytes
-rwxr-xr-xres/drawable-xxxhdpi/ic_tx_videocam.pngbin0 -> 687 bytes
-rwxr-xr-xres/drawable-xxxhdpi/phone_account.pngbin0 -> 1406 bytes
-rwxr-xr-xres/drawable-xxxhdpi/sim1_account.pngbin0 -> 1601 bytes
-rwxr-xr-xres/drawable-xxxhdpi/sim2_account.pngbin0 -> 2040 bytes
-rwxr-xr-xres/drawable-xxxhdpi/simcard_account.pngbin0 -> 1517 bytes
-rw-r--r--res/drawable/call_background_activated.xml10
-rw-r--r--res/drawable/call_background_holo.xml10
-rw-r--r--res/drawable/ic_action_call_background.xml27
-rw-r--r--res/layout/contact_tile_frequent.xml2
-rw-r--r--res/layout/contact_tile_starred.xml2
-rw-r--r--res/layout/ip_prefix_dialog.xml43
-rw-r--r--res/layout/search_bar_expanded.xml2
-rw-r--r--res/values-af/cm_strings.xml57
-rw-r--r--res/values-ar/cm_strings.xml21
-rw-r--r--res/values-ast-rES/cm_strings.xml57
-rw-r--r--res/values-ast-rES/strings.xml257
-rw-r--r--res/values-az-rAZ/cm_strings.xml34
-rw-r--r--res/values-bn-rBD/cm_strings.xml22
-rw-r--r--res/values-ca/cm_strings.xml57
-rw-r--r--res/values-cs/cm_strings.xml58
-rw-r--r--res/values-da/cm_strings.xml57
-rw-r--r--res/values-de/cm_strings.xml57
-rw-r--r--res/values-el/cm_strings.xml57
-rw-r--r--res/values-en-rAU/cm_strings.xml57
-rw-r--r--res/values-en-rIN/cm_strings.xml57
-rw-r--r--res/values-es/cm_strings.xml57
-rw-r--r--res/values-et-rEE/cm_strings.xml57
-rw-r--r--res/values-eu-rES/cm_strings.xml21
-rw-r--r--res/values-fi/cm_strings.xml53
-rw-r--r--res/values-fr/cm_strings.xml57
-rw-r--r--res/values-gl-rES/cm_strings.xml21
-rw-r--r--res/values-hr/cm_strings.xml21
-rw-r--r--res/values-hu/cm_strings.xml57
-rw-r--r--res/values-in/cm_strings.xml56
-rw-r--r--res/values-it/cm_strings.xml57
-rw-r--r--res/values-iw/cm_strings.xml57
-rw-r--r--res/values-ja/cm_strings.xml56
-rw-r--r--res/values-ko/cm_strings.xml56
-rw-r--r--res/values-ku/cm_strings.xml35
-rw-r--r--res/values-ku/strings.xml247
-rw-r--r--res/values-lb/cm_strings.xml57
-rw-r--r--res/values-lb/strings.xml253
-rw-r--r--res/values-lt/cm_strings.xml58
-rw-r--r--res/values-lv/cm_strings.xml35
-rw-r--r--res/values-nb/cm_strings.xml57
-rw-r--r--res/values-nl/cm_strings.xml57
-rw-r--r--res/values-pl/cm_strings.xml53
-rw-r--r--res/values-pt-rBR/cm_strings.xml57
-rw-r--r--res/values-pt-rPT/cm_strings.xml57
-rw-r--r--res/values-ro/cm_strings.xml39
-rw-r--r--res/values-ru/cm_strings.xml58
-rw-r--r--res/values-si-rLK/cm_strings.xml35
-rw-r--r--res/values-sk/cm_strings.xml58
-rw-r--r--res/values-sr/cm_strings.xml59
-rw-r--r--res/values-sv/cm_strings.xml35
-rw-r--r--res/values-th/cm_strings.xml35
-rw-r--r--res/values-tr/cm_strings.xml57
-rw-r--r--res/values-ug/cm_strings.xml56
-rw-r--r--res/values-ug/strings.xml235
-rw-r--r--res/values-uk/cm_strings.xml58
-rw-r--r--res/values-zh-rCN/cm_strings.xml56
-rw-r--r--res/values-zh-rHK/cm_strings.xml23
-rw-r--r--res/values-zh-rTW/cm_strings.xml56
-rw-r--r--res/values/attrs.xml4
-rwxr-xr-xres/values/cm_colors.xml20
-rw-r--r--res/values/cm_strings.xml91
-rw-r--r--res/values/colors.xml2
-rw-r--r--res/values/donottranslate_config.xml8
-rw-r--r--res/values/ids.xml2
-rw-r--r--src/com/android/contacts/common/CallUtil.java80
-rw-r--r--src/com/android/contacts/common/ContactPhotoManager.java117
-rw-r--r--src/com/android/contacts/common/ContactTileLoaderFactory.java57
-rw-r--r--src/com/android/contacts/common/MoreContactUtils.java662
-rw-r--r--src/com/android/contacts/common/SimContactsConstants.java77
-rw-r--r--src/com/android/contacts/common/SimContactsOperation.java352
-rw-r--r--src/com/android/contacts/common/editor/SelectAccountDialogFragment.java2
-rw-r--r--src/com/android/contacts/common/format/TextHighlighter.java24
-rw-r--r--src/com/android/contacts/common/interactions/ImportExportDialogFragment.java635
-rw-r--r--src/com/android/contacts/common/interactions/ImportSIMContactsDialogFragment.java36
-rw-r--r--src/com/android/contacts/common/lettertiles/LetterTileDrawable.java49
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/list/AccountFilterActivity.java3
-rw-r--r--src/com/android/contacts/common/list/ContactEntry.java2
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/list/ContactEntryListAdapter.java29
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/list/ContactEntryListFragment.java50
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/list/ContactListAdapter.java67
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/list/ContactListFilter.java1
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/list/ContactListFilterView.java12
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/list/ContactListItemView.java195
-rw-r--r--src/com/android/contacts/common/list/ContactTileAdapter.java32
-rw-r--r--src/com/android/contacts/common/list/ContactTileView.java6
-rw-r--r--src/com/android/contacts/common/list/ContactsSectionIndexer.java4
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/list/CustomContactListFilterActivity.java27
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/list/DefaultContactListAdapter.java64
-rw-r--r--src/com/android/contacts/common/list/PhoneNumberListAdapter.java51
-rw-r--r--src/com/android/contacts/common/list/PhoneNumberPickerFragment.java13
-rw-r--r--src/com/android/contacts/common/list/ShortcutIntentBuilder.java51
-rw-r--r--src/com/android/contacts/common/model/AccountTypeManager.java90
-rw-r--r--src/com/android/contacts/common/model/RawContactDelta.java138
-rw-r--r--src/com/android/contacts/common/model/RawContactModifier.java2
-rw-r--r--src/com/android/contacts/common/model/ValuesDelta.java16
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/model/account/AccountType.java113
-rw-r--r--src/com/android/contacts/common/model/account/BaseAccountType.java2
-rw-r--r--src/com/android/contacts/common/model/account/PhoneAccountType.java99
-rw-r--r--src/com/android/contacts/common/model/account/SimAccountType.java123
-rw-r--r--src/com/android/contacts/common/preference/ContactsPreferences.java28
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/preference/DisplayOrderPreference.java11
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/preference/SortOrderPreference.java11
-rw-r--r--src/com/android/contacts/common/util/AccountSelectionUtil.java116
-rwxr-xr-x[-rw-r--r--]src/com/android/contacts/common/util/AccountsListAdapter.java38
-rw-r--r--src/com/android/contacts/common/util/TelephonyManagerUtils.java73
-rw-r--r--src/com/android/contacts/common/vcard/ExportProcessor.java11
-rw-r--r--src/com/android/contacts/common/vcard/ExportVCardActivity.java92
-rw-r--r--src/com/android/contacts/common/vcard/ImportVCardActivity.java76
-rw-r--r--src/com/android/contacts/common/vcard/NotificationImportExportListener.java8
-rw-r--r--src/com/android/contacts/common/vcard/SelectAccountActivity.java37
-rw-r--r--src/com/android/contacts/common/vcard/VCardService.java30
-rw-r--r--src/com/android/contacts/common/widget/CheckableFlipDrawable.java300
-rw-r--r--src/com/android/contacts/common/widget/CheckableImageView.java96
-rw-r--r--src/com/android/contacts/common/widget/CheckableQuickContactBadge.java98
-rw-r--r--src/com/android/contacts/common/widget/FlipDrawable.java266
-rw-r--r--src/com/android/contacts/common/widget/FloatingActionButtonController.java15
180 files changed, 7891 insertions, 246 deletions
diff --git a/Android.mk b/Android.mk
index 626a737b..3687e476 100644
--- a/Android.mk
+++ b/Android.mk
@@ -28,6 +28,8 @@ LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
--extra-packages com.android.phone.common
+LOCAL_JAVA_LIBRARIES := telephony-common
+
LOCAL_STATIC_JAVA_LIBRARIES := \
com.android.vcard \
guava \
diff --git a/TestCommon/src/com/android/contacts/common/test/mocks/MockAccountTypeManager.java b/TestCommon/src/com/android/contacts/common/test/mocks/MockAccountTypeManager.java
index ab2d3954..d3dd722c 100644
--- a/TestCommon/src/com/android/contacts/common/test/mocks/MockAccountTypeManager.java
+++ b/TestCommon/src/com/android/contacts/common/test/mocks/MockAccountTypeManager.java
@@ -66,6 +66,11 @@ public class MockAccountTypeManager extends AccountTypeManager {
}
@Override
+ public List<AccountWithDataSet> getAccounts(boolean writableOnly, int flag) {
+ return Arrays.asList(mAccounts);
+ }
+
+ @Override
public List<AccountWithDataSet> getGroupWritableAccounts() {
return Arrays.asList(mAccounts);
}
diff --git a/TestCommon/src/com/android/contacts/common/test/mocks/MockContactPhotoManager.java b/TestCommon/src/com/android/contacts/common/test/mocks/MockContactPhotoManager.java
index db8f06f2..3b143deb 100644
--- a/TestCommon/src/com/android/contacts/common/test/mocks/MockContactPhotoManager.java
+++ b/TestCommon/src/com/android/contacts/common/test/mocks/MockContactPhotoManager.java
@@ -16,6 +16,7 @@
package com.android.contacts.common.test.mocks;
+import android.accounts.Account;
import android.graphics.Bitmap;
import android.net.Uri;
import android.view.View;
@@ -29,16 +30,19 @@ import com.android.contacts.common.ContactPhotoManager;
*/
public class MockContactPhotoManager extends ContactPhotoManager {
@Override
- public void loadThumbnail(ImageView view, long photoId, boolean darkTheme, boolean isCircular,
- DefaultImageRequest defaultImageRequest, DefaultImageProvider defaultProvider) {
- defaultProvider.applyDefaultImage(view, -1, darkTheme, null);
+ public void loadThumbnail(ImageView view, long photoId, Account account,
+ boolean darkTheme, boolean isCircular,
+ DefaultImageRequest defaultImageRequest,
+ DefaultImageProvider defaultProvider) {
+ defaultProvider.applyDefaultImage(view, account, -1, darkTheme, null);
}
@Override
- public void loadPhoto(ImageView view, Uri photoUri, int requestedExtent, boolean darkTheme,
- boolean isCircular, DefaultImageRequest defaultImageRequest,
+ public void loadPhoto(ImageView view, Uri photoUri, Account account,
+ int requestedExtent, boolean darkTheme, boolean isCircular,
+ DefaultImageRequest defaultImageRequest,
DefaultImageProvider defaultProvider) {
- defaultProvider.applyDefaultImage(view, requestedExtent, darkTheme, null);
+ defaultProvider.applyDefaultImage(view, account, requestedExtent, darkTheme, null);
}
@Override
@@ -69,4 +73,8 @@ public class MockContactPhotoManager extends ContactPhotoManager {
@Override
public void preloadPhotosInBackground() {
}
+
+ @Override
+ public void clear() {
+ }
}
diff --git a/res/drawable-hdpi/ic_action_call.png b/res/drawable-hdpi/ic_action_call.png
new file mode 100644
index 00000000..7493a607
--- /dev/null
+++ b/res/drawable-hdpi/ic_action_call.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_check_wht_24dp.png b/res/drawable-hdpi/ic_check_wht_24dp.png
new file mode 100644
index 00000000..12ce8e0d
--- /dev/null
+++ b/res/drawable-hdpi/ic_check_wht_24dp.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_contact_picture_sim.png b/res/drawable-hdpi/ic_contact_picture_sim.png
new file mode 100755
index 00000000..7b6cc26f
--- /dev/null
+++ b/res/drawable-hdpi/ic_contact_picture_sim.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_contact_picture_sim_1.png b/res/drawable-hdpi/ic_contact_picture_sim_1.png
new file mode 100755
index 00000000..ec2ebcb5
--- /dev/null
+++ b/res/drawable-hdpi/ic_contact_picture_sim_1.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_contact_picture_sim_2.png b/res/drawable-hdpi/ic_contact_picture_sim_2.png
new file mode 100755
index 00000000..3b68c682
--- /dev/null
+++ b/res/drawable-hdpi/ic_contact_picture_sim_2.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_contact_picture_sim_business.png b/res/drawable-hdpi/ic_contact_picture_sim_business.png
new file mode 100755
index 00000000..4df1ecd5
--- /dev/null
+++ b/res/drawable-hdpi/ic_contact_picture_sim_business.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_contact_picture_sim_personal.png b/res/drawable-hdpi/ic_contact_picture_sim_personal.png
new file mode 100755
index 00000000..44f4b930
--- /dev/null
+++ b/res/drawable-hdpi/ic_contact_picture_sim_personal.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_contact_picture_sim_primary.png b/res/drawable-hdpi/ic_contact_picture_sim_primary.png
new file mode 100755
index 00000000..a5bf9214
--- /dev/null
+++ b/res/drawable-hdpi/ic_contact_picture_sim_primary.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_menu_settings_holo_light.png b/res/drawable-hdpi/ic_menu_settings_holo_light.png
index b7bb5c41..ca012b85 100644..100755
--- a/res/drawable-hdpi/ic_menu_settings_holo_light.png
+++ b/res/drawable-hdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_rx_videocam.png b/res/drawable-hdpi/ic_rx_videocam.png
new file mode 100644
index 00000000..ccdda670
--- /dev/null
+++ b/res/drawable-hdpi/ic_rx_videocam.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_tx_videocam.png b/res/drawable-hdpi/ic_tx_videocam.png
new file mode 100644
index 00000000..603ddc89
--- /dev/null
+++ b/res/drawable-hdpi/ic_tx_videocam.png
Binary files differ
diff --git a/res/drawable-hdpi/phone_account.png b/res/drawable-hdpi/phone_account.png
new file mode 100755
index 00000000..f2324885
--- /dev/null
+++ b/res/drawable-hdpi/phone_account.png
Binary files differ
diff --git a/res/drawable-hdpi/sim1_account.png b/res/drawable-hdpi/sim1_account.png
new file mode 100755
index 00000000..2d9a51c0
--- /dev/null
+++ b/res/drawable-hdpi/sim1_account.png
Binary files differ
diff --git a/res/drawable-hdpi/sim2_account.png b/res/drawable-hdpi/sim2_account.png
new file mode 100755
index 00000000..c512d524
--- /dev/null
+++ b/res/drawable-hdpi/sim2_account.png
Binary files differ
diff --git a/res/drawable-hdpi/simcard_account.png b/res/drawable-hdpi/simcard_account.png
new file mode 100755
index 00000000..0ee3dac2
--- /dev/null
+++ b/res/drawable-hdpi/simcard_account.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_action_call.png b/res/drawable-mdpi/ic_action_call.png
new file mode 100644
index 00000000..a5a7c371
--- /dev/null
+++ b/res/drawable-mdpi/ic_action_call.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_check_wht_24dp.png b/res/drawable-mdpi/ic_check_wht_24dp.png
new file mode 100644
index 00000000..c7de7050
--- /dev/null
+++ b/res/drawable-mdpi/ic_check_wht_24dp.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture_sim.png b/res/drawable-mdpi/ic_contact_picture_sim.png
new file mode 100755
index 00000000..dd63d11d
--- /dev/null
+++ b/res/drawable-mdpi/ic_contact_picture_sim.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture_sim_1.png b/res/drawable-mdpi/ic_contact_picture_sim_1.png
new file mode 100755
index 00000000..4793a07e
--- /dev/null
+++ b/res/drawable-mdpi/ic_contact_picture_sim_1.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture_sim_2.png b/res/drawable-mdpi/ic_contact_picture_sim_2.png
new file mode 100755
index 00000000..665a6714
--- /dev/null
+++ b/res/drawable-mdpi/ic_contact_picture_sim_2.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture_sim_business.png b/res/drawable-mdpi/ic_contact_picture_sim_business.png
new file mode 100755
index 00000000..c266e266
--- /dev/null
+++ b/res/drawable-mdpi/ic_contact_picture_sim_business.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture_sim_personal.png b/res/drawable-mdpi/ic_contact_picture_sim_personal.png
new file mode 100755
index 00000000..f1e75966
--- /dev/null
+++ b/res/drawable-mdpi/ic_contact_picture_sim_personal.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_contact_picture_sim_primary.png b/res/drawable-mdpi/ic_contact_picture_sim_primary.png
new file mode 100755
index 00000000..493067a9
--- /dev/null
+++ b/res/drawable-mdpi/ic_contact_picture_sim_primary.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_menu_settings_holo_light.png b/res/drawable-mdpi/ic_menu_settings_holo_light.png
index 1ebc112e..45a5ff0f 100644..100755
--- a/res/drawable-mdpi/ic_menu_settings_holo_light.png
+++ b/res/drawable-mdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_rx_videocam.png b/res/drawable-mdpi/ic_rx_videocam.png
new file mode 100755
index 00000000..1b43a07d
--- /dev/null
+++ b/res/drawable-mdpi/ic_rx_videocam.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_tx_videocam.png b/res/drawable-mdpi/ic_tx_videocam.png
new file mode 100755
index 00000000..64995d14
--- /dev/null
+++ b/res/drawable-mdpi/ic_tx_videocam.png
Binary files differ
diff --git a/res/drawable-mdpi/phone_account.png b/res/drawable-mdpi/phone_account.png
new file mode 100755
index 00000000..1fa24f6c
--- /dev/null
+++ b/res/drawable-mdpi/phone_account.png
Binary files differ
diff --git a/res/drawable-mdpi/sim1_account.png b/res/drawable-mdpi/sim1_account.png
new file mode 100755
index 00000000..cd80def2
--- /dev/null
+++ b/res/drawable-mdpi/sim1_account.png
Binary files differ
diff --git a/res/drawable-mdpi/sim2_account.png b/res/drawable-mdpi/sim2_account.png
new file mode 100755
index 00000000..fd52224a
--- /dev/null
+++ b/res/drawable-mdpi/sim2_account.png
Binary files differ
diff --git a/res/drawable-mdpi/simcard_account.png b/res/drawable-mdpi/simcard_account.png
new file mode 100755
index 00000000..e5a76881
--- /dev/null
+++ b/res/drawable-mdpi/simcard_account.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_action_call.png b/res/drawable-xhdpi/ic_action_call.png
new file mode 100644
index 00000000..e16ef951
--- /dev/null
+++ b/res/drawable-xhdpi/ic_action_call.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_check_wht_24dp.png b/res/drawable-xhdpi/ic_check_wht_24dp.png
new file mode 100644
index 00000000..e34b73e5
--- /dev/null
+++ b/res/drawable-xhdpi/ic_check_wht_24dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture_sim.png b/res/drawable-xhdpi/ic_contact_picture_sim.png
new file mode 100755
index 00000000..a39b7df0
--- /dev/null
+++ b/res/drawable-xhdpi/ic_contact_picture_sim.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture_sim_1.png b/res/drawable-xhdpi/ic_contact_picture_sim_1.png
new file mode 100755
index 00000000..300c0288
--- /dev/null
+++ b/res/drawable-xhdpi/ic_contact_picture_sim_1.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture_sim_2.png b/res/drawable-xhdpi/ic_contact_picture_sim_2.png
new file mode 100755
index 00000000..c7ce4223
--- /dev/null
+++ b/res/drawable-xhdpi/ic_contact_picture_sim_2.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture_sim_business.png b/res/drawable-xhdpi/ic_contact_picture_sim_business.png
new file mode 100755
index 00000000..abf631f9
--- /dev/null
+++ b/res/drawable-xhdpi/ic_contact_picture_sim_business.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture_sim_personal.png b/res/drawable-xhdpi/ic_contact_picture_sim_personal.png
new file mode 100755
index 00000000..e5f0cf0a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_contact_picture_sim_personal.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_contact_picture_sim_primary.png b/res/drawable-xhdpi/ic_contact_picture_sim_primary.png
new file mode 100755
index 00000000..543d6a7a
--- /dev/null
+++ b/res/drawable-xhdpi/ic_contact_picture_sim_primary.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_menu_settings_holo_light.png b/res/drawable-xhdpi/ic_menu_settings_holo_light.png
index 68ba92bd..91d0444d 100644..100755
--- a/res/drawable-xhdpi/ic_menu_settings_holo_light.png
+++ b/res/drawable-xhdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_rx_videocam.png b/res/drawable-xhdpi/ic_rx_videocam.png
new file mode 100755
index 00000000..43319dc9
--- /dev/null
+++ b/res/drawable-xhdpi/ic_rx_videocam.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tx_videocam.png b/res/drawable-xhdpi/ic_tx_videocam.png
new file mode 100755
index 00000000..d2671edf
--- /dev/null
+++ b/res/drawable-xhdpi/ic_tx_videocam.png
Binary files differ
diff --git a/res/drawable-xhdpi/phone_account.png b/res/drawable-xhdpi/phone_account.png
new file mode 100755
index 00000000..a61f2034
--- /dev/null
+++ b/res/drawable-xhdpi/phone_account.png
Binary files differ
diff --git a/res/drawable-xhdpi/sim1_account.png b/res/drawable-xhdpi/sim1_account.png
new file mode 100755
index 00000000..c0ae46f2
--- /dev/null
+++ b/res/drawable-xhdpi/sim1_account.png
Binary files differ
diff --git a/res/drawable-xhdpi/sim2_account.png b/res/drawable-xhdpi/sim2_account.png
new file mode 100755
index 00000000..68fb25ce
--- /dev/null
+++ b/res/drawable-xhdpi/sim2_account.png
Binary files differ
diff --git a/res/drawable-xhdpi/simcard_account.png b/res/drawable-xhdpi/simcard_account.png
new file mode 100755
index 00000000..92b382ee
--- /dev/null
+++ b/res/drawable-xhdpi/simcard_account.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_action_call.png b/res/drawable-xxhdpi/ic_action_call.png
new file mode 100644
index 00000000..c4cfdac8
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_action_call.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_check_wht_24dp.png b/res/drawable-xxhdpi/ic_check_wht_24dp.png
new file mode 100644
index 00000000..4c6a653f
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_check_wht_24dp.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_menu_settings_holo_light.png b/res/drawable-xxhdpi/ic_menu_settings_holo_light.png
index 5b672a3d..c87e0463 100644..100755
--- a/res/drawable-xxhdpi/ic_menu_settings_holo_light.png
+++ b/res/drawable-xxhdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_rx_videocam.png b/res/drawable-xxhdpi/ic_rx_videocam.png
new file mode 100755
index 00000000..89d29b7f
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_rx_videocam.png
Binary files differ
diff --git a/res/drawable-xxhdpi/ic_tx_videocam.png b/res/drawable-xxhdpi/ic_tx_videocam.png
new file mode 100755
index 00000000..8d897ba5
--- /dev/null
+++ b/res/drawable-xxhdpi/ic_tx_videocam.png
Binary files differ
diff --git a/res/drawable-xxhdpi/phone_account.png b/res/drawable-xxhdpi/phone_account.png
new file mode 100755
index 00000000..04b06fda
--- /dev/null
+++ b/res/drawable-xxhdpi/phone_account.png
Binary files differ
diff --git a/res/drawable-xxhdpi/sim1_account.png b/res/drawable-xxhdpi/sim1_account.png
new file mode 100755
index 00000000..9293bdbe
--- /dev/null
+++ b/res/drawable-xxhdpi/sim1_account.png
Binary files differ
diff --git a/res/drawable-xxhdpi/sim2_account.png b/res/drawable-xxhdpi/sim2_account.png
new file mode 100755
index 00000000..4788f1cd
--- /dev/null
+++ b/res/drawable-xxhdpi/sim2_account.png
Binary files differ
diff --git a/res/drawable-xxhdpi/simcard_account.png b/res/drawable-xxhdpi/simcard_account.png
new file mode 100755
index 00000000..e98fd1d9
--- /dev/null
+++ b/res/drawable-xxhdpi/simcard_account.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_menu_settings_holo_light.png b/res/drawable-xxxhdpi/ic_menu_settings_holo_light.png
new file mode 100755
index 00000000..dfdd5798
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_menu_settings_holo_light.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_rx_videocam.png b/res/drawable-xxxhdpi/ic_rx_videocam.png
new file mode 100755
index 00000000..095e0905
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_rx_videocam.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/ic_tx_videocam.png b/res/drawable-xxxhdpi/ic_tx_videocam.png
new file mode 100755
index 00000000..79ea67b2
--- /dev/null
+++ b/res/drawable-xxxhdpi/ic_tx_videocam.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/phone_account.png b/res/drawable-xxxhdpi/phone_account.png
new file mode 100755
index 00000000..3d726f60
--- /dev/null
+++ b/res/drawable-xxxhdpi/phone_account.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/sim1_account.png b/res/drawable-xxxhdpi/sim1_account.png
new file mode 100755
index 00000000..389569ac
--- /dev/null
+++ b/res/drawable-xxxhdpi/sim1_account.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/sim2_account.png b/res/drawable-xxxhdpi/sim2_account.png
new file mode 100755
index 00000000..ce5d8ddb
--- /dev/null
+++ b/res/drawable-xxxhdpi/sim2_account.png
Binary files differ
diff --git a/res/drawable-xxxhdpi/simcard_account.png b/res/drawable-xxxhdpi/simcard_account.png
new file mode 100755
index 00000000..5f18f34b
--- /dev/null
+++ b/res/drawable-xxxhdpi/simcard_account.png
Binary files differ
diff --git a/res/drawable/call_background_activated.xml b/res/drawable/call_background_activated.xml
new file mode 100644
index 00000000..9fe8d3f6
--- /dev/null
+++ b/res/drawable/call_background_activated.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <gradient android:startColor="#33b5e5" android:endColor="#33b5e5"
+ android:angle="270" />
+ <corners android:radius="2dp" />
+ <stroke android:color="#33b5e5" android:width="1dp" />
+ <padding android:top="5dp" android:bottom="5dp" android:left="5dp"
+ android:right="5dp" />
+</shape> \ No newline at end of file
diff --git a/res/drawable/call_background_holo.xml b/res/drawable/call_background_holo.xml
new file mode 100644
index 00000000..b947b20a
--- /dev/null
+++ b/res/drawable/call_background_holo.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <gradient android:startColor="#00000000"
+ android:endColor="#00000000"
+ android:angle="270" />
+ <corners android:radius="2dp" />
+ <padding android:top="5dp" android:bottom="5dp" android:left="5dp"
+ android:right="5dp" />
+</shape> \ No newline at end of file
diff --git a/res/drawable/ic_action_call_background.xml b/res/drawable/ic_action_call_background.xml
new file mode 100644
index 00000000..71ac2a9b
--- /dev/null
+++ b/res/drawable/ic_action_call_background.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true"
+ android:state_pressed="true"
+ android:drawable="@drawable/call_background_activated" />
+ <item android:state_focused="false"
+ android:state_pressed="true"
+ android:drawable="@drawable/call_background_activated"/>
+ <item android:state_focused="false"
+ android:state_pressed="false"
+ android:drawable="@drawable/call_background_holo"/>
+</selector> \ No newline at end of file
diff --git a/res/layout/contact_tile_frequent.xml b/res/layout/contact_tile_frequent.xml
index b1e83ce0..8c718fb2 100644
--- a/res/layout/contact_tile_frequent.xml
+++ b/res/layout/contact_tile_frequent.xml
@@ -38,7 +38,7 @@
android:id="@+id/contact_tile_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:textColor="@android:color/black"
+ android:textColor="@color/frequent_contact_text_color"
android:textSize="@dimen/contact_browser_list_item_text_size"
android:singleLine="true"
android:fadingEdge="horizontal"
diff --git a/res/layout/contact_tile_starred.xml b/res/layout/contact_tile_starred.xml
index 777cc058..88aa1e88 100644
--- a/res/layout/contact_tile_starred.xml
+++ b/res/layout/contact_tile_starred.xml
@@ -43,7 +43,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="7dp"
- android:textColor="#202020"
+ android:textColor="@color/contact_tile_text_color"
android:textSize="@dimen/contact_browser_list_item_text_size"
android:singleLine="true"
android:fadingEdge="horizontal"
diff --git a/res/layout/ip_prefix_dialog.xml b/res/layout/ip_prefix_dialog.xml
new file mode 100644
index 00000000..9de02dcb
--- /dev/null
+++ b/res/layout/ip_prefix_dialog.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <EditText
+ android:id="@+id/ip_prefix_dialog_edit"
+ android:layout_width="match_parent"
+ android:layout_height="45dip"
+ android:layout_margin="10dip"
+ android:inputType="phone"
+ android:hint="@string/ipcall_dialog_edit_hint"/>
+
+</LinearLayout>
diff --git a/res/layout/search_bar_expanded.xml b/res/layout/search_bar_expanded.xml
index 3c71b508..ff7c3227 100644
--- a/res/layout/search_bar_expanded.xml
+++ b/res/layout/search_bar_expanded.xml
@@ -37,7 +37,7 @@
android:layout_width="0dp"
android:layout_height="@dimen/search_box_icon_size"
android:layout_weight="1"
- android:layout_marginLeft="@dimen/search_box_text_left_margin"
+ android:layout_marginStart="@dimen/search_box_text_left_margin"
android:textSize="@dimen/search_text_size"
android:fontFamily="@string/search_font_family"
android:textColor="@color/searchbox_text_color"
diff --git a/res/values-af/cm_strings.xml b/res/values-af/cm_strings.xml
new file mode 100644
index 00000000..6ab5a69c
--- /dev/null
+++ b/res/values-af/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Plaaslike tablet rekening</string>
+ <string name="local_storage_account" product="default">Plaaslike telefoon rekening</string>
+ <string name="import_contacts_sim">Voer kontakte in van SIM kaart?</string>
+ <string name="manage_sim_contacts">Bestuur SIM kaart kontakte</string>
+ <string name="export_to_sim">Uitvoer na SIM-kaart</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' kon nie ingevoer word nie a.g.v. \'n I/U fout</string>
+ <string name="contact_share_failed_toast">Nie meer as <xliff:g id="count">%d</xliff:g> kontakte kan gedeel word nie</string>
+ <string name="label_groups">Groepe</string>
+ <string name="exporting">Uitvoering\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> van <xliff:g id="total_number">%2$s</xliff:g> lêers</string>
+ <string name="export_failed">Uitvoer het misluk</string>
+ <string name="sim_card_full">SIM kaart is vol</string>
+ <string name="export_finished">Uitvoer Klaar</string>
+ <string name="tag_too_long">Kontak naam is te lank</string>
+ <string name="sim_contacts_not_loaded">Kon nie SIM kontakte laai nie</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Uitvoering was gekanselleer, %d item is uitgevoer</item>
+ <item quantity="other">Uitvoering was gekanselleer, %d items is uitgevoer</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> het nie \'n telefoonnommer of epos adres nie</string>
+ <string name="import_from_sim_select">Kies kaart om in te voer</string>
+ <string name="no_sdcard_title" product="nosdcard">Spasie onbeskikbaar</string>
+ <string name="no_sdcard_title" product="default">Geen SD kaart</string>
+ <string name="deleteConfirmation_title">Verwyder kontak?</string>
+ <string name="deleteConfirmation">Hierdie kontak sal verwyder word.</string>
+ <string name="copy_done">Kontak suksesvol gekopieer</string>
+ <string name="copy_failure">Kopiëring van die kontak het misluk</string>
+ <string name="card_no_space">Kopiëring van die kontak het misluk, die SIM-kaart is vol</string>
+ <string name="settings_contact_display_options_description">Stel hoe jou kontakte vertoon en gesorteer sal word.</string>
+ <string name="ip_call_by_slot">IP oproep via <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Geen IP nommer</string>
+ <string name="no_ip_number_on_sim_card">Geen IP nommer op SIM-kaart</string>
+ <string name="set_ip_number">Stel IP nommer</string>
+ <string name="ipcall_dialog_title">IP oproep instellings</string>
+ <string name="ipcall_dialog_edit_hint">Voer die IP voorvoegsel in</string>
+ <string name="import_contacts_from_all_cards">Voer kontakte in van alle SIM kaarte</string>
+ <string name="select_path">Kies</string>
+ <string name="select_sim">Kies SIM</string>
+</resources>
diff --git a/res/values-ar/cm_strings.xml b/res/values-ar/cm_strings.xml
new file mode 100644
index 00000000..02e6d067
--- /dev/null
+++ b/res/values-ar/cm_strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">حساب الكمبيوتر اللوحي المحلي</string>
+ <string name="local_storage_account" product="default">حساب الهاتف المحلية</string>
+</resources>
diff --git a/res/values-ast-rES/cm_strings.xml b/res/values-ast-rES/cm_strings.xml
new file mode 100644
index 00000000..bb45c4fb
--- /dev/null
+++ b/res/values-ast-rES/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Cuenta llocal de la tablet</string>
+ <string name="local_storage_account" product="default">Cuenta llocal del teléfonu</string>
+ <string name="import_contacts_sim">¿Importar contautos de la tarxeta SIM?</string>
+ <string name="manage_sim_contacts">Xestionar contautos de tarxeta SIM</string>
+ <string name="export_to_sim">Esportar a la tarxeta SIM</string>
+ <string name="fail_reason_import_vcard">\u00AB<xliff:g id="name">%s</xliff:g>\u00BB nun pue importase pola mor d\'un fallu de E/S</string>
+ <string name="contact_share_failed_toast">Nun puen compartise más de <xliff:g id="count">%d</xliff:g> contautos</string>
+ <string name="label_groups">Grupu</string>
+ <string name="exporting">Esportando\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> de <xliff:g id="total_number">%2$s</xliff:g> ficheros</string>
+ <string name="export_failed">Falló al esportar</string>
+ <string name="sim_card_full">La tarxeta SIM ta enllena</string>
+ <string name="export_finished">Finó la esportación</string>
+ <string name="tag_too_long">El nome del contautu ye enforma llargu</string>
+ <string name="sim_contacts_not_loaded">Nun puen cargase los contautos de la tarxeta SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Esportación encaboxada. Esportóse %d contautu</item>
+ <item quantity="other">Esportación encaboxada. Esportáronse %d contautos</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> nun tien un númberu de tefnu o una direición de corréu</string>
+ <string name="import_from_sim_select">Escueyi una tarxeta pa importar</string>
+ <string name="no_sdcard_title" product="nosdcard">Almacenamientu non disponible</string>
+ <string name="no_sdcard_title" product="default">Falta la tarxeta SD</string>
+ <string name="deleteConfirmation_title">Desaniciar contautu?</string>
+ <string name="deleteConfirmation">El contautu va desaniciase.</string>
+ <string name="copy_done">Contautu copiáu correchamente</string>
+ <string name="copy_failure">Falló la copia del contautu</string>
+ <string name="card_no_space">Falló la copia de tolos contautos. La tarxeta SIM ta enllena</string>
+ <string name="settings_contact_display_options_description">Configurar cómo s\'amuesen y s\'ordenen los contautos</string>
+ <string name="ip_call_by_slot">Llamada IP vía <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Nun hai númberu IP</string>
+ <string name="no_ip_number_on_sim_card">Nun hai númberu IP na tarxeta SIM</string>
+ <string name="set_ip_number">Afitar númberu IP</string>
+ <string name="ipcall_dialog_title">Axustes de llamada IP</string>
+ <string name="ipcall_dialog_edit_hint">Introduz el prefixu IP</string>
+ <string name="import_contacts_from_all_cards">Importar contautos de toles tarxetes SIM</string>
+ <string name="select_path">Seleiciona\'l camín</string>
+ <string name="select_sim">Seleicionar SIM</string>
+</resources>
diff --git a/res/values-ast-rES/strings.xml b/res/values-ast-rES/strings.xml
new file mode 100644
index 00000000..6883c771
--- /dev/null
+++ b/res/values-ast-rES/strings.xml
@@ -0,0 +1,257 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ ~ Copyright (C) 2012 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_text_copied">Testu copiáu</string>
+ <string name="call_custom">Llamar a <xliff:g id="CUSTOM">%s</xliff:g>
+ </string>
+ <string name="call_home">Llamar a casa</string>
+ <string name="call_mobile">Llamar al móvil</string>
+ <string name="call_work">Llamar al trabayu</string>
+ <string name="call_fax_work">Llamar al fax del trabayu</string>
+ <string name="call_fax_home">Llamar al fax de casa</string>
+ <string name="call_pager">Llamar al busca</string>
+ <string name="call_other">Llamar</string>
+ <string name="call_callback">Llamar a un númberu de devolución de llamada</string>
+ <string name="call_car">Llamar al coche</string>
+ <string name="call_company_main">Llamar al teléfonu principal de la empresa</string>
+ <string name="call_isdn">Llamar a RDSI</string>
+ <string name="call_main">Llamar al teléfonu principal</string>
+ <string name="call_other_fax">Llamar al fax</string>
+ <string name="call_radio">Llamar a la radio</string>
+ <string name="call_telex">Llamar al télex</string>
+ <string name="call_tty_tdd">Llamar a TTY/TDD</string>
+ <string name="call_work_mobile">Llamar al móvil del trabayu</string>
+ <string name="call_work_pager">Llamar al busca del trabayu</string>
+ <string name="call_assistant">Llamar al <xliff:g id="ASSISTANT">%s</xliff:g></string>
+ <string name="call_mms">Llamar a MMS</string>
+ <string name="sms_custom">Testu <xliff:g id="CUSTOM">%s</xliff:g></string>
+ <string name="sms_home">Unviar SMS a casa</string>
+ <string name="sms_mobile">Unviar SMS al móvil</string>
+ <string name="sms_work">Unviar SMS al trabayu</string>
+ <string name="sms_fax_work">Unviar SMS al fax del trabayu</string>
+ <string name="sms_fax_home">Unviar SMS al fax de casa</string>
+ <string name="sms_pager">Unviar SMS al busca</string>
+ <string name="sms_other">Unviar SMS</string>
+ <string name="sms_callback">Unviar SMS a un númberu de devolución de llamada</string>
+ <string name="sms_car">Unviar SMS al coche</string>
+ <string name="sms_company_main">Unviar SMS al teléfonu principal de la empresa</string>
+ <string name="sms_isdn">Unviar SMS a RDSI</string>
+ <string name="sms_main">Unviar SMS al númberu de teléfonu principal</string>
+ <string name="sms_other_fax">Unviar SMS al fax</string>
+ <string name="sms_radio">Unviar SMS a la radio</string>
+ <string name="sms_telex">Unviar SMS al télex</string>
+ <string name="sms_tty_tdd">Unviar SMS a TTY/TDD</string>
+ <string name="sms_work_mobile">Unviar SMS al móvil del trabayu</string>
+ <string name="sms_work_pager">Unviar SMS al busca del trabayu</string>
+ <string name="sms_assistant">Unviar SMS al <xliff:g id="ASSISTANT">%s</xliff:g></string>
+ <string name="sms_mms">Unviar SMS a MMS</string>
+ <string name="description_video_call">Facer videollamada</string>
+ <string name="clearFrequentsConfirmation_title">¿Llimpiar contautos frecuentes?</string>
+ <string name="clearFrequentsConfirmation">Vas llimpiar la llista de contautos frecuentes de les aplicaciones Contautos y Teléfonu y con esto vas obligar a les aplicaciones de corréu-e a que memoricen les tos preferencies otra vegada.</string>
+ <string name="clearFrequentsProgress_title">Llimpiando contautos frecuentes…</string>
+ <string name="status_available">Disponible</string>
+ <string name="status_away">Ausente</string>
+ <string name="status_busy">Ocupáu</string>
+ <string name="contactsList">Contautos</string>
+ <string name="local_invisible_directory">Otros</string>
+ <string name="directory_search_label">Direutoriu</string>
+ <string name="local_search_label">Tolos contautos</string>
+ <string name="user_profile_contacts_list_header" msgid="9154761216179882405">Yo</string>
+ <string name="search_results_searching">Buscando...</string>
+ <string name="foundTooManyContacts">Alcontráronse más de <xliff:g id="COUNT">%d</xliff:g> contautos.</string>
+ <string name="listFoundAllContactsZero">Nengún contautu</string>
+ <plurals name="searchFoundContacts">
+ <item quantity="one">1 contautu alcontráu</item>
+ <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> contautos alcontraos\"</item>
+ </plurals>
+ <string name="description_quick_contact_for">Contautu rápidu de <xliff:g id="NAME">%1$s</xliff:g></string>
+ <string name="missing_name">(Ensin nome)</string>
+ <string name="favoritesFrequentCalled">Más llamaos</string>
+ <string name="favoritesFrequentContacted">Contautos frecuentes</string>
+ <string name="description_view_contact_detail" msgid="2795575601596468581">Ver contautu</string>
+ <string name="list_filter_phones">Tolos contautos con númberu</string>
+ <string name="view_updates_from_group">Ver anovamientos</string>
+ <string name="account_phone" product="tablet">Namái na tablet (ensin sincronizar)</string>
+ <string name="account_phone" product="default">Namái nel teléfonu, non sincronizáu</string>
+ <string name="nameLabelsGroup">Nome</string>
+ <string name="nicknameLabelsGroup">Nomatu</string>
+ <string name="full_name">Nome</string>
+ <string name="name_given">Nome</string>
+ <string name="name_family">Apellíu</string>
+ <string name="name_prefix">Prefixu del nome</string>
+ <string name="name_middle">Segundu nome</string>
+ <string name="name_suffix">Sufixu del nome</string>
+ <string name="name_phonetic">Nome fonéticu</string>
+ <string name="name_phonetic_given">Nome fonéticu</string>
+ <string name="name_phonetic_middle">Segundu nome fonéticu</string>
+ <string name="name_phonetic_family">Apellíu fonéticu</string>
+ <string name="phoneLabelsGroup">Teléfonu</string>
+ <string name="emailLabelsGroup">Corréu-e</string>
+ <string name="postalLabelsGroup">Señes</string>
+ <string name="imLabelsGroup">Chat</string>
+ <string name="organizationLabelsGroup">Organización</string>
+ <string name="relationLabelsGroup">Rellación</string>
+ <string name="eventLabelsGroup">Eventos</string>
+ <string name="sms">Mensaxe de testu</string>
+ <string name="postal_address">Señes</string>
+ <string name="ghostData_company">Empresa</string>
+ <string name="ghostData_title">Nome</string>
+ <string name="label_notes">Notes</string>
+ <string name="label_sip_address">SIP</string>
+ <string name="websiteLabelsGroup">Sitiu web</string>
+ <string name="groupsLabel">Grupos</string>
+ <string name="email_home">Unviar corréu a casa</string>
+ <string name="email_mobile">Unviar corréu al móvil</string>
+ <string name="email_work">Unviar corréu al trabayu</string>
+ <string name="email_other">Unviar corréu</string>
+ <string name="email_custom">Unviar corréu a <xliff:g id="CUSTOM">%s</xliff:g></string>
+ <string name="email">Corréu-e electrónicu</string>
+ <string name="postal_street">Cai</string>
+ <string name="postal_pobox">Apartáu postal</string>
+ <string name="postal_neighborhood">Vecindariu</string>
+ <string name="postal_city">Ciudá</string>
+ <string name="postal_region">Estáu</string>
+ <string name="postal_postcode">Códigu postal</string>
+ <string name="postal_country">País</string>
+ <string name="map_home">Ver direición de casa</string>
+ <string name="map_work">Ver direición del trabayu</string>
+ <string name="map_other">Ver direición</string>
+ <string name="map_custom">Ver direición de <xliff:g id="CUSTOM">%s</xliff:g></string>
+ <string name="chat_aim">Chat con AIM</string>
+ <string name="chat_msn">Chat con Windows Live</string>
+ <string name="chat_yahoo">Chat con Yahoo!</string>
+ <string name="chat_skype">Chat con Skype</string>
+ <string name="chat_qq">Chat con QQ</string>
+ <string name="chat_gtalk">Chat con Google Talk</string>
+ <string name="chat_icq">Chat con ICQ</string>
+ <string name="chat_jabber">Chat con Jabber</string>
+ <string name="chat">Chat</string>
+ <string name="description_minus_button">desaniciar</string>
+ <string name="expand_collapse_name_fields_description">Enantar o contrayer campos de nome</string>
+ <string name="list_filter_all_accounts">Tolos contautos</string>
+ <string name="list_filter_all_starred">Destacaos</string>
+ <string name="list_filter_customize">Personalizar</string>
+ <string name="list_filter_single">Contautu</string>
+ <string name="display_ungrouped">Tolos demás contautos</string>
+ <string name="display_all_contacts">Tolos contautos</string>
+ <string name="menu_sync_remove">Desaniciar grupu de sincronización</string>
+ <string name="dialog_sync_add">Amestar grupu de sincronización</string>
+ <string name="display_more_groups">Más grupos…</string>
+ <string name="display_warn_remove_ungrouped">Si desanicies \"<xliff:g id="GROUP">%s</xliff:g>\" de les sincronizaciones, tamién van desaniciase tolos contautos ensin agrupar.</string>
+ <string name="savingDisplayGroups">Guardando opciones de visualización…</string>
+ <string name="menu_done">Fecho</string>
+ <string name="menu_doNotSave">Encaboxar</string>
+ <string name="listAllContactsInAccount">Contautos en <xliff:g id="NAME">%s</xliff:g></string>
+ <string name="listCustomView">Contautos en vista personalizada</string>
+ <string name="listSingleContact">Contautu únicu</string>
+ <string name="dialog_new_contact_account">Crear contautu na cuenta</string>
+ <string name="import_from_sim">Importar contautos de la tarxeta SIM</string>
+ <string name="import_from_sim_number">Importar dende tarxeta SIM #<xliff:g id="sim_number" example="2">%d</xliff:g></string>
+ <string name="import_from_sdcard" product="default">Importar d\'almacenamientu</string>
+ <string name="cancel_import_confirmation_message">¿Quies encaboxar la importación de <xliff:g id="FILENAME">%s</xliff:g>?</string>
+ <string name="cancel_export_confirmation_message">¿Quies encaboxar la esportación de <xliff:g id="FILENAME">%s</xliff:g>?</string>
+ <string name="cancel_vcard_import_or_export_failed">Fallu al encaboxar la importación/esportación de vCard</string>
+ <string name="fail_reason_unknown">Fallu desconocíu</string>
+ <string name="fail_reason_could_not_open_file">Nun pudo abrise\'l ficheru \"<xliff:g id="FILE_NAME">%s</xliff:g>" (<xliff:g id="EXACT_REASON">%s</xliff:g>).</string>
+ <string name="fail_reason_could_not_initialize_exporter">Nun pudo aniciase l\'esportador (\"<xliff:g id="EXACT_REASON">%s</xliff:g>\").</string>
+ <string name="fail_reason_no_exportable_contact">Nun hai contautos qu\'esportar.</string>
+ <string name="fail_reason_error_occurred_during_export">Hebo un fallu al esportar (\"<xliff:g id="EXACT_REASON">%s</xliff:g>\").</string>
+ <string name="fail_reason_too_long_filename">El nome de ficheru ye enforma llargu (\"<xliff:g id="FILENAME">%s</xliff:g>\").</string>
+ <string name="fail_reason_too_many_vcard" product="nosdcard">Hai munchos ficheros vCard nel almacenamientu.</string>
+ <string name="fail_reason_too_many_vcard" product="default">Hai munchos ficheros vCard na tarxeta SD.</string>
+ <string name="fail_reason_io_error">Fallu de E/S</string>
+ <string name="fail_reason_low_memory_during_import">Nun hai bastante espaciu de memoria (el ficheru pue ser enforma grande).</string>
+ <string name="fail_reason_vcard_parse_error">Nun pudo analizase\'l ficheru vCard por un fallu inesperáu.</string>
+ <string name="fail_reason_not_supported">Formatu non almitíu</string>
+ <string name="fail_reason_failed_to_collect_vcard_meta_info">Nun pudieron recuperase los metadatos de los ficheros vCard.</string>
+ <string name="fail_reason_failed_to_read_files">Nun pudo importase ún o más ficheros (%s).</string>
+ <string name="exporting_vcard_finished_title">Esportación de <xliff:g id="FILENAME">%s</xliff:g> finada</string>
+ <string name="exporting_vcard_canceled_title">Encaboxóse la esportación de <xliff:g id="FILENAME">%s</xliff:g>.</string>
+ <string name="exporting_contact_list_title">Esportando datos de contautu...</string>
+ <string name="exporting_contact_list_message">Tán esportándose los tos datos de contautos a <xliff:g id="FILE_NAME">%s</xliff:g>.</string>
+ <string name="composer_failed_to_get_database_infomation">Nun pudo obtenese información de la base de datos.</string>
+ <string name="composer_has_no_exportable_contact" product="tablet">Nun hai contautos qu\'esportar. Si yá tienes contautos na tablet, ye dable que\'l fornidor de datos nun permita que s\'esporten los contautos del tablet.</string>
+ <string name="composer_has_no_exportable_contact" product="default">Nun hai contautos qu\'esportar. Si yá tienes contautos nel teléfonu, ye dable que\'l fornidor de datos nun permita que s\'esporten los contautos del teléfonu.</string>
+ <string name="composer_not_initialized">El redautor de vCard nun s\'anició correutamente.</string>
+ <string name="exporting_contact_failed_title">Fallu al esportar</string>
+ <string name="exporting_contact_failed_message">Nun s\'esportaron los datos de contautu(\"\n\"motivu: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\").</string>
+ <string name="no_sdcard_message" product="nosdcard">Nun hai nengún almacenamientu.</string>
+ <string name="no_sdcard_message" product="default">Nun se deteutó nenguna tarxeta SD.</string>
+ <string name="confirm_export_message">La to llista de contautos va esportase al ficheru <xliff:g id="VCARD_FILENAME">%s</xliff:g>.</string>
+ <string name="importing_vcard_description">Importando <xliff:g id="NAME">%s</xliff:g>...</string>
+ <string name="reading_vcard_failed_title">Fallu al lleer los datos de vCard</string>
+ <string name="reading_vcard_canceled_title">Llectura de datos de vCard encaboxada</string>
+ <string name="importing_vcard_finished_title">Importación de <xliff:g id="FILENAME">%s</xliff:g> de vCard finada</string>
+ <string name="importing_vcard_canceled_title">Encaboxóse la importación de <xliff:g id="FILENAME">%s</xliff:g>.</string>
+ <string name="vcard_import_will_start_message"><xliff:g id="FILENAME">%s</xliff:g> va importase darréu.</string>
+ <string name="vcard_import_will_start_message_with_default_name">El ficheru va importase darréu.</string>
+ <string name="vcard_import_request_rejected_message">Refugóse la solicitú d\'importación de vCard. Inténtalo de nueves más tarde.</string>
+ <string name="vcard_export_will_start_message"><xliff:g id="FILENAME">%s</xliff:g> va esportase darréu.</string>
+ <string name="vcard_export_request_rejected_message">Refugóse la solicitú d\'esportación de vCard. Inténtalo de nueves más tarde.</string>
+ <string name="vcard_unknown_filename">contautu</string>
+ <string name="caching_vcard_message">Tán almacenándose los ficheros vCard na la caché. La importación va aniciase aína.</string>
+ <string name="percentage"><xliff:g id="PERCENTAGE">%s</xliff:g><xliff:g id="PERCENTSIGN">%%</xliff:g></string>
+ <string name="vcard_import_failed">Fallu al importar el ficheru vCard</string>
+ <string name="import_failure_no_vcard_file" product="nosdcard">Nun s\'atoparon ficheros vCard nel almacenamientu.</string>
+ <string name="import_failure_no_vcard_file" product="default">Nun s\'atoparon ficheros vCard na tarxeta SD.</string>
+ <string name="nfc_vcard_file_name">Contautu recibíu per NFC</string>
+ <string name="confirm_export_title">¿Esportar contautos?</string>
+ <string name="select_vcard_title">Seleicionar ficheru vCard</string>
+ <string name="import_one_vcard_string">Importar un ficheru de vCard</string>
+ <string name="import_multiple_vcard_string">Importar dellos ficheros de vCard</string>
+ <string name="import_all_vcard_string">Importar tolos ficheros de vCard</string>
+ <string name="searching_vcard_message" product="nosdcard">Guetando por datos de vCard nel almacenamientu...</string>
+ <string name="searching_vcard_message" product="default">Guetando por datos de vCard na tarxeta SD...</string>
+ <string name="caching_vcard_title">Almacenando na caché...</string>
+ <string name="scanning_sdcard_failed_message" product="nosdcard">Nun pudo analizase l\'almacenamientu (motivu: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\").</string>
+ <string name="scanning_sdcard_failed_message" product="default">Nun pudo analizase la tarxeta SD (motivu: \"<xliff:g id="FAIL_REASON">%s</xliff:g>\").</string>
+ <string name="progress_notifier_message">Importando <xliff:g id="CURRENT_NUMBER">%s</xliff:g>/<xliff:g id="TOTAL_NUMBER">%s</xliff:g>: <xliff:g id="NAME">%s</xliff:g></string>
+ <string name="export_to_sdcard" product="default">Esportar a almacenamientu</string>
+ <string name="display_options_sort_list_by">Ordenar por</string>
+ <string name="display_options_sort_by_given_name">Nome</string>
+ <string name="display_options_sort_by_family_name">Apellíu</string>
+ <string name="display_options_view_names_as">Formatu nome</string>
+ <string name="display_options_view_given_name_first">Nome primero</string>
+ <string name="display_options_view_family_name_first">Apellíu primero</string>
+ <string name="share_visible_contacts">Compartir contautos visibles</string>
+ <string name="dialog_import_export">Importar/esportar contautos</string>
+ <string name="dialog_import">Importar contautos</string>
+ <string name="share_error">Nun pue compartise esti contautu.</string>
+ <string name="menu_search">Guetar</string>
+ <string name="menu_contacts_filter">Contautos qu\'amosar</string>
+ <string name="activity_title_contacts_filter">Contautos qu\'amosar</string>
+ <string name="custom_list_filter">Definición de vista personalizada</string>
+ <string name="hint_findContacts">Guetar contautos</string>
+ <string name="contactsFavoritesLabel">Favoritos</string>
+ <string name="listTotalAllContactsZero">Nun hai nengún contautu.</string>
+ <string name="listTotalAllContactsZeroCustom">Nun hai contautos visibles.</string>
+ <string name="listTotalAllContactsZeroStarred">Nun hai favoritos.</string>
+ <string name="listTotalAllContactsZeroGroup">Nengún contautu en <xliff:g id="name" example="Friends">%s</xliff:g></string>
+ <string name="menu_clear_frequents">Llimpiar frecuentes</string>
+ <string name="menu_select_sim">Seleicionar tarxeta SIM</string>
+ <string name="menu_accounts">Cuentes</string>
+ <string name="menu_import_export">Importar/esportar</string>
+ <string name="tab_font_family">sans-serif</string>
+ <string name="contact_status_update_attribution">per aciu de <xliff:g id="source" example="Google Talk">%1$s</xliff:g></string>
+ <string name="contact_status_update_attribution_with_date"><xliff:g id="date" example="3 hours ago">%1$s</xliff:g> per aciu de <xliff:g id="source" example="Google Talk">%2$s</xliff:g></string>
+ <string name="letter_tile_letter_font_family">sans-serif-light</string>
+ <string name="action_menu_back_from_search">Parar la gueta</string>
+ <string name="description_clear_search">Llimpiar gueta</string>
+ <string name="search_font_family">sans-serif</string>
+ <string name="settings_contact_display_options_title">Opciones visualización contautos</string>
+</resources>
diff --git a/res/values-az-rAZ/cm_strings.xml b/res/values-az-rAZ/cm_strings.xml
new file mode 100644
index 00000000..c0d1b6bf
--- /dev/null
+++ b/res/values-az-rAZ/cm_strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Yerli tablet hesabı</string>
+ <string name="local_storage_account" product="default">Yerli telefon hesabı</string>
+ <string name="label_groups">Qrup</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> / <xliff:g id="total_number">%2$s</xliff:g> fayl</string>
+ <string name="export_failed">İxrac uğursuz oldu</string>
+ <string name="export_finished">İxrac tamamlandı</string>
+ <string name="import_from_sim_select">İdxal olunacaq kartı seçin</string>
+ <string name="no_sdcard_title" product="nosdcard">Yaddaş əlçatmazdır</string>
+ <string name="no_sdcard_title" product="default">SD kart yoxdur</string>
+ <string name="deleteConfirmation_title">Şəxs silinsin?</string>
+ <string name="deleteConfirmation">Bu şəxs silinəcək.</string>
+ <string name="no_ip_number">IP nömrəsi yoxdur</string>
+ <string name="no_ip_number_on_sim_card">SIM kartda IP nömrəsi yoxdur</string>
+ <string name="ipcall_dialog_edit_hint">Zəhmət olmasa IP önəlavəsini daxil edin</string>
+ <string name="select_sim">SIM seç</string>
+</resources>
diff --git a/res/values-bn-rBD/cm_strings.xml b/res/values-bn-rBD/cm_strings.xml
new file mode 100644
index 00000000..f0655567
--- /dev/null
+++ b/res/values-bn-rBD/cm_strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">স্থানীয় ট্যাবলেট একাউন্ট</string>
+ <string name="export_to_sim">সিম কার্ডে রপ্তানি করুন</string>
+ <string name="select_sim">সিম নির্বাচন</string>
+</resources>
diff --git a/res/values-ca/cm_strings.xml b/res/values-ca/cm_strings.xml
new file mode 100644
index 00000000..0ed51aea
--- /dev/null
+++ b/res/values-ca/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Compte local de la tauleta</string>
+ <string name="local_storage_account" product="default">Compte local del telèfon</string>
+ <string name="import_contacts_sim">Vols importar els contactes de la targeta SIM?</string>
+ <string name="manage_sim_contacts">Gestiona els contactes de la targeta SIM</string>
+ <string name="export_to_sim">Exporta a la targeta SIM</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' no han pogut ser importats degur a un error d\'E/S</string>
+ <string name="contact_share_failed_toast">Només hi ha <xliff:g id="count">%d</xliff:g> contactes que puguin ser compartits</string>
+ <string name="label_groups">Grup</string>
+ <string name="exporting">S\'està exportant\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> de <xliff:g id="total_number">%2$s</xliff:g> fitxers</string>
+ <string name="export_failed">S\'ha produït un error en l\'exportació</string>
+ <string name="sim_card_full">La targeta SIM és plena</string>
+ <string name="export_finished">S\'ha finalitzat l\'exportació</string>
+ <string name="tag_too_long">El nom del contacte és massa llarg</string>
+ <string name="sim_contacts_not_loaded">No s\'han pogut carregar els contactes de la SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">S\'ha cancel·lat l\'exportació, %d element ha sigut exportat</item>
+ <item quantity="other">S\'ha cancel·lat l\'exportació, %d elements han sigut exportats</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> no té un número de telèfon o una adreça de correu electrònic</string>
+ <string name="import_from_sim_select">Tria la targeta a importar</string>
+ <string name="no_sdcard_title" product="nosdcard">Emmagatzematge no disponible</string>
+ <string name="no_sdcard_title" product="default">No hi ha targeta SD</string>
+ <string name="deleteConfirmation_title">Vols esborrar el contacte?</string>
+ <string name="deleteConfirmation">Aquest contacte serà esborrat.</string>
+ <string name="copy_done">El contacte ha sigut copiat satisfactòriament</string>
+ <string name="copy_failure">No s\'ha pogut copiar el contacte</string>
+ <string name="card_no_space">No s\'ha pogut copiar el contacte, la targeta SIM és plena</string>
+ <string name="settings_contact_display_options_description">Configura com són mostrats i ordenats els contactes.</string>
+ <string name="ip_call_by_slot">Trucada IP amb <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Sense número IP</string>
+ <string name="no_ip_number_on_sim_card">Sense número IP a la targeta SIM</string>
+ <string name="set_ip_number">Estableix un número IP</string>
+ <string name="ipcall_dialog_title">Ajustaments de trucada IP</string>
+ <string name="ipcall_dialog_edit_hint">Si us plau introdueix el prefix IP</string>
+ <string name="import_contacts_from_all_cards">Importa els contactes de totes les targetes SIM</string>
+ <string name="select_path">Selecciona la ruta</string>
+ <string name="select_sim">Selecciona SIM</string>
+</resources>
diff --git a/res/values-cs/cm_strings.xml b/res/values-cs/cm_strings.xml
new file mode 100644
index 00000000..a10c6aa1
--- /dev/null
+++ b/res/values-cs/cm_strings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Lokální účet tabletu</string>
+ <string name="local_storage_account" product="default">Lokální účet telefonu</string>
+ <string name="import_contacts_sim">Importovat kontakty ze SIM karty?</string>
+ <string name="manage_sim_contacts">Spravovat kontakty na SIM kartě</string>
+ <string name="export_to_sim">Exportovat na SIM kartu</string>
+ <string name="fail_reason_import_vcard">Z důvodu chyby přístupu nelze importovat „<xliff:g id="name">%s</xliff:g>“</string>
+ <string name="contact_share_failed_toast">Nelze sdílet více než <xliff:g id="count">%d</xliff:g> kontaktů</string>
+ <string name="label_groups">Skupina</string>
+ <string name="exporting">Exportování\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> z <xliff:g id="total_number">%2$s</xliff:g> souborů</string>
+ <string name="export_failed">Export se nezdařil</string>
+ <string name="sim_card_full">SIM karta je plná</string>
+ <string name="export_finished">Export dokončen</string>
+ <string name="tag_too_long">Jméno kontaktu je příliš dlouhé</string>
+ <string name="sim_contacts_not_loaded">Nelze načíst kontakty SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Export byl zrušen, %d kontakt byl exportován</item>
+ <item quantity="few">Export byl zrušen, %d kontakty byly exportovány</item>
+ <item quantity="other">Export byl zrušen, %d kontaktů bylo exportováno</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s </xliff:g> nemá telefonní číslo ani e-mailovou adresu</string>
+ <string name="import_from_sim_select">Vyberte kartu pro import</string>
+ <string name="no_sdcard_title" product="nosdcard">Úložiště nedostupné</string>
+ <string name="no_sdcard_title" product="default">Žádná SD karta</string>
+ <string name="deleteConfirmation_title">Odstranit kontakt?</string>
+ <string name="deleteConfirmation">Tento kontakt bude odstraněn.</string>
+ <string name="copy_done">Kontakt byl úspěšně zkopírován</string>
+ <string name="copy_failure">Kopírování kontaktu selhalo</string>
+ <string name="card_no_space">Kopírování kontaktu selhalo, SIM karta je plná</string>
+ <string name="settings_contact_display_options_description">Nastavit jak budou kontakty zobrazeny a řazeny.</string>
+ <string name="ip_call_by_slot">IP volání prostřednictvím <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Žádné IP číslo</string>
+ <string name="no_ip_number_on_sim_card">Žádné IP číslo na SIM kartě</string>
+ <string name="set_ip_number">Nastavit IP číslo</string>
+ <string name="ipcall_dialog_title">Nastavení IP volání</string>
+ <string name="ipcall_dialog_edit_hint">Zadejte prefix pro IP</string>
+ <string name="import_contacts_from_all_cards">Importovat kontakty ze všech SIM karet</string>
+ <string name="select_path">Vybrat cestu</string>
+ <string name="select_sim">Vybrat SIM kartu</string>
+</resources>
diff --git a/res/values-da/cm_strings.xml b/res/values-da/cm_strings.xml
new file mode 100644
index 00000000..e6cd5b2e
--- /dev/null
+++ b/res/values-da/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Lokal tabletkonto</string>
+ <string name="local_storage_account" product="default">Lokal telefonkonto</string>
+ <string name="import_contacts_sim">Importér kontakter fra SIM-kort?</string>
+ <string name="manage_sim_contacts">Administrer SIM-kort kontakter</string>
+ <string name="export_to_sim">Eksportér til SIM-kortet</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' kunne ikke importeres på grund af en I/O-fejl</string>
+ <string name="contact_share_failed_toast">Ikke mere end <xliff:g id="count">%d</xliff:g> kontakter kan deles</string>
+ <string name="label_groups">Gruppe</string>
+ <string name="exporting">Eksporterer\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> af <xliff:g id="total_number">%2$s</xliff:g> filer</string>
+ <string name="export_failed">Eksport mislykkedes</string>
+ <string name="sim_card_full">SIM-kort er fyldt</string>
+ <string name="export_finished">Eksport afsluttet</string>
+ <string name="tag_too_long">Kontaktnavn er for langt</string>
+ <string name="sim_contacts_not_loaded">Kan ikke indlæse SIM-kontakter</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Eksport blev annulleret, %d element blev eksporteret</item>
+ <item quantity="other">Eksport blev annulleret, %d elementer blev eksporteret</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> har ikke et telefonnummer eller en e-mail adresse</string>
+ <string name="import_from_sim_select">Vælg det kort, der skal importeres</string>
+ <string name="no_sdcard_title" product="nosdcard">Lager ikke tilgængelig</string>
+ <string name="no_sdcard_title" product="default">Intet SD-kort</string>
+ <string name="deleteConfirmation_title">Slet kontaktperson?</string>
+ <string name="deleteConfirmation">Denne kontaktperson vil blive slettet.</string>
+ <string name="copy_done">Kontakt blev kopieret korrekt</string>
+ <string name="copy_failure">Kopiering af kontaktpersonen mislykkedes</string>
+ <string name="card_no_space">Kopiering af kontaktpersonen mislykkedes, SIM-kortet er fyldt</string>
+ <string name="settings_contact_display_options_description">Konfigurer hvordan, dine kontakter vises og sorteres.</string>
+ <string name="ip_call_by_slot">IP-opkald med <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Intet IP-nummer</string>
+ <string name="no_ip_number_on_sim_card">Intet IP-nummer på SIM-kortet</string>
+ <string name="set_ip_number">Angiv IP-nummer</string>
+ <string name="ipcall_dialog_title">IP-opkaldsindstillinger</string>
+ <string name="ipcall_dialog_edit_hint">Indtast IP-præfiks</string>
+ <string name="import_contacts_from_all_cards">Importér kontakter fra alle SIM-kort</string>
+ <string name="select_path">Vælg sti</string>
+ <string name="select_sim">Vælg SIM</string>
+</resources>
diff --git a/res/values-de/cm_strings.xml b/res/values-de/cm_strings.xml
new file mode 100644
index 00000000..2c175fc8
--- /dev/null
+++ b/res/values-de/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Lokales Tablet-Konto</string>
+ <string name="local_storage_account" product="default">Lokales Telefon-Konto</string>
+ <string name="import_contacts_sim">Kontakte von der SIM-Karte importieren?</string>
+ <string name="manage_sim_contacts">Kontakte auf SIM-Karte verwalten</string>
+ <string name="export_to_sim">Auf SIM-Karte exportieren</string>
+ <string name="fail_reason_import_vcard">\"<xliff:g id="name">%s</xliff:g>\" konnte aufgrund eines I/O-Fehlers nicht importiert werden</string>
+ <string name="contact_share_failed_toast">Es können nicht mehr als <xliff:g id="count">%d</xliff:g> Kontakte geteilt werden</string>
+ <string name="label_groups">Gruppe</string>
+ <string name="exporting">Exportieren\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> von <xliff:g id="total_number">%2$s</xliff:g> Dateien</string>
+ <string name="export_failed">Exportieren fehlgeschlagen</string>
+ <string name="sim_card_full">SIM-Karte ist voll</string>
+ <string name="export_finished">Export abgeschlossen</string>
+ <string name="tag_too_long">Der Kontaktname ist zu lang</string>
+ <string name="sim_contacts_not_loaded">SIM-Kontakte konnten nicht geladen werden</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Exportieren abgebrochen, %d Element wurde exportiert</item>
+ <item quantity="other">Exportieren abgebrochen, %d Elemente wurden exportiert</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> hat keine Telefonnummer oder E-Mail-Adresse</string>
+ <string name="import_from_sim_select">SIM-Karte zum Importieren wählen</string>
+ <string name="no_sdcard_title" product="nosdcard">Speicher nicht verfügbar</string>
+ <string name="no_sdcard_title" product="default">Keine SD-Karte</string>
+ <string name="deleteConfirmation_title">Kontakt löschen?</string>
+ <string name="deleteConfirmation">Dieser Kontakt wird gelöscht.</string>
+ <string name="copy_done">Kontakt wurde erfolgreich kopiert</string>
+ <string name="copy_failure">Kopieren des Kontaktes fehlgeschlagen</string>
+ <string name="card_no_space">Das Kopieren des Kontaktes ist fehlgeschlagen, da die SIM-Karte voll ist</string>
+ <string name="settings_contact_display_options_description">Konfigurieren Sie, wie Ihre Kontakte angezeigt und sortiert werden.</string>
+ <string name="ip_call_by_slot">VoIP-Anruf über <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Keine VoIP-Nummer</string>
+ <string name="no_ip_number_on_sim_card">Keine VoIP-Nummer auf der SIM-Karte</string>
+ <string name="set_ip_number">VoIP-Nummer festlegen</string>
+ <string name="ipcall_dialog_title">VoIP-Einstellungen</string>
+ <string name="ipcall_dialog_edit_hint">Bitte VoIP-Prefix eingeben</string>
+ <string name="import_contacts_from_all_cards">Kontakte von allen SIM-Karten importieren</string>
+ <string name="select_path">Pfad auswählen</string>
+ <string name="select_sim">SIM-Karte wählen</string>
+</resources>
diff --git a/res/values-el/cm_strings.xml b/res/values-el/cm_strings.xml
new file mode 100644
index 00000000..ff219acb
--- /dev/null
+++ b/res/values-el/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Τοπικός λογαριασμός tablet</string>
+ <string name="local_storage_account" product="default">Τοπικός λογαριασμός τηλεφώνου</string>
+ <string name="import_contacts_sim">Εισαγωγή επαφών από την κάρτα SIM;</string>
+ <string name="manage_sim_contacts">Διαχείριση επαφών κάρτας SIM</string>
+ <string name="export_to_sim">Εξαγωγή στην κάρτα SIM</string>
+ <string name="fail_reason_import_vcard">Δεν ήταν δυνατή η εισαγωγή του \'<xliff:g id="name">%s</xliff:g>\' εξαιτίας σφάλματος εισόδου/εξόδου</string>
+ <string name="contact_share_failed_toast">Δεν είναι δυνατή η κοινή χρήση περισσότερων από <xliff:g id="count">%d</xliff:g> επαφών</string>
+ <string name="label_groups">Ομάδα</string>
+ <string name="exporting">Εξαγωγή\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> από <xliff:g id="total_number">%2$s</xliff:g> αρχεία</string>
+ <string name="export_failed">Η εξαγωγή απέτυχε</string>
+ <string name="sim_card_full">Η κάρτα SIM είναι γεμάτη</string>
+ <string name="export_finished">Η εξαγωγή ολοκληρώθηκε</string>
+ <string name="tag_too_long">Το όνομα της επαφής είναι πολύ μεγάλο</string>
+ <string name="sim_contacts_not_loaded">Δεν είναι δυνατή η φόρτωση των επαφών SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Η εξαγωγή ακυρώθηκε, %d επαφή εξήχθη</item>
+ <item quantity="other">Η εξαγωγή ακυρώθηκε, %d επαφές εξήχθησαν</item>
+ </plurals>
+ <string name="export_no_phone_or_email">Η επαφή <xliff:g id="name">%s</xliff:g> δεν έχει τηλεφωνικό αριθμό ή ηλεκτρονική διεύθυνση</string>
+ <string name="import_from_sim_select">Επιλέξτε κάρτα για εισαγωγή</string>
+ <string name="no_sdcard_title" product="nosdcard">Ο αποθ. χώρος δεν είναι διαθέσιμος</string>
+ <string name="no_sdcard_title" product="default">Δεν υπάρχει κάρτα SD</string>
+ <string name="deleteConfirmation_title">Διαγραφή επαφής;</string>
+ <string name="deleteConfirmation">Αυτή η επαφή θα διαγραφεί.</string>
+ <string name="copy_done">Η επαφή αντιγράφηκε με επιτυχία</string>
+ <string name="copy_failure">Η αντιγραφή της επαφής απέτυχε</string>
+ <string name="card_no_space">Η αντιγραφή της επαφής απέτυχε, η κάρτα SIM είναι γεμάτη</string>
+ <string name="settings_contact_display_options_description">Ρυθμίσετε το πώς εμφανίζονται και ταξινομούνται οι επαφές σας.</string>
+ <string name="ip_call_by_slot">Κλήση IP μέσω <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Κανένας αριθμός IP</string>
+ <string name="no_ip_number_on_sim_card">Κανένας αριθμός IP στην κάρτα SIM</string>
+ <string name="set_ip_number">Ορισμός αριθμού IP</string>
+ <string name="ipcall_dialog_title">Ρυθμίσεις κλήσεων IP</string>
+ <string name="ipcall_dialog_edit_hint">Παρακαλώ εισάγετε το πρόθεμα της IP</string>
+ <string name="import_contacts_from_all_cards">Εισαγωγή επαφών από όλες τις κάρτες SIM</string>
+ <string name="select_path">Επιλέξτε διαδρομή</string>
+ <string name="select_sim">Επιλέξτε SIM</string>
+</resources>
diff --git a/res/values-en-rAU/cm_strings.xml b/res/values-en-rAU/cm_strings.xml
new file mode 100644
index 00000000..54626950
--- /dev/null
+++ b/res/values-en-rAU/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Local tablet account</string>
+ <string name="local_storage_account" product="default">Local phone account</string>
+ <string name="import_contacts_sim">Import contacts from SIM card?</string>
+ <string name="manage_sim_contacts">Manage SIM card contacts</string>
+ <string name="export_to_sim">Export to SIM card</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' could not be imported due to an I/O error</string>
+ <string name="contact_share_failed_toast">No more than <xliff:g id="count">%d</xliff:g> contacts can be shared</string>
+ <string name="label_groups">Group</string>
+ <string name="exporting">Exporting\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> of <xliff:g id="total_number">%2$s</xliff:g> files</string>
+ <string name="export_failed">Export failed</string>
+ <string name="sim_card_full">SIM card is full</string>
+ <string name="export_finished">Export finished</string>
+ <string name="tag_too_long">Contact name is too long</string>
+ <string name="sim_contacts_not_loaded">Unable to load SIM contacts</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Export was cancelled, %d item was exported</item>
+ <item quantity="other">Export was cancelled, %d items were exported</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> does not have a phone number or email address</string>
+ <string name="import_from_sim_select">Choose card to import</string>
+ <string name="no_sdcard_title" product="nosdcard">Storage unavailable</string>
+ <string name="no_sdcard_title" product="default">No SD card</string>
+ <string name="deleteConfirmation_title">Delete contact?</string>
+ <string name="deleteConfirmation">This contact will be deleted.</string>
+ <string name="copy_done">Contact was copied successfully</string>
+ <string name="copy_failure">Copying the contact failed</string>
+ <string name="card_no_space">Copying the contact failed, SIM card is full</string>
+ <string name="settings_contact_display_options_description">Configure how your contacts are displayed and sorted.</string>
+ <string name="ip_call_by_slot">IP call via <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">No IP number</string>
+ <string name="no_ip_number_on_sim_card">No IP number on SIM card</string>
+ <string name="set_ip_number">Set IP number</string>
+ <string name="ipcall_dialog_title">IP call settings</string>
+ <string name="ipcall_dialog_edit_hint">Please input the IP prefix</string>
+ <string name="import_contacts_from_all_cards">Import contacts from all SIM cards</string>
+ <string name="select_path">Select path</string>
+ <string name="select_sim">Select SIM</string>
+</resources>
diff --git a/res/values-en-rIN/cm_strings.xml b/res/values-en-rIN/cm_strings.xml
new file mode 100644
index 00000000..54626950
--- /dev/null
+++ b/res/values-en-rIN/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Local tablet account</string>
+ <string name="local_storage_account" product="default">Local phone account</string>
+ <string name="import_contacts_sim">Import contacts from SIM card?</string>
+ <string name="manage_sim_contacts">Manage SIM card contacts</string>
+ <string name="export_to_sim">Export to SIM card</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' could not be imported due to an I/O error</string>
+ <string name="contact_share_failed_toast">No more than <xliff:g id="count">%d</xliff:g> contacts can be shared</string>
+ <string name="label_groups">Group</string>
+ <string name="exporting">Exporting\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> of <xliff:g id="total_number">%2$s</xliff:g> files</string>
+ <string name="export_failed">Export failed</string>
+ <string name="sim_card_full">SIM card is full</string>
+ <string name="export_finished">Export finished</string>
+ <string name="tag_too_long">Contact name is too long</string>
+ <string name="sim_contacts_not_loaded">Unable to load SIM contacts</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Export was cancelled, %d item was exported</item>
+ <item quantity="other">Export was cancelled, %d items were exported</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> does not have a phone number or email address</string>
+ <string name="import_from_sim_select">Choose card to import</string>
+ <string name="no_sdcard_title" product="nosdcard">Storage unavailable</string>
+ <string name="no_sdcard_title" product="default">No SD card</string>
+ <string name="deleteConfirmation_title">Delete contact?</string>
+ <string name="deleteConfirmation">This contact will be deleted.</string>
+ <string name="copy_done">Contact was copied successfully</string>
+ <string name="copy_failure">Copying the contact failed</string>
+ <string name="card_no_space">Copying the contact failed, SIM card is full</string>
+ <string name="settings_contact_display_options_description">Configure how your contacts are displayed and sorted.</string>
+ <string name="ip_call_by_slot">IP call via <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">No IP number</string>
+ <string name="no_ip_number_on_sim_card">No IP number on SIM card</string>
+ <string name="set_ip_number">Set IP number</string>
+ <string name="ipcall_dialog_title">IP call settings</string>
+ <string name="ipcall_dialog_edit_hint">Please input the IP prefix</string>
+ <string name="import_contacts_from_all_cards">Import contacts from all SIM cards</string>
+ <string name="select_path">Select path</string>
+ <string name="select_sim">Select SIM</string>
+</resources>
diff --git a/res/values-es/cm_strings.xml b/res/values-es/cm_strings.xml
new file mode 100644
index 00000000..9a31f140
--- /dev/null
+++ b/res/values-es/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Cuenta local del tablet</string>
+ <string name="local_storage_account" product="default">Cuenta local del teléfono</string>
+ <string name="import_contacts_sim">¿Importar contactos de la tarjeta SIM?</string>
+ <string name="manage_sim_contacts">Gestionar los contactos de la tarjeta SIM</string>
+ <string name="export_to_sim">Exportar a la tarjeta SIM</string>
+ <string name="fail_reason_import_vcard">\u00AB<xliff:g id="name">%s</xliff:g>\u00BB no puede ser importado debido a un error de E/S</string>
+ <string name="contact_share_failed_toast">No pueden ser compartidos más de <xliff:g id="count">%d</xliff:g> contactos</string>
+ <string name="label_groups">Grupo</string>
+ <string name="exporting">Exportando\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> de <xliff:g id="total_number">%2$s</xliff:g> archivos</string>
+ <string name="export_failed">Fallo al exportar</string>
+ <string name="sim_card_full">La tarjeta SIM está llena</string>
+ <string name="export_finished">Exportación finalizada</string>
+ <string name="tag_too_long">El nombre del contacto es demasiado largo</string>
+ <string name="sim_contacts_not_loaded">No se puede cargar los contactos de la tarjeta SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Exportación cancelada. Se exportó %d contacto</item>
+ <item quantity="other">Exportación cancelada. Se exportaron %d contactos</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> no tiene un número de teléfono o una dirección de correo</string>
+ <string name="import_from_sim_select">Elige una tarjeta para importar</string>
+ <string name="no_sdcard_title" product="nosdcard">Almacenamiento no disponible</string>
+ <string name="no_sdcard_title" product="default">No hay tarjeta SD</string>
+ <string name="deleteConfirmation_title">¿Eliminar contacto?</string>
+ <string name="deleteConfirmation">Este contacto será eliminado.</string>
+ <string name="copy_done">Contacto copiado satisfactoriamente</string>
+ <string name="copy_failure">Falló la copia del contacto</string>
+ <string name="card_no_space">Falló la copia de todos los contactos. La tarjeta SIM está llena</string>
+ <string name="settings_contact_display_options_description">Configurar cómo se muestran y se ordenan tus contactos.</string>
+ <string name="ip_call_by_slot">Llamada IP vía <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">No hay número IP</string>
+ <string name="no_ip_number_on_sim_card">No hay número IP en la tarjeta SIM</string>
+ <string name="set_ip_number">Establecer número IP</string>
+ <string name="ipcall_dialog_title">Configuracion de llamadas IP</string>
+ <string name="ipcall_dialog_edit_hint">Por favor, introduce el prefijo IP</string>
+ <string name="import_contacts_from_all_cards">Importar contactos de todas las tarjetas SIM</string>
+ <string name="select_path">Selecciona la ruta</string>
+ <string name="select_sim">Seleccionar SIM</string>
+</resources>
diff --git a/res/values-et-rEE/cm_strings.xml b/res/values-et-rEE/cm_strings.xml
new file mode 100644
index 00000000..b72098a0
--- /dev/null
+++ b/res/values-et-rEE/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Kohalik tahvli konto</string>
+ <string name="local_storage_account" product="default">Kohalik telefoni konto</string>
+ <string name="import_contacts_sim">Impordi kontaktid SIM-kaardilt?</string>
+ <string name="manage_sim_contacts">Halda SIM-kaardi kontakte</string>
+ <string name="export_to_sim">Ekspordi SIM-kaardile</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' ei saa importida, kuna ilmnes I/O tõrge</string>
+ <string name="contact_share_failed_toast">Enam kui <xliff:g id="count">%d </xliff:g> kontakti ei saa jagada</string>
+ <string name="label_groups">Grupp</string>
+ <string name="exporting">Ekspordin\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> fail <xliff:g id="total_number">%2$s</xliff:g>-st</string>
+ <string name="export_failed">Eksportimine nurjus</string>
+ <string name="sim_card_full">SIM-kaart on täis</string>
+ <string name="export_finished">Eksport lõpetatud</string>
+ <string name="tag_too_long">Kontakti nimi on liiga pikk</string>
+ <string name="sim_contacts_not_loaded">Ei saa laadida kontakte SIM-kaardilt</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Eksport katkestati, %d kirje eksporditi</item>
+ <item quantity="other">Eksport katkestati, %d kirjet eksporditi</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> on ilma telefoni numbri või e-posti aadressita</string>
+ <string name="import_from_sim_select">Vali SIM-kaart importimiseks</string>
+ <string name="no_sdcard_title" product="nosdcard">Mälu pole saadaval</string>
+ <string name="no_sdcard_title" product="default">SD kaarti pole</string>
+ <string name="deleteConfirmation_title">Kustuta kontakt?</string>
+ <string name="deleteConfirmation">See kontakt kustutatakse.</string>
+ <string name="copy_done">Kontakt kopeeriti edukalt</string>
+ <string name="copy_failure">Kontakti kopeerimine nurjus</string>
+ <string name="card_no_space">Kontakti kopeerimine nurjus, SIM-kaart on täis</string>
+ <string name="settings_contact_display_options_description">Saate seadistada, kuidas kontakte kuvada ja sorteerida.</string>
+ <string name="ip_call_by_slot">IP kõne läbi <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Ei ole IP number</string>
+ <string name="no_ip_number_on_sim_card">Ei ole IP numbrit SIM-kaardil</string>
+ <string name="set_ip_number">Määra IP number</string>
+ <string name="ipcall_dialog_title">IP kõne seaded</string>
+ <string name="ipcall_dialog_edit_hint">Sisestage IP eesliide</string>
+ <string name="import_contacts_from_all_cards">Impordi kontaktid kõikidelt SIM-kaartidelt</string>
+ <string name="select_path">Vali teekond</string>
+ <string name="select_sim">Vali SIM-kaart</string>
+</resources>
diff --git a/res/values-eu-rES/cm_strings.xml b/res/values-eu-rES/cm_strings.xml
new file mode 100644
index 00000000..83343617
--- /dev/null
+++ b/res/values-eu-rES/cm_strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Tablet-aren tokiko kontua</string>
+ <string name="local_storage_account" product="default">Telefonoaren tokiko kontua</string>
+</resources>
diff --git a/res/values-fi/cm_strings.xml b/res/values-fi/cm_strings.xml
new file mode 100644
index 00000000..2ac50502
--- /dev/null
+++ b/res/values-fi/cm_strings.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Paikallinen tablet-tili</string>
+ <string name="local_storage_account" product="default">Paikallinen puhelin-tili</string>
+ <string name="import_contacts_sim">Tuo yhteystiedot SIM-kortilta?</string>
+ <string name="manage_sim_contacts">Hallitse SIM-kortin yhteystietoja</string>
+ <string name="export_to_sim">Vie SIM-kortille</string>
+ <string name="fail_reason_import_vcard">Yhteystietoa \'<xliff:g id="name">%s</xliff:g>\' ei voitu tuoda I/O-virheen takia</string>
+ <string name="contact_share_failed_toast">Enintään <xliff:g id="count">%d</xliff:g> yhteystietoa voidaan jakaa</string>
+ <string name="label_groups">Ryhmä</string>
+ <string name="exporting">Viedään\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g>/<xliff:g id="total_number">%2$s</xliff:g> tiedostoa</string>
+ <string name="export_failed">Vienti epäonnistui</string>
+ <string name="sim_card_full">SIM-kortti on täynnä</string>
+ <string name="export_finished">Vienti valmis</string>
+ <string name="tag_too_long">Yhteystiedon nimi on liian pitkä</string>
+ <string name="sim_contacts_not_loaded">Ei voi ladata SIM-kortin yhteystietoja</string>
+ <string name="export_no_phone_or_email">Yhteystiedolla <xliff:g id="name">%s</xliff:g> ei ole puhelinnumeroa tai sähköpostiosoitetta</string>
+ <string name="import_from_sim_select">Valitse kortti josta tuodaan</string>
+ <string name="no_sdcard_title" product="nosdcard">Tallennustila ei saatavilla</string>
+ <string name="no_sdcard_title" product="default">Ei SD-korttia</string>
+ <string name="deleteConfirmation_title">Poista yhteystieto?</string>
+ <string name="deleteConfirmation">Tämä yhteystieto poistetaan.</string>
+ <string name="copy_done">Yhteystieto kopioitu onnistuneesti</string>
+ <string name="copy_failure">Yhteystiedon kopioiminen epäonnistui</string>
+ <string name="card_no_space">Yhteystiedon kopioiminen epäonnistui, SIM-kortti on täynnä</string>
+ <string name="settings_contact_display_options_description">Määritä, kuinka yhteystiedot näytetään ja lajitellaan.</string>
+ <string name="ip_call_by_slot">IP-puhelu <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Ei IP-numeroa</string>
+ <string name="no_ip_number_on_sim_card">Ei IP-numeroa SIM-kortilla</string>
+ <string name="set_ip_number">Aseta IP-numero</string>
+ <string name="ipcall_dialog_title">IP-puheluasetukset</string>
+ <string name="ipcall_dialog_edit_hint">Anna IP:n etuliite</string>
+ <string name="import_contacts_from_all_cards">Tuo yhteystietoja kaikilta SIM-korteilta</string>
+ <string name="select_path">Valitse polku</string>
+ <string name="select_sim">Valitse SIM</string>
+</resources>
diff --git a/res/values-fr/cm_strings.xml b/res/values-fr/cm_strings.xml
new file mode 100644
index 00000000..12176218
--- /dev/null
+++ b/res/values-fr/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Compte local de la tablette</string>
+ <string name="local_storage_account" product="default">Compte local du téléphone</string>
+ <string name="import_contacts_sim">Importer les contacts depuis la carte SIM ?</string>
+ <string name="manage_sim_contacts">Gérer les contacts de la carte SIM</string>
+ <string name="export_to_sim">Exporter vers la carte SIM</string>
+ <string name="fail_reason_import_vcard">« <xliff:g id="name">%s</xliff:g> » n\'a pas pu être importé en raison d\'une erreur I/O</string>
+ <string name="contact_share_failed_toast">Vous ne pouvez pas partager plus de <xliff:g id="count">%d</xliff:g> contacts</string>
+ <string name="label_groups">Groupe</string>
+ <string name="exporting">Exportation\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> sur <xliff:g id="total_number">%2$s</xliff:g> fichiers</string>
+ <string name="export_failed">Échec de l\'exportation</string>
+ <string name="sim_card_full">Carte SIM saturée</string>
+ <string name="export_finished">Export terminé</string>
+ <string name="tag_too_long">Nom du contact trop long</string>
+ <string name="sim_contacts_not_loaded">Impossible de charger les contacts SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">L\'exportation à été annulée, %d élément a été exporté</item>
+ <item quantity="other">L\'exportation à été annulée, %d éléments ont été exportés</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> n\'a pas de numéro de téléphone ou d\'adresse e-mail</string>
+ <string name="import_from_sim_select">Choisissez la carte SIM à importer</string>
+ <string name="no_sdcard_title" product="nosdcard">Stockage non disponible</string>
+ <string name="no_sdcard_title" product="default">Aucune carte SD</string>
+ <string name="deleteConfirmation_title">Supprimer le contact ?</string>
+ <string name="deleteConfirmation">Ce contact sera supprimé.</string>
+ <string name="copy_done">Le contact a été copié avec succès</string>
+ <string name="copy_failure">Copie du contact échouée</string>
+ <string name="card_no_space">Copie du contact échouée, la carte SIM est saturée</string>
+ <string name="settings_contact_display_options_description">Configurer comment vos contacts sont affichés et triés.</string>
+ <string name="ip_call_by_slot">Appel IP via <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Aucun numéro IP</string>
+ <string name="no_ip_number_on_sim_card">Aucun numéro IP sur la carte SIM</string>
+ <string name="set_ip_number">Définir un numéro IP</string>
+ <string name="ipcall_dialog_title">Paramètres d\'appels IP</string>
+ <string name="ipcall_dialog_edit_hint">Veuillez entrer le préfixe IP</string>
+ <string name="import_contacts_from_all_cards">Importer les contacts de toutes les cartes SIM</string>
+ <string name="select_path">Sélectionner un répertoire</string>
+ <string name="select_sim">Sélectionner la SIM</string>
+</resources>
diff --git a/res/values-gl-rES/cm_strings.xml b/res/values-gl-rES/cm_strings.xml
new file mode 100644
index 00000000..87dba162
--- /dev/null
+++ b/res/values-gl-rES/cm_strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Conta local do tablet</string>
+ <string name="local_storage_account" product="default">Conta local do teléfono</string>
+</resources>
diff --git a/res/values-hr/cm_strings.xml b/res/values-hr/cm_strings.xml
new file mode 100644
index 00000000..336acdf9
--- /dev/null
+++ b/res/values-hr/cm_strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Lokalni tablet račun</string>
+ <string name="local_storage_account" product="default">Lokalni račun telefona</string>
+</resources>
diff --git a/res/values-hu/cm_strings.xml b/res/values-hu/cm_strings.xml
new file mode 100644
index 00000000..53bebee3
--- /dev/null
+++ b/res/values-hu/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Helyi táblagép fiók</string>
+ <string name="local_storage_account" product="default">Helyi telefon fiók</string>
+ <string name="import_contacts_sim">Importálja a névjegyeket a SIM-kártyáról?</string>
+ <string name="manage_sim_contacts">SIM-kártya névjegyek kezelése</string>
+ <string name="export_to_sim">Exportálás SIM kártyára</string>
+ <string name="fail_reason_import_vcard">\"<xliff:g id="name">%s</xliff:g>\" I/O hiba miatt nem lehetett importálni</string>
+ <string name="contact_share_failed_toast"><xliff:g id="count">%d</xliff:g> névjegynél több nem osztható meg</string>
+ <string name="label_groups">Csoport</string>
+ <string name="exporting">Exportálás\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> / <xliff:g id="total_number">%2$s</xliff:g> fájl</string>
+ <string name="export_failed">Exportálás sikertelen</string>
+ <string name="sim_card_full">SIM-kártya megtelt</string>
+ <string name="export_finished">Exportálás kész</string>
+ <string name="tag_too_long">A névjegynél megadott név túl hosszú</string>
+ <string name="sim_contacts_not_loaded">Nem sikerült betölteni a SIM névjegyeket</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Exportálás megszakítva, %d elem lett importálva</item>
+ <item quantity="other">Exportálás megszakítva, %d elem lett importálva</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> nem rendelkezik telefonszámmal, vagy e-mail címmel</string>
+ <string name="import_from_sim_select">Kártya kiválasztása importáláshoz</string>
+ <string name="no_sdcard_title" product="nosdcard">A tárhely nem érhető el</string>
+ <string name="no_sdcard_title" product="default">Nincs SD kártya</string>
+ <string name="deleteConfirmation_title">Törli a névjegyet?</string>
+ <string name="deleteConfirmation">Ez a névjegy törlésre kerül.</string>
+ <string name="copy_done">A névjegy másolása sikeres</string>
+ <string name="copy_failure">A névjegy másolása sikertelen</string>
+ <string name="card_no_space">A névjegy másolása sikertelen, a SIM-kártya megtelt</string>
+ <string name="settings_contact_display_options_description">Névjegy megjelenítési lehetőségei.</string>
+ <string name="ip_call_by_slot">IP hívás a következővel: <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Nincs IP szám</string>
+ <string name="no_ip_number_on_sim_card">Nincs IP szám a SIM kártyán</string>
+ <string name="set_ip_number">IP cím beállítása</string>
+ <string name="ipcall_dialog_title">IP hívás beállításai</string>
+ <string name="ipcall_dialog_edit_hint">Kérem adja meg az IP előtagot</string>
+ <string name="import_contacts_from_all_cards">Névjegyek importálása az összes SIM-kártyáról</string>
+ <string name="select_path">Útvonal kiválasztása</string>
+ <string name="select_sim">SIM kiválasztása</string>
+</resources>
diff --git a/res/values-in/cm_strings.xml b/res/values-in/cm_strings.xml
new file mode 100644
index 00000000..69abdb9c
--- /dev/null
+++ b/res/values-in/cm_strings.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Akun lokal tablet</string>
+ <string name="local_storage_account" product="default">Akun lokal telepon</string>
+ <string name="import_contacts_sim">Impor kontak dari kartu SIM?</string>
+ <string name="manage_sim_contacts">Kelola kontak kartu SIM</string>
+ <string name="export_to_sim">Ekspor ke kartu SIM</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' tidak dapat diimpor karena kesalahan I/O</string>
+ <string name="contact_share_failed_toast">Tidak lebih dari <xliff:g id="count">%d</xliff:g> kontak dapat ditambahkan</string>
+ <string name="label_groups">Grup</string>
+ <string name="exporting">Mengekspor\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> dari <xliff:g id="total_number">%2$s</xliff:g> berkas</string>
+ <string name="export_failed">Ekspor gagal</string>
+ <string name="sim_card_full">Kartu SIM penuh</string>
+ <string name="export_finished">Ekspor selesai</string>
+ <string name="tag_too_long">Nama kontak terlalu panjang</string>
+ <string name="sim_contacts_not_loaded">Tidak dapat memuat kontak SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="other">Ekspor dibatalkan, %d item telah diekspor</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> tidak memiliki nomor telepon atau alamat email</string>
+ <string name="import_from_sim_select">Pilih kartu untuk mengimpor</string>
+ <string name="no_sdcard_title" product="nosdcard">Penyimpanan tidak tersedia</string>
+ <string name="no_sdcard_title" product="default">Tidak ada kartu SD</string>
+ <string name="deleteConfirmation_title">Hapus kontak?</string>
+ <string name="deleteConfirmation">Kontak ini akan dihapus.</string>
+ <string name="copy_done">Kontak berhasil disalin</string>
+ <string name="copy_failure">Menyalin kontak gagal</string>
+ <string name="card_no_space">Menyalin kontak gagal, kartu SIM penuh</string>
+ <string name="settings_contact_display_options_description">Konfigurasi bagaimana kontak Anda ditampilkan dan diurutkan.</string>
+ <string name="ip_call_by_slot">Panggilan IP melalui <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Tidak ada Nomor IP</string>
+ <string name="no_ip_number_on_sim_card">Tidak ada Nomor IP pada kartu SIM</string>
+ <string name="set_ip_number">Atur nomor IP</string>
+ <string name="ipcall_dialog_title">Pengaturan panggilan IP</string>
+ <string name="ipcall_dialog_edit_hint">Silahkan memasukkan awalan IP</string>
+ <string name="import_contacts_from_all_cards">Impor kontak dari semua kartu SIM</string>
+ <string name="select_path">Pilih path</string>
+ <string name="select_sim">Pilih SIM</string>
+</resources>
diff --git a/res/values-it/cm_strings.xml b/res/values-it/cm_strings.xml
new file mode 100644
index 00000000..0a894806
--- /dev/null
+++ b/res/values-it/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Account locale tablet</string>
+ <string name="local_storage_account" product="default">Account locale telefono</string>
+ <string name="import_contacts_sim">Importare i contatti dalla scheda SIM?</string>
+ <string name="manage_sim_contacts">Gestisci i contatti della SIM</string>
+ <string name="export_to_sim">Esporta nella SIM</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' non possono essere importati a causa di un errore di I/O</string>
+ <string name="contact_share_failed_toast">Non possono essere condivisi più di <xliff:g id="count">%d</xliff:g> contatti</string>
+ <string name="label_groups">Gruppo</string>
+ <string name="exporting">Esportando\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> di <xliff:g id="total_number">%2$s</xliff:g> file</string>
+ <string name="export_failed">Esportazione fallita</string>
+ <string name="sim_card_full">Scheda SIM piena</string>
+ <string name="export_finished">Esportazione completata</string>
+ <string name="tag_too_long">Nome del contatto troppo lungo</string>
+ <string name="sim_contacts_not_loaded">Impossibile caricare contatti SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Importazione annullata, %d elemento è stato eliminato</item>
+ <item quantity="other">Importazione annullata, %d elementi sono stati eliminati</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> non ha un numero di telefono o un indirizzo email</string>
+ <string name="import_from_sim_select">Scegli la scheda da importare</string>
+ <string name="no_sdcard_title" product="nosdcard">Memoria non disponibile</string>
+ <string name="no_sdcard_title" product="default">Nessuna scheda SD</string>
+ <string name="deleteConfirmation_title">Eliminare il contatto?</string>
+ <string name="deleteConfirmation">Questo contatto sarà eliminato.</string>
+ <string name="copy_done">Contatto copiato con successo</string>
+ <string name="copy_failure">Copia del contatto fallita</string>
+ <string name="card_no_space">Copia del contatto fallita, la SIM è piena</string>
+ <string name="settings_contact_display_options_description">Configurare la visualizzazione dei contatti.</string>
+ <string name="ip_call_by_slot">Chiamata IP con <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Nessun numero IP</string>
+ <string name="no_ip_number_on_sim_card">Nessun numero IP sulla SIM</string>
+ <string name="set_ip_number">Imposta numero IP</string>
+ <string name="ipcall_dialog_title">Impostazioni chiamata IP</string>
+ <string name="ipcall_dialog_edit_hint">Inserisci il prefisso IP</string>
+ <string name="import_contacts_from_all_cards">Importa i contatti da tutte le schede SIM</string>
+ <string name="select_path">Seleziona percorso</string>
+ <string name="select_sim">Seleziona SIM</string>
+</resources>
diff --git a/res/values-iw/cm_strings.xml b/res/values-iw/cm_strings.xml
new file mode 100644
index 00000000..a2555e34
--- /dev/null
+++ b/res/values-iw/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">חשבון טאבלט מקומי</string>
+ <string name="local_storage_account" product="default">חשבון סמארטפון מקומי</string>
+ <string name="import_contacts_sim">לייבא אנשי קשר מכרטיס ה-SIM?</string>
+ <string name="manage_sim_contacts">נהל אנשי קשר ב-SIM</string>
+ <string name="export_to_sim">יצא לכרטיס SIM</string>
+ <string name="fail_reason_import_vcard">הייבוא של \'<xliff:g id="name">%s</xliff:g>\' נכשל עקב שגיאת קלט/פלט</string>
+ <string name="contact_share_failed_toast">לא ניתן לשתף יותר מ- <xliff:g id="count">%d</xliff:g> אנשי קשר</string>
+ <string name="label_groups">קבוצה</string>
+ <string name="exporting">מייצא\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number"> %1$s </xliff:g> מ- <xliff:g id="total_number"> %2$s </xliff:g> קבצים</string>
+ <string name="export_failed">הייצוא נכשל</string>
+ <string name="sim_card_full">כרטיס ה-SIM מלא</string>
+ <string name="export_finished">הייצוא הסתיים</string>
+ <string name="tag_too_long">שם איש הקשר ארוך מדי</string>
+ <string name="sim_contacts_not_loaded">לא ניתן לטעון את אנשי הקשר מה-SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">הייבוא בוטל, פריט %d יובא</item>
+ <item quantity="other">הייבוא בוטל, %d פריטים יובאו</item>
+ </plurals>
+ <string name="export_no_phone_or_email">ל<xliff:g id="name">%s</xliff:g> אין מספר טלפון או כתובת דוא\"ל</string>
+ <string name="import_from_sim_select">בחר כרטיס לייבוא</string>
+ <string name="no_sdcard_title" product="nosdcard">שטח אחסון אינו זמין</string>
+ <string name="no_sdcard_title" product="default">אין כרטיס זיכרון</string>
+ <string name="deleteConfirmation_title">למחוק איש קשר?</string>
+ <string name="deleteConfirmation">איש קשר זה יימחק.</string>
+ <string name="copy_done">איש הקשר הועתק בהצלחה</string>
+ <string name="copy_failure">העתקת איש הקשר נכשלה</string>
+ <string name="card_no_space">העתקת איש הקשר נכשלה, כרטיס ה-SIM מלא</string>
+ <string name="settings_contact_display_options_description">הגדר כיצד אנשי הקשר שלך יוצגו ובאיזה סדר.</string>
+ <string name="ip_call_by_slot">שיחת IP דרך <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">אין מספר IP</string>
+ <string name="no_ip_number_on_sim_card">אין מספר IP בכרטיס ה-SIM</string>
+ <string name="set_ip_number">הכנס מספר IP</string>
+ <string name="ipcall_dialog_title">הגדרות שיחת IP</string>
+ <string name="ipcall_dialog_edit_hint">הזן את קידומת ה-IP</string>
+ <string name="import_contacts_from_all_cards">ייבא אנשי קשר מכל כרטיסי ה-SIM</string>
+ <string name="select_path">בחר נתיב</string>
+ <string name="select_sim">בחר SIM</string>
+</resources>
diff --git a/res/values-ja/cm_strings.xml b/res/values-ja/cm_strings.xml
new file mode 100644
index 00000000..7a1325fd
--- /dev/null
+++ b/res/values-ja/cm_strings.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">タブレットのローカルアカウント</string>
+ <string name="local_storage_account" product="default">携帯電話のローカルアカウント</string>
+ <string name="import_contacts_sim">SIMカードから連絡先をインポートしますか?</string>
+ <string name="manage_sim_contacts">SIMカードの連絡先を管理</string>
+ <string name="export_to_sim">SIMカードにエクスポート</string>
+ <string name="fail_reason_import_vcard">「<xliff:g id="name">%s</xliff:g>」はI/0エラーによりインポートできませんでした</string>
+ <string name="contact_share_failed_toast"><xliff:g id="count">%d</xliff:g>件以上の連絡先は共有できません</string>
+ <string name="label_groups">グループ</string>
+ <string name="exporting">エクスポート中\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="total_number">%2$s</xliff:g>個のうち<xliff:g id="current_number">%1$s</xliff:g>個のファイル</string>
+ <string name="export_failed">エクスポートできませんでした</string>
+ <string name="sim_card_full">SIMカードがいっぱいです</string>
+ <string name="export_finished">エクスポートが完了しました</string>
+ <string name="tag_too_long">連絡先の名前が長すぎます</string>
+ <string name="sim_contacts_not_loaded">SIMの連絡先を読み込めませんでした</string>
+ <plurals name="export_cancelled">
+ <item quantity="other">エクスポートはキャンセルされました、%d個のアイテムがエクスポートされました</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g>には電話番号またはメールアドレスがありません</string>
+ <string name="import_from_sim_select">インポートするカードを選択</string>
+ <string name="no_sdcard_title" product="nosdcard">ストレージが利用できません</string>
+ <string name="no_sdcard_title" product="default">SDカードがありません</string>
+ <string name="deleteConfirmation_title">連絡先を削除しますか?</string>
+ <string name="deleteConfirmation">この連絡先は削除されます。</string>
+ <string name="copy_done">連絡先のコピーが完了しました</string>
+ <string name="copy_failure">連絡先をコピーできませんでした</string>
+ <string name="card_no_space">連絡先をコピーできませんでした、SIMカードがいっぱいです</string>
+ <string name="settings_contact_display_options_description">連絡先の表示と並び順を設定する</string>
+ <string name="ip_call_by_slot"><xliff:g id="subName">%s</xliff:g>経由でIP電話で発信</string>
+ <string name="no_ip_number">IP番号がありません</string>
+ <string name="no_ip_number_on_sim_card">SIMカードにIP番号がありません</string>
+ <string name="set_ip_number">IP番号を設定</string>
+ <string name="ipcall_dialog_title">IP電話の設定</string>
+ <string name="ipcall_dialog_edit_hint">IP電話のプレフィックスを入力してください</string>
+ <string name="import_contacts_from_all_cards">すべてのSIMカードから連絡先をインポート</string>
+ <string name="select_path">パスを選択</string>
+ <string name="select_sim">SIMを選択</string>
+</resources>
diff --git a/res/values-ko/cm_strings.xml b/res/values-ko/cm_strings.xml
new file mode 100644
index 00000000..32bed9b7
--- /dev/null
+++ b/res/values-ko/cm_strings.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">로컬 태블릿 계정</string>
+ <string name="local_storage_account" product="default">로컬 휴대전화 계정</string>
+ <string name="import_contacts_sim">SIM 카드에서 연락처를 가져올까요?</string>
+ <string name="manage_sim_contacts">SIM 카드 연락처 관리</string>
+ <string name="export_to_sim">SIM 카드로 내보내기</string>
+ <string name="fail_reason_import_vcard">I/O 오류로 인해 \'<xliff:g id="name">%s</xliff:g>\'을(를) 가져올 수 없었습니다</string>
+ <string name="contact_share_failed_toast"><xliff:g id="count">%d</xliff:g>건보다 많은 수의 연락처는 공유할 수 없습니다</string>
+ <string name="label_groups">그룹</string>
+ <string name="exporting">내보내는 중\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="total_number">%2$s</xliff:g>개 중 <xliff:g id="current_number">%1$s</xliff:g>번째 파일</string>
+ <string name="export_failed">내보내기 실패</string>
+ <string name="sim_card_full">SIM 카드가 가득 찼습니다</string>
+ <string name="export_finished">내보내기 완료</string>
+ <string name="tag_too_long">연락처 이름이 너무 깁니다</string>
+ <string name="sim_contacts_not_loaded">SIM 연락처를 불러올 수 없습니다</string>
+ <plurals name="export_cancelled">
+ <item quantity="other">내보내기가 취소되었으며, %d건의 항목의 내보내기가 완료되었습니다</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g>에 전화번호 또는 이메일 주소가 필요합니다</string>
+ <string name="import_from_sim_select">가져올 SIM 카드 선택</string>
+ <string name="no_sdcard_title" product="nosdcard">저장소를 사용할 수 없음</string>
+ <string name="no_sdcard_title" product="default">SD 카드 없음</string>
+ <string name="deleteConfirmation_title">연락처를 삭제할까요?</string>
+ <string name="deleteConfirmation">이 연락처가 삭제될 것입니다.</string>
+ <string name="copy_done">연락처가 성공적으로 복사되었습니다</string>
+ <string name="copy_failure">연락처를 복사하지 못했습니다</string>
+ <string name="card_no_space">SIM 카드가 가득 차 있어 연락처를 복사하지 못했습니다</string>
+ <string name="settings_contact_display_options_description">연락처가 표시 및 정렬되는 방식을 구성합니다.</string>
+ <string name="ip_call_by_slot"><xliff:g id="subName">%s</xliff:g>(으)로 IP 통화</string>
+ <string name="no_ip_number">IP 번호 없음</string>
+ <string name="no_ip_number_on_sim_card">SIM 카드에 IP 번호 없음</string>
+ <string name="set_ip_number">IP 번호 설정</string>
+ <string name="ipcall_dialog_title">IP 통화 설정</string>
+ <string name="ipcall_dialog_edit_hint">IP 접두사를 입력해주세요</string>
+ <string name="import_contacts_from_all_cards">모든 SIM 카드에서 연락처 가져오기</string>
+ <string name="select_path">경로 선택</string>
+ <string name="select_sim">SIM 선택</string>
+</resources>
diff --git a/res/values-ku/cm_strings.xml b/res/values-ku/cm_strings.xml
new file mode 100644
index 00000000..34ca6eda
--- /dev/null
+++ b/res/values-ku/cm_strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">هەژماری ناوخۆی تاتەبژمێر</string>
+ <string name="local_storage_account" product="default">هەژماری ناوخۆی تەلەفۆن</string>
+ <string name="export_to_sim">ناردنی ناو بۆ سیماکارت</string>
+ <string name="label_groups">گرووپ</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> ی <xliff:g id="total_number">%2$s</xliff:g> فایلەکان</string>
+ <string name="export_failed">هەناردن سەرکەوتوو نەبوو</string>
+ <string name="export_finished">هەناردن تەواو بوو</string>
+ <string name="import_from_sim_select">کارتێک هەڵبژێرە بۆ هاوردن</string>
+ <string name="no_sdcard_title" product="nosdcard">بیرگە بەردەست نییە</string>
+ <string name="no_sdcard_title" product="default">میمۆری ده‌ره‌کی نییه‌</string>
+ <string name="deleteConfirmation_title">سڕینەوەی پەیوەندی؟?</string>
+ <string name="deleteConfirmation">ئەم پەیوەندییە دەسڕدرێتەوە.</string>
+ <string name="no_ip_number">ژمارەی IP نییە</string>
+ <string name="no_ip_number_on_sim_card">ژمارەی IP لە ناو سیمکارتدا نییە</string>
+ <string name="ipcall_dialog_edit_hint">تکایە پێشگری IP تێبکە</string>
+ <string name="select_sim">دیاریکردنی سیم</string>
+</resources>
diff --git a/res/values-ku/strings.xml b/res/values-ku/strings.xml
new file mode 100644
index 00000000..ed234831
--- /dev/null
+++ b/res/values-ku/strings.xml
@@ -0,0 +1,247 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ ~ Copyright (C) 2012 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_text_copied">ده‌ق له‌ به‌ر گیرایه‌وه‌</string>
+ <string name="call_custom">په‌یوه‌ندی
+ <xliff:g id="custom">%s</xliff:g>
+ </string>
+ <string name="call_home">په‌یوه‌ندی ماڵه‌وه‌</string>
+ <string name="call_mobile">په‌یوه‌ندی مۆبایل</string>
+ <string name="call_work">په‌یوه‌ندی سه‌رکار</string>
+ <string name="call_fax_work">په‌یوه‌ندی فاکسی سه‌رکار</string>
+ <string name="call_fax_home">په‌یوه‌ندی فاکسی ماڵه‌وه‌</string>
+ <string name="call_pager">لاپه‌ڕه‌ په‌یوه‌ندی</string>
+ <string name="call_other">پەیوەندیکردن</string>
+ <string name="call_callback">په‌یوه‌ندی گه‌ڕانه‌وه‌</string>
+ <string name="call_car">په‌یوه‌ندی ئۆتۆمبێل</string>
+ <string name="call_company_main">په‌یوه‌ندی کۆمپانیای سه‌ره‌کی</string>
+ <string name="call_isdn">په‌یوه‌ندی ISDN</string>
+ <string name="call_main">په‌یوه‌ندی سه‌ره‌کی</string>
+ <string name="call_other_fax">په‌یوه‌ندی فاکس</string>
+ <string name="call_radio">په‌یوه‌ندی ڕادیۆ</string>
+ <string name="call_telex">په‌یوه‌ندی تێلئێکس</string>
+ <string name="call_tty_tdd">په‌یوه‌ندی TTY/TDD</string>
+ <string name="call_work_mobile">په‌یوه‌ندی سه‌رکاری مۆبایل</string>
+ <string name="call_work_pager">لاپه‌ڕه‌ په‌یوه‌ندی سه‌ر کار</string>
+ <string name="call_assistant">په‌یوه‌ندی
+ <xliff:g id="assistant">%s</xliff:g>
+ </string>
+ <string name="call_mms">په‌یوه‌ندی MMS</string>
+ <string name="sms_custom">ده‌ق
+ <xliff:g id="custom">%s</xliff:g>
+ </string>
+ <string name="sms_home">ده‌قی ماڵه‌وه‌</string>
+ <string name="sms_mobile">ده‌قی مۆبایل</string>
+ <string name="sms_work">ده‌قی سه‌ر کار</string>
+ <string name="sms_fax_work">ده‌قی سه‌رکاری فاکس</string>
+ <string name="sms_fax_home">ده‌قی ماڵه‌وه‌ی فاکس</string>
+ <string name="sms_pager">لاپه‌ڕه‌ ده‌ق</string>
+ <string name="sms_other">ده‌ق</string>
+ <string name="sms_callback">ده‌قی په‌یوه‌ندی گه‌ڕانه‌وه‌</string>
+ <string name="sms_car">ده‌قی ئۆتۆمبێل</string>
+ <string name="sms_company_main">ده‌قی کۆمپانیای سه‌ره‌کی</string>
+ <string name="sms_isdn">ده‌قی ISDN</string>
+ <string name="sms_main">ده‌قی سه‌ره‌کی</string>
+ <string name="sms_other_fax">ده‌قی فاکس</string>
+ <string name="sms_radio">ده‌قی ڕادیۆ</string>
+ <string name="sms_telex">ده‌قی تێلێکس</string>
+ <string name="sms_tty_tdd">ده‌قی TTY/TDD</string>
+ <string name="sms_work_mobile">ده‌قی ژماره‌ی سه‌ر کار</string>
+ <string name="sms_work_pager">ده‌قی لاپه‌ڕه‌ی سه‌ر کار</string>
+ <string name="sms_assistant">ده‌ق
+ <xliff:g id="assistant">%s</xliff:g>
+ </string>
+ <string name="sms_mms">ده‌قی MMS</string>
+ <string name="clearFrequentsConfirmation_title">پاککردنه‌وه‌ی زوو-زوو په‌یوه‌ندی پێوه‌کراوه‌کان؟</string>
+ <string name="clearFrequentsConfirmation">تۆ زوو-زوو په‌یوه‌ندی پێوه‌کراوه‌کان پاک ده‌که‌یته‌وه‌ له‌ لیستی
+ خه‌ڵک وه‌ ژماره‌. وه‌ به‌رنامه‌ مێڵه‌کان بۆ فێربوونی ڕێکخستنی ناونیشانه‌کان
+ .
+ </string>
+ <string name="clearFrequentsProgress_title">پاککردنه‌وه‌ی په‌یوه‌ندییه‌ زوو-زووه‌کان\u2026</string>
+ <string name="status_available">بەردەست</string>
+ <string name="status_away">ئاماده‌ نییه‌</string>
+ <string name="status_busy">سەرقاڵ</string>
+ <string name="contactsList">ناوەکان</string>
+ <string name="local_invisible_directory">دیکە</string>
+ <string name="directory_search_label">بوخچه‌</string>
+ <string name="local_search_label">هەموو ناوەکان</string>
+ <string name="user_profile_contacts_list_header" msgid="9154761216179882405">من</string>
+ <string name="search_results_searching">گەڕان\u2026</string>
+ <string name="foundTooManyContacts">زیاتر له‌ <xliff:g id="count">%d</xliff:g> دۆزرایه‌وه‌.</string>
+ <string name="listFoundAllContactsZero">ناو نییە</string>
+ <plurals name="searchFoundContacts">
+ <item quantity="one">١ دانە دۆزرایەوە</item>
+ <item quantity="other"><xliff:g id="count">%d</xliff:g> دانە دۆزرایەوە</item>
+ </plurals>
+ <string name="description_quick_contact_for">په‌یوه‌ندی خێرا بۆ <xliff:g id="name">%1$s</xliff:g></string>
+ <string name="missing_name">(ناوی نییه‌)</string>
+ <string name="favoritesFrequentCalled">زۆرترین پەیوەندیکردن</string>
+ <string name="favoritesFrequentContacted">زۆرترین ژماره‌ په‌یوه‌ندییه‌کان</string>
+ <string name="description_view_contact_detail" msgid="2795575601596468581">بینینی ناو</string>
+ <string name="list_filter_phones">هه‌موو په‌یوه‌ندییه‌کان لەگەڵ ژمارەی تەلەفۆنەکان</string>
+ <string name="view_updates_from_group">بینینی نوێکاری</string>
+ <string name="account_phone" product="tablet">ته‌نیا-تابلێت، گواستنه‌وه‌ نه‌کراوه‌</string>
+ <string name="account_phone" product="default">ته‌نیا-مۆبایل، گواستنه‌وه‌ نه‌کراوه‌</string>
+ <string name="nameLabelsGroup">ناو</string>
+ <string name="nicknameLabelsGroup">نازناو</string>
+ <string name="full_name">ناو</string>
+ <string name="name_prefix">ناوی پێشگر</string>
+ <string name="name_middle">ناوی ناوه‌ند</string>
+ <string name="name_suffix">ناوی پاشگر</string>
+ <string name="name_phonetic">ناوی ده‌نگی</string>
+ <string name="name_phonetic_middle">ناوی ده‌نگی ناوه‌ند</string>
+ <string name="phoneLabelsGroup">مۆبایل</string>
+ <string name="emailLabelsGroup">پۆست</string>
+ <string name="postalLabelsGroup">ناونیشان</string>
+ <string name="imLabelsGroup">IM</string>
+ <string name="organizationLabelsGroup">ناوی ڕێکخراو</string>
+ <string name="relationLabelsGroup">په‌یوه‌ندی کۆمه‌ڵایه‌تی</string>
+ <string name="eventLabelsGroup">ڕۆژه‌ تایبه‌ته‌کان</string>
+ <string name="sms">نامه‌ی ده‌قی</string>
+ <string name="postal_address">ناونیشان</string>
+ <string name="ghostData_company">کۆمپانیا</string>
+ <string name="ghostData_title">سەردێڕ</string>
+ <string name="label_notes">تێبینییه‌کان</string>
+ <string name="websiteLabelsGroup">ماڵپەڕ</string>
+ <string name="groupsLabel">کۆمه‌ڵه‌کان</string>
+ <string name="email_home">پۆستی ئه‌لیکترۆنی ماڵه‌وه‌</string>
+ <string name="email_mobile">پۆستی ئه‌لیکترۆنی مۆبایل</string>
+ <string name="email_work">پۆستی ئه‌لیکترۆنی سه‌ر کار</string>
+ <string name="email_other">پۆستی ئه‌لەکترۆنی</string>
+ <string name="email_custom">پۆست <xliff:g id="custom">%s</xliff:g></string>
+ <string name="email">پۆستی ئه‌لەکترۆنی</string>
+ <string name="postal_street">شه‌قام</string>
+ <string name="postal_pobox">سندوقی PO</string>
+ <string name="postal_neighborhood">دراوسێ</string>
+ <string name="postal_city">شار</string>
+ <string name="postal_region">وڵات</string>
+ <string name="postal_postcode">کۆدی پۆستی</string>
+ <string name="postal_country">وڵات</string>
+ <string name="map_home">بینینی ناونیشانی ماڵه‌وه‌</string>
+ <string name="map_work">بینینی ناونیشانی سه‌ر کار</string>
+ <string name="map_other">بینینی ناونیشان</string>
+ <string name="map_custom">بینینی <xliff:g id="custom">%s</xliff:g> ناونیشان</string>
+ <string name="chat_aim">گفتوگۆکردن به‌به‌کارهێنانی AIM</string>
+ <string name="chat_msn">گفتوگۆکردن به‌به‌کارهێنانی Windows Live</string>
+ <string name="chat_yahoo">گفتوگۆکردن به‌به‌کارهێنانی Yahoo</string>
+ <string name="chat_skype">گفتوگۆکردن به‌به‌کارهێنانی سکایپ</string>
+ <string name="chat_qq">گفتوگۆکردن به‌به‌کارهێنانی QQ</string>
+ <string name="chat_gtalk">گفتوگۆکردن به‌به‌کارهێنانی Google Talk</string>
+ <string name="chat_icq">گفتوگۆکردن به‌به‌کارهێنانی ICQ</string>
+ <string name="chat_jabber">گفتوگۆکردن به‌به‌کارهێنانی Jabber</string>
+ <string name="chat">گفتوگۆکردن</string>
+ <string name="description_minus_button">سڕینەوە</string>
+ <string name="expand_collapse_name_fields_description">فراوانکردن یان ته‌سک کردنه‌وه‌ی بۆشایی ناوه‌کان</string>
+ <string name="list_filter_all_accounts">هەموو ناوەکان</string>
+ <string name="list_filter_all_starred">ئه‌ستێره‌دار</string>
+ <string name="list_filter_customize">خواستی خۆت</string>
+ <string name="list_filter_single">ناو</string>
+ <string name="display_ungrouped">هه‌موو په‌یوه‌ندییه‌کانی تر</string>
+ <string name="display_all_contacts">هەموو ناوەکان</string>
+ <string name="menu_sync_remove">سڕینه‌وه‌ی گواستنه‌وه‌ی گروپ</string>
+ <string name="dialog_sync_add">زیادکردنی گواستنه‌وه‌ی گروپ</string>
+ <string name="display_more_groups">گروپی زیاتر\u2026</string>
+ <string name="display_warn_remove_ungrouped">سڕینه‌وه‌ی \"<xliff:g id="group" example="Starred">%s</xliff:g>\" له‌ گواستنه‌وه‌ و هه‌روه‌ها سڕینه‌وه‌ی هه‌ر نا گروپێکی په‌یوه‌ندی له‌ گواستنه‌وه‌.</string>
+ <string name="savingDisplayGroups">پاشه‌که‌وتکردنی نیشاندانی ڕێکخستن\u2026</string>
+ <string name="menu_done">کراو</string>
+ <string name="menu_doNotSave">هەڵوەشاندنەوە</string>
+ <string name="listAllContactsInAccount">په‌یوه‌ندی له‌ <xliff:g id="name" example="abc@gmail.com">%s</xliff:g></string>
+ <string name="listCustomView">په‌یوه‌ندی له‌ بینینی خوازراو</string>
+ <string name="listSingleContact">په‌یوه‌ندی تاک</string>
+ <string name="dialog_new_contact_account">دروستکردنی په‌یوه‌ندی له‌ ژێر هه‌ژماردا</string>
+ <string name="import_from_sim">هاورده‌کردن له‌ سیمکارده‌وه‌</string>
+ <string name="import_from_sdcard" product="default">هاورده‌کردن له‌ بیرگه‌وه‌</string>
+ <string name="cancel_import_confirmation_message">لابردنی هاورده‌کردن له‌ <xliff:g id="filename" example="import.vcf">%s</xliff:g>؟</string>
+ <string name="cancel_export_confirmation_message">لابردنی ناردن له‌ <xliff:g id="filename" example="export.vcf">%s</xliff:g>؟</string>
+ <string name="cancel_vcard_import_or_export_failed">نه‌توانرا هاورده‌ کردن و ناردنی vCard هه‌ڵبوه‌شێنرێت</string>
+ <string name="fail_reason_unknown">هه‌ڵه‌ی نه‌زانراو.</string>
+ <string name="fail_reason_could_not_open_file">نه‌توانرا \"<xliff:g id="file_name">%s</xliff:g>" بکرێته‌وه‌: <xliff:g id="exact_reason">%s</xliff:g>.</string>
+ <string name="fail_reason_could_not_initialize_exporter">نه‌توانرا ده‌ستبکرێت به‌ ناردن: \"<xliff:g id="exact_reason">%s</xliff:g>\".</string>
+ <string name="fail_reason_no_exportable_contact">هیچ په‌یوه‌ندییه‌کانی شایه‌ن ناردن نییه‌.</string>
+ <string name="fail_reason_error_occurred_during_export">هه‌ڵه‌یه‌ک ڕوویدا له‌کاتی ناردن: \"<xliff:g id="exact_reason">%s</xliff:g>\".</string>
+ <string name="fail_reason_too_long_filename">داواکاری ناوی په‌ڕگه‌ زۆر درێژه‌ (\"<xliff:g id="filename">%s</xliff:g>\").</string>
+ <string name="fail_reason_too_many_vcard" product="nosdcard">زۆر په‌ڕگه‌ی vCard هه‌یه‌ له‌ بیرگه‌.</string>
+ <string name="fail_reason_too_many_vcard" product="default">زۆر په‌ڕگه‌ی vCard هه‌یه‌ له‌ بیرگه‌ی ده‌ره‌کی.</string>
+ <string name="fail_reason_io_error">هه‌ڵه‌ی I/O</string>
+ <string name="fail_reason_low_memory_during_import">بۆشایی بیرگه‌ نییه‌. په‌ڕگه‌که‌ زۆر گه‌وره‌یه‌.</string>
+ <string name="fail_reason_vcard_parse_error">نه‌توانرا پێوانه‌ی vCard بکرێت به‌هۆی هۆکارێکی چاوه‌ڕوان نه‌کراوه‌وه‌.</string>
+ <string name="fail_reason_not_supported">جۆری په‌ڕگه‌که‌ گونجاو نییه‌.</string>
+ <string name="fail_reason_failed_to_collect_vcard_meta_info">نه‌توانرا زانیاری مێتا ده‌ستبکه‌وێت له‌ په‌ڕگه‌ی vCard.</string>
+ <string name="fail_reason_failed_to_read_files">په‌ڕگه‌یه‌ک یان زیاتر له‌ دانه‌یه‌ک نه‌توانرا هاورده‌ بکرێت (%s).</string>
+ <string name="exporting_vcard_finished_title">ناردن ته‌واوبوو <xliff:g id="filename" example="export.vcf">%s</xliff:g>.</string>
+ <string name="exporting_vcard_canceled_title">ناردنی<xliff:g id="filename" example="export.vcf">%s</xliff:g> هه‌ڵوه‌شێنرایه‌وه‌.</string>
+ <string name="exporting_contact_list_title">ناردنی زانیاری په‌یوه‌ندی</string>
+ <string name="exporting_contact_list_message">زانیاری په‌یوه‌ندی ده‌نێردرێت بۆ: <xliff:g id="file_name">%s</xliff:g>.</string>
+ <string name="composer_failed_to_get_database_infomation">نه‌توانرا زانیاری داتابه‌یس وه‌ربگیرێت.</string>
+ <string name="composer_has_no_exportable_contact" product="tablet">هیچ په‌یوه‌ندییه‌کانی شایه‌ن ناردن نیه‌. ئه‌گه‌ر په‌یوه‌ندیت هه‌یه‌ له‌سه‌ر تابلێته‌که‌ت، هه‌ندێک داتا له‌وانه‌یه‌ ڕێگری بکات له‌ په‌یوه‌ندییه‌کان بۆ ناردن له‌سه‌ر تابلێته‌که‌ت.</string>
+ <string name="composer_has_no_exportable_contact" product="default">هیچ په‌یوه‌ندییه‌کانی شایه‌ن ناردن نیه‌. ئه‌گه‌ر په‌یوه‌ندیت هه‌یه‌ له‌سه‌ر مۆبایله‌که‌ت، هه‌ندێک داتا له‌وانه‌یه‌ ڕێگری بکات له‌ په‌یوه‌ندییه‌کان بۆ ناردن له‌سه‌ر مۆبایله‌که‌ت.</string>
+ <string name="composer_not_initialized">که‌پسکه‌ری vCard کاری نه‌کرد.</string>
+ <string name="exporting_contact_failed_title">نه‌توانرا بنێردرێ</string>
+ <string name="exporting_contact_failed_message">داتای په‌یوه‌ندی نه‌توانرا بنێردرێ.\nهۆکار: \"<xliff:g id="fail_reason">%s</xliff:g>\"</string>
+ <string name="no_sdcard_message" product="nosdcard">هیچ بیرگه‌یه‌ک نه‌دۆزرایه‌وه‌.</string>
+ <string name="no_sdcard_message" product="default">هیچ بیرگه‌ی ده‌ره‌کی نه‌دۆزرایه‌وه‌.</string>
+ <string name="confirm_export_message">لیستی په‌یوه‌ندییه‌کانت ده‌نێردرێ بۆ په‌ڕگه‌ی: <xliff:g id="vcard_filename">%s</xliff:g>.</string>
+ <string name="importing_vcard_description">هاورده‌کردن <xliff:g id="name" example="Joe Due">%s</xliff:g></string>
+ <string name="reading_vcard_failed_title">نه‌توانرا VCard بخوێنرێته‌وه‌</string>
+ <string name="reading_vcard_canceled_title">خوێندنه‌وه‌ی vCard هه‌ڵوه‌شێنرایه‌وه‌</string>
+ <string name="importing_vcard_finished_title">هاورده‌کردنی VCard ته‌واوبوو <xliff:g id="filename" example="import.vcf">%s</xliff:g></string>
+ <string name="importing_vcard_canceled_title">هاورده‌کردنی <xliff:g id="filename" example="import.vcf">%s</xliff:g> هه‌ڵوه‌شێنرایه‌وه‌</string>
+ <string name="vcard_import_will_start_message"><xliff:g id="filename" example="import.vcf">%s</xliff:g> هاورده‌ ده‌کرێت به‌ کورتی.</string>
+ <string name="vcard_import_will_start_message_with_default_name">په‌ڕگه‌که‌ هاورده‌ ده‌کرێ به‌ کورتی</string>
+ <string name="vcard_import_request_rejected_message">vCard و ناردنی وه‌ داواکردنی ڕه‌تکرایه‌وه‌. دواتر هه‌وڵ بده‌ره‌وه‌.</string>
+ <string name="vcard_export_will_start_message"><xliff:g id="filename" example="import.vcf">%s</xliff:g> ده‌نێردرێت به‌ کورتی.</string>
+ <string name="vcard_export_request_rejected_message">vCard و ناردنی وه‌ داواکردنی ڕه‌تکرایه‌وه‌. دواتر هه‌وڵ بده‌ره‌وه‌.</string>
+ <string name="vcard_unknown_filename">په‌یوه‌ندی</string>
+ <string name="caching_vcard_message">گرتنی vCard بۆ بیرگه‌ی ناوه‌کی. له‌ ڕاستیدا دێته‌ ناوی به‌ زویی.</string>
+ <string name="percentage"><xliff:g id="percentage" example="50">%s</xliff:g><xliff:g id="percentsign" example="%">%%</xliff:g></string>
+ <string name="vcard_import_failed">نه‌توانرا vCard تێبکرێت.</string>
+ <string name="import_failure_no_vcard_file" product="nosdcard">هیچ vCard ـێک نه‌دۆزرایه‌وه‌.</string>
+ <string name="import_failure_no_vcard_file" product="default">هیچ vCard نه‌دۆزرایه‌وه‌ له‌سه‌ر بیرگه‌.</string>
+ <string name="nfc_vcard_file_name">وه‌رگری په‌یوه‌ندی له‌لایه‌ن NFC</string>
+ <string name="confirm_export_title">ناردنی په‌یوه‌ندییه‌کان؟</string>
+ <string name="select_vcard_title">دیاریکردنی په‌ڕگه‌ی vCard</string>
+ <string name="import_one_vcard_string">کردنه‌ناوی یه‌ک په‌ڕگه‌ی vCard</string>
+ <string name="import_multiple_vcard_string">کردنه‌ ناوی چه‌ند په‌ڕگه‌یه‌کی vCard</string>
+ <string name="import_all_vcard_string">تێکردنی هه‌موو په‌ڕگه‌کانی vCard</string>
+ <string name="searching_vcard_message" product="nosdcard">گه‌ڕان به‌ دوای داتا له‌ بیرگه‌ی vCard\u2026</string>
+ <string name="searching_vcard_message" product="default">گه‌ڕان به‌ دوای داتای vCard له‌ بیرگه‌ی ده‌ره‌کی\u2026</string>
+ <string name="caching_vcard_title">حه‌شارگه‌کردن</string>
+ <string name="scanning_sdcard_failed_message" product="nosdcard">بیرگه‌که‌ نه‌توانرا بپشکنرێ. (هۆکار: \"\"<xliff:g id="fail_reason">%s</xliff:g>\")</string>
+ <string name="scanning_sdcard_failed_message" product="default">بیرگه‌که‌ نه‌توانرا بپشکنرێ. (هۆکار: \"\"<xliff:g id="fail_reason">%s</xliff:g>\")</string>
+ <string name="progress_notifier_message">هاورده‌کردنی <xliff:g id="current_number">%s</xliff:g>/<xliff:g id="total_number">%s</xliff:g>: <xliff:g id="name" example="Joe Due">%s</xliff:g></string>
+ <string name="export_to_sdcard" product="default">ناردن بۆ بیرگه‌</string>
+ <string name="share_visible_contacts">به‌شداریپێکردنی په‌یوه‌ندییه‌ دیاره‌کان</string>
+ <string name="dialog_import_export">هاورده‌کردن/ناردنی په‌یوه‌ندی</string>
+ <string name="dialog_import">هاوردنی ناوەکان</string>
+ <string name="share_error">ئه‌م په‌یوه‌ندییه‌ ناتوانرێ به‌شداریپێبکرێت.</string>
+ <string name="menu_search">گه‌ڕان</string>
+ <string name="menu_contacts_filter">په‌یوه‌ندی شایه‌ن نیشاندان</string>
+ <string name="activity_title_contacts_filter">ناوەکان بۆ پیشاندان</string>
+ <string name="custom_list_filter">شایه‌نی بینینی خوازراو</string>
+ <string name="hint_findContacts">دۆزینه‌وه‌ی په‌یوه‌ندی</string>
+ <string name="contactsFavoritesLabel">دڵخوازه‌کان</string>
+ <string name="listTotalAllContactsZero">ناو نییە.</string>
+ <string name="listTotalAllContactsZeroCustom">هیچ په‌یوه‌ندییه‌کی دیار نییه‌.</string>
+ <string name="listTotalAllContactsZeroStarred">هیچ دڵخوازێک نییه‌.</string>
+ <string name="listTotalAllContactsZeroGroup">هیچ په‌یوه‌ندییه‌ک نییه‌ له‌ <xliff:g id="name" example="Friends">%s</xliff:g></string>
+ <string name="menu_clear_frequents">پاککردنه‌وه‌ی زوو-زووه‌ په‌یوه‌ندییه‌کان</string>
+ <string name="menu_accounts">هه‌ژماره‌کان</string>
+ <string name="menu_import_export">هاورده‌کردن/ناردن</string>
+ <string name="contact_status_update_attribution">له‌لایه‌ن <xliff:g id="source" example="Google Talk">%1$s</xliff:g></string>
+ <string name="contact_status_update_attribution_with_date"><xliff:g id="date" example="3 hours ago">%1$s</xliff:g> له‌ڕێگه‌ی <xliff:g id="source" example="Google Talk">%2$s</xliff:g></string>
+</resources>
diff --git a/res/values-lb/cm_strings.xml b/res/values-lb/cm_strings.xml
new file mode 100644
index 00000000..f2ee54b9
--- /dev/null
+++ b/res/values-lb/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Lokalen Tabletkont</string>
+ <string name="local_storage_account" product="default">Lokalen Telefonskont</string>
+ <string name="import_contacts_sim">Kontakter vun der SIM-Kaart importéieren?</string>
+ <string name="manage_sim_contacts">Kontakter vun der SIM-Kaart geréieren</string>
+ <string name="export_to_sim">Op d\'SIM-Kaart exportéieren</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' konnt wéinst engem I/O-Feeler net importéiert ginn</string>
+ <string name="contact_share_failed_toast">Et kënnen net méi wéi <xliff:g id="count">%d</xliff:g> Kontakter gedeelt ginn</string>
+ <string name="label_groups">Grupp</string>
+ <string name="exporting">Gëtt exportéiert\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> / <xliff:g id="total_number">%2$s</xliff:g> Fichieren</string>
+ <string name="export_failed">Export feelgeschloen</string>
+ <string name="sim_card_full">SIM-Kaart ass voll</string>
+ <string name="export_finished">Export ofgeschloss</string>
+ <string name="tag_too_long">Kontaktnumm ass ze laang</string>
+ <string name="sim_contacts_not_loaded">SIM-Kontakter kënnen net geluede ginn</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Den Export gouf ofgebrach, %d Element gouf importéiert</item>
+ <item quantity="other">Den Export gouf ofgebrach, %d Elementer goufen importéiert</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> huet keng Telefonsnummer oder E-Mail-Adress</string>
+ <string name="import_from_sim_select">SIM-Kaart fir den Import auswielen</string>
+ <string name="no_sdcard_title" product="nosdcard">Späicher net disponibel</string>
+ <string name="no_sdcard_title" product="default">Keng SD-Kaart</string>
+ <string name="deleteConfirmation_title">Kontakt läschen?</string>
+ <string name="deleteConfirmation">Dëse Kontakt gëtt geläscht.</string>
+ <string name="copy_done">Kontakt gouf erfollegräich kopéiert</string>
+ <string name="copy_failure">De Kontakt konnt net kopéiert ginn</string>
+ <string name="card_no_space">D\'Kopéiere vu Kontakter ass feelgeschloen, d\'SIM-Kaart ass voll</string>
+ <string name="settings_contact_display_options_description">Konfiguréier, wéi deng Kontakter ugewisen an zortéiert solle ginn.</string>
+ <string name="ip_call_by_slot">VOIP-Uruff iwwer <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Keng VOIP-Nummer</string>
+ <string name="no_ip_number_on_sim_card">Keng VOIP-Nummer op der SIM-Kaart</string>
+ <string name="set_ip_number">VOIP-Nummer setzen</string>
+ <string name="ipcall_dialog_title">Astellunge fir VOIP-Uriff</string>
+ <string name="ipcall_dialog_edit_hint">Gëff w.e.g. de VOIP-Prefix an</string>
+ <string name="import_contacts_from_all_cards">Kontakter vun alle SIM-Kaarten importéieren</string>
+ <string name="select_path">Pad auswielen</string>
+ <string name="select_sim">SIM auswielen</string>
+</resources>
diff --git a/res/values-lb/strings.xml b/res/values-lb/strings.xml
new file mode 100644
index 00000000..ccb684ba
--- /dev/null
+++ b/res/values-lb/strings.xml
@@ -0,0 +1,253 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ ~ Copyright (C) 2012 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_text_copied">Text kopéiert</string>
+ <string name="call_custom"><xliff:g id="custom">%s</xliff:g> uruffen</string>
+ <string name="call_home">Doheem uruffen</string>
+ <string name="call_mobile">Handy uruffen</string>
+ <string name="call_work">Aarbecht uruffen</string>
+ <string name="call_fax_work">Fax op der Aarbecht uruffen</string>
+ <string name="call_fax_home">Fax doheem uruffen</string>
+ <string name="call_pager">Pager uruffen</string>
+ <string name="call_other">Uruffen</string>
+ <string name="call_callback">Réckruffnummer uruffen</string>
+ <string name="call_car">Auto uruffen</string>
+ <string name="call_company_main">Firmentelefon uruffen</string>
+ <string name="call_isdn">ISDN uruffen</string>
+ <string name="call_main">Haaptnummer uruffen</string>
+ <string name="call_other_fax">Fax uruffen</string>
+ <string name="call_radio">Radio uruffen</string>
+ <string name="call_telex">Telex uruffen</string>
+ <string name="call_tty_tdd">TTY/TDD uruffen</string>
+ <string name="call_work_mobile">Aarbechtshandy uruffen</string>
+ <string name="call_work_pager">Aarbechtspager uruffen</string>
+ <string name="call_assistant"><xliff:g id="assistant">%s</xliff:g> uruffen</string>
+ <string name="call_mms">MMS uruffen</string>
+ <string name="sms_custom"><xliff:g id="custom">%s</xliff:g> eng SMS schreiwen</string>
+ <string name="sms_home">SMS un déi privat Nummer schécken</string>
+ <string name="sms_mobile">SMS un den Handy schécken</string>
+ <string name="sms_work">SMS un d\'Aarbecht schécken</string>
+ <string name="sms_fax_work">SMS un den Aarbechtsfax schécken</string>
+ <string name="sms_fax_home">Fax un déi privat Nummer schécken</string>
+ <string name="sms_pager">SMS un de Pager schécken</string>
+ <string name="sms_other">SMS schécken</string>
+ <string name="sms_callback">SMS zréckschécken</string>
+ <string name="sms_car">SMS un den Auto schécken</string>
+ <string name="sms_company_main">SMS un d\'Haaptnummer vun der Firma schécken</string>
+ <string name="sms_isdn">SMS un d\'ISDN-Nummer schécken</string>
+ <string name="sms_main">SMS un d\'Haaptnummer schécken</string>
+ <string name="sms_other_fax">SMS un de Fax schécken</string>
+ <string name="sms_radio">SMS un de Radio schécken</string>
+ <string name="sms_telex">SMS un den Telex schécken</string>
+ <string name="sms_tty_tdd">SMS un den TTY/TDD schécken</string>
+ <string name="sms_work_mobile">SMS un den Aarbechtshandy schécken</string>
+ <string name="sms_work_pager">SMS un den Aarbechtspager schécken</string>
+ <string name="sms_assistant">Dem <xliff:g id="assistant">%s</xliff:g> eng SMS schécken</string>
+ <string name="sms_mms">MMS schécken</string>
+ <string name="description_video_call">Videouruff maachen</string>
+ <string name="clearFrequentsConfirmation_title">Dacks kontaktéiert eidel maachen?</string>
+ <string name="clearFrequentsConfirmation">Du läschs d\'Lëscht mat den dacks Kontaktéierten an den Appe \"Leit\" an \"Telefon\", an du forcéiers d\'Email-Appen d\'Adressastellungen nei ze léieren.</string>
+ <string name="clearFrequentsProgress_title">Dacks kontaktéiert gëtt eidel gemaach\u2026</string>
+ <string name="status_available">Disponibel</string>
+ <string name="status_away">Fort</string>
+ <string name="status_busy">Beschäftegt</string>
+ <string name="contactsList">Kontakter</string>
+ <string name="local_invisible_directory">Aner</string>
+ <string name="directory_search_label">Verzeechnes</string>
+ <string name="local_search_label">All d\'Kontakter</string>
+ <string name="user_profile_contacts_list_header" msgid="9154761216179882405">Ech</string>
+ <string name="search_results_searching">Gëtt gesicht\u2026</string>
+ <string name="foundTooManyContacts">Méi wéi <xliff:g id="count">%d</xliff:g> fonnt.</string>
+ <string name="listFoundAllContactsZero">Keng Kontakter</string>
+ <plurals name="searchFoundContacts">
+ <item quantity="one">1 fonnt</item>
+ <item quantity="other"><xliff:g id="count">%d</xliff:g> fonnt</item>
+ </plurals>
+ <string name="description_quick_contact_for">Séiere Kontakt fir <xliff:g id="name">%1$s</xliff:g></string>
+ <string name="missing_name">(Keen Numm)</string>
+ <string name="favoritesFrequentCalled">Dacks ugeruff</string>
+ <string name="favoritesFrequentContacted">Dacks kontaktéiert</string>
+ <string name="description_view_contact_detail" msgid="2795575601596468581">Kontakt ukucken</string>
+ <string name="list_filter_phones">All d\'Kontakter mat Telefonsnummer</string>
+ <string name="view_updates_from_group">Aktualiséierungen uweisen</string>
+ <string name="account_phone" product="tablet">Just Tablet, onsynchroniséiert</string>
+ <string name="account_phone" product="default">Just Telefon, onsynchroniséiert</string>
+ <string name="nameLabelsGroup">Numm</string>
+ <string name="nicknameLabelsGroup">Spëtznumm</string>
+ <string name="full_name">Numm</string>
+ <string name="name_given">Virnumm</string>
+ <string name="name_family">Familljennumm</string>
+ <string name="name_prefix">Nummprefix</string>
+ <string name="name_middle">Zweete Virnumm</string>
+ <string name="name_suffix">Nummsuffix</string>
+ <string name="name_phonetic">Phoneteschen Numm</string>
+ <string name="name_phonetic_given">Phonetesche Virnumm</string>
+ <string name="name_phonetic_middle">Phoneteschen zweete VIrnumm</string>
+ <string name="name_phonetic_family">Phonetesche Familljennumm</string>
+ <string name="phoneLabelsGroup">Telefon</string>
+ <string name="emailLabelsGroup">E-Mail</string>
+ <string name="postalLabelsGroup">Adress</string>
+ <string name="imLabelsGroup">IM</string>
+ <string name="organizationLabelsGroup">Organisatioun</string>
+ <string name="relationLabelsGroup">Relatioun</string>
+ <string name="eventLabelsGroup">Speziell Daten</string>
+ <string name="sms">Text-Message</string>
+ <string name="postal_address">Adress</string>
+ <string name="ghostData_company">Firma</string>
+ <string name="ghostData_title">Titel</string>
+ <string name="label_notes">Notten</string>
+ <string name="label_sip_address">SIP</string>
+ <string name="websiteLabelsGroup">Websäit</string>
+ <string name="groupsLabel">Gruppen</string>
+ <string name="email_home">E-Mail un déi privat Adress schécken</string>
+ <string name="email_mobile">E-Mail un déi mobil Adress schécken</string>
+ <string name="email_work">E-Mail un d\'Aarbechtsadress schécken</string>
+ <string name="email_other">E-Mail schécken</string>
+ <string name="email_custom">E-Mail (<xliff:g id="custom">%s</xliff:g>)</string>
+ <string name="email">E-Mail</string>
+ <string name="postal_street">Strooss</string>
+ <string name="postal_pobox">Postfach</string>
+ <string name="postal_neighborhood">Noperschaft</string>
+ <string name="postal_city">Stad</string>
+ <string name="postal_region">Staat</string>
+ <string name="postal_postcode">Postleetzuel</string>
+ <string name="postal_country">Land</string>
+ <string name="map_home">Privatadress ukucken</string>
+ <string name="map_work">Aarbechtsadress ukucken</string>
+ <string name="map_other">Adress ukucken</string>
+ <string name="map_custom"><xliff:g id="custom">%s</xliff:g>-Adress ukucken</string>
+ <string name="chat_aim">Iwwer AIM chatten</string>
+ <string name="chat_msn">Iwwer Windows Live chatten</string>
+ <string name="chat_yahoo">Iwwer Yahoo chatten</string>
+ <string name="chat_skype">Iwwer Skype chatten</string>
+ <string name="chat_qq">Iwwer QQ chatten</string>
+ <string name="chat_gtalk">Iwwer Google Talk chatten</string>
+ <string name="chat_icq">Iwwer ICQ chatten</string>
+ <string name="chat_jabber">Iwwer Jabber chatten</string>
+ <string name="chat">Chatten</string>
+ <string name="description_minus_button">läschen</string>
+ <string name="expand_collapse_name_fields_description">Felder fir d\'Nimm ausklappen oder zesummeklappen</string>
+ <string name="list_filter_all_accounts">All d\'Kontakter</string>
+ <string name="list_filter_all_starred">Markéiert</string>
+ <string name="list_filter_customize">Personaliséieren</string>
+ <string name="list_filter_single">Kontakt</string>
+ <string name="display_ungrouped">All déi aner Kontakter</string>
+ <string name="display_all_contacts">All d\'Kontakter</string>
+ <string name="menu_sync_remove">Synchroniséierungsgrupp läschen</string>
+ <string name="dialog_sync_add">Synchroniséierungsgrupp dobäisetzen</string>
+ <string name="display_more_groups">Méi Gruppen\u2026</string>
+ <string name="display_warn_remove_ungrouped">Wann \"<xliff:g id="group" example="Starred">%s</xliff:g>\" aus der Synchroniséierung geläscht gëtt, ginn och all déi net gruppéiert Kontakter aus der Synchroniséierung geläscht.</string>
+ <string name="savingDisplayGroups">Uweisastellunge gi gespäichert\u2026</string>
+ <string name="menu_done">Fäerdeg</string>
+ <string name="menu_doNotSave">Ofbriechen</string>
+ <string name="listAllContactsInAccount">Kontakter am Kont <xliff:g id="name" example="abc@gmail.com">%s</xliff:g></string>
+ <string name="listCustomView">Kontakter an der personaliséierter Usiicht</string>
+ <string name="listSingleContact">Eenzelne Kontakt</string>
+ <string name="dialog_new_contact_account">Kontakt ënner dem Kont uleeën</string>
+ <string name="import_from_sim">Vun der SIM-Kaart importéieren</string>
+ <string name="import_from_sim_number">Vun der SIM-Kaart #<xliff:g id="sim_number" example="2">%d</xliff:g> importéieren</string>
+ <string name="import_from_sdcard" product="default">Aus dem Späicher importéieren</string>
+ <string name="cancel_import_confirmation_message">Import vum Fichier <xliff:g id="filename" example="import.vcf">%s</xliff:g> ofbriechen?</string>
+ <string name="cancel_export_confirmation_message">Export vum Fichier <xliff:g id="filename" example="import.vcf">%s</xliff:g> ofbriechen?</string>
+ <string name="cancel_vcard_import_or_export_failed">Konnt den Import/Export vun der vCard net ofbriechen</string>
+ <string name="fail_reason_unknown">Onbekannte Feeler.</string>
+ <string name="fail_reason_could_not_open_file">Konnt \"<xliff:g id="file_name">%s</xliff:g>" net opmaachen: <xliff:g id="exact_reason">%s</xliff:g>.</string>
+ <string name="fail_reason_could_not_initialize_exporter">Konnt den Exportéierprogramm net starten: \"<xliff:g id="exact_reason">%s</xliff:g>\".</string>
+ <string name="fail_reason_no_exportable_contact">Et gëtt kee Kontakt deen exportéiert ka ginn.</string>
+ <string name="fail_reason_error_occurred_during_export">Beim Exportéieren ass e Feeler opgetrueden: \"<xliff:g id="exact_reason">%s</xliff:g>\".</string>
+ <string name="fail_reason_too_long_filename">Den Numm vum Fichier ass ze laang (\"<xliff:g id="filename">%s</xliff:g>\").</string>
+ <string name="fail_reason_too_many_vcard" product="nosdcard">Et sinn ze vill vCard-Fichieren am Späicher.</string>
+ <string name="fail_reason_too_many_vcard" product="default">Et sinn ze vill vCard-Fichieren op der SD-Kaart.</string>
+ <string name="fail_reason_io_error">Lies-/Schreiffeeler</string>
+ <string name="fail_reason_low_memory_during_import">Net genuch Späicher. De Fichier kéint ze grouss ze sinn.</string>
+ <string name="fail_reason_vcard_parse_error">Konnt d\'vCard aus onerwaarte Grënn net liesen.</string>
+ <string name="fail_reason_not_supported">D\'Format ass net ënnerstëtzt.</string>
+ <string name="fail_reason_failed_to_collect_vcard_meta_info">Konnt d\'Metadate vun dëse vCard-Fichieren net liesen.</string>
+ <string name="fail_reason_failed_to_read_files">Een oder méi Fichiere konnten net importéiert ginn (%s).</string>
+ <string name="exporting_vcard_finished_title">Exportéierung vum Fichier <xliff:g id="filename" example="export.vcf">%s</xliff:g> ofgeschloss.</string>
+ <string name="exporting_vcard_canceled_title">Exportéierung vum Fichier <xliff:g id="filename" example="export.vcf">%s</xliff:g> ofgebrach.</string>
+ <string name="exporting_contact_list_title">Kontaktdate ginn exportéiert</string>
+ <string name="exporting_contact_list_message">Deng Kontaktdate ginn exportéiert als: <xliff:g id="file_name">%s</xliff:g>.</string>
+ <string name="composer_failed_to_get_database_infomation">Konnt d\'Datebankinformatiounen net lueden.</string>
+ <string name="composer_has_no_exportable_contact" product="tablet">Et gi keng Kontakter déi exportéiert kënne ginn. Wann s du keng Kontakter op dengem Tablet hues, kéinte verschidden Dateprovidere verbidden d\'Kontakter vum Tablet z\'exportéieren.</string>
+ <string name="composer_has_no_exportable_contact" product="default">Et gi keng Kontakter déi exportéiert kënne ginn. Wann s du keng Kontakter op dengem Telefon hues, kéinte verschidden Dateprovidere verbidden d\'Kontakter vum Telefon z\'exportéieren.</string>
+ <string name="composer_not_initialized">De vCard-Editor konnt net gestart ginn.</string>
+ <string name="exporting_contact_failed_title">Konnt net exportéieren</string>
+ <string name="exporting_contact_failed_message">D\'Kontaktdate goufen net exportéiert.\nGrond: \"<xliff:g id="fail_reason">%s</xliff:g>\"</string>
+ <string name="no_sdcard_message" product="nosdcard">De Späicher gouf net fonnt.</string>
+ <string name="no_sdcard_message" product="default">D\'SD-Kaart gouf net fonnt.</string>
+ <string name="confirm_export_message">Deng Kontaktlëscht gëtt an dëse Fichier exportéiert: <xliff:g id="vcard_filename">%s</xliff:g>.</string>
+ <string name="importing_vcard_description"><xliff:g id="name" example="Joe Due">%s</xliff:g> gëtt importéiert</string>
+ <string name="reading_vcard_failed_title">Konnt d\'vCard-Daten net liesen</string>
+ <string name="reading_vcard_canceled_title">D\'Liese vun de vCard-Date gouf ënnerbrach</string>
+ <string name="importing_vcard_finished_title">D\'vCard <xliff:g id="filename" example="import.vcf">%s</xliff:g> ass fäerdeg importéiert</string>
+ <string name="importing_vcard_canceled_title">Importéiere vum Fichier <xliff:g id="filename" example="export.vcf">%s</xliff:g> ofgebrach</string>
+ <string name="vcard_import_will_start_message"><xliff:g id="filename" example="import.vcf">%s</xliff:g> gëtt geschwënn importéiert.</string>
+ <string name="vcard_import_will_start_message_with_default_name">De Fichier gëtt geschwënn importéiert.</string>
+ <string name="vcard_import_request_rejected_message">D\'vCard-Importufro gouf rejetéiert. Probéier méi spéit nees.</string>
+ <string name="vcard_export_will_start_message"><xliff:g id="filename" example="import.vcf">%s</xliff:g> gëtt geschwënn exportéiert.</string>
+ <string name="vcard_export_request_rejected_message">D\'vCard-Exportufro gouf rejetéiert. Probéier méi spéit nees.</string>
+ <string name="vcard_unknown_filename">Kontakt</string>
+ <string name="caching_vcard_message">D\'vCard-Date ginn an den Tëschespäichere gelueden. Den Import fänkt geschwënn un.</string>
+ <string name="percentage"><xliff:g id="percentage" example="50">%s</xliff:g><xliff:g id="percentsign" example="%">%%</xliff:g></string>
+ <string name="vcard_import_failed">Konnt d\'vCard net importéieren.</string>
+ <string name="import_failure_no_vcard_file" product="nosdcard">Kee vCard-Fichier am Späicher fonnt.</string>
+ <string name="import_failure_no_vcard_file" product="default">Kee vCard-Fichier op der SD-Kaart fonnt.</string>
+ <string name="nfc_vcard_file_name">Kontakt iwwer NFC empfaangen</string>
+ <string name="confirm_export_title">Kontakter exportéieren?</string>
+ <string name="select_vcard_title">vCard-Fichier auswielen</string>
+ <string name="import_one_vcard_string">Ee vCard-Fichier importéieren</string>
+ <string name="import_multiple_vcard_string">Méi vCard-Fichieren importéieren</string>
+ <string name="import_all_vcard_string">All vCard-Fichieren importéieren</string>
+ <string name="searching_vcard_message" product="nosdcard">Sichen no vCard-Daten am Späicher\u2026</string>
+ <string name="searching_vcard_message" product="default">Sichen no vCard-Daten op der SD-Kaart\u2026</string>
+ <string name="caching_vcard_title">Tëschespäicher gëtt gefëllt</string>
+ <string name="scanning_sdcard_failed_message" product="nosdcard">De Späicher konnt net duerchsicht ginn. (Grond: \"<xliff:g id="fail_reason">%s</xliff:g>\")</string>
+ <string name="scanning_sdcard_failed_message" product="default">D\'SD-Kaart konnt net duerchsicht ginn. (Grond: \"<xliff:g id="fail_reason">%s</xliff:g>\")</string>
+ <string name="progress_notifier_message"><xliff:g id="current_number">%s</xliff:g>/<xliff:g id="total_number">%s</xliff:g>: <xliff:g id="name" example="Joe Due">%s</xliff:g> gëtt importéiert</string>
+ <string name="export_to_sdcard" product="default">An de Späicher exportéieren</string>
+ <string name="display_options_sort_list_by">Zortéieren no</string>
+ <string name="display_options_sort_by_given_name">Virnumm</string>
+ <string name="display_options_sort_by_family_name">Familljennumm</string>
+ <string name="display_options_view_names_as">Format vum Numm</string>
+ <string name="display_options_view_given_name_first">Virnumm fir d\'éischt</string>
+ <string name="display_options_view_family_name_first">Familljennumm fir d\'éischt</string>
+ <string name="share_visible_contacts">Siichtbar Kontakter deelen</string>
+ <string name="dialog_import_export">Kontakter importéieren/exportéieren</string>
+ <string name="dialog_import">Kontakter importéieren</string>
+ <string name="share_error">Dëse Kontakt kann net gedeelt ginn.</string>
+ <string name="menu_search">Sichen</string>
+ <string name="menu_contacts_filter">Kontakter fir unzeweisen</string>
+ <string name="activity_title_contacts_filter">Kontakter fir unzeweisen</string>
+ <string name="custom_list_filter">Personaliséiert Usiicht definéieren</string>
+ <string name="hint_findContacts">Kontakter fannen</string>
+ <string name="contactsFavoritesLabel">Favoritten</string>
+ <string name="listTotalAllContactsZero">Keng Kontakter.</string>
+ <string name="listTotalAllContactsZeroCustom">Keng siichtbar Kontakter.</string>
+ <string name="listTotalAllContactsZeroStarred">Keng Favoritten.</string>
+ <string name="listTotalAllContactsZeroGroup">Keng Kontakter an der Grupp <xliff:g id="name" example="Friends">%s</xliff:g></string>
+ <string name="menu_clear_frequents">Dacks kontaktéiert eidel maachen</string>
+ <string name="menu_select_sim">SIM-Kaart auswielen</string>
+ <string name="menu_accounts">Konten</string>
+ <string name="menu_import_export">Import/Export</string>
+ <string name="contact_status_update_attribution">iwwer <xliff:g id="source" example="Google Talk">%1$s</xliff:g></string>
+ <string name="contact_status_update_attribution_with_date"><xliff:g id="date" example="3 hours ago">%1$s</xliff:g> iwwer <xliff:g id="source" example="Google Talk">%2$s</xliff:g></string>
+ <string name="action_menu_back_from_search">Ophale mat Sichen</string>
+ <string name="description_clear_search">Sich läschen</string>
+ <string name="settings_contact_display_options_title">Uweisoptioune vun de Kontakter</string>
+</resources>
diff --git a/res/values-lt/cm_strings.xml b/res/values-lt/cm_strings.xml
new file mode 100644
index 00000000..8bf96c6c
--- /dev/null
+++ b/res/values-lt/cm_strings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Vietinė planšetinio kompiuterio paskyra</string>
+ <string name="local_storage_account" product="default">Vietinė telefono paskyra</string>
+ <string name="import_contacts_sim">Importuoti kontaktus iš SIM kortelės?</string>
+ <string name="manage_sim_contacts">Tvarkyti SIM kortelės kontaktus</string>
+ <string name="export_to_sim">Eksportuoti į SIM kortelę</string>
+ <string name="fail_reason_import_vcard">„<xliff:g id="name">%s</xliff:g>“ negali būti importuota, dėl I / O klaidos</string>
+ <string name="contact_share_failed_toast">Ne daugiau kaip <xliff:g id="count">%d</xliff:g> kontaktų gali būti bendrinama</string>
+ <string name="label_groups">Grupė</string>
+ <string name="exporting">Eksportuojama\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> iš <xliff:g id="total_number">%2$s</xliff:g> failų</string>
+ <string name="export_failed">Eksportavimas nepavyko</string>
+ <string name="sim_card_full">SIM kortelė yra pilna</string>
+ <string name="export_finished">Eksportavimas baigtas</string>
+ <string name="tag_too_long">Kontakto vardas yra per ilgas</string>
+ <string name="sim_contacts_not_loaded">Nepavyko įkelti SIM kontaktų</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Eksportavimas buvo atšauktas, %d elementas buvo eksportuotas</item>
+ <item quantity="few">Eksportavimas buvo atšauktas, %d elementai buvo eksportuoti</item>
+ <item quantity="other">Eksportavimas buvo atšauktas, %d elementų buvo eksportuota</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> neturi telefono numerio arba el. pašto</string>
+ <string name="import_from_sim_select">Pasirinkite kortelę importuoti</string>
+ <string name="no_sdcard_title" product="nosdcard">Saugykla nepasiekiama</string>
+ <string name="no_sdcard_title" product="default">Nėras SD kortelės</string>
+ <string name="deleteConfirmation_title">Ištrinti kontaktą?</string>
+ <string name="deleteConfirmation">Šis kontaktas bus ištrintas.</string>
+ <string name="copy_done">Kontaktas buvo sėkmingai nukopijuotas</string>
+ <string name="copy_failure">Nepavyko nukopijuoti kontakto</string>
+ <string name="card_no_space">Nukopijuoti kontakto nepavyko, SIM kortelė yra pilna</string>
+ <string name="settings_contact_display_options_description">Konfigūruoti kaip jūsų kontaktai yra rodomi ir rūšiuojami.</string>
+ <string name="ip_call_by_slot">IP skambutis per <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Nėra IP numerio</string>
+ <string name="no_ip_number_on_sim_card">IP numerio SIM kortelėje nėra</string>
+ <string name="set_ip_number">Nustatyti IP numerį</string>
+ <string name="ipcall_dialog_title">IP skambučio nustatymai</string>
+ <string name="ipcall_dialog_edit_hint">Prašome įvesti IP priešdėlį</string>
+ <string name="import_contacts_from_all_cards">Importuoti kontaktus iš visų SIM kortelių</string>
+ <string name="select_path">Pasirinkti kelią</string>
+ <string name="select_sim">Pasirinkti SIM</string>
+</resources>
diff --git a/res/values-lv/cm_strings.xml b/res/values-lv/cm_strings.xml
new file mode 100644
index 00000000..f9a00afd
--- /dev/null
+++ b/res/values-lv/cm_strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Vietējais planšetes konts</string>
+ <string name="local_storage_account" product="default">Vietējais telefona konts</string>
+ <string name="export_to_sim">Eksportēt uz SIM karti</string>
+ <string name="label_groups">Grupa</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> no <xliff:g id="total_number">%2$s</xliff:g> failiem</string>
+ <string name="export_failed">Eksports neizdevās</string>
+ <string name="export_finished">Eksports pabeigts</string>
+ <string name="import_from_sim_select">Izvēlēties karti, kurā importēt</string>
+ <string name="no_sdcard_title" product="nosdcard">Krātuve nav pieejama</string>
+ <string name="no_sdcard_title" product="default">Nav SD kartes</string>
+ <string name="deleteConfirmation_title">Dzēst kontaktu?</string>
+ <string name="deleteConfirmation">Šī kontakts tiks dzēsts.</string>
+ <string name="no_ip_number">Nav IP numura</string>
+ <string name="no_ip_number_on_sim_card">SIM kartē nav IP numura</string>
+ <string name="ipcall_dialog_edit_hint">Lūdzu ievadiet IP priedēkli</string>
+ <string name="select_sim">Izvēlieties SIM</string>
+</resources>
diff --git a/res/values-nb/cm_strings.xml b/res/values-nb/cm_strings.xml
new file mode 100644
index 00000000..6b7035a6
--- /dev/null
+++ b/res/values-nb/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Lokal tablet konto</string>
+ <string name="local_storage_account" product="default">Lokal mobilkonto</string>
+ <string name="import_contacts_sim">Importere kontakter fra SIM-kortet?</string>
+ <string name="manage_sim_contacts">Administrere SIM-kortkontakter</string>
+ <string name="export_to_sim">Eksportere til SIM-kortet</string>
+ <string name="fail_reason_import_vcard">\' <xliff:g id="name">%s\' </xliff:g> kan ikke importeres pga I/O feil</string>
+ <string name="contact_share_failed_toast">Ikke mer enn <xliff:g id="count">%d</xliff:g> kontakter kan bli delt</string>
+ <string name="label_groups">Gruppe</string>
+ <string name="exporting">Eksporterer\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> <xliff:g id="total_number">%2$s</xliff:g> filer</string>
+ <string name="export_failed">Eksporteringen mislyktes</string>
+ <string name="sim_card_full">SIM-kortet er fullt</string>
+ <string name="export_finished">Eksporten er ferdig</string>
+ <string name="tag_too_long">Navn på kontakt er for langt</string>
+ <string name="sim_contacts_not_loaded">Kan ikke laste inn SIM-kontakter</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Eksporten ble avbrutt, %d element ble eksportert</item>
+ <item quantity="other">Eksporten ble avbrutt, %d elementer ble eksportert</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> har ikke ett telefonnummer eller e-postadresse</string>
+ <string name="import_from_sim_select">Velg kort å importere</string>
+ <string name="no_sdcard_title" product="nosdcard">Lagring utilgjengelig</string>
+ <string name="no_sdcard_title" product="default">Ingen SD-kort</string>
+ <string name="deleteConfirmation_title">Slette kontakt?</string>
+ <string name="deleteConfirmation">Denne kontakten vil bli slettet.</string>
+ <string name="copy_done">Kontakten ble vellykket kopiert</string>
+ <string name="copy_failure">Kopiering av kontakten mislyktes</string>
+ <string name="card_no_space">Kopiering av kontakten mislyktes, SIM-kortet er fullt</string>
+ <string name="settings_contact_display_options_description">Konfigurer hvordan kontaktene skal vises og sorteres.</string>
+ <string name="ip_call_by_slot">IP-samtale med <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Ingen IP-nummer</string>
+ <string name="no_ip_number_on_sim_card">Ingen IP-nummeret på SIM-kortet</string>
+ <string name="set_ip_number">Angi IP-nummeret</string>
+ <string name="ipcall_dialog_title">IP Samtaleinnstillinger</string>
+ <string name="ipcall_dialog_edit_hint">Skriv inn IP prefiks</string>
+ <string name="import_contacts_from_all_cards">Importere kontakter fra alle SIM-kort</string>
+ <string name="select_path">Velg bane</string>
+ <string name="select_sim">Velg SIM</string>
+</resources>
diff --git a/res/values-nl/cm_strings.xml b/res/values-nl/cm_strings.xml
new file mode 100644
index 00000000..74ffc1c1
--- /dev/null
+++ b/res/values-nl/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Lokaal tabletaccount</string>
+ <string name="local_storage_account" product="default">Lokaal telefoonaccount</string>
+ <string name="import_contacts_sim">Contacten van simkaart importeren?</string>
+ <string name="manage_sim_contacts">Contacten op simkaart beheren</string>
+ <string name="export_to_sim">Exporteren naar simkaart</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' kon niet worden geïmporteerd door een lees-/schrijffout</string>
+ <string name="contact_share_failed_toast">Er kunnen niet meer dan <xliff:g id="count">%d</xliff:g> contacten worden gedeeld</string>
+ <string name="label_groups">Groep</string>
+ <string name="exporting">Exporteren\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> van <xliff:g id="total_number">%2$s</xliff:g> bestanden</string>
+ <string name="export_failed">Exporteren mislukt</string>
+ <string name="sim_card_full">Simkaart is vol</string>
+ <string name="export_finished">Exporteren voltooid</string>
+ <string name="tag_too_long">Naam van contact is te lang</string>
+ <string name="sim_contacts_not_loaded">Kan SIM-contacten niet laden</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Exporteren geannuleerd, %d item geëxporteerd</item>
+ <item quantity="other">Exporteren geannuleerd, %d items geëxporteerd</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> beschikt niet over een telefoonnummer of e-mailadres</string>
+ <string name="import_from_sim_select">Kies kaart om te importeren</string>
+ <string name="no_sdcard_title" product="nosdcard">Opslag niet beschikbaar</string>
+ <string name="no_sdcard_title" product="default">Geen SD-kaart</string>
+ <string name="deleteConfirmation_title">Contact verwijderen?</string>
+ <string name="deleteConfirmation">Dit contact wordt verwijderd.</string>
+ <string name="copy_done">Contact kopiëren gelukt</string>
+ <string name="copy_failure">Contact kopiëren mislukt</string>
+ <string name="card_no_space">Kopiëren van contact mislukt, simkaart is vol</string>
+ <string name="settings_contact_display_options_description">Instellen hoe uw contacten worden weergegeven en gesorteerd.</string>
+ <string name="ip_call_by_slot">IP-oproep via <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Geen IP-nummer</string>
+ <string name="no_ip_number_on_sim_card">Geen IP-nummer op simkaart</string>
+ <string name="set_ip_number">IP-nummer instellen</string>
+ <string name="ipcall_dialog_title">Instellingen IP-oproep</string>
+ <string name="ipcall_dialog_edit_hint">Voer IP-voorvoegsel in</string>
+ <string name="import_contacts_from_all_cards">Contacten van alle simkaarten importeren</string>
+ <string name="select_path">Pad selecteren</string>
+ <string name="select_sim">Simkaart selecteren</string>
+</resources>
diff --git a/res/values-pl/cm_strings.xml b/res/values-pl/cm_strings.xml
new file mode 100644
index 00000000..ee771d5b
--- /dev/null
+++ b/res/values-pl/cm_strings.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Lokalne konto tabletu</string>
+ <string name="local_storage_account" product="default">Lokalne konto telefonu</string>
+ <string name="import_contacts_sim">Importować kontakty z karty SIM?</string>
+ <string name="manage_sim_contacts">Zarządzaj kontaktami z karty SIM</string>
+ <string name="export_to_sim">Eksportuj do karty SIM</string>
+ <string name="fail_reason_import_vcard"><xliff:g id="name">%s</xliff:g> nie może zostać importowany z powodu błędu we/wy</string>
+ <string name="contact_share_failed_toast">Nie więcej niż <xliff:g id="count">%d</xliff:g> kontaktów może zostać udostępnionych</string>
+ <string name="label_groups">Grupa</string>
+ <string name="exporting">Eksportowanie\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> z <xliff:g id="total_number">%2$s</xliff:g> plików</string>
+ <string name="export_failed">Eksport nie powiódł się</string>
+ <string name="sim_card_full">Karta SIM jest pełna</string>
+ <string name="export_finished">Eksport zakończony</string>
+ <string name="tag_too_long">Nazwa kontaktu jest zbyt długa</string>
+ <string name="sim_contacts_not_loaded">Nie można załadować kontaktów z SIM</string>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> nie ma numeru telefonu ani adresu e-mail</string>
+ <string name="import_from_sim_select">Wybierz kartę do zimportowania</string>
+ <string name="no_sdcard_title" product="nosdcard">Pamięć niedostępna</string>
+ <string name="no_sdcard_title" product="default">Brak karty SD</string>
+ <string name="deleteConfirmation_title">Usunąć kontakt?</string>
+ <string name="deleteConfirmation">Ten kontakt zostanie usunięty.</string>
+ <string name="copy_done">Kontakt został skopiowany pomyślnie</string>
+ <string name="copy_failure">Kopiowanie kontaktu nie powiodło się</string>
+ <string name="card_no_space">Kopiowanie kontaktu nie powiodło się, karta SIM jest pełna</string>
+ <string name="settings_contact_display_options_description">Skonfiguruj jak wyświetlane i sortowane mają być twoje kontakty.</string>
+ <string name="ip_call_by_slot">Połączenie IP przez <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Brak numeru IP</string>
+ <string name="no_ip_number_on_sim_card">Brak numeru IP na karcie SIM</string>
+ <string name="set_ip_number">Ustaw numer IP</string>
+ <string name="ipcall_dialog_title">Ustawienia połączeń IP</string>
+ <string name="ipcall_dialog_edit_hint">Proszę wpisać prefiks IP</string>
+ <string name="import_contacts_from_all_cards">Import kontaktów z wszystkich kart SIM</string>
+ <string name="select_path">Wybierz ścieżkę</string>
+ <string name="select_sim">Wybierz SIM</string>
+</resources>
diff --git a/res/values-pt-rBR/cm_strings.xml b/res/values-pt-rBR/cm_strings.xml
new file mode 100644
index 00000000..07c3698d
--- /dev/null
+++ b/res/values-pt-rBR/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Conta local de tablet</string>
+ <string name="local_storage_account" product="default">Conta local de telefone</string>
+ <string name="import_contacts_sim">Importar contatos do cartão SIM?</string>
+ <string name="manage_sim_contacts">Gerenciar contatos do cartão SIM</string>
+ <string name="export_to_sim">Exportar para o cartão SIM</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' não pôde ser importado devido a um erro</string>
+ <string name="contact_share_failed_toast">Não podem ser compartilhados mais que <xliff:g id="count">%d</xliff:g> contatos</string>
+ <string name="label_groups">Grupo</string>
+ <string name="exporting">Exportando\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> de <xliff:g id="total_number">%2$s</xliff:g> arquivos</string>
+ <string name="export_failed">Falha na exportação</string>
+ <string name="sim_card_full">O cartão SIM está cheio</string>
+ <string name="export_finished">Exportação concluída</string>
+ <string name="tag_too_long">O nome do contato é muito longo</string>
+ <string name="sim_contacts_not_loaded">Não é possível carregar os contatos do cartão SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">A exportação foi cancelada, %d item foi exportado</item>
+ <item quantity="other">A exportação foi cancelada, %d itens foram exportados</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> não tem um número de telefone ou endereço de e-mail</string>
+ <string name="import_from_sim_select">Escolha o cartão para importar</string>
+ <string name="no_sdcard_title" product="nosdcard">Cartão SD indisponível</string>
+ <string name="no_sdcard_title" product="default">Nenhum cartão SD</string>
+ <string name="deleteConfirmation_title">Apagar contato?</string>
+ <string name="deleteConfirmation">Este contato será apagado.</string>
+ <string name="copy_done">Contato foi copiado com sucesso</string>
+ <string name="copy_failure">Falha ao copiar o contato</string>
+ <string name="card_no_space">Falha ao copiar o contato, o cartão SIM está cheio</string>
+ <string name="settings_contact_display_options_description">Defina como os seus contatos são exibidos e classificados.</string>
+ <string name="ip_call_by_slot">Chamada IP por <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Nenhum número IP</string>
+ <string name="no_ip_number_on_sim_card">Nenhum número IP no cartão SIM</string>
+ <string name="set_ip_number">Definir número IP</string>
+ <string name="ipcall_dialog_title">Configurações de chamadas IP</string>
+ <string name="ipcall_dialog_edit_hint">Por favor, insira o prefixo IP</string>
+ <string name="import_contacts_from_all_cards">Importar contatos de todos os cartões SIM</string>
+ <string name="select_path">Selecionar caminho</string>
+ <string name="select_sim">Selecione o SIM</string>
+</resources>
diff --git a/res/values-pt-rPT/cm_strings.xml b/res/values-pt-rPT/cm_strings.xml
new file mode 100644
index 00000000..7799beb8
--- /dev/null
+++ b/res/values-pt-rPT/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Conta local do tablet</string>
+ <string name="local_storage_account" product="default">Conta local do telefone</string>
+ <string name="import_contacts_sim">Importar contactos do cartão SIM?</string>
+ <string name="manage_sim_contacts">Gerir os contactos do cartão SIM</string>
+ <string name="export_to_sim">Exportar para o cartão SIM</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' não pôde ser importado devido a um erro</string>
+ <string name="contact_share_failed_toast">Não podem ser partilhados mais que <xliff:g id="count">%d</xliff:g> contactos</string>
+ <string name="label_groups">Grupo</string>
+ <string name="exporting">A exportar\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> de <xliff:g id="total_number">%2$s</xliff:g> ficheiros</string>
+ <string name="export_failed">A exportação falhou</string>
+ <string name="sim_card_full">O cartão SIM está cheio</string>
+ <string name="export_finished">Exportação terminada</string>
+ <string name="tag_too_long">O nome do contacto é muito longo</string>
+ <string name="sim_contacts_not_loaded">Não é possível carregar os contactos do SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">A exportação foi cancelada, %d item foi exportado</item>
+ <item quantity="other">A exportação foi cancelada, %d itens foram exportados</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> não tem um número de telefone ou endereço de e-mail</string>
+ <string name="import_from_sim_select">Escolher o cartão a importar</string>
+ <string name="no_sdcard_title" product="nosdcard">Armazenamento indisponível</string>
+ <string name="no_sdcard_title" product="default">Sem cartão SD</string>
+ <string name="deleteConfirmation_title">Apagar contacto?</string>
+ <string name="deleteConfirmation">Este contacto será apagado.</string>
+ <string name="copy_done">O contacto foi copiado com sucesso</string>
+ <string name="copy_failure">Falhou a cópia do contacto</string>
+ <string name="card_no_space">A cópia do contacto falhou, o cartão SIM está cheio</string>
+ <string name="settings_contact_display_options_description">Defina como os seus contactos são exibidos e classificados.</string>
+ <string name="ip_call_by_slot">Chamada IP com <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Nenhum número IP</string>
+ <string name="no_ip_number_on_sim_card">Nenhum número IP no cartão SIM</string>
+ <string name="set_ip_number">Colocar o número IP</string>
+ <string name="ipcall_dialog_title">Definições de chamada por IP</string>
+ <string name="ipcall_dialog_edit_hint">Por favor, insira o prefixo IP</string>
+ <string name="import_contacts_from_all_cards">Importar contactos de todos os cartões SIM</string>
+ <string name="select_path">Selecionar o caminho</string>
+ <string name="select_sim">Selecionar SIM</string>
+</resources>
diff --git a/res/values-ro/cm_strings.xml b/res/values-ro/cm_strings.xml
new file mode 100644
index 00000000..ca5787de
--- /dev/null
+++ b/res/values-ro/cm_strings.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Cont local tabletă</string>
+ <string name="local_storage_account" product="default">Cont local telefon</string>
+ <string name="export_to_sim">Export în cartela SIM</string>
+ <string name="label_groups">Grup</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> din <xliff:g id="total_number">%2$s</xliff:g> fişiere</string>
+ <string name="export_failed">Exportul a eșuat</string>
+ <string name="sim_card_full">Cartela SIM este plină</string>
+ <string name="export_finished">Exportul s-a terminat</string>
+ <string name="tag_too_long">Numele contactului este prea lung</string>
+ <string name="import_from_sim_select">Alege cardul ce se va importa</string>
+ <string name="no_sdcard_title" product="nosdcard">Stocare indisponibilă</string>
+ <string name="no_sdcard_title" product="default">Nu există card SD</string>
+ <string name="deleteConfirmation_title">Ştergeţi persoana de contact?</string>
+ <string name="deleteConfirmation">Acest contact va fi şters.</string>
+ <string name="copy_failure">Copierea contactului a eșuat</string>
+ <string name="ip_call_by_slot">Apel IP prin <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Niciun număr de IP</string>
+ <string name="no_ip_number_on_sim_card">Niciun număr de IP pe cartela SIM</string>
+ <string name="ipcall_dialog_edit_hint">Introduceți prefixul IP</string>
+ <string name="select_sim">Selectaţi SIM</string>
+</resources>
diff --git a/res/values-ru/cm_strings.xml b/res/values-ru/cm_strings.xml
new file mode 100644
index 00000000..9c81f10b
--- /dev/null
+++ b/res/values-ru/cm_strings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Локальная учётная запись планшета</string>
+ <string name="local_storage_account" product="default">Локальная учётная запись телефона</string>
+ <string name="import_contacts_sim">Импортировать контакты с SIM-карты?</string>
+ <string name="manage_sim_contacts">Управление контактами SIM-карты</string>
+ <string name="export_to_sim">Экспорт на SIM-карту</string>
+ <string name="fail_reason_import_vcard">Не удалось импортировать файл «<xliff:g id="name">%s</xliff:g>» из-за ошибки ввода-вывода</string>
+ <string name="contact_share_failed_toast">Можно отправить не более <xliff:g id="count">%d</xliff:g> контактов</string>
+ <string name="label_groups">Группа</string>
+ <string name="exporting">Экспорт\u2026</string>
+ <string name="reading_vcard_files">Обработка: <xliff:g id="current_number">%1$s</xliff:g> из <xliff:g id="total_number">%2$s</xliff:g></string>
+ <string name="export_failed">Не удалось выполнить экспорт</string>
+ <string name="sim_card_full">SIM-карта заполнена</string>
+ <string name="export_finished">Экспорт завершён</string>
+ <string name="tag_too_long">Слишком длинное имя контакта</string>
+ <string name="sim_contacts_not_loaded">Не удалось загрузить контакты SIM-карты</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Экспорт отменён, экспортирован %d элемент</item>
+ <item quantity="few">Экспорт отменён, экспортировано %d элемента</item>
+ <item quantity="other">Экспорт отменён, экспортировано %d элементов</item>
+ </plurals>
+ <string name="export_no_phone_or_email">У контакта «<xliff:g id="name">%s</xliff:g>» нет номера телефона или адреса электронной почты</string>
+ <string name="import_from_sim_select">Выберите карту для импорта</string>
+ <string name="no_sdcard_title" product="nosdcard">Внешний накопитель недоступен</string>
+ <string name="no_sdcard_title" product="default">SD-карта не подключена</string>
+ <string name="deleteConfirmation_title">Удалить контакт?</string>
+ <string name="deleteConfirmation">Этот контакт будет удалён.</string>
+ <string name="copy_done">Контакт успешно скопирован</string>
+ <string name="copy_failure">Копирование контакта не удалось</string>
+ <string name="card_no_space">Копирование контакта не удалось, SIM-карта заполнена</string>
+ <string name="settings_contact_display_options_description">Настройка параметров отображения и сортировки контактов.</string>
+ <string name="ip_call_by_slot">IP-вызов через <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Нет IP-номера</string>
+ <string name="no_ip_number_on_sim_card">На SIM-карте нет IP-номера</string>
+ <string name="set_ip_number">Задать IP-номер</string>
+ <string name="ipcall_dialog_title">Настройки IP-телефонии</string>
+ <string name="ipcall_dialog_edit_hint">Введите IP-префикс</string>
+ <string name="import_contacts_from_all_cards">Импорт контактов со всех SIM-карт</string>
+ <string name="select_path">Выбрать путь</string>
+ <string name="select_sim">Выберите SIM-карту</string>
+</resources>
diff --git a/res/values-si-rLK/cm_strings.xml b/res/values-si-rLK/cm_strings.xml
new file mode 100644
index 00000000..1f3da679
--- /dev/null
+++ b/res/values-si-rLK/cm_strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">ස්ථානීය ටැබ්ලට් ගිණුම</string>
+ <string name="local_storage_account" product="default">ස්ථානීය දුරකථන ගිණුම</string>
+ <string name="export_to_sim">සිම් කාඩ්පතට නිර්යාත කරන්න</string>
+ <string name="label_groups">කාණ්ඩය</string>
+ <string name="reading_vcard_files">ගොනු <xliff:g id="total_number">%2$s</xliff:g> න් <xliff:g id="current_number">%1$s</xliff:g></string>
+ <string name="export_failed">නිර්යාතය අසමත්විය</string>
+ <string name="export_finished">නිර්යාතය නිමාවුනි</string>
+ <string name="import_from_sim_select">ආයාත කිරීමට කාඩ්පත තෝරන්න</string>
+ <string name="no_sdcard_title" product="nosdcard">ආචයනය ලබාගත නොහැක</string>
+ <string name="no_sdcard_title" product="default">SD කාඩ්පතක් නොමැත</string>
+ <string name="deleteConfirmation_title">සම්බන්ධතාව මකන්නද?</string>
+ <string name="deleteConfirmation">මෙම සම්බන්ධතාව මකා දැමෙනු ඇත.</string>
+ <string name="no_ip_number">IP අංකයක් නැත</string>
+ <string name="no_ip_number_on_sim_card">සිම් පතෙහි IP අංකයක් නැත</string>
+ <string name="ipcall_dialog_edit_hint">කරුණාකර IP උපසර්ගය ආදානය කරන්න</string>
+ <string name="select_sim">සිම්පත තෝරන්න</string>
+</resources>
diff --git a/res/values-sk/cm_strings.xml b/res/values-sk/cm_strings.xml
new file mode 100644
index 00000000..9416257a
--- /dev/null
+++ b/res/values-sk/cm_strings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Miestny účet tabletu</string>
+ <string name="local_storage_account" product="default">Miestny účet telefónu</string>
+ <string name="import_contacts_sim">Importovať kontakty z karty SIM?</string>
+ <string name="manage_sim_contacts">Spravovať kontakty na karte SIM</string>
+ <string name="export_to_sim">Exportovať na kartu SIM</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' nie je možné importovať kvôli vstupno-výstupnej chybe</string>
+ <string name="contact_share_failed_toast">Nie viac ako <xliff:g id="count">%d</xliff:g> kontaktov môže byť zdieľaných</string>
+ <string name="label_groups">Skupina</string>
+ <string name="exporting">Exportovanie\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> z <xliff:g id="total_number">%2$s</xliff:g> súborov</string>
+ <string name="export_failed">Export zlyhal</string>
+ <string name="sim_card_full">Karta SIM je plná</string>
+ <string name="export_finished">Export sa dokončil</string>
+ <string name="tag_too_long">Meno kontaktu je príliš dlhé</string>
+ <string name="sim_contacts_not_loaded">Nepodarilo sa načítať kontakty zo SIM</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Export bol zrušený, %d položka bola exportovaná</item>
+ <item quantity="few">Export bol zrušený, %d položky boli exportované</item>
+ <item quantity="other">Export bol zrušený, %d položiek bolo exportovaných</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> nemá svoje telefónne číslo alebo e-mailovú adresu</string>
+ <string name="import_from_sim_select">Vyberte kartu na importovanie</string>
+ <string name="no_sdcard_title" product="nosdcard">Nedostupné úložisko</string>
+ <string name="no_sdcard_title" product="default">Žiadna karta SD</string>
+ <string name="deleteConfirmation_title">Vymazať kontakt?</string>
+ <string name="deleteConfirmation">Tento kontakt sa odstráni.</string>
+ <string name="copy_done">Kontakt bol úspešne skopírovaný</string>
+ <string name="copy_failure">Kopírovanie kontaktu zlyhalo</string>
+ <string name="card_no_space">Kopírovanie kontaktu zlyhalo, karta SIM je plná</string>
+ <string name="settings_contact_display_options_description">Nastaviť, ako sa majú kontakty zobrazovať a zoraďovať.</string>
+ <string name="ip_call_by_slot">IP hovor cez <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Žiadne IP číslo</string>
+ <string name="no_ip_number_on_sim_card">Žiadne IP číslo na karte SIM</string>
+ <string name="set_ip_number">Nastaviť IP číslo</string>
+ <string name="ipcall_dialog_title">Nastavenia IP hovoru</string>
+ <string name="ipcall_dialog_edit_hint">Prosím, zadajte predčíslie IP</string>
+ <string name="import_contacts_from_all_cards">Importovať kontakty zo všetkých kariet SIM</string>
+ <string name="select_path">Vyberte cestu</string>
+ <string name="select_sim">Vyberte SIM</string>
+</resources>
diff --git a/res/values-sr/cm_strings.xml b/res/values-sr/cm_strings.xml
new file mode 100644
index 00000000..e587fd97
--- /dev/null
+++ b/res/values-sr/cm_strings.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Локални налог таблета</string>
+ <string name="local_storage_account" product="default">Локални налог телефона</string>
+ <string name="import_contacts_sim">Увези контакте са SIM картице?</string>
+ <string name="manage_sim_contacts">Управљај контактима са SIM картице</string>
+ <string name="export_to_sim">Извези на SIM картицу</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' неможе бити увезен због I/O грешке</string>
+ <string name="contact_share_failed_toast">Не више од <xliff:g id="count">%d</xliff:g> контаката може бити дељено</string>
+ <string name="label_groups">Група</string>
+ <string name="exporting">Извоз\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> од <xliff:g id="total_number">%2$s</xliff:g> фајлова</string>
+ <string name="export_failed">Извоз није успео</string>
+ <string name="sim_card_full">SIM картица је пуна</string>
+ <string name="export_finished">Извоз завршен</string>
+ <string name="tag_too_long">Име контакта је предуго</string>
+ <string name="sim_contacts_not_loaded">Не могу учитати SIM контакте</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Извоз је отказан. %d ставка је извежена</item>
+ <item quantity="few">Извоз је отказан. %d ставки је извежено</item>
+ <item quantity="many">Извоз је отказан. %d ставки је извежено</item>
+ <item quantity="other">Извоз је отказан. %d ставки је извежено</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> нема број телефона или адресу е-поште</string>
+ <string name="import_from_sim_select">Изабери картицу за увоз</string>
+ <string name="no_sdcard_title" product="nosdcard">Складиште недоступно</string>
+ <string name="no_sdcard_title" product="default">Нема SD картице</string>
+ <string name="deleteConfirmation_title">Избриши контакт?</string>
+ <string name="deleteConfirmation">Овај контакт ће бити избрисан.</string>
+ <string name="copy_done">Контакт је копиран успешно</string>
+ <string name="copy_failure">Копирање контакта није успело</string>
+ <string name="card_no_space">Копирање контакта није успело, SIM картица је пуна</string>
+ <string name="settings_contact_display_options_description">Конфигуриши како су твоји контакти приказани и сортирани.</string>
+ <string name="ip_call_by_slot">IP позив преко <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Нема IP броја</string>
+ <string name="no_ip_number_on_sim_card">Нема IP броја на SIM картици</string>
+ <string name="set_ip_number">Постави IP број</string>
+ <string name="ipcall_dialog_title">Подешавања IP позива</string>
+ <string name="ipcall_dialog_edit_hint">Унеси IP префикс</string>
+ <string name="import_contacts_from_all_cards">Увези контакте са свих SIM картица</string>
+ <string name="select_path">Изабери путању</string>
+ <string name="select_sim">Изабери SIM</string>
+</resources>
diff --git a/res/values-sv/cm_strings.xml b/res/values-sv/cm_strings.xml
new file mode 100644
index 00000000..97340c7b
--- /dev/null
+++ b/res/values-sv/cm_strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Lokalt surfplattekonto</string>
+ <string name="local_storage_account" product="default">Lokalt telefonkonto</string>
+ <string name="export_to_sim">Exportera till SIM-kort</string>
+ <string name="label_groups">Grupp</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> av <xliff:g id="total_number">%2$s</xliff:g> filer</string>
+ <string name="export_failed">Exporten misslyckades</string>
+ <string name="export_finished">Export slutförd</string>
+ <string name="import_from_sim_select">Välj kort att importera</string>
+ <string name="no_sdcard_title" product="nosdcard">Lagring ej tillgänglig</string>
+ <string name="no_sdcard_title" product="default">Inget SD-kort</string>
+ <string name="deleteConfirmation_title">Ta bort kontakt?</string>
+ <string name="deleteConfirmation">Denna kontakt kommer tas bort.</string>
+ <string name="no_ip_number">Inget IP-nummer</string>
+ <string name="no_ip_number_on_sim_card">Inget IP-nummer på SIM-kort</string>
+ <string name="ipcall_dialog_edit_hint">Skriv in IP-prefixet</string>
+ <string name="select_sim">Välj SIM</string>
+</resources>
diff --git a/res/values-th/cm_strings.xml b/res/values-th/cm_strings.xml
new file mode 100644
index 00000000..64f6603d
--- /dev/null
+++ b/res/values-th/cm_strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">บัญชีภายในแท็บเล็ต</string>
+ <string name="local_storage_account" product="default">บัญชีภายในโทรศัพท์</string>
+ <string name="export_to_sim">ส่งออกไปยังซิมการ์ด</string>
+ <string name="label_groups">กลุ่ม</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> จาก <xliff:g id="total_number">%2$s</xliff:g> ไฟล์</string>
+ <string name="export_failed">ส่งออกล้มเหลว</string>
+ <string name="export_finished">ส่งออกเสร็จสมบูรณ์</string>
+ <string name="import_from_sim_select">เลือกบัตรที่จะนำเข้า</string>
+ <string name="no_sdcard_title" product="nosdcard">ไม่มีที่เก็บข้อมูล</string>
+ <string name="no_sdcard_title" product="default">ไม่มี SD card</string>
+ <string name="deleteConfirmation_title">ลบ​ราย​ชื่อ?</string>
+ <string name="deleteConfirmation">ราย​ชื่อ​นี้​จะ​ถูกลบ​ออก</string>
+ <string name="no_ip_number">ไม่มีหมายเลข IP</string>
+ <string name="no_ip_number_on_sim_card">ไม่มีหมายเลข IP ในซิมการ์ด</string>
+ <string name="ipcall_dialog_edit_hint">กรุณากรอกเลขนำหน้า IP</string>
+ <string name="select_sim">เลือกซิมการ์ด</string>
+</resources>
diff --git a/res/values-tr/cm_strings.xml b/res/values-tr/cm_strings.xml
new file mode 100644
index 00000000..de4b6b66
--- /dev/null
+++ b/res/values-tr/cm_strings.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Yerel tablet hesabı</string>
+ <string name="local_storage_account" product="default">Yerel telefon hesabı</string>
+ <string name="import_contacts_sim">Kişiler SIM karttan alınsın mı?</string>
+ <string name="manage_sim_contacts">SIM kart kişilerini yönet</string>
+ <string name="export_to_sim">SIM karta aktar</string>
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' bir G/Ç hatasından dolayı alınamadı</string>
+ <string name="contact_share_failed_toast"><xliff:g id="count">%d</xliff:g> \'den fazla kişi paylaşılamaz</string>
+ <string name="label_groups">Grup</string>
+ <string name="exporting">Dışa aktarılıyor\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> / <xliff:g id="total_number">%2$s</xliff:g> dosya</string>
+ <string name="export_failed">Aktarım başarısız</string>
+ <string name="sim_card_full">SIM kart dolu</string>
+ <string name="export_finished">Dışa aktarım bitti</string>
+ <string name="tag_too_long">Kişi adı çok uzun</string>
+ <string name="sim_contacts_not_loaded">SIM kişileri yüklenemedi</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Aktarma iptal edildi, %d öge aktarıldı</item>
+ <item quantity="other">Aktarma iptal edildi, %d öge aktarıldı</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> bir telefon numarasına veya e-posta adresine sahip değil</string>
+ <string name="import_from_sim_select">Alınacak kartı seç</string>
+ <string name="no_sdcard_title" product="nosdcard">Depolama kullanılabilir değil</string>
+ <string name="no_sdcard_title" product="default">SD kart yok</string>
+ <string name="deleteConfirmation_title">Kişi silinsin mi?</string>
+ <string name="deleteConfirmation">Bu kişi silinecek.</string>
+ <string name="copy_done">Kişi başarıyla kopyalandı</string>
+ <string name="copy_failure">Kişi kopyalanamadı</string>
+ <string name="card_no_space">Kişi kopyalanamadı, SIM kart dolu</string>
+ <string name="settings_contact_display_options_description">Kişilerinizin nasıl görüntüleneceğini ve sıralanacağını yapılandırın.</string>
+ <string name="ip_call_by_slot"><xliff:g id="subName">%s</xliff:g> ile IP araması</string>
+ <string name="no_ip_number">IP numarası yok</string>
+ <string name="no_ip_number_on_sim_card">SIM kartta IP numarası yok</string>
+ <string name="set_ip_number">IP numarasını ayarla</string>
+ <string name="ipcall_dialog_title">IP arama ayarları</string>
+ <string name="ipcall_dialog_edit_hint">Lütfen IP önekini girin</string>
+ <string name="import_contacts_from_all_cards">Tüm SIM kartlardan kişileri al</string>
+ <string name="select_path">Konumu seçin</string>
+ <string name="select_sim">SIM seç</string>
+</resources>
diff --git a/res/values-ug/cm_strings.xml b/res/values-ug/cm_strings.xml
new file mode 100644
index 00000000..d989a42f
--- /dev/null
+++ b/res/values-ug/cm_strings.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">يەرلىك تاختا كومپيۇتېر ھېساباتى</string>
+ <string name="local_storage_account" product="default">يەرلىك تېلېفون ھېساباتى</string>
+ <string name="import_contacts_sim">ئالاقەداشلارنى SIM كارتىدىن ئەكىرەمدۇ؟</string>
+ <string name="manage_sim_contacts">SIM كارتىدىكى ئالاقەداشلارنى باشقۇرۇش</string>
+ <string name="export_to_sim">SIM كارتىغا چىقار</string>
+ <string name="fail_reason_import_vcard">بىر كىرگۈزۈش چىقىرىش خاتالىقى سەۋەبىدىن <xliff:g id="name">%s</xliff:g> نى ئەكىرەلمىدى</string>
+ <string name="contact_share_failed_toast">ھەمبەھىرلەيدىغان ئالاقەداش <xliff:g id="count">%d</xliff:g> دىن ئاشمايدۇ</string>
+ <string name="label_groups">گۇرۇپپا</string>
+ <string name="exporting">چىقىرىۋاتىدۇ\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g>/<xliff:g id="total_number">%2$s</xliff:g> ھۆججەت</string>
+ <string name="export_failed">چىقىرالمىدى</string>
+ <string name="sim_card_full">SIM كارتا لىق</string>
+ <string name="export_finished">چىقىرىش تامام</string>
+ <string name="tag_too_long">ئالاقەداش ئىسمى بەك ئۇزۇن</string>
+ <string name="sim_contacts_not_loaded">SIM كارتىدىكى ئالاقەداشلارنى يۈكلىيەلمىدى</string>
+ <plurals name="export_cancelled">
+ <item quantity="other">چىقىرىشتىن ۋاز كەچتى، %d تۈر چىقىرىلدى</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g>نىڭ تېلېفون نومۇرى ياكى تورخەت ئادرېسى يوق</string>
+ <string name="import_from_sim_select">ئەكىرىدىغان كارتىنى تاللاڭ</string>
+ <string name="no_sdcard_title" product="nosdcard">ساقلىغۇچنى ئىشلەتكىلى بولمايدۇ</string>
+ <string name="no_sdcard_title" product="default">SD كارتا يوق</string>
+ <string name="deleteConfirmation_title">ئالاقەداش ئۆچۈرەمدۇ؟</string>
+ <string name="deleteConfirmation">بۇ ئالاقەداش ئۆچۈرۈلىدۇ.</string>
+ <string name="copy_done">ئالاقەداش مۇۋەپپەقىيەتلىك كۆچۈرۈلدى</string>
+ <string name="copy_failure">ئالاقەداشنى كۆچۈرەلمىدى</string>
+ <string name="card_no_space">ئالاقەداشنى كۆچۈرەلمىدى، SIM كارتا لىق</string>
+ <string name="settings_contact_display_options_description">ئالاقەداشلىرىڭىزنى كۆرسىتىش ۋە تەرتىپلەش ئۇسۇلىنى سەپلەڭ.</string>
+ <string name="ip_call_by_slot"><xliff:g id="subName">%s</xliff:g> بىلەن IP چاقىرىش</string>
+ <string name="no_ip_number">IP نومۇر يوق</string>
+ <string name="no_ip_number_on_sim_card">SIM كارتىدا IP نومۇر يوق</string>
+ <string name="set_ip_number">IP نومۇر تەڭشەك</string>
+ <string name="ipcall_dialog_title">IP چاقىرىش تەڭشەكلىرى</string>
+ <string name="ipcall_dialog_edit_hint">IP ئالدى قوشۇلغۇچىسىنى كىرگۈزۈڭ</string>
+ <string name="import_contacts_from_all_cards">ھەممە SIM كارتىدىن ئالاقەداشلارنى ئەكىر</string>
+ <string name="select_path">يول تاللاڭ</string>
+ <string name="select_sim">SIM كارتا تاللا</string>
+</resources>
diff --git a/res/values-ug/strings.xml b/res/values-ug/strings.xml
new file mode 100644
index 00000000..d25a8bca
--- /dev/null
+++ b/res/values-ug/strings.xml
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ ~ Copyright (C) 2012 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="toast_text_copied">تېكىست كۆچۈرۈلدى</string>
+ <string name="call_custom"><xliff:g id="CUSTOM">%s</xliff:g> نى چاقىر</string>
+ <string name="call_home">ئۆي تېلېفوننى چاقىر</string>
+ <string name="call_mobile">تېلېفوننى چاقىر</string>
+ <string name="call_work">خىزمەت تېلېفوننى چاقىر</string>
+ <string name="call_fax_work">خىزمەت فاكىسنى چاقىر</string>
+ <string name="call_fax_home">ئۆي فاكىسنى چاقىر</string>
+ <string name="call_pager">چاقىرغۇنى چاقىر</string>
+ <string name="call_other">چاقىر</string>
+ <string name="call_callback">قايتا چاقىرىلغان نومۇرنى چاقىر</string>
+ <string name="call_car">ماشىنا تېلېفونىنى چاقىر</string>
+ <string name="call_company_main">شىركەت باش ئاپپاراتىنى چاقىر</string>
+ <string name="call_isdn">ISDN چاقىر</string>
+ <string name="call_main">باش ئاپپاراتنى چاقىر</string>
+ <string name="call_other_fax">فاكىسنى چاقىر</string>
+ <string name="call_radio">رادىيو چاقىر</string>
+ <string name="call_telex">تېلېگرامما چاقىر</string>
+ <string name="call_tty_tdd">TTY/TDD چاقىر</string>
+ <string name="call_work_mobile">خىزمەت تېلېفوننى چاقىر</string>
+ <string name="call_work_pager">خىزمەت چاقىرغۇنى چاقىر</string>
+ <string name="call_assistant"><xliff:g id="ASSISTANT">%s</xliff:g> نى چاقىر</string>
+ <string name="call_mms">MMS چاقىر</string>
+ <string name="sms_custom"><xliff:g id="CUSTOM">%s</xliff:g> غا قىسقا ئۇچۇر يوللا</string>
+ <string name="sms_home">ئۆي تېلېفونغا ئۇچۇر يوللا</string>
+ <string name="sms_mobile">تېلېفونغا ئۇچۇر يوللا</string>
+ <string name="sms_work">خىزمەت تېلېفونغا ئۇچۇر يوللا</string>
+ <string name="sms_fax_work">خىزمەت فاكىسقا ئۇچۇر يوللا</string>
+ <string name="sms_fax_home">ئۆي فاكىسقا ئۇچۇر يوللا</string>
+ <string name="sms_pager">چاقىرغۇغا ئۇچۇر يوللا</string>
+ <string name="sms_other">قىسقا ئۇچۇر</string>
+ <string name="sms_callback">قايتا چاقىرىلغان نومۇرغا ئۇچۇر يوللا</string>
+ <string name="sms_car">ماشىنا تېلېفونىغا ئۇچۇر يوللا</string>
+ <string name="sms_company_main">شىركەت باش ئاپپاراتىغا ئۇچۇر يوللا</string>
+ <string name="sms_isdn">ISDN گە ئۇچۇر يوللا</string>
+ <string name="sms_main">باش ئاپپاراتقا ئۇچۇر يوللا</string>
+ <string name="sms_other_fax">فاكىسقا قىسقا ئۇچۇر يوللا</string>
+ <string name="sms_radio">رادىيوغا ئۇچۇر يوللا</string>
+ <string name="sms_telex">تېلېگراممىغا ئۇچۇر يوللا</string>
+ <string name="sms_tty_tdd">TTY/TDD غا ئۇچۇر يوللا</string>
+ <string name="sms_work_mobile">خىزمەت تېلېفونغا ئۇچۇر يوللا</string>
+ <string name="sms_work_pager">خىزمەت چاقىرغۇغا ئۇچۇر يوللا</string>
+ <string name="sms_assistant"><xliff:g id="ASSISTANT">%s</xliff:g> غا قىسقا ئۇچۇر يوللا</string>
+ <string name="sms_mms">MMS كە ئۇچۇر يوللا</string>
+ <string name="clearFrequentsConfirmation_title">دائىملىق ئالاقەداشلارنى تازىلامدۇ؟</string>
+ <string name="clearFrequentsConfirmation">بۇ مەشغۇلات ئالاقەداشلار ۋە نومۇر بۇرايدىغان ئەپتىكى دائىملىق ئالاقەداشلار تىزىمىنى تازىلايدۇ ھەمدە ئېلخەت ئەپتىن مەجبۇرىي ھالدا دائىملىق ئالاقەداشلىرىڭىزنىڭ ئادرېسىغا قايتىدىن ئېرىشىدۇ.</string>
+ <string name="clearFrequentsProgress_title">دائىملىق ئالاقەداشلارنى تازىلاۋاتىدۇ…</string>
+ <string name="status_available">ئىشلىتىلىشچان</string>
+ <string name="status_away">ئايرىلدى</string>
+ <string name="status_busy">ئالدىراش</string>
+ <string name="contactsList">ئالاقەداشلار</string>
+ <string name="local_invisible_directory">باشقا</string>
+ <string name="directory_search_label">مۇندەرىجە</string>
+ <string name="local_search_label">ھەممە ئالاقەداشلار</string>
+ <string name="user_profile_contacts_list_header" msgid="9154761216179882405">مەن</string>
+ <string name="search_results_searching">ئىزدەۋاتىدۇ…</string>
+ <string name="foundTooManyContacts"><xliff:g id="COUNT">%d</xliff:g> دىن كۆپ تاپتى.</string>
+ <string name="listFoundAllContactsZero">ئالاقەداش يوق</string>
+ <plurals name="searchFoundContacts">
+ <item quantity="other">1 نى تاپتى</item>
+ </plurals>
+ <string name="description_quick_contact_for"><xliff:g id="NAME">%1$s</xliff:g> نىڭ تېز ئالاقەداشلىرى</string>
+ <string name="missing_name">(ئاتسىز)</string>
+ <string name="favoritesFrequentCalled">دائىملىق چاقىرىلىش</string>
+ <string name="favoritesFrequentContacted">دائىملىق ئالاقەداشلار</string>
+ <string name="description_view_contact_detail" msgid="2795575601596468581">ئالاقەداشنى كۆرسەت</string>
+ <string name="list_filter_phones">تېلېفون نومۇرى بار ھەممە ئالاقەداشلار</string>
+ <string name="view_updates_from_group">يېڭىلانمىلارنى كۆرسەت</string>
+ <string name="account_phone" product="tablet">تاختا كومپيۇتېرلا، قەدەمداشلانمىغان</string>
+ <string name="account_phone" product="default">تېلېفوندىلا، قەدەمداشلانمىغان</string>
+ <string name="nameLabelsGroup">ئاتى</string>
+ <string name="nicknameLabelsGroup">تەخەللۇس</string>
+ <string name="full_name">ئاتى</string>
+ <string name="name_prefix">ئات ئالدى قوشۇلغۇچىسى</string>
+ <string name="name_middle">ئوتتۇرا ئاتى</string>
+ <string name="name_suffix">ئات ئارقا قوشۇلغۇچىسى</string>
+ <string name="name_phonetic">تاۋۇشلۇق ئات</string>
+ <string name="name_phonetic_middle">تاۋۇشلۇق ئوتتۇرا ئات</string>
+ <string name="phoneLabelsGroup">تېلېفون</string>
+ <string name="emailLabelsGroup">ئېلخەت</string>
+ <string name="postalLabelsGroup">ئادرېس</string>
+ <string name="imLabelsGroup">پەيتلىك ئۇچۇر</string>
+ <string name="organizationLabelsGroup">تەشكىل</string>
+ <string name="relationLabelsGroup">مۇناسىۋەت</string>
+ <string name="eventLabelsGroup">پائالىيەتلەر</string>
+ <string name="sms">تېكىست ئۇچۇر</string>
+ <string name="postal_address">ئادرېس</string>
+ <string name="ghostData_company">شىركەت</string>
+ <string name="ghostData_title">ماۋزۇ</string>
+ <string name="label_notes">ئىزاھاتلار</string>
+ <string name="websiteLabelsGroup">تور بېكەت</string>
+ <string name="groupsLabel">گۇرۇپپا</string>
+ <string name="email_home">ئۆيگە ئېلخەت يوللا</string>
+ <string name="email_mobile">تېلېفونغا ئېلخەت يوللا</string>
+ <string name="email_work">خىزمەت تېلېفونغا ئېلخەت يوللا</string>
+ <string name="email_other">ئېلخەت</string>
+ <string name="email_custom"><xliff:g id="CUSTOM">%s</xliff:g> غا ئېلخەت يوللا</string>
+ <string name="email">ئېلخەت</string>
+ <string name="postal_street">كوچا</string>
+ <string name="postal_pobox">خەت ساندۇق</string>
+ <string name="postal_neighborhood">قوشنا</string>
+ <string name="postal_city">شەھەر</string>
+ <string name="postal_region">دۆلەت</string>
+ <string name="postal_postcode">پوچتا نومۇر</string>
+ <string name="postal_country">دۆلەت</string>
+ <string name="map_home">ئۆي ئادرېسىنى كۆرسەت</string>
+ <string name="map_work">خىزمەت ئادرېسىنى كۆرسەت</string>
+ <string name="map_other">ئادرېسنى كۆرسەت</string>
+ <string name="map_custom"><xliff:g id="CUSTOM">%s</xliff:g> ئادرېسنى كۆرسەت</string>
+ <string name="chat_aim">AIM دا مۇڭداش</string>
+ <string name="chat_msn">Windows Live دا مۇڭداش</string>
+ <string name="chat_yahoo">Yahoo دا مۇڭداش</string>
+ <string name="chat_skype">Skype دا مۇڭداش</string>
+ <string name="chat_qq">QQ دا مۇڭداش</string>
+ <string name="chat_gtalk">Google Talk تا مۇڭداش</string>
+ <string name="chat_icq">ICQ دا مۇڭداش</string>
+ <string name="chat_jabber">Jabber دا مۇڭداش</string>
+ <string name="chat">مۇڭداش</string>
+ <string name="description_minus_button">ئۆچۈر</string>
+ <string name="expand_collapse_name_fields_description">ئىسىم سۆز بۆلىكىنى ياي ياكى قاتلا</string>
+ <string name="list_filter_all_accounts">ھەممە ئالاقەداشلار</string>
+ <string name="list_filter_all_starred">يۇلتۇزلۇق</string>
+ <string name="list_filter_customize">ئىختىيارىي</string>
+ <string name="list_filter_single">ئالاقەداش</string>
+ <string name="display_ungrouped">بارلىق باشقا ئالاقەداشلار</string>
+ <string name="display_all_contacts">ھەممە ئالاقەداشلار</string>
+ <string name="menu_sync_remove">قەدەمداش گۇرۇپپىنى چىقىرىۋەت</string>
+ <string name="dialog_sync_add">قەدەمداش گۇرۇپپا قوش</string>
+ <string name="display_more_groups">تېخىمۇ كۆپ گۇرۇپپا…</string>
+ <string name="display_warn_remove_ungrouped">ئەگەر قەدەمداشتىن \"<xliff:g id="GROUP">%s</xliff:g>\" گۇرۇپپا چىقىرىۋېتىلسە ئۇنداقتا گۇرۇپپىغا ئايرىلمىغان باشقا ھەممە ئالاقەداشلارمۇ بىللە چىقىرىۋېتىلىدۇ.</string>
+ <string name="savingDisplayGroups">كۆرسىتىش تاللانمىسى ساقلاۋاتىدۇ…</string>
+ <string name="menu_done">تامام</string>
+ <string name="menu_doNotSave">ۋاز كەچ</string>
+ <string name="listAllContactsInAccount"><xliff:g id="NAME">%s</xliff:g> دىكى ئالاقەداشلار</string>
+ <string name="listCustomView">ئۆزلەشتۈرگەن كۆرۈنۈشتىكى ئالاقەداشلار</string>
+ <string name="listSingleContact">يەككە ئالاقەداش</string>
+ <string name="dialog_new_contact_account">ھېساباتقا ئالاقەداش قۇر</string>
+ <string name="import_from_sim">SIM كارتىدىن ئەكىر</string>
+ <string name="import_from_sdcard" product="default">ساقلىغۇچتىن ئەكىر</string>
+ <string name="cancel_import_confirmation_message"><xliff:g id="FILENAME">%S</xliff:g> ئەكىرىشتىن ۋاز كېچەمسىز؟</string>
+ <string name="cancel_export_confirmation_message"><xliff:g id="FILENAME">%S</xliff:g> چىقىرىشتىن ۋاز كېچەمسىز؟</string>
+ <string name="cancel_vcard_import_or_export_failed">vCard ئەكىر/چىقاردىن ۋاز كېچەلمەيدۇ</string>
+ <string name="fail_reason_unknown">يوچۇن خاتالىق.</string>
+ <string name="fail_reason_could_not_open_file"><xliff:g id="FILE_NAME">%s</xliff:g> ئاچالمايدۇ: <xliff:g id="EXACT_REASON">%s</xliff:g>.</string>
+ <string name="fail_reason_could_not_initialize_exporter">چىقارغۇچنى قوزغىتالمايدۇ: <xliff:g id="EXACT_REASON">%s</xliff:g>.</string>
+ <string name="fail_reason_no_exportable_contact">چىقىرىشقا بولىدىغان ئالاقەداش يوق.</string>
+ <string name="fail_reason_error_occurred_during_export">چىقىرىۋاتقاندا خاتالىق كۆرۈلدى: <xliff:g id="EXACT_REASON">%s</xliff:g>.</string>
+ <string name="fail_reason_too_long_filename">\"لازىملىق ھۆججەت ئاتى بەك ئۇزۇن (\"%s\").\"<xliff:g id="FILENAME"/></string>
+ <string name="fail_reason_too_many_vcard" product="nosdcard">ساقلىغۇچتا vCard ھۆججىتى بەك كۆپ.</string>
+ <string name="fail_reason_too_many_vcard" product="default">SD كارتىدا vCard ھۆججىتى بەك كۆپ.</string>
+ <string name="fail_reason_io_error">I/O خاتالىقى</string>
+ <string name="fail_reason_low_memory_during_import">ئەسلەك بوشلۇقى يېتىشمىدى. ھۆججەت بەك چوڭ بولۇشى مۇمكىن.</string>
+ <string name="fail_reason_vcard_parse_error"> ئويلاشمىغان سەۋەپ تۈپەيلىدىن vCard نى يېشەلمىدى</string>
+ <string name="fail_reason_not_supported">بۇ پىچىمنى قوللىمايدۇ.</string>
+ <string name="fail_reason_failed_to_collect_vcard_meta_info">بېرىلگەن vCard ھۆججەت(لەر)نىڭ مېتا سانلىق مەلۇماتىنى توپلىيالمىدى.</string>
+ <string name="fail_reason_failed_to_read_files">بىر ياكى بىر قانچە ھۆججەتنى ئەكىرەلمىدى (%s).</string>
+ <string name="exporting_vcard_finished_title"><xliff:g id="FILENAME">%s</xliff:g> چىقىرىش تاماملاندى.</string>
+ <string name="exporting_vcard_canceled_title"><xliff:g id="FILENAME">%s</xliff:g> نى چىقىرىشتىن ۋاز كەچتى</string>
+ <string name="exporting_contact_list_title">ئالاقەداش سانلىق مەلۇماتلىرىنى چىقىرىۋاتىدۇ</string>
+ <string name="exporting_contact_list_message">ئالاقەداش سانلىق مەلۇماتىڭىز ھۆججەتكە چىقىرىلىدۇ: <xliff:g id="FILE_NAME">%s</xliff:g>.</string>
+ <string name="composer_failed_to_get_database_infomation">ساندان ئۇچۇرىغا ئېرىشەلمەيدۇ.</string>
+ <string name="composer_has_no_exportable_contact" product="tablet">چىقىرىدىغان ئالاقەداشلار يوق. ئەگەر تاختا كومپيۇتېرىڭىزدا ئالاقەداشلارىڭىز بولسا ئۇنداقتا مەلۇم سانلىق مەلۇمات تەمىنلەش پىروگراممىسى تېلېفونىڭىزدىن ھەر قانداق ئالاقەداش چىقىرىشنى چەكلىگەن بولۇشى مۇمكىن.</string>
+ <string name="composer_has_no_exportable_contact" product="default">چىقىرىدىغان ئالاقەداشلار يوق. ئەگەر تېلېفونىڭىزدا ئالاقەداشلارىڭىز بولسا ئۇنداقتا مەلۇم سانلىق مەلۇمات تەمىنلەش پىروگراممىسى تېلېفونىڭىزدىن ھەر قانداق ئالاقەداش چىقىرىشنى چەكلىگەن بولۇشى مۇمكىن.</string>
+ <string name="composer_not_initialized">vCard ياساش پىروگراممىسى توغرا قوزغىتالمىدى.</string>
+ <string name="exporting_contact_failed_title">چىقىرالمايدۇ</string>
+ <string name="exporting_contact_failed_message">ئالاقەداش سانلىق مەلۇماتىنى چىقىرالمىدى.\"\n\"سەۋەبى: <xliff:g id="FAIL_REASON">%s</xliff:g></string>
+ <string name="no_sdcard_message" product="nosdcard">ھېچقانداق ساقلىغۇچ تېپىلمىدى.</string>
+ <string name="no_sdcard_message" product="default">SD كارتا تېپىلمىدى.</string>
+ <string name="confirm_export_message">ئالاقەداش تىزىمىڭىز ھۆججەتكە چىقىرىلىدۇ: <xliff:g id="VCARD_FILENAME">%s</xliff:g>.</string>
+ <string name="importing_vcard_description"> <xliff:g id="NAME">%s</xliff:g>ئەكىرىۋاتىدۇ</string>
+ <string name="reading_vcard_failed_title">vCard سانلىق مەلۇماتىنى ئوقۇيالمايدۇ</string>
+ <string name="reading_vcard_canceled_title">vCard سانلىق مەلۇماتىنى ئوقۇشتىن ۋاز كەچتى</string>
+ <string name="importing_vcard_finished_title">vCard <xliff:g id="FILENAME">%s</xliff:g> نى ئېلىپ كىرىش تاماملاندى</string>
+ <string name="importing_vcard_canceled_title"><xliff:g id="FILENAME">%s</xliff:g> ئېلىپ كىرىشتىن ۋاز كەچتى</string>
+ <string name="vcard_import_will_start_message"><xliff:g id="FILENAME">%s</xliff:g> نى تېزلا ئېلىپ كىرىدۇ.</string>
+ <string name="vcard_import_will_start_message_with_default_name">بۇ ھۆججەتنى تېزلا ئېلىپ كىرىدۇ.</string>
+ <string name="vcard_import_request_rejected_message">vCard ئېلىپ كىرىش ئىلتىماسى رەت قىلىندى. سەل تۇرۇپ قايتا سىناڭ.</string>
+ <string name="vcard_export_will_start_message"><xliff:g id="FILENAME">%s</xliff:g> نى تېزلا چىقىرىدۇ.</string>
+ <string name="vcard_export_request_rejected_message">vCard چىقىرىش ئىلتىماسى رەت قىلىندى. سەل تۇرۇپ قايتا سىناڭ.</string>
+ <string name="vcard_unknown_filename">ئالاقەداش</string>
+ <string name="caching_vcard_message">vCard نى يەرلىك ۋاقىتلىق ساقلىغۇچقا غەملەۋاتىدۇ. ناھايىتى تېزلا ھەقىقىي ئەكىرىشنى باشلايدۇ.</string>
+ <string name="percentage"><xliff:g id="PERCENTAGE">%s</xliff:g><xliff:g id="PERCENTSIGN">%%</xliff:g></string>
+ <string name="vcard_import_failed">vCard نى ئەكىرەلمەيدۇ</string>
+ <string name="import_failure_no_vcard_file" product="nosdcard">بۇ ساقلىغۇچتىن vCard ھۆججىتىنى تاپالمىدى</string>
+ <string name="import_failure_no_vcard_file" product="default">SD كارتىدىن vCard ھۆججىتىنى تاپالمىدى.</string>
+ <string name="nfc_vcard_file_name">NFC ئارقىلىق ئالاقەداش قوبۇللىدى</string>
+ <string name="confirm_export_title">ئالاقەداشلارنى چىقار؟</string>
+ <string name="select_vcard_title">vCard ھۆججەت تاللاڭ</string>
+ <string name="import_one_vcard_string">بىر vCard ھۆججەت ئەكىر</string>
+ <string name="import_multiple_vcard_string">كۆپ vCard ھۆججەت ئەكىر</string>
+ <string name="import_all_vcard_string">ھەممە vCard ھۆججەتنى ئەكىر</string>
+ <string name="searching_vcard_message" product="nosdcard">ساقلىغۇچتىن vCard سانلىق مەلۇماتىنى ئىزدەۋاتىدۇ…</string>
+ <string name="searching_vcard_message" product="default">SD كارتىدىن vCard سانلىق مەلۇماتىنى ئىزدەۋاتىدۇ</string>
+ <string name="caching_vcard_title">غەملەۋاتىدۇ</string>
+ <string name="scanning_sdcard_failed_message" product="nosdcard">ساقلىغۇچنى تەكشۈرەلمىدى. (سەۋەبى: <xliff:g id="FAIL_REASON">%s</xliff:g>)</string>
+ <string name="scanning_sdcard_failed_message" product="default">SD كارتا تەكشۈرەلمىدى(سەۋەبى: <xliff:g id="FAIL_REASON">%s</xliff:g>)</string>
+ <string name="progress_notifier_message">ئەكىرىۋاتىدۇ <xliff:g id="CURRENT_NUMBER">%s</xliff:g>/<xliff:g id="TOTAL_NUMBER">%s</xliff:g>: <xliff:g id="NAME">%s</xliff:g></string>
+ <string name="export_to_sdcard" product="default">ساقلىغۇچقا چىقار</string>
+ <string name="share_visible_contacts">كۆرۈنىدىغان ئالاقەداش ھەمبەھىر</string>
+ <string name="dialog_import_export">ئالاقەداش ئەكىر/چىقار</string>
+ <string name="dialog_import">ئالاقەداش ئەكىر</string>
+ <string name="share_error">بۇ ئالاقەداشنى ھەمبەھىرلىگىلى بولمايدۇ.</string>
+ <string name="menu_search">ئىزدە</string>
+ <string name="menu_contacts_filter">كۆرسىتىدىغان ئالاقەداشلار</string>
+ <string name="activity_title_contacts_filter">كۆرسىتىدىغان ئالاقەداشلار</string>
+ <string name="custom_list_filter">ئۆزلەشتۈرگەن كۆرۈنۈش بەلگىلەش</string>
+ <string name="hint_findContacts">ئالاقەداش ئىزدە</string>
+ <string name="contactsFavoritesLabel">يىغقۇچ</string>
+ <string name="listTotalAllContactsZero">ئالاقەداشلار يوق.</string>
+ <string name="listTotalAllContactsZeroCustom">كۆرسىتىدىغان ئالاقەداش يوق.</string>
+ <string name="listTotalAllContactsZeroStarred">ياقتۇرىدىغانلار يوق.</string>
+ <string name="listTotalAllContactsZeroGroup"><xliff:g id="NAME">%s</xliff:g> دا ئالاقەداش يوق</string>
+ <string name="menu_clear_frequents">دائىملىق ئالاقەداشلارنى تازىلا</string>
+ <string name="menu_accounts">ھېساباتلار</string>
+ <string name="menu_import_export">ئەكىر/چىقار</string>
+ <string name="contact_status_update_attribution">via <xliff:g id="source" example="Google Talk">%1$s</xliff:g></string>
+ <string name="contact_status_update_attribution_with_date"><xliff:g id="source" example="Google Talk">%2$s</xliff:g> ئارقىلىق <xliff:g id="date" example="3 hours ago">%1$s</xliff:g></string>
+</resources>
diff --git a/res/values-uk/cm_strings.xml b/res/values-uk/cm_strings.xml
new file mode 100644
index 00000000..72c7e8fa
--- /dev/null
+++ b/res/values-uk/cm_strings.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">Локальний обліковий запис планшета</string>
+ <string name="local_storage_account" product="default">Локальний обліковий запис телефону</string>
+ <string name="import_contacts_sim">Імпорт контактів з SIM-карти?</string>
+ <string name="manage_sim_contacts">Керування контактами SIM-карти</string>
+ <string name="export_to_sim">Експорт до SIM-картки</string>
+ <string name="fail_reason_import_vcard">Не вдалося імпортувати \'<xliff:g id="name">%s</xliff:g>\' через помилку вводу/виводу</string>
+ <string name="contact_share_failed_toast">Можливо відправити не більш ніж <xliff:g id="count">%d</xliff:g> контактів</string>
+ <string name="label_groups">Група</string>
+ <string name="exporting">Експорт\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> із <xliff:g id="total_number">%2$s</xliff:g> файлів</string>
+ <string name="export_failed">Помилка експорту</string>
+ <string name="sim_card_full">SIM-карта заповнена</string>
+ <string name="export_finished">Експорт завершено</string>
+ <string name="tag_too_long">Ім`я контакта занадто довге</string>
+ <string name="sim_contacts_not_loaded">Не вдається завантажити контакти SIM-карти</string>
+ <plurals name="export_cancelled">
+ <item quantity="one">Експорт було скасовано, експортовано %d елемент</item>
+ <item quantity="few">Експорт було скасовано, експортовано %d елемента</item>
+ <item quantity="other">Експорт було скасовано, експортовано %d елементів</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> не мае телефонного номеру чи електронної пошти</string>
+ <string name="import_from_sim_select">Виберіть карту для імпорту</string>
+ <string name="no_sdcard_title" product="nosdcard">Носій недоступний</string>
+ <string name="no_sdcard_title" product="default">Немає SD-карти</string>
+ <string name="deleteConfirmation_title">Видалити контакт?</string>
+ <string name="deleteConfirmation">Цей контакт буде видалено.</string>
+ <string name="copy_done">Контакт був скопійован успішно</string>
+ <string name="copy_failure">Не вдалося скопіювати контакт</string>
+ <string name="card_no_space">Копіювання контактів не вдалося, SIM-карта заповнена</string>
+ <string name="settings_contact_display_options_description">Налаштувати відображання та сортування контактів.</string>
+ <string name="ip_call_by_slot">IP-виклик за допомогою <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">Немає IP номера</string>
+ <string name="no_ip_number_on_sim_card">Немає IP номера на SIM-картці</string>
+ <string name="set_ip_number">Задати IP-номер</string>
+ <string name="ipcall_dialog_title">Налаштування IP-телефонії</string>
+ <string name="ipcall_dialog_edit_hint">Будь ласка, введіть префікс IP</string>
+ <string name="import_contacts_from_all_cards">Імпорт контактів із усіх SIM-карт</string>
+ <string name="select_path">Оберіть шлях</string>
+ <string name="select_sim">Виберіть SIM-картку</string>
+</resources>
diff --git a/res/values-zh-rCN/cm_strings.xml b/res/values-zh-rCN/cm_strings.xml
new file mode 100644
index 00000000..3134001a
--- /dev/null
+++ b/res/values-zh-rCN/cm_strings.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">本地平板电脑帐户</string>
+ <string name="local_storage_account" product="default">本地手机帐户</string>
+ <string name="import_contacts_sim">从 SIM 卡导入联系人吗?</string>
+ <string name="manage_sim_contacts">管理 SIM 卡联系人</string>
+ <string name="export_to_sim">导出到 SIM 卡</string>
+ <string name="fail_reason_import_vcard">“<xliff:g id="name">%s</xliff:g>” 由于读写错误无法导入</string>
+ <string name="contact_share_failed_toast">可以共享不超过 <xliff:g id="count">%d</xliff:g> 个联系人</string>
+ <string name="label_groups">群组</string>
+ <string name="exporting">正在导出\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="current_number">%2$s</xliff:g> 个中的 <xliff:g id="total_number">%1$s</xliff:g> 个文件</string>
+ <string name="export_failed">导出失败</string>
+ <string name="sim_card_full">SIM 卡空间已满</string>
+ <string name="export_finished">导出完成</string>
+ <string name="tag_too_long">联系人名称过长</string>
+ <string name="sim_contacts_not_loaded">无法加载 SIM 卡联系人</string>
+ <plurals name="export_cancelled">
+ <item quantity="other">导出已取消,%d 个项目已被导出</item>
+ </plurals>
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> 没有电话号码或电子邮件地址</string>
+ <string name="import_from_sim_select">选择要导入的卡</string>
+ <string name="no_sdcard_title" product="nosdcard">存储不可用</string>
+ <string name="no_sdcard_title" product="default">无 SD 卡</string>
+ <string name="deleteConfirmation_title">删除联系人?</string>
+ <string name="deleteConfirmation">此联系人将被删除。</string>
+ <string name="copy_done">已成功复制联系人</string>
+ <string name="copy_failure">复制联系人失败</string>
+ <string name="card_no_space">复制联系人失败,SIM 卡已满</string>
+ <string name="settings_contact_display_options_description">设置您的联系人的显示和排序方式。</string>
+ <string name="ip_call_by_slot">IP 呼叫由 <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">没有 IP 号码</string>
+ <string name="no_ip_number_on_sim_card">在 SIM 卡上没有 IP 号码</string>
+ <string name="set_ip_number">设置 IP 号码</string>
+ <string name="ipcall_dialog_title">IP 呼叫设置</string>
+ <string name="ipcall_dialog_edit_hint">请输入 IP 前缀</string>
+ <string name="import_contacts_from_all_cards">从所有 SIM 卡导入联系人</string>
+ <string name="select_path">选择路径</string>
+ <string name="select_sim">选择 SIM 卡</string>
+</resources>
diff --git a/res/values-zh-rHK/cm_strings.xml b/res/values-zh-rHK/cm_strings.xml
new file mode 100644
index 00000000..3eaca935
--- /dev/null
+++ b/res/values-zh-rHK/cm_strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">本機平板電腦帳戶</string>
+ <string name="local_storage_account" product="default">本機電話帳戶</string>
+ <string name="export_to_sim">匯出至 SIM 咭</string>
+ <string name="select_sim">選擇 SIM 咭</string>
+</resources>
diff --git a/res/values-zh-rTW/cm_strings.xml b/res/values-zh-rTW/cm_strings.xml
new file mode 100644
index 00000000..4c307079
--- /dev/null
+++ b/res/values-zh-rTW/cm_strings.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--Generated by crowdin.com-->
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="local_storage_account" product="tablet">本機平板電腦帳戶</string>
+ <string name="local_storage_account" product="default">本機手機帳戶</string>
+ <string name="import_contacts_sim">從 SIM 卡匯入聯絡人嗎?</string>
+ <string name="manage_sim_contacts">管理 SIM 卡聯絡人</string>
+ <string name="export_to_sim">匯出至 SIM 卡</string>
+ <string name="fail_reason_import_vcard">由於 I/O 錯誤導致無法匯入「<xliff:g id="name">%s</xliff:g>」</string>
+ <string name="contact_share_failed_toast">無法分享超過 <xliff:g id="count">%d</xliff:g> 個聯絡人</string>
+ <string name="label_groups">群組</string>
+ <string name="exporting">正在匯出\u2026</string>
+ <string name="reading_vcard_files"><xliff:g id="total_number">%2$s</xliff:g> 個檔案中的 <xliff:g id="current_number">%1$s</xliff:g> 個</string>
+ <string name="export_failed">匯出失敗</string>
+ <string name="sim_card_full">SIM 卡已滿</string>
+ <string name="export_finished">已完成匯出</string>
+ <string name="tag_too_long">聯絡人名稱過長</string>
+ <string name="sim_contacts_not_loaded">無法載入 SIM 卡聯絡人</string>
+ <plurals name="export_cancelled">
+ <item quantity="other">已取消匯出,已匯出 %d 個項目</item>
+ </plurals>
+ <string name="export_no_phone_or_email">「<xliff:g id="name">%s</xliff:g>」沒有電話號碼或電子郵件地址</string>
+ <string name="import_from_sim_select">選取要匯入的 SIM 卡</string>
+ <string name="no_sdcard_title" product="nosdcard">無法使用儲存空間</string>
+ <string name="no_sdcard_title" product="default">沒有 SD 卡</string>
+ <string name="deleteConfirmation_title">刪除聯絡人?</string>
+ <string name="deleteConfirmation">此聯絡人將被刪除。</string>
+ <string name="copy_done">已成功複製聯絡人</string>
+ <string name="copy_failure">複製聯絡人失敗</string>
+ <string name="card_no_space">複製聯絡人失敗,SIM 卡已滿</string>
+ <string name="settings_contact_display_options_description">配置您的聯絡人顯示及分類的方式。</string>
+ <string name="ip_call_by_slot">來自「<xliff:g id="subName">%s</xliff:g>」的網路通話</string>
+ <string name="no_ip_number">無 IP 號碼</string>
+ <string name="no_ip_number_on_sim_card">SIM 卡上沒有 IP 號碼</string>
+ <string name="set_ip_number">設定 IP 號碼</string>
+ <string name="ipcall_dialog_title">IP 通話設定</string>
+ <string name="ipcall_dialog_edit_hint">請輸入 IP 地區號碼</string>
+ <string name="import_contacts_from_all_cards">從所有 SIM 卡匯入聯絡人</string>
+ <string name="select_path">選取路徑</string>
+ <string name="select_sim">選取 SIM 卡</string>
+</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 64397caf..921469ff 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -17,6 +17,7 @@
<resources>
<declare-styleable name="Theme">
<attr name="android:textColorSecondary" />
+ <attr name="android:colorPrimary" />
</declare-styleable>
<declare-styleable name="ContactsDataKind">
@@ -62,6 +63,9 @@
<attr name="list_item_text_offset_top" format="dimension"/>
<attr name="list_item_data_width_weight" format="integer"/>
<attr name="list_item_label_width_weight" format="integer"/>
+ <attr name="list_item_quick_call_view_source" format="reference" />
+ <attr name="list_item_quick_call_view_background" format="reference" />
+ <attr name="list_item_quick_call_size" format="dimension" />
</declare-styleable>
<declare-styleable name="ContactBrowser">
diff --git a/res/values/cm_colors.xml b/res/values/cm_colors.xml
new file mode 100755
index 00000000..53e920ab
--- /dev/null
+++ b/res/values/cm_colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <color name="contact_tile_text_color">#ff202020</color>
+ <color name="frequent_contact_text_color">#ff000000</color>
+</resources>
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
new file mode 100644
index 00000000..52958407
--- /dev/null
+++ b/res/values/cm_strings.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014-2015 The CyanogenMod Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Virtual local storage account name -->
+ <string name="local_storage_account" product="tablet">Local tablet account</string>
+ <string name="local_storage_account" product="default">Local phone account</string>
+
+ <!-- CMCC -->
+ <string name="import_contacts_sim">Import contacts from SIM card?</string>
+
+ <!-- CAF -->
+ <!-- Action string for managing SIM contacts -->
+ <string name="manage_sim_contacts">Manage SIM card contacts</string>
+
+ <!-- Action that exports all contacts to SIM -->
+ <string name="export_to_sim">Export to SIM card</string>
+
+ <!--The failed reason shown when importing a vCard file -->
+ <string name="fail_reason_import_vcard">\'<xliff:g id="name">%s</xliff:g>\' could not be imported due to an I/O error</string>
+
+ <!-- Toast indicating that sharing too many contact has failed. [CHAR LIMIT=NONE] -->
+ <string name="contact_share_failed_toast">No more than <xliff:g id="count">%d</xliff:g> contacts can be shared</string>
+
+ <string name="label_groups">Group</string>
+ <string name="exporting">Exporting\u2026</string>
+
+ <!-- Message while reading multiple vCard files "(current number) of (total number) files"
+ The order of "current number" and "total number" cannot be changed -->
+ <string name="reading_vcard_files"><xliff:g id="current_number">%1$s</xliff:g> of <xliff:g id="total_number">%2$s</xliff:g> files</string>
+
+ <string name="export_failed">Export failed</string>
+ <string name="sim_card_full">SIM card is full</string>
+ <string name="export_finished">Export finished</string>
+ <string name="tag_too_long">Contact name is too long</string>
+ <string name="sim_contacts_not_loaded">Unable to load SIM contacts</string>
+
+ <plurals name="export_cancelled">
+ <item quantity="one">Export was cancelled, %d item was exported</item>
+ <item quantity="other">Export was cancelled, %d items were exported</item>
+ </plurals>
+
+ <string name="export_no_phone_or_email"><xliff:g id="name">%s</xliff:g> does not have a phone number or email address</string>
+
+ <string name="import_from_sim_select">Choose card to import</string>
+
+ <!-- Dialog title shown when (USB) storage does not exist [CHAR LIMIT=25] -->
+ <string name="no_sdcard_title" product="nosdcard">Storage unavailable</string>
+ <!-- Dialog title shown when SD Card does not exist -->
+ <string name="no_sdcard_title" product="default">No SD card</string>
+
+ <!-- Confirmation dialog title after users selects to delete a contact. [CHAR LIMIT=25]-->
+ <string name="deleteConfirmation_title">Delete contact?</string>
+
+ <!-- Confirmation dialog contents after users selects to delete a Writable contact. -->
+ <string name="deleteConfirmation">This contact will be deleted.</string>
+
+ <string name="copy_done">Contact was copied successfully</string>
+ <string name="copy_failure">Copying the contact failed</string>
+ <string name="card_no_space">Copying the contact failed, SIM card is full</string>
+
+ <!-- Detailed description of the preference section that allows users to configure how they
+ want their contacts to be displayed. [CHAR LIMIT=128] -->
+ <string name="settings_contact_display_options_description">Configure how your contacts are displayed and sorted.</string>
+
+ <!-- Menu item used to initiate ip call -->
+ <string name="ip_call_by_slot">IP call via <xliff:g id="subName">%s</xliff:g></string>
+ <string name="no_ip_number">No IP number</string>
+ <string name="no_ip_number_on_sim_card">No IP number on SIM card</string>
+ <string name="set_ip_number">Set IP number</string>
+ <string name="ipcall_dialog_title">IP call settings</string>
+ <string name="ipcall_dialog_edit_hint">Please input the IP prefix</string>
+
+ <string name="import_contacts_from_all_cards">Import contacts from all SIM cards</string>
+ <string name="select_path">Select path</string>
+ <string name="select_sim">Select SIM</string>
+
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 376fd3f0..8f5d5387 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -118,6 +118,8 @@
<color name="letter_tile_font_color">#ffffff</color>
+ <color name="text_highlight_color">#3B77E7</color>
+
<!-- Background color of action bars. Ensure this stays in sync with packages/Telephony
actionbar_background_color. -->
<color name="actionbar_background_color">#0fc6dc</color>
diff --git a/res/values/donottranslate_config.xml b/res/values/donottranslate_config.xml
index fe690ada..06c7f5d3 100644
--- a/res/values/donottranslate_config.xml
+++ b/res/values/donottranslate_config.xml
@@ -84,4 +84,12 @@
<!-- Flag indicating whether Contacts app is allowed to share contacts with devices outside -->
<bool name="config_allow_share_visible_contacts">true</bool>
+ <!-- configuration for set CG option -->
+ <bool name="config_set_CG_option">false</bool>
+
+ <!-- configuration for set search call logs in SmartDial -->
+ <bool name="config_smart_search">false</bool>
+
+ <!-- configuration for set operator show in dialpad or calllog -->
+ <bool name="config_show_operator">false</bool>
</resources>
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 093901ba..0b7d3a2c 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -40,6 +40,8 @@
<item type="id" name="cliv_phoneticname_textview"/>
<item type="id" name="cliv_label_textview"/>
<item type="id" name="cliv_data_view"/>
+ <!-- For ContactDeletionInteraction -->
+ <item type="id" name="dialog_delete_contact_confirmation"/>
<!-- For tag ids used by ContactPhotoManager to tag views with contact details -->
<item type="id" name="tag_display_name"/>
diff --git a/src/com/android/contacts/common/CallUtil.java b/src/com/android/contacts/common/CallUtil.java
index 3a932abe..3d5f7eab 100644
--- a/src/com/android/contacts/common/CallUtil.java
+++ b/src/com/android/contacts/common/CallUtil.java
@@ -19,14 +19,18 @@ package com.android.contacts.common;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.SystemProperties;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
+import android.telephony.PhoneNumberUtils;
import com.android.contacts.common.util.PhoneNumberHelper;
import com.android.phone.common.PhoneConstants;
+import java.util.List;
+
/**
* Utilities related to calls.
*/
@@ -90,6 +94,27 @@ public class CallUtil {
}
/**
+ * get intent to start csvt.
+ */
+ public static Intent getCSVTCallIntent(String number) {
+ Intent intent = new Intent("com.borqs.videocall.action.LaunchVideoCallScreen");
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ intent.putExtra("IsCallOrAnswer", true);
+ intent.putExtra("LaunchMode", 1);
+ intent.putExtra("call_number_key", number);
+ return intent;
+ }
+
+ /**
+ * if true, csvt is enabled.
+ */
+ public static boolean isCSVTEnabled() {
+ boolean CSVTSupported = SystemProperties.getBoolean("persist.radio.csvt.enabled", false);
+ return CSVTSupported;
+ }
+
+ /**
* A variant of {@link #getCallIntent(String, String)} for starting a video call.
*/
public static Intent getVideoCallIntent(String number, String callOrigin) {
@@ -143,6 +168,46 @@ public class CallUtil {
/**
* Return Uri with an appropriate scheme, accepting both SIP and usual phone call
+ * Checks whether two phone numbers resolve to the same phone.
+ */
+ public static boolean phoneNumbersEqual(String number1, String number2) {
+ if (PhoneNumberUtils.isUriNumber(number1) || PhoneNumberUtils.isUriNumber(number2)) {
+ return sipAddressesEqual(number1, number2);
+ } else {
+ return PhoneNumberUtils.compare(number1, number2);
+ }
+ }
+
+ private static boolean sipAddressesEqual(String number1, String number2) {
+ if (number1 == null || number2 == null) return number1 == number2;
+
+ int index1 = number1.indexOf('@');
+ final String userinfo1;
+ final String rest1;
+ if (index1 != -1) {
+ userinfo1 = number1.substring(0, index1);
+ rest1 = number1.substring(index1);
+ } else {
+ userinfo1 = number1;
+ rest1 = "";
+ }
+
+ int index2 = number2.indexOf('@');
+ final String userinfo2;
+ final String rest2;
+ if (index2 != -1) {
+ userinfo2 = number2.substring(0, index2);
+ rest2 = number2.substring(index2);
+ } else {
+ userinfo2 = number2;
+ rest2 = "";
+ }
+
+ return userinfo1.equals(userinfo2) && rest1.equalsIgnoreCase(rest2);
+ }
+
+ /**
+ * Return Uri with an appropriate scheme, accepting Voicemail, SIP, and usual phone call
* numbers.
*/
public static Uri getCallUri(String number) {
@@ -152,15 +217,24 @@ public class CallUtil {
return Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null);
}
+ private static boolean hasCapability(PhoneAccount phoneAccount, int capability) {
+ return (phoneAccount != null) &&
+ ((phoneAccount.getCapabilities() & capability) == capability);
+ }
+
public static boolean isVideoEnabled(Context context) {
TelecomManager telecommMgr = (TelecomManager)
context.getSystemService(Context.TELECOM_SERVICE);
if (telecommMgr == null) {
return false;
}
-
- // TODO: Check telecommManager for value instead.
- // return telecommMgr.isVideoEnabled();
+ List<PhoneAccountHandle> phoneAccountHandles = telecommMgr.getCallCapablePhoneAccounts();
+ for (PhoneAccountHandle handle : phoneAccountHandles) {
+ final PhoneAccount phoneAccount = telecommMgr.getPhoneAccount(handle);
+ if (hasCapability(phoneAccount, PhoneAccount.CAPABILITY_VIDEO_CALLING)) {
+ return true;
+ }
+ }
return false;
}
}
diff --git a/src/com/android/contacts/common/ContactPhotoManager.java b/src/com/android/contacts/common/ContactPhotoManager.java
index 12faadb0..f700fd8a 100644
--- a/src/com/android/contacts/common/ContactPhotoManager.java
+++ b/src/com/android/contacts/common/ContactPhotoManager.java
@@ -16,6 +16,7 @@
package com.android.contacts.common;
+import android.accounts.Account;
import android.app.ActivityManager;
import android.content.ComponentCallbacks2;
import android.content.ContentResolver;
@@ -113,19 +114,24 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 {
* draw a letter tile avatar based on the request parameters defined in the
* {@link DefaultImageRequest}.
*/
- public static Drawable getDefaultAvatarDrawableForContact(Resources resources, boolean hires,
+ public static Drawable getDefaultAvatarDrawableForContact(Context context, boolean hires,
DefaultImageRequest defaultImageRequest) {
+ return getDefaultAvatarDrawableForContact(context, hires, defaultImageRequest, null);
+ }
+
+ public static Drawable getDefaultAvatarDrawableForContact(Context context, boolean hires,
+ DefaultImageRequest defaultImageRequest, Account account) {
if (defaultImageRequest == null) {
if (sDefaultLetterAvatar == null) {
// Cache and return the letter tile drawable that is created by a null request,
// so that it doesn't have to be recreated every time it is requested again.
sDefaultLetterAvatar = LetterTileDefaultImageProvider.getDefaultImageForContact(
- resources, null);
+ context, null, account);
}
return sDefaultLetterAvatar;
}
- return LetterTileDefaultImageProvider.getDefaultImageForContact(resources,
- defaultImageRequest);
+ return LetterTileDefaultImageProvider.getDefaultImageForContact(context,
+ defaultImageRequest, account);
}
/**
@@ -365,8 +371,8 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 {
* @param defaultImageRequest {@link DefaultImageRequest} object that specifies how a
* default letter tile avatar should be drawn.
*/
- public abstract void applyDefaultImage(ImageView view, int extent, boolean darkTheme,
- DefaultImageRequest defaultImageRequest);
+ public abstract void applyDefaultImage(ImageView view, Account account,
+ int extent, boolean darkTheme, DefaultImageRequest defaultImageRequest);
}
/**
@@ -376,16 +382,17 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 {
*/
private static class LetterTileDefaultImageProvider extends DefaultImageProvider {
@Override
- public void applyDefaultImage(ImageView view, int extent, boolean darkTheme,
- DefaultImageRequest defaultImageRequest) {
- final Drawable drawable = getDefaultImageForContact(view.getResources(),
- defaultImageRequest);
+ public void applyDefaultImage(ImageView view, Account account, int extent,
+ boolean darkTheme, DefaultImageRequest defaultImageRequest) {
+ final Drawable drawable = getDefaultImageForContact(view.getContext(),
+ defaultImageRequest, account);
view.setImageDrawable(drawable);
}
- public static Drawable getDefaultImageForContact(Resources resources,
- DefaultImageRequest defaultImageRequest) {
- final LetterTileDrawable drawable = new LetterTileDrawable(resources);
+ public static Drawable getDefaultImageForContact(Context context,
+ DefaultImageRequest defaultImageRequest, Account account) {
+ final LetterTileDrawable drawable = new LetterTileDrawable(
+ context, account);
if (defaultImageRequest != null) {
// If the contact identifier is null or empty, fallback to the
// displayName. In that case, use {@code null} for the contact's
@@ -410,8 +417,8 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 {
private static Drawable sDrawable;
@Override
- public void applyDefaultImage(ImageView view, int extent, boolean darkTheme,
- DefaultImageRequest defaultImageRequest) {
+ public void applyDefaultImage(ImageView view, Account account, int extent,
+ boolean darkTheme, DefaultImageRequest defaultImageRequest) {
if (sDrawable == null) {
Context context = view.getContext();
sDrawable = new ColorDrawable(context.getResources().getColor(
@@ -440,13 +447,15 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 {
return new ContactPhotoManagerImpl(context);
}
+ public abstract void clear();
+
/**
* Load thumbnail image into the supplied image view. If the photo is already cached,
* it is displayed immediately. Otherwise a request is sent to load the photo
* from the database.
*/
- public abstract void loadThumbnail(ImageView view, long photoId, boolean darkTheme,
- boolean isCircular, DefaultImageRequest defaultImageRequest,
+ public abstract void loadThumbnail(ImageView view, long photoId, Account account,
+ boolean darkTheme, boolean isCircular, DefaultImageRequest defaultImageRequest,
DefaultImageProvider defaultProvider);
/**
@@ -454,10 +463,23 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 {
* DefaultImageProvider)} using the {@link DefaultImageProvider} {@link #DEFAULT_AVATAR}.
*/
public final void loadThumbnail(ImageView view, long photoId, boolean darkTheme,
- boolean isCircular, DefaultImageRequest defaultImageRequest) {
- loadThumbnail(view, photoId, darkTheme, isCircular, defaultImageRequest, DEFAULT_AVATAR);
+ boolean isCircular, DefaultImageRequest defaultImageRequest) {
+ loadThumbnail(view, photoId, null, darkTheme, isCircular,
+ defaultImageRequest, DEFAULT_AVATAR);
}
+ public final void loadThumbnail(ImageView view, long photoId, Account account,
+ boolean darkTheme, boolean isCircular, DefaultImageRequest defaultImageRequest) {
+ loadThumbnail(view, photoId, account, darkTheme, isCircular,
+ defaultImageRequest, DEFAULT_AVATAR);
+ }
+
+ public final void loadThumbnail(ImageView view, long photoId, boolean darkTheme,
+ boolean isCircular, DefaultImageRequest defaultImageRequest,
+ DefaultImageProvider defaultProvider) {
+ loadThumbnail(view, photoId, null, darkTheme, isCircular,
+ defaultImageRequest, defaultProvider);
+ }
/**
* Load photo into the supplied image view. If the photo is already cached,
@@ -476,8 +498,9 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 {
* @param defaultProvider The provider of default avatars (this is used if photoUri doesn't
* refer to an existing image)
*/
- public abstract void loadPhoto(ImageView view, Uri photoUri, int requestedExtent,
- boolean darkTheme, boolean isCircular, DefaultImageRequest defaultImageRequest,
+ public abstract void loadPhoto(ImageView view, Uri photoUri,
+ Account account, int requestedExtent, boolean darkTheme,
+ boolean isCircular, DefaultImageRequest defaultImageRequest,
DefaultImageProvider defaultProvider);
/**
@@ -488,12 +511,26 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 {
* @param defaultImageRequest {@link DefaultImageRequest} object that specifies how a default
* letter tile avatar should be drawn.
*/
+
public final void loadPhoto(ImageView view, Uri photoUri, int requestedExtent,
boolean darkTheme, boolean isCircular, DefaultImageRequest defaultImageRequest) {
- loadPhoto(view, photoUri, requestedExtent, darkTheme, isCircular,
+ loadPhoto(view, photoUri, null, requestedExtent, darkTheme, isCircular,
defaultImageRequest, DEFAULT_AVATAR);
}
+ public final void loadPhoto(ImageView view, Uri photoUri, Account account, int requestedExtent,
+ boolean darkTheme, boolean isCircular, DefaultImageRequest defaultImageRequest) {
+ loadPhoto(view, photoUri, account, requestedExtent, darkTheme, isCircular,
+ defaultImageRequest, DEFAULT_AVATAR);
+ }
+
+ public final void loadPhoto(ImageView view, Uri photoUri, int requestedExtent,
+ boolean darkTheme, boolean isCircular, DefaultImageRequest defaultImageRequest,
+ DefaultImageProvider defaultProvider) {
+ loadPhoto(view, photoUri, null, requestedExtent, darkTheme, isCircular,
+ defaultImageRequest, defaultProvider);
+ }
+
/**
* Calls {@link #loadPhoto(ImageView, Uri, boolean, boolean, DefaultImageRequest,
* DefaultImageProvider)} with {@link #DEFAULT_AVATAR} and with the assumption, that
@@ -504,7 +541,15 @@ public abstract class ContactPhotoManager implements ComponentCallbacks2 {
*/
public final void loadDirectoryPhoto(ImageView view, Uri photoUri, boolean darkTheme,
boolean isCircular, DefaultImageRequest defaultImageRequest) {
- loadPhoto(view, photoUri, -1, darkTheme, isCircular, defaultImageRequest, DEFAULT_AVATAR);
+ loadPhoto(view, photoUri, null, -1, darkTheme, isCircular,
+ defaultImageRequest, DEFAULT_AVATAR);
+ }
+
+ public final void loadDirectoryPhoto(ImageView view, Uri photoUri,
+ Account account, boolean darkTheme, boolean isCircular,
+ DefaultImageRequest defaultImageRequest) {
+ loadPhoto(view, photoUri, account, -1, darkTheme, isCircular,
+ defaultImageRequest, DEFAULT_AVATAR);
}
/**
@@ -784,11 +829,12 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback {
}
@Override
- public void loadThumbnail(ImageView view, long photoId, boolean darkTheme, boolean isCircular,
- DefaultImageRequest defaultImageRequest, DefaultImageProvider defaultProvider) {
+ public void loadThumbnail(ImageView view, long photoId, Account account,
+ boolean darkTheme, boolean isCircular, DefaultImageRequest defaultImageRequest,
+ DefaultImageProvider defaultProvider) {
if (photoId == 0) {
// No photo is needed
- defaultProvider.applyDefaultImage(view, -1, darkTheme, defaultImageRequest);
+ defaultProvider.applyDefaultImage(view, account, -1, darkTheme, defaultImageRequest);
mPendingRequests.remove(view);
} else {
if (DEBUG) Log.d(TAG, "loadPhoto request: " + photoId);
@@ -798,19 +844,19 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback {
}
@Override
- public void loadPhoto(ImageView view, Uri photoUri, int requestedExtent, boolean darkTheme,
- boolean isCircular, DefaultImageRequest defaultImageRequest,
+ public void loadPhoto(ImageView view, Uri photoUri, Account account, int requestedExtent,
+ boolean darkTheme, boolean isCircular, DefaultImageRequest defaultImageRequest,
DefaultImageProvider defaultProvider) {
if (photoUri == null) {
// No photo is needed
- defaultProvider.applyDefaultImage(view, requestedExtent, darkTheme,
+ defaultProvider.applyDefaultImage(view, account, requestedExtent, darkTheme,
defaultImageRequest);
mPendingRequests.remove(view);
} else {
if (DEBUG) Log.d(TAG, "loadPhoto request: " + photoUri);
if (isDefaultImageUri(photoUri)) {
- createAndApplyDefaultImageForUri(view, photoUri, requestedExtent, darkTheme,
- isCircular, defaultProvider);
+ createAndApplyDefaultImageForUri(view, account, photoUri, requestedExtent,
+ darkTheme, isCircular, defaultProvider);
} else {
loadPhotoByIdOrUri(view, Request.createFromUri(photoUri, requestedExtent,
darkTheme, isCircular, defaultProvider));
@@ -818,11 +864,12 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback {
}
}
- private void createAndApplyDefaultImageForUri(ImageView view, Uri uri, int requestedExtent,
- boolean darkTheme, boolean isCircular, DefaultImageProvider defaultProvider) {
+ private void createAndApplyDefaultImageForUri(ImageView view,
+ Account account, Uri uri, int requestedExtent, boolean darkTheme,
+ boolean isCircular, DefaultImageProvider defaultProvider) {
DefaultImageRequest request = getDefaultImageRequestFromUri(uri);
request.isCircular = isCircular;
- defaultProvider.applyDefaultImage(view, requestedExtent, darkTheme, request);
+ defaultProvider.applyDefaultImage(view, account, requestedExtent, darkTheme, request);
}
private void loadPhotoByIdOrUri(ImageView view, Request request) {
@@ -1646,7 +1693,7 @@ class ContactPhotoManagerImpl extends ContactPhotoManager implements Callback {
? DefaultImageRequest.EMPTY_DEFAULT_BUSINESS_IMAGE_REQUEST
: DefaultImageRequest.EMPTY_DEFAULT_IMAGE_REQUEST;
}
- mDefaultProvider.applyDefaultImage(view, mRequestedExtent, mDarkTheme, request);
+ mDefaultProvider.applyDefaultImage(view, null, mRequestedExtent, mDarkTheme, request);
}
}
}
diff --git a/src/com/android/contacts/common/ContactTileLoaderFactory.java b/src/com/android/contacts/common/ContactTileLoaderFactory.java
index f8b0c359..ee9a2bf1 100644
--- a/src/com/android/contacts/common/ContactTileLoaderFactory.java
+++ b/src/com/android/contacts/common/ContactTileLoaderFactory.java
@@ -23,6 +23,8 @@ import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+import android.text.TextUtils;
/**
* Used to create {@link CursorLoader}s to load different groups of
@@ -35,19 +37,23 @@ public final class ContactTileLoaderFactory {
public final static int STARRED = 2;
public final static int PHOTO_URI = 3;
public final static int LOOKUP_KEY = 4;
- public final static int CONTACT_PRESENCE = 5;
- public final static int CONTACT_STATUS = 6;
+ public final static int ACCOUNT_TYPE = 5;
+ public final static int ACCOUNT_NAME = 6;
+
+ public final static int CONTACT_PRESENCE = 7;
+ public final static int CONTACT_STATUS = 8;
+ public final static int PHOTO_ID = 9;
// Only used for StrequentPhoneOnlyLoader
- public final static int PHONE_NUMBER = 5;
- public final static int PHONE_NUMBER_TYPE = 6;
- public final static int PHONE_NUMBER_LABEL = 7;
- public final static int IS_DEFAULT_NUMBER = 8;
- public final static int PINNED = 9;
+ public final static int PHONE_NUMBER = 7;
+ public final static int PHONE_NUMBER_TYPE = 8;
+ public final static int PHONE_NUMBER_LABEL = 9;
+ public final static int IS_DEFAULT_NUMBER = 10;
+ public final static int PINNED = 11;
// The _ID field returned for strequent items actually contains data._id instead of
// contacts._id because the query is performed on the data table. In order to obtain the
// contact id for strequent items, we thus have to use Phone.contact_id instead.
- public final static int CONTACT_ID_FOR_DATA = 10;
+ public final static int CONTACT_ID_FOR_DATA = 12;
private static final String[] COLUMNS = new String[] {
Contacts._ID, // ..........................................0
@@ -55,8 +61,11 @@ public final class ContactTileLoaderFactory {
Contacts.STARRED, // ......................................2
Contacts.PHOTO_URI, // ....................................3
Contacts.LOOKUP_KEY, // ...................................4
- Contacts.CONTACT_PRESENCE, // .............................5
- Contacts.CONTACT_STATUS, // ...............................6
+ RawContacts.ACCOUNT_TYPE, // 5
+ RawContacts.ACCOUNT_NAME, // 6
+ Contacts.CONTACT_PRESENCE, // .............................7
+ Contacts.CONTACT_STATUS, // ...............................8
+ Contacts.PHOTO_ID, // .....................................9
};
/**
@@ -72,12 +81,14 @@ public final class ContactTileLoaderFactory {
Contacts.STARRED, // ......................................2
Contacts.PHOTO_URI, // ....................................3
Contacts.LOOKUP_KEY, // ...................................4
- Phone.NUMBER, // ..........................................5
- Phone.TYPE, // ............................................6
- Phone.LABEL, // ...........................................7
- Phone.IS_SUPER_PRIMARY, //.................................8
- Contacts.PINNED, // .......................................9
- Phone.CONTACT_ID //........................................10
+ RawContacts.ACCOUNT_TYPE, // 5
+ RawContacts.ACCOUNT_NAME, // 6
+ Phone.NUMBER, // ..........................................7
+ Phone.TYPE, // ............................................8
+ Phone.LABEL, // ............................................9
+ Phone.IS_SUPER_PRIMARY, //.................................10
+ Contacts.PINNED, // .......................................11
+ Phone.CONTACT_ID //........................................12
};
private static final String STARRED_ORDER = Contacts.DISPLAY_NAME+" COLLATE NOCASE ASC";
@@ -88,10 +99,16 @@ public final class ContactTileLoaderFactory {
}
public static CursorLoader createStrequentPhoneOnlyLoader(Context context) {
- Uri uri = Contacts.CONTENT_STREQUENT_URI.buildUpon()
- .appendQueryParameter(ContactsContract.STREQUENT_PHONE_ONLY, "true").build();
-
- return new CursorLoader(context, uri, COLUMNS_PHONE_ONLY, null, null, null);
+ Uri.Builder builder = Contacts.CONTENT_STREQUENT_URI.buildUpon();
+ builder.appendQueryParameter(ContactsContract.STREQUENT_PHONE_ONLY, "true");
+ // Do not show contacts in disabled SIM card
+ String disabledSimFilter = MoreContactUtils.getDisabledSimFilter();
+ if (!TextUtils.isEmpty(disabledSimFilter)) {
+ builder.appendQueryParameter(RawContacts.ACCOUNT_NAME, disabledSimFilter);
+ builder.appendQueryParameter(SimContactsConstants
+ .WITHOUT_SIM_FLAG, "true");
+ }
+ return new CursorLoader(context, builder.build(), COLUMNS_PHONE_ONLY, null, null, null);
}
public static CursorLoader createStarredLoader(Context context) {
diff --git a/src/com/android/contacts/common/MoreContactUtils.java b/src/com/android/contacts/common/MoreContactUtils.java
index 16b4e8d9..7e96c62a 100644
--- a/src/com/android/contacts/common/MoreContactUtils.java
+++ b/src/com/android/contacts/common/MoreContactUtils.java
@@ -1,6 +1,10 @@
/*
+ * Copyright (C) 2013-2014, The Linux Foundation. All Rights Reserved.
+ * Not a Contribution.
+ *
* Copyright (C) 2012 The Android Open Source Project
*
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
@@ -16,20 +20,59 @@
package com.android.contacts.common;
+import android.accounts.Account;
+
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.DialogInterface;
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.ComponentName;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.content.OperationApplicationException;
+import android.content.res.Resources;
+import android.database.Cursor;
import android.graphics.Rect;
import android.net.Uri;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.Settings;
+import android.telephony.SubscriptionManager;
import android.telephony.PhoneNumberUtils;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.util.Log;
import android.view.View;
+import android.widget.EditText;
import android.widget.TextView;
import com.android.contacts.common.model.account.AccountType;
+import com.android.contacts.common.model.account.SimAccountType;
+import com.android.internal.telephony.uicc.AdnRecord;
+import com.android.internal.telephony.uicc.IccConstants;
+import com.android.internal.telephony.IIccPhoneBook;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* Shared static contact utility methods.
@@ -37,7 +80,30 @@ import com.android.contacts.common.model.account.AccountType;
public class MoreContactUtils {
private static final String WAIT_SYMBOL_AS_STRING = String.valueOf(PhoneNumberUtils.WAIT);
+ private static final boolean DBG = true;
+ private static final String TAG = "MoreContactUtils";
+ public static final int MAX_LENGTH_NAME_IN_SIM = 14;
+ public static final int MAX_LENGTH_NAME_WITH_CHINESE_IN_SIM = 6;
+ public static final int MAX_LENGTH_NUMBER_IN_SIM = 20;
+ public static final int MAX_LENGTH_EMAIL_IN_SIM = 40;
+ private static final int NAME_POS = 0;
+ private static final int NUMBER_POS = 1;
+ private static final int EMAIL_POS = 2;
+ private static final int ANR_POS = 3;
+ private static final String PHONEBOOK = "simphonebook";
+ public static final String[] MULTI_SIM_NAME = { "perferred_name_sub1",
+ "perferred_name_sub2" };
+ public static final String PREFERRED_SIM_ICON_INDEX = "preferred_sim_icon_index";
+ public static final String[] IPCALL_PREFIX = { "ip_call_prefix_sub1",
+ "ip_call_prefix_sub2" };
+ public final static int[] IC_SIM_PICTURE = {
+ R.drawable.ic_contact_picture_sim_1,
+ R.drawable.ic_contact_picture_sim_2,
+ R.drawable.ic_contact_picture_sim_personal,
+ R.drawable.ic_contact_picture_sim_business,
+ R.drawable.ic_contact_picture_sim_primary
+ };
/**
* Returns true if two data with mimetypes which represent values in contact entries are
* considered equal for collapsing in the GUI. For caller-id, use
@@ -232,4 +298,600 @@ public class MoreContactUtils {
intent.setData(lookupUri);
return intent;
}
+
+ /** get disabled SIM card's name */
+ public static String getDisabledSimFilter() {
+ int count = TelephonyManager.getDefault().getPhoneCount();
+ StringBuilder simFilter = new StringBuilder("");
+
+ for (int i = 0; i < count; i++) {
+ if (TelephonyManager.SIM_STATE_UNKNOWN == TelephonyManager
+ .getDefault().getSimState(i)) {
+ simFilter.append(getSimAccountName(i) + ',');
+ }
+ }
+
+ return simFilter.toString();
+ }
+
+ public static boolean isShowOperator(Context context) {
+ return context.getResources().getBoolean(R.bool.config_show_operator);
+ }
+
+ public static boolean isShowOperator(Resources resources) {
+ return resources.getBoolean(R.bool.config_show_operator);
+ }
+
+ public static boolean sdCardExist(Context context) {
+ String sdcardPath = getSDPath(context);
+ if (sdcardPath == null) {
+ return false;
+ }
+ StorageManager mStorageManager = (StorageManager) context
+ .getSystemService(Context.STORAGE_SERVICE);
+ return mStorageManager.getVolumeState(sdcardPath).equals(
+ android.os.Environment.MEDIA_MOUNTED);
+ }
+
+ public static String getSDPath(Context context) {
+ StorageManager mStorageManager = (StorageManager) context
+ .getSystemService(Context.STORAGE_SERVICE);
+ StorageVolume[] volumes = mStorageManager.getVolumeList();
+ for (int i = 0; i < volumes.length; i++) {
+ if (volumes[i].isRemovable() && volumes[i].allowMassStorage()
+ && volumes[i].getDescription(context).contains("SD")) {
+ return volumes[i].getPath();
+ }
+ }
+ return null;
+ }
+
+ public static boolean isAPMOnAndSIMPowerDown(Context context) {
+ if (context == null) {
+ return false;
+ }
+ boolean isAirPlaneMode = Settings.System.getInt(context.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
+ boolean isSIMPowerDown = SystemProperties.getInt(
+ "persist.radio.apm_sim_not_pwdn", 0) == 0;
+ return isAirPlaneMode && isSIMPowerDown;
+ }
+
+ /**
+ * Get SIM card account name
+ */
+ public static String getSimAccountName(int subscription) {
+ if (TelephonyManager.getDefault().isMultiSimEnabled()) {
+ return SimContactsConstants.SIM_NAME + (subscription + 1);
+ } else {
+ return SimContactsConstants.SIM_NAME;
+ }
+ }
+
+ public static int getSubscription(String accountType, String accountName) {
+ int subscription = SimContactsConstants.SUB_INVALID;
+ if (accountType == null || accountName == null)
+ return subscription;
+ if (accountType.equals(SimContactsConstants.ACCOUNT_TYPE_SIM)) {
+ if (accountName.equals(SimContactsConstants.SIM_NAME)
+ || accountName.equals(SimContactsConstants.SIM_NAME_1)) {
+ subscription = SimContactsConstants.SUB_1;
+ } else if (accountName.equals(SimContactsConstants.SIM_NAME_2)) {
+ subscription = SimContactsConstants.SUB_2;
+ }
+ }
+ return subscription;
+ }
+
+ public static int getAnrCount(int slot) {
+ int anrCount = 0;
+ int[] subId = SubscriptionManager.getSubId(slot);
+ try {
+ IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
+ ServiceManager.getService("simphonebook"));
+
+ if (iccIpb != null) {
+ if (subId != null
+ && TelephonyManager.getDefault().isMultiSimEnabled()) {
+ anrCount = iccIpb.getAnrCountUsingSubId(subId[0]);
+ } else {
+ anrCount = iccIpb.getAnrCount();
+ }
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+
+ return anrCount;
+ }
+
+ public static int getSpareAnrCount(int slot) {
+ int anrCount = 0;
+ int[] subId = SubscriptionManager.getSubId(slot);
+ try {
+ IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
+ ServiceManager.getService("simphonebook"));
+
+ if (iccIpb != null) {
+ if (subId != null
+ && TelephonyManager.getDefault().isMultiSimEnabled()) {
+ anrCount = iccIpb.getSpareAnrCountUsingSubId(subId[0]);
+ } else {
+ anrCount = iccIpb.getSpareAnrCount();
+ }
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+
+ return anrCount;
+ }
+
+ public static int getAdnCount(int slot) {
+ int adnCount = 0;
+ int[] subId = SubscriptionManager.getSubId(slot);
+ try {
+ IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
+ ServiceManager.getService("simphonebook"));
+
+ if (iccIpb != null) {
+ if (subId != null
+ && TelephonyManager.getDefault().isMultiSimEnabled()) {
+ adnCount = iccIpb.getAdnCountUsingSubId(subId[0]);
+ } else {
+ adnCount = iccIpb.getAdnCount();
+ }
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+
+ return adnCount;
+ }
+
+ public static int getEmailCount(int slot) {
+ int emailCount = 0;
+ int[] subId = SubscriptionManager.getSubId(slot);
+ try {
+ IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
+ ServiceManager.getService("simphonebook"));
+
+ if (iccIpb != null) {
+ if (subId != null
+ && TelephonyManager.getDefault().isMultiSimEnabled()) {
+ emailCount = iccIpb.getEmailCountUsingSubId(subId[0]);
+ } else {
+ emailCount = iccIpb.getEmailCount();
+ }
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+
+ return emailCount;
+ }
+
+ public static int getSpareEmailCount(int slot) {
+ int emailCount = 0;
+ int[] subId = SubscriptionManager.getSubId(slot);
+ try {
+ IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
+ ServiceManager.getService("simphonebook"));
+
+ if (iccIpb != null) {
+ if (subId != null
+ && TelephonyManager.getDefault().isMultiSimEnabled()) {
+ emailCount = iccIpb.getSpareEmailCountUsingSubId(subId[0]);
+ } else {
+ emailCount = iccIpb.getSpareEmailCount();
+ }
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+
+ return emailCount;
+ }
+
+ /**
+ * Returns the subscription's card can save anr or not.
+ */
+ public static boolean canSaveAnr(int slot) {
+ return getAnrCount(slot) > 0 ? true : false;
+ }
+
+ /**
+ * Returns the subscription's card can save email or not.
+ */
+ public static boolean canSaveEmail(int slot) {
+ return getEmailCount(slot) > 0 ? true : false;
+ }
+
+ public static int getOneSimAnrCount(int slot) {
+ int count = 0;
+ int anrCount = getAnrCount(slot);
+ int adnCount = getAdnCount(slot);
+ if (adnCount > 0) {
+ count = anrCount % adnCount != 0 ? (anrCount / adnCount + 1)
+ : (anrCount / adnCount);
+ }
+ return count;
+ }
+
+ public static int getOneSimEmailCount(int slot) {
+ int count = 0;
+ int emailCount = getEmailCount(slot);
+ int adnCount = getAdnCount(slot);
+ if (adnCount > 0) {
+ count = emailCount % adnCount != 0 ? (emailCount
+ / adnCount + 1)
+ : (emailCount / adnCount);
+ }
+ return count;
+ }
+
+ public static boolean insertToPhone(String[] values, final ContentResolver resolver,int sub) {
+ Account account = getAcount(sub);
+ final String name = values[NAME_POS];
+ final String phoneNumber = values[NUMBER_POS];
+ final String emailAddresses = values[EMAIL_POS];
+ final String anrs = values[ANR_POS];
+
+ final String[] emailAddressArray;
+ final String[] anrArray;
+ boolean success = true;
+ if (!TextUtils.isEmpty(emailAddresses)) {
+ emailAddressArray = emailAddresses.split(",");
+ } else {
+ emailAddressArray = null;
+ }
+ if (!TextUtils.isEmpty(anrs)) {
+ anrArray = anrs.split(",");
+ } else {
+ anrArray = null;
+ }
+ if (DBG) {
+ Log.d(TAG, "insertToPhone: name= " + name + ", phoneNumber= " + phoneNumber
+ + ", emails= " + emailAddresses + ", anrs= " + anrs + ", account= " + account);
+ }
+ final ArrayList<ContentProviderOperation> operationList =
+ new ArrayList<ContentProviderOperation>();
+ ContentProviderOperation.Builder builder = ContentProviderOperation
+ .newInsert(RawContacts.CONTENT_URI);
+ builder.withValue(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED);
+
+ if (account != null) {
+ builder.withValue(RawContacts.ACCOUNT_NAME, account.name);
+ builder.withValue(RawContacts.ACCOUNT_TYPE, account.type);
+ }
+ operationList.add(builder.build());
+
+ // do not allow empty value insert into database.
+ if (!TextUtils.isEmpty(name)) {
+ 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, name);
+ operationList.add(builder.build());
+ }
+
+ if (!TextUtils.isEmpty(phoneNumber)) {
+ 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, Phone.TYPE_MOBILE);
+ builder.withValue(Phone.NUMBER, phoneNumber);
+ builder.withValue(Data.IS_PRIMARY, 1);
+ operationList.add(builder.build());
+ }
+
+ if (anrArray != null) {
+ for (String anr : anrArray) {
+ if (!TextUtils.isEmpty(anr)) {
+ 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, Phone.TYPE_HOME);
+ builder.withValue(Phone.NUMBER, anr);
+ operationList.add(builder.build());
+ }
+ }
+ }
+
+ if (emailAddressArray != null) {
+ for (String emailAddress : emailAddressArray) {
+ if (!TextUtils.isEmpty(emailAddress)) {
+ builder = ContentProviderOperation.newInsert(Data.CONTENT_URI);
+ builder.withValueBackReference(Email.RAW_CONTACT_ID, 0);
+ builder.withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
+ builder.withValue(Email.TYPE, Email.TYPE_MOBILE);
+ builder.withValue(Email.ADDRESS, emailAddress);
+ operationList.add(builder.build());
+ }
+ }
+ }
+
+ try {
+ ContentProviderResult[] results =
+ resolver.applyBatch(ContactsContract.AUTHORITY, operationList);
+ for (ContentProviderResult result: results) {
+ if (result.uri == null) {
+ success = false;
+ break;
+ }
+ }
+ return success;
+ } catch (RemoteException e) {
+ Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
+ return false;
+ } catch (OperationApplicationException e) {
+ Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
+ return false;
+ }
+ }
+
+ public static Uri insertToCard(Context context, String name, String number, String emails,
+ String anrNumber, int subscription) {
+ // add the max count limit of Chinese code or not
+ if (!TextUtils.isEmpty(name)) {
+ final int maxLen = hasChinese(name) ? MAX_LENGTH_NAME_WITH_CHINESE_IN_SIM
+ : MAX_LENGTH_NAME_IN_SIM;
+ if (name.length() > maxLen) {
+ name = name.substring(0, maxLen);
+ }
+ }
+ Uri result;
+ ContentValues mValues = new ContentValues();
+ mValues.clear();
+ mValues.put(SimContactsConstants.STR_TAG, name);
+ if (!TextUtils.isEmpty(number)) {
+ number = PhoneNumberUtils.stripSeparators(number);
+ if (number.length() > MAX_LENGTH_NUMBER_IN_SIM) {
+ number = number.substring(0, MAX_LENGTH_NUMBER_IN_SIM);
+ }
+
+ mValues.put(SimContactsConstants.STR_NUMBER, number);
+ }
+ if (!TextUtils.isEmpty(emails)) {
+ mValues.put(SimContactsConstants.STR_EMAILS, emails);
+ }
+ if (!TextUtils.isEmpty(anrNumber)) {
+ anrNumber = PhoneNumberUtils.stripSeparators(anrNumber);
+ mValues.put(SimContactsConstants.STR_ANRS, anrNumber);
+ }
+
+ SimContactsOperation mSimContactsOperation = new SimContactsOperation(context);
+ result = mSimContactsOperation.insert(mValues, subscription);
+
+ if (result != null) {
+ // we should import the contact to the sim account at the same time.
+ String[] value = new String[] {
+ name, number, emails, anrNumber
+ };
+ insertToPhone(value, context.getContentResolver(),subscription);
+ } else {
+ Log.e(TAG, "export contact: [" + name + ", " + number + ", " + emails + "] to slot "
+ + subscription + " failed");
+ }
+ return result;
+ }
+
+ public static Account getAcount(int sub) {
+ Account account = null;
+ if (TelephonyManager.getDefault().isMultiSimEnabled()) {
+ if (sub == SimContactsConstants.SUB_1) {
+ account = new Account(SimContactsConstants.SIM_NAME_1,
+ SimContactsConstants.ACCOUNT_TYPE_SIM);
+ } else if (sub == SimContactsConstants.SUB_2) {
+ account = new Account(SimContactsConstants.SIM_NAME_2,
+ SimContactsConstants.ACCOUNT_TYPE_SIM);
+ }
+ } else {
+ if (sub == SimContactsConstants.SUB_1) {
+ account = new Account(SimContactsConstants.SIM_NAME,
+ SimContactsConstants.ACCOUNT_TYPE_SIM);
+ }
+ }
+ if (account == null) {
+ account = new Account(SimContactsConstants.PHONE_NAME,
+ SimContactsConstants.ACCOUNT_TYPE_PHONE);
+ }
+ return account;
+ }
+
+ public static int getEnabledSimCount() {
+ int mPhoneCount = TelephonyManager.getDefault().getPhoneCount();
+ int enabledSimCount = 0;
+ for (int i = 0; i < mPhoneCount; i++) {
+ if (TelephonyManager.SIM_STATE_READY == TelephonyManager
+ .getDefault().getSimState(i)) {
+ enabledSimCount++;
+ }
+ }
+ return enabledSimCount;
+ }
+
+ public static int getSimFreeCount(Context context, int sub) {
+ String accountName = getAcount(sub).name;
+ int count = 0;
+
+ if (context == null) {
+ return 0;
+ }
+
+ Cursor queryCursor = context.getContentResolver().query(
+ RawContacts.CONTENT_URI,
+ new String[] {
+ RawContacts._ID
+ },
+ RawContacts.ACCOUNT_NAME + " = '" + accountName + "' AND " + RawContacts.DELETED
+ + " = 0", null, null);
+ if (queryCursor != null) {
+ try {
+ count = queryCursor.getCount();
+ } finally {
+ queryCursor.close();
+ }
+ }
+ return getAdnCount(sub) - count;
+ }
+
+ private static boolean hasChinese(String name) {
+ return name != null && name.getBytes().length > name.length();
+ }
+
+ /**
+ * Get SIM card aliases name, which defined in Settings
+ */
+ public static String getMultiSimAliasesName(Context context, int subscription) {
+ if (context == null || subscription < 0) {
+ return null;
+ }
+ String name = "";
+ if (TelephonyManager.getDefault().isMultiSimEnabled()) {
+ name = Settings.System.getString(context.getContentResolver(),
+ MULTI_SIM_NAME[subscription]);
+ }
+ if (TextUtils.isEmpty(name)) {
+ name = getSimAccountName(subscription);
+ }
+ return name;
+ }
+
+ /**
+ * Get SIM card icon index by slot
+ */
+ public static int getCurrentSimIconIndex(Context context, int slot) {
+ if (context == null || slot < SimContactsConstants.SUB_1
+ || slot >= TelephonyManager.getDefault().getPhoneCount()) {
+ return -1;
+ }
+
+ String simIconIndex = Settings.System.getString(context.getContentResolver(),
+ PREFERRED_SIM_ICON_INDEX);
+ if (TextUtils.isEmpty(simIconIndex)) {
+ return slot;
+ } else {
+ String[] indexs = simIconIndex.split(",");
+ if (slot >= indexs.length) {
+ return -1;
+ }
+ return Integer.parseInt(indexs[slot]);
+ }
+ }
+
+ /**
+ * Get Network SPN name, e.g. China Unicom
+ */
+ public static String getNetworkSpnName(Context context, int subscription) {
+ TelephonyManager tm = (TelephonyManager)
+ context.getSystemService(Context.TELEPHONY_SERVICE);
+ String netSpnName = "";
+ netSpnName = tm.getNetworkOperatorName(subscription);
+ if (TextUtils.isEmpty(netSpnName)) {
+ // if could not get the operator name, use account name instead of
+ netSpnName = getSimAccountName(subscription);
+ }
+ return toUpperCaseFirstOne(netSpnName);
+ }
+
+ public static String toUpperCaseFirstOne(String s) {
+ if (Character.isUpperCase(s.charAt(0))) {
+ return s;
+ } else {
+ return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0)))
+ .append(s.substring(1)).toString();
+ }
+ }
+
+ /**
+ * Display IP call setting dialog
+ */
+ public static void showNoIPNumberDialog(final Context mContext, final int subscription) {
+ try {
+ new AlertDialog.Builder(mContext)
+ .setTitle(R.string.no_ip_number)
+ .setMessage(R.string.no_ip_number_on_sim_card)
+ .setPositiveButton(R.string.set_ip_number,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ setIPNumber(mContext, subscription);
+ }
+ }).setNegativeButton(android.R.string.cancel, null).show();
+ } catch (Exception e) {
+ }
+ }
+
+ /**
+ * Setting IP Call number
+ */
+ public static void setIPNumber(final Context mContext, final int subscription) {
+ try {
+ LayoutInflater mInflater = LayoutInflater.from(mContext);
+ View v = mInflater.inflate(R.layout.ip_prefix_dialog, null);
+ final EditText edit = (EditText) v.findViewById(R.id.ip_prefix_dialog_edit);
+ String ip_prefix = Settings.System.getString(mContext.getContentResolver(),
+ IPCALL_PREFIX[subscription]);
+ edit.setText(ip_prefix);
+
+ new AlertDialog.Builder(mContext).setTitle(R.string.ipcall_dialog_title)
+ .setIcon(android.R.drawable.ic_dialog_info).setView(v)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String ip_prefix = edit.getText().toString();
+ Settings.System.putString(mContext.getContentResolver(),
+ IPCALL_PREFIX[subscription], ip_prefix);
+ }
+ }).setNegativeButton(android.R.string.cancel, null).show();
+ } catch (Exception e) {
+ }
+ }
+
+ /**
+ * Check one SIM card is enabled
+ */
+ public static boolean isMultiSimEnable(Context context, int slotId) {
+ if (Settings.System.getInt(context.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) != 0
+ || TelephonyManager.SIM_STATE_READY != TelephonyManager
+ .getDefault()
+ .getSimState(slotId)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get IP Call prefix
+ */
+ public static String getIPCallPrefix(Context context, int slot) {
+ String ipCallPrefix = "";
+ ipCallPrefix = Settings.System.getString(context.getContentResolver(),
+ IPCALL_PREFIX[slot]);
+ return ipCallPrefix;
+ }
+
+ public static PhoneAccountHandle getAccount(int slot) {
+ ComponentName serviceName = new ComponentName("com.android.phone",
+ "com.android.services.telephony.TelephonyConnectionService");
+ int[] subId = SubscriptionManager.getSubId(slot);
+ return new PhoneAccountHandle(serviceName, String.valueOf(subId[0]));
+ }
+
+ public static boolean shouldSearchCallLogsInSmartDial(Context context) {
+ return context.getResources().getBoolean(R.bool.config_smart_search);
+ }
+
+ public static boolean isCAndGOption(Context context) {
+ return context.getResources().getBoolean(R.bool.config_set_CG_option);
+ }
+
+ public static boolean isCAndGState(Context context) {
+ int SelectSmartfrenState = Settings.Global.getInt(context.getContentResolver(),
+ "smartfren_voice_sms_selection", 1);
+ return SelectSmartfrenState == 1 ? true : false;
+ }
+
}
diff --git a/src/com/android/contacts/common/SimContactsConstants.java b/src/com/android/contacts/common/SimContactsConstants.java
new file mode 100644
index 00000000..5928b1e6
--- /dev/null
+++ b/src/com/android/contacts/common/SimContactsConstants.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014, The Linux Foundation. All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ */
+package com.android.contacts.common;
+
+import android.telephony.SubscriptionManager;
+import com.android.internal.telephony.PhoneConstants;
+
+public interface SimContactsConstants {
+
+ public static final String SIM_NAME_1 = "SIM1";
+ public static final String SIM_NAME_2 = "SIM2";
+ public static final String SIM_NAME = "SIM";
+ public static final String PHONE_NAME = "PHONE";
+ public static final String PASSWORD = "";
+ public static final String ACCOUNT_TYPE_SIM = "com.android.sim";
+ public static final String ACCOUNT_TYPE_PHONE = "com.android.localphone";
+ public static final String SUB = PhoneConstants.SLOT_KEY;
+ public static final String ACCOUNT_TYPE = "account_type";
+ public static final String ACCOUNT_NAME = "account_name";
+ public static final String ACCOUNT_DATA = "data_set";
+ public static final String STR_TAG = "tag";
+ public static final String STR_NUMBER = "number";
+ public static final String STR_EMAILS = "emails";
+ public static final String STR_ANRS = "anrs";
+ public static final String STR_NEW_TAG = "newTag";
+ public static final String STR_NEW_NUMBER = "newNumber";
+ public static final String STR_NEW_EMAILS = "newEmails";
+ public static final String STR_NEW_ANRS = "newAnrs";
+ public static final String INTENT_EXPORT_COMPLETE =
+ "com.android.sim.INTENT_EXPORT_COMPLETE";
+ public static final String SIM_URI = "content://icc/adn";
+ public static final String SIM_SUB_URI = "content://icc/adn/subId/";
+ public static final String WITHOUT_SIM_FLAG ="no_sim";
+ public static final String IS_CONTACT = "is_contact";
+ public static final String RESULT_KEY = "result";
+ public static final String ACTION_MULTI_PICK =
+ "com.android.contacts.action.MULTI_PICK";
+ public static final String ACTION_MULTI_PICK_EMAIL =
+ "com.android.contacts.action.MULTI_PICK_EMAIL";
+ public static final String ACTION_MULTI_PICK_CALL =
+ "com.android.contacts.action.MULTI_PICK_CALL";
+ public static final String ACTION_MULTI_PICK_SIM =
+ "com.android.contacts.action.MULTI_PICK_SIM";
+ public static final int SUB_1 = PhoneConstants.SUB1;
+ public static final int SUB_2 = PhoneConstants.SUB2;
+ public static final int SUB_INVALID = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+
+}
+
+
diff --git a/src/com/android/contacts/common/SimContactsOperation.java b/src/com/android/contacts/common/SimContactsOperation.java
new file mode 100644
index 00000000..60fc9f12
--- /dev/null
+++ b/src/com/android/contacts/common/SimContactsOperation.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2014, The Linux Foundation. All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ */
+
+package com.android.contacts.common;
+
+import android.content.AsyncQueryHandler;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.ContentUris;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.CommonDataKinds;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.RawContacts;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
+import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.contacts.common.SimContactsConstants;
+
+public class SimContactsOperation {
+
+ private static final String TAG = "SimContactsOperation";
+ private static final boolean DBG = true;
+ private static final int QUERY_TOKEN = 0;
+ private static final int INSERT_TOKEN = 1;
+ private static final int UPDATE_TOKEN = 2;
+ private static final int DELETE_TOKEN = 3;
+
+ public static final String[] ACCOUNT_PROJECTION = new String[] {
+ RawContacts._ID,
+ RawContacts.CONTACT_ID,
+ RawContacts.ACCOUNT_NAME,
+ RawContacts.ACCOUNT_TYPE,
+ };
+
+
+ private static final int ACCOUNT_COLUMN_RAW_ID = 0;
+ private static final int ACCOUNT_COLUMN_CONTACT_ID = 1;
+ private static final int ACCOUNT_COLUMN_NAME = 2;
+ private static final int ACCOUNT_COLUMN_TYPE = 3;
+ private static final int ACCOUNT_COLUMN_PHONE_NAME = 4;
+
+
+
+ private static Context mContext;
+ private ContentResolver mResolver;
+ private ContentValues mValues = new ContentValues();
+
+
+ public SimContactsOperation(Context context) {
+ this.mContext = context;
+ this.mResolver = context.getContentResolver();
+ }
+
+
+ public Uri insert(ContentValues values, int subscription) {
+
+ Uri uri = getContentUri(subscription);
+ if (uri == null) {
+ return null;
+ }
+ String number = values.getAsString(SimContactsConstants.STR_NUMBER);
+ String anrs = values.getAsString(SimContactsConstants.STR_ANRS);
+ String emails = values.getAsString(SimContactsConstants.STR_EMAILS);
+ values.put(SimContactsConstants.STR_NUMBER,PhoneNumberUtils.stripSeparators(number));
+ values.put(SimContactsConstants.STR_ANRS,PhoneNumberUtils.stripSeparators(anrs));
+ values.put(SimContactsConstants.STR_EMAILS,emails);
+
+ Uri resultUri;
+ resultUri = mResolver.insert(uri,values);
+ return resultUri;
+ }
+
+ public int update(ContentValues values,int subscription) {
+ Uri uri = getContentUri(subscription);
+ if (uri == null) {
+ return -1;
+ }
+ int result;
+ String oldNumber = values.getAsString(SimContactsConstants.STR_NUMBER);
+ String newNumber = values.getAsString(SimContactsConstants.STR_NEW_NUMBER);
+ String oldAnrs = values.getAsString(SimContactsConstants.STR_ANRS);
+ String newAnrs = values.getAsString(SimContactsConstants.STR_NEW_ANRS);
+ values.put(SimContactsConstants.STR_NUMBER,PhoneNumberUtils.stripSeparators(oldNumber));
+ values.put(SimContactsConstants.STR_NEW_NUMBER,PhoneNumberUtils.stripSeparators(newNumber));
+ values.put(SimContactsConstants.STR_ANRS,PhoneNumberUtils.stripSeparators(oldAnrs));
+ values.put(SimContactsConstants.STR_NEW_ANRS,PhoneNumberUtils.stripSeparators(newAnrs));
+
+ result = mResolver.update(uri,values,null,null);
+ return result;
+
+ }
+
+ public int delete(ContentValues values, int subscription) {
+ int result;
+ StringBuilder buf = new StringBuilder();
+ String num = null;
+ String name = values.getAsString(SimContactsConstants.STR_TAG);
+ String number = values.getAsString(SimContactsConstants.STR_NUMBER);
+ String emails = values.getAsString(SimContactsConstants.STR_EMAILS);
+ String anrs = values.getAsString(SimContactsConstants.STR_ANRS);
+ if (number != null)
+ num = PhoneNumberUtils.stripSeparators(number);
+ if (anrs != null)
+ anrs = PhoneNumberUtils.stripSeparators(anrs);
+ Uri uri = getContentUri(subscription);
+
+ if (uri == null) {
+ return -1;
+ }
+
+
+ if (!TextUtils.isEmpty(name)) {
+ buf.append("tag='");
+ buf.append(name);
+ buf.append("'");
+ }
+ if (!TextUtils.isEmpty(num)) {
+ buf.append(" AND number='");
+ buf.append(num);
+ buf.append("'");
+ }
+ if (!TextUtils.isEmpty(emails)) {
+ buf.append(" AND emails='");
+ buf.append(emails);
+ buf.append("'");
+ }
+ if (!TextUtils.isEmpty(anrs)) {
+ buf.append(" AND anrs='");
+ buf.append(anrs);
+ buf.append("'");
+ }
+
+ result = mResolver.delete(uri,buf.toString(),null);
+ return result;
+
+ }
+
+ private Uri getContentUri(int subscription) {
+ Uri uri = null;
+ int[] subId = SubscriptionManager.getSubId(subscription);
+
+ if (subId != null && TelephonyManager.getDefault().isMultiSimEnabled()) {
+ if (subId.length < 1 || subId[0] < 0) {
+ return null;
+ }
+ uri = Uri.parse(SimContactsConstants.SIM_SUB_URI + subId[0]);
+ } else {
+ uri = Uri.parse(SimContactsConstants.SIM_URI);
+ }
+ return uri;
+ }
+
+ private static Cursor setupAccountCursor(long contactId) {
+ ContentResolver resolver = mContext.getContentResolver();
+
+ Cursor cursor = null;
+ try {
+ cursor = resolver.query(RawContacts.CONTENT_URI,
+ ACCOUNT_PROJECTION,
+ RawContacts.CONTACT_ID + "="
+ + Long.toString(contactId), null, null);
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ } finally {
+ if (cursor != null && cursor.moveToFirst()) {
+ return cursor;
+ }
+ if (cursor != null) {
+ cursor.close();
+ }
+ cursor = null;
+ return null;
+ }
+ }
+
+ public static ContentValues getSimAccountValues(long contactId) {
+ ContentValues mValues = new ContentValues();
+ Cursor cursor = setupAccountCursor(contactId);
+ if (cursor == null || cursor.getCount() == 0) {
+ mValues.clear();
+ return mValues;
+ }
+ long rawContactId = cursor.getLong(cursor.getColumnIndex(RawContacts._ID));
+ String accountName = cursor.getString(cursor.getColumnIndex(RawContacts.ACCOUNT_NAME));
+ String accountType = cursor.getString(cursor.getColumnIndex(RawContacts.ACCOUNT_TYPE));
+ cursor.close();
+ if (SimContactsConstants.ACCOUNT_TYPE_SIM.equals(accountType)) {
+ mValues.clear();
+ String name = getContactItems(rawContactId,StructuredName.CONTENT_ITEM_TYPE,
+ ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
+ mValues.put(SimContactsConstants.STR_TAG,name);
+
+ String number = getContactPhoneNumber(rawContactId,
+ Phone.CONTENT_ITEM_TYPE, String.valueOf(Phone.TYPE_MOBILE),
+ ContactsContract.CommonDataKinds.Phone.DATA);
+ mValues.put(SimContactsConstants.STR_NUMBER,number);
+
+ int sub = getSimSubscription(contactId);
+
+ if (MoreContactUtils.canSaveAnr(sub)) {
+ String anrs = getContactPhoneNumber(rawContactId,
+ Phone.CONTENT_ITEM_TYPE, String.valueOf(Phone.TYPE_HOME),
+ ContactsContract.CommonDataKinds.Phone.DATA);
+ mValues.put(SimContactsConstants.STR_ANRS, anrs);
+ }
+
+ if (MoreContactUtils.canSaveEmail(sub)) {
+ String emails = getContactItems(rawContactId,
+ Email.CONTENT_ITEM_TYPE, ContactsContract.CommonDataKinds.Email.DATA);
+ mValues.put(SimContactsConstants.STR_EMAILS, emails);
+ }
+ }
+ return mValues;
+ }
+
+ public static int getSimSubscription(long contactId) {
+ int subscription = SimContactsConstants.SUB_INVALID;
+ Cursor cursor = setupAccountCursor(contactId);
+ if (cursor == null || cursor.getCount() == 0) {
+ return subscription;
+ }
+
+ String accountName = cursor.getString(cursor.getColumnIndex(RawContacts.ACCOUNT_NAME));
+ String accountType = cursor.getString(cursor.getColumnIndex(RawContacts.ACCOUNT_TYPE));
+ if (accountType == null || accountName == null) {
+ return subscription;
+ }
+ if (SimContactsConstants.ACCOUNT_TYPE_SIM.equals(accountType)) {
+ subscription = MoreContactUtils.getSubscription(accountType, accountName);
+ }
+ cursor.close();
+ return subscription;
+ }
+
+
+ private static String getContactItems(long rawContactId, String selectionArg,
+ String columnName) {
+ StringBuilder retval = new StringBuilder();
+ Uri baseUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
+ Uri dataUri = Uri.withAppendedPath(baseUri, RawContacts.Data.CONTENT_DIRECTORY);
+
+ Cursor c = null;
+ try {
+ c = mContext.getContentResolver().query(dataUri, null,
+ Data.MIMETYPE + "=?", new String[] {selectionArg}, null);
+ if (c == null || c.getCount() == 0) {
+ if(c != null) {
+ c.close();
+ }
+ return null;
+ }
+ c.moveToPosition(-1);
+
+ while (c.moveToNext()) {
+ if (!TextUtils.isEmpty(retval.toString())) {
+ retval.append(",");
+ }
+ retval.append(c.getString(c.getColumnIndex(columnName)));
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+
+ return retval.toString();
+ }
+
+ private static
+ String getContactPhoneNumber(long rawContactId, String selectionArg1,
+ String selectionArg2, String columnName) {
+ StringBuilder retval = new StringBuilder();
+ Uri baseUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
+ Uri dataUri = Uri.withAppendedPath(baseUri, RawContacts.Data.CONTENT_DIRECTORY);
+
+ Cursor c = null;
+ try {
+ c = mContext.getContentResolver().query(dataUri, null,
+ Data.MIMETYPE + "=? AND " + Phone.TYPE + "=?",
+ new String[] {selectionArg1,selectionArg2}, null);
+ if (c == null || c.getCount() == 0) {
+ if(c != null) {
+ c.close();
+ }
+ return null;
+ }
+ c.moveToPosition(-1);
+
+ while (c.moveToNext()) {
+ if (!TextUtils.isEmpty(retval.toString())) {
+ retval.append(",");
+ }
+ retval.append(c.getString(c.getColumnIndex(columnName)));
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ } finally {
+ if (c != null) {
+ c.close();
+ }
+ }
+
+ return retval.toString();
+ }
+
+
+ private void log(String msg) {
+ if (DBG) Log.d(TAG, msg);
+ }
+
+}
diff --git a/src/com/android/contacts/common/editor/SelectAccountDialogFragment.java b/src/com/android/contacts/common/editor/SelectAccountDialogFragment.java
index c2ebbbfa..26fc7712 100644
--- a/src/com/android/contacts/common/editor/SelectAccountDialogFragment.java
+++ b/src/com/android/contacts/common/editor/SelectAccountDialogFragment.java
@@ -65,7 +65,7 @@ public final class SelectAccountDialogFragment extends DialogFragment {
final SelectAccountDialogFragment instance = new SelectAccountDialogFragment();
instance.setArguments(args);
instance.setTargetFragment(targetFragment, 0);
- instance.show(fragmentManager, null);
+ instance.show(fragmentManager, SelectAccountDialogFragment.TAG);
}
@Override
diff --git a/src/com/android/contacts/common/format/TextHighlighter.java b/src/com/android/contacts/common/format/TextHighlighter.java
index 496dcdae..47b36e39 100644
--- a/src/com/android/contacts/common/format/TextHighlighter.java
+++ b/src/com/android/contacts/common/format/TextHighlighter.java
@@ -16,15 +16,12 @@
package com.android.contacts.common.format;
-import android.graphics.Typeface;
import android.text.SpannableString;
import android.text.style.CharacterStyle;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.widget.TextView;
-import com.google.common.base.Preconditions;
-
/**
* Highlights the text in a text field.
*/
@@ -33,12 +30,20 @@ public class TextHighlighter {
private final static boolean DEBUG = false;
private int mTextStyle;
+ private int mHighlightColor;
private CharacterStyle mTextStyleSpan;
+ private CharacterStyle mTextColorStyleSpan;
public TextHighlighter(int textStyle) {
+ this(textStyle, -1);
+ }
+
+ public TextHighlighter(int textStyle, int highlightColor) {
mTextStyle = textStyle;
+ mHighlightColor = highlightColor;
mTextStyleSpan = getStyleSpan();
+ mTextColorStyleSpan = getColorStyleSpan();
}
/**
@@ -56,6 +61,13 @@ public class TextHighlighter {
return new StyleSpan(mTextStyle);
}
+ private CharacterStyle getColorStyleSpan() {
+ if (mHighlightColor != -1) {
+ return new ForegroundColorSpan(mHighlightColor);
+ }
+ return null;
+ }
+
/**
* Applies highlight span to the text.
* @param text Text sequence to be highlighted.
@@ -65,6 +77,9 @@ public class TextHighlighter {
public void applyMaskingHighlight(SpannableString text, int start, int end) {
/** Sets text color of the masked locations to be highlighted. */
text.setSpan(getStyleSpan(), start, end, 0);
+ if (mTextColorStyleSpan != null) {
+ text.setSpan(getColorStyleSpan(), start, end, 0);
+ }
}
/**
@@ -90,6 +105,9 @@ public class TextHighlighter {
if (index != -1) {
final SpannableString result = new SpannableString(text);
result.setSpan(mTextStyleSpan, index, index + trimmedPrefix.length(), 0 /* flags */);
+ if (mTextColorStyleSpan != null) {
+ result.setSpan(mTextColorStyleSpan, index, index + trimmedPrefix.length(), 0 /* flags */);
+ }
return result;
} else {
return text;
diff --git a/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java b/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java
index 6f002e45..68fb7df4 100644
--- a/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java
+++ b/src/com/android/contacts/common/interactions/ImportExportDialogFragment.java
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2010 The Android Open Source Project
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,23 +18,45 @@
package com.android.contacts.common.interactions;
+import android.accounts.Account;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
+import android.app.ProgressDialog;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
import android.content.DialogInterface;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Resources;
+import android.content.OperationApplicationException;
import android.database.Cursor;
+import android.text.TextUtils;
import android.net.Uri;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.Settings;
import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@@ -42,8 +66,13 @@ import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;
+import com.android.contacts.common.MoreContactUtils;
+import com.android.contacts.common.SimContactsOperation;
+import com.android.contacts.common.SimContactsConstants;
import com.android.contacts.common.R;
import com.android.contacts.common.editor.SelectAccountDialogFragment;
+import com.android.contacts.common.list.AccountFilterActivity;
+import com.android.contacts.common.list.ContactListFilter;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.account.AccountWithDataSet;
import com.android.contacts.common.util.AccountSelectionUtil;
@@ -54,6 +83,8 @@ import com.android.contacts.commonbind.analytics.AnalyticsUtil;
import java.util.Collections;
import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
/**
* An dialog invoked to import/export contacts.
@@ -65,11 +96,70 @@ public class ImportExportDialogFragment extends DialogFragment
private static final String KEY_RES_ID = "resourceId";
private static final String KEY_SUBSCRIPTION_ID = "subscriptionId";
private static final String ARG_CONTACTS_ARE_AVAILABLE = "CONTACTS_ARE_AVAILABLE";
+ private static int SIM_ID_INVALID = -1;
+ private static int mSelectedSim = SIM_ID_INVALID;
+
+ private static final boolean DEBUG = true;
+
+ public static final int SUBACTIVITY_EXPORT_CONTACTS = 100;
+
+ // This values must be consistent with ImportExportDialogFragment.SUBACTIVITY_EXPORT_CONTACTS.
+ // This values is set 101,That is avoid to conflict with other new subactivity.
+ public static final int SUBACTIVITY_SHARE_VISILBLE_CONTACTS = 101;
+ public static final int MAX_COUNT_ALLOW_SHARE_CONTACT = 2000;
private final String[] LOOKUP_PROJECTION = new String[] {
Contacts.LOOKUP_KEY
};
+ static final int PHONE_ID_COLUMN_INDEX = 0;
+ static final int PHONE_TYPE_COLUMN_INDEX = 1;
+ static final int PHONE_LABEL_COLUMN_INDEX = 2;
+ static final int PHONE_NUMBER_COLUMN_INDEX = 3;
+ static final int PHONE_DISPLAY_NAME_COLUMN_INDEX = 4;
+ static final int PHONE_CONTACT_ID_COLUMN_INDEX = 5;
+ // This value needs to start at 7. See {@link PeopleActivity}.
+ public static final int SUBACTIVITY_MULTI_PICK_CONTACT = 7;
+ //TODO: we need to refactor the export code in future release.
+ // QRD enhancement: export subscription selected by user
+ public static int mExportSub;
+ //this flag is the same as defined in MultiPickContactActivit
+ private static final String EXT_NOT_SHOW_SIM_FLAG = "not_sim_show";
+ // QRD enhancement: Toast handler for exporting concat to sim card
+ private static final int TOAST_EXPORT_FAILED = 0;
+ private static final int TOAST_EXPORT_FINISHED = 1;
+ // only for sim card is full
+ private static final int TOAST_SIM_CARD_FULL = 2;
+ // only for contact name too long
+ private static final int TOAST_CONTACT_NAME_TOO_LONG = 3;
+ // there is a case export is canceled by user
+ private static final int TOAST_EXPORT_CANCELED = 4;
+ // only for not have phone number or email address
+ private static final int TOAST_EXPORT_NO_PHONE_OR_EMAIL = 5;
+ // only for sim contacts haven't been loaded completely
+ private static final int TOAST_SIM_CARD_NOT_LOAD_COMPLETE = 6;
+ private SimContactsOperation mSimContactsOperation;
+ private ArrayAdapter<Integer> mAdapter;
+ private Activity mActivity;
+ private static boolean isExportingToSIM = false;
+ public static boolean isExportingToSIM(){
+ return isExportingToSIM;
+ }
+ private static ExportToSimThread mExportThread = null;
+ public ExportToSimThread createExportToSimThread(int subscription,
+ ArrayList<String[]> contactList, Activity mActivity){
+ if (mExportThread == null)
+ mExportThread = new ExportToSimThread(subscription, contactList, mActivity);
+ return mExportThread;
+ }
+
+ public static void destroyExportToSimThread(){
+ mExportThread = null;
+ }
+ public void showExportToSIMProgressDialog(Activity activity){
+ mExportThread.showExportProgressDialog(activity);
+ }
+
private SubscriptionManager mSubscriptionManager;
/** Preferred way to show this dialog */
@@ -92,6 +182,7 @@ public class ImportExportDialogFragment extends DialogFragment
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Wrap our context to inflate list items using the correct theme
+ mActivity = getActivity();
final Resources res = getActivity().getResources();
final LayoutInflater dialogInflater = (LayoutInflater)getActivity()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -112,6 +203,10 @@ public class ImportExportDialogFragment extends DialogFragment
}
};
+ // Manually call notifyDataSetChanged() to refresh the list.
+ adapter.setNotifyOnChange(false);
+ loadData(contactsAreAvailable);
+
final TelephonyManager manager =
(TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
@@ -162,71 +257,94 @@ public class ImportExportDialogFragment extends DialogFragment
adapter.getItem(which).mSubscriptionId);
break;
}
+ case R.string.export_to_sim: {
+ handleExportToSimRequest(resId);
+ break;
+ }
case R.string.export_to_sdcard: {
- dismissDialog = true;
- Intent exportIntent = new Intent(getActivity(), ExportVCardActivity.class);
- exportIntent.putExtra(VCardCommonArguments.ARG_CALLING_ACTIVITY,
- callingActivity);
- getActivity().startActivity(exportIntent);
+ Intent exportIntent = new Intent(SimContactsConstants.ACTION_MULTI_PICK,
+ Contacts.CONTENT_URI);
+ exportIntent.putExtra(SimContactsConstants.IS_CONTACT, true);
+ getActivity().startActivityForResult(exportIntent,
+ SUBACTIVITY_EXPORT_CONTACTS);
break;
}
case R.string.share_visible_contacts: {
- dismissDialog = true;
doShareVisibleContacts();
break;
}
default: {
- dismissDialog = true;
Log.e(TAG, "Unexpected resource: "
+ getActivity().getResources().getResourceEntryName(resId));
}
}
- if (dismissDialog) {
dialog.dismiss();
- }
}
};
return new AlertDialog.Builder(getActivity())
.setTitle(contactsAreAvailable
? R.string.dialog_import_export
: R.string.dialog_import)
- .setSingleChoiceItems(adapter, -1, clickListener)
+ .setSingleChoiceItems(mAdapter, -1, clickListener)
.create();
}
- private void doShareVisibleContacts() {
- // TODO move the query into a loader and do this in a background thread
- final Cursor cursor = getActivity().getContentResolver().query(Contacts.CONTENT_URI,
- LOOKUP_PROJECTION, Contacts.IN_VISIBLE_GROUP + "!=0", null, null);
- if (cursor != null) {
- try {
- if (!cursor.moveToFirst()) {
- Toast.makeText(getActivity(), R.string.share_error, Toast.LENGTH_SHORT).show();
- return;
- }
+ /**
+ * Loading the menu list data.
+ * @param contactsAreAvailable
+ */
+ private void loadData(boolean contactsAreAvailable) {
+ if (null == mActivity && null == mAdapter) {
+ return;
+ }
- StringBuilder uriListBuilder = new StringBuilder();
- int index = 0;
- do {
- if (index != 0)
- uriListBuilder.append(':');
- uriListBuilder.append(cursor.getString(0));
- index++;
- } while (cursor.moveToNext());
- Uri uri = Uri.withAppendedPath(
- Contacts.CONTENT_MULTI_VCARD_URI,
- Uri.encode(uriListBuilder.toString()));
-
- final Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType(Contacts.CONTENT_VCARD_TYPE);
- intent.putExtra(Intent.EXTRA_STREAM, uri);
- getActivity().startActivity(intent);
- } finally {
- cursor.close();
+ mAdapter.clear();
+ final Resources res = mActivity.getResources();
+ boolean hasIccCard = false;
+ if (TelephonyManager.getDefault().isMultiSimEnabled()) {
+ for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+ hasIccCard = TelephonyManager.getDefault().hasIccCard(i);
+ if (hasIccCard) {
+ break;
+ }
+ }
+ } else {
+ hasIccCard = TelephonyManager.getDefault().hasIccCard();
+ }
+
+ if (hasIccCard
+ && res.getBoolean(R.bool.config_allow_sim_import)) {
+ mAdapter.add(R.string.import_from_sim);
+ }
+ if (res.getBoolean(R.bool.config_allow_import_from_sdcard)) {
+ mAdapter.add(R.string.import_from_sdcard);
+ }
+
+ if (hasIccCard) {
+ mAdapter.add(R.string.export_to_sim);
+ }
+ if (res.getBoolean(R.bool.config_allow_export_to_sdcard)) {
+ // If contacts are available and there is at least one contact in
+ // database, show "Export to SD card" menu item. Otherwise hide it
+ // because it makes no sense.
+ if (contactsAreAvailable) {
+ mAdapter.add(R.string.export_to_sdcard);
+ }
+ }
+ if (res.getBoolean(R.bool.config_allow_share_visible_contacts)) {
+ if (contactsAreAvailable) {
+ mAdapter.add(R.string.share_visible_contacts);
}
}
}
+ private void doShareVisibleContacts() {
+ Intent intent = new Intent(SimContactsConstants.ACTION_MULTI_PICK);
+ intent.setType(Contacts.CONTENT_TYPE);
+ intent.putExtra(SimContactsConstants.IS_CONTACT,true);
+ getActivity().startActivityForResult(intent, SUBACTIVITY_SHARE_VISILBLE_CONTACTS);
+ }
+
/**
* Handle "import from SIM" and "import from SD".
*
@@ -237,18 +355,18 @@ public class ImportExportDialogFragment extends DialogFragment
// - more than one accounts -> ask the user
// - just one account -> use the account without asking the user
// - no account -> use phone-local storage without asking the user
- final AccountTypeManager accountTypes = AccountTypeManager.getInstance(getActivity());
+ final AccountTypeManager accountTypes = AccountTypeManager.getInstance(mActivity);
final List<AccountWithDataSet> accountList = accountTypes.getAccounts(true);
final int size = accountList.size();
- if (size > 1) {
+ if (size > 0) {
// Send over to the account selector
final Bundle args = new Bundle();
args.putInt(KEY_RES_ID, resId);
args.putInt(KEY_SUBSCRIPTION_ID, subscriptionId);
SelectAccountDialogFragment.show(
- getFragmentManager(), this,
+ mActivity.getFragmentManager(), this,
R.string.dialog_new_contact_account,
- AccountListFilter.ACCOUNTS_CONTACT_WRITABLE, args);
+ AccountListFilter.ACCOUNTS_CONTACT_WRITABLE_WITHOUT_SIM, args);
// In this case, because this DialogFragment is used as a target fragment to
// SelectAccountDialogFragment, we can't close it yet. We close the dialog when
@@ -280,6 +398,437 @@ public class ImportExportDialogFragment extends DialogFragment
dismiss();
}
+ private class ExportToSimSelectListener implements DialogInterface.OnClickListener {
+ public void onClick(DialogInterface dialog, int which) {
+ if (which >= 0) {
+ mExportSub = which;
+ } else if (which == DialogInterface.BUTTON_POSITIVE) {
+ Intent pickPhoneIntent = new Intent(
+ SimContactsConstants.ACTION_MULTI_PICK, Contacts.CONTENT_URI);
+ // do not show the contacts in SIM card
+ pickPhoneIntent.putExtra(AccountFilterActivity.KEY_EXTRA_CONTACT_LIST_FILTER,
+ ContactListFilter
+ .createFilterWithType(ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS));
+ pickPhoneIntent.putExtra(EXT_NOT_SHOW_SIM_FLAG, true);
+ pickPhoneIntent.putExtra(SimContactsConstants.IS_CONTACT,true);
+ mActivity.startActivityForResult(pickPhoneIntent, SUBACTIVITY_MULTI_PICK_CONTACT);
+ }
+ }
+ }
+
+ public class ImportFromSimSelectListener implements DialogInterface.OnClickListener {
+ public void onClick(DialogInterface dialog, int which) {
+ if (which >= 0) {
+ AccountSelectionUtil.setImportSubscription(which);
+ } else if (which == DialogInterface.BUTTON_POSITIVE) {
+ handleImportRequest(R.string.import_from_sim, which);
+ }
+ }
+ }
+
+ /**
+ * A thread that export contacts to sim card
+ */
+ public class ExportToSimThread extends Thread {
+ private int subscription;
+ private boolean canceled;
+ private ArrayList<String[]> contactList;
+ private ProgressDialog mExportProgressDlg;
+ private ContentValues mValues = new ContentValues();
+ Activity mPeople;
+ private int freeSimCount = 0;
+
+ public ExportToSimThread(int subscription, ArrayList<String[]> contactList,
+ Activity mActivity) {
+ super();
+ this.subscription = subscription;
+ this.contactList = contactList;
+ canceled = false;
+ mPeople = mActivity;
+ showExportProgressDialog(mPeople);
+ }
+
+ @Override
+ public void run() {
+ isExportingToSIM = true;
+ Account account = MoreContactUtils.getAcount(subscription);
+ boolean isAirplaneMode = false;
+ boolean isSimCardFull = false;
+ boolean isSimCardLoaded = true;
+ // GoogleSource.createMyContactsIfNotExist(account, getActivity());
+ // in case export is stopped, record the count of inserted successfully
+ int insertCount = 0;
+
+ mSimContactsOperation = new SimContactsOperation(mPeople);
+ Cursor cr = null;
+ // call query first, otherwise insert will fail if this insert is called
+ // without any query before
+ try{
+ int[] subId = SubscriptionManager.getSubId(subscription);
+ if (subId != null
+ && TelephonyManager.getDefault().isMultiSimEnabled()) {
+ cr = mPeople.getContentResolver().query(
+ Uri.parse(SimContactsConstants.SIM_SUB_URI
+ + subId[0]), null, null, null, null);
+ } else {
+ cr = mPeople.getContentResolver().query(
+ Uri.parse(SimContactsConstants.SIM_URI), null,
+ null, null, null);
+ }
+ } catch (NullPointerException e) {
+ Log.e(TAG, "Exception:" + e);
+ } finally {
+ if (cr != null) {
+ cr.close();
+ }
+ }
+ freeSimCount = MoreContactUtils.getSimFreeCount(mPeople,subscription);
+ boolean canSaveAnr = MoreContactUtils.canSaveAnr(subscription);
+ boolean canSaveEmail = MoreContactUtils.canSaveEmail(subscription);
+ int emptyAnr = MoreContactUtils.getSpareAnrCount(subscription);
+ int emptyEmail = MoreContactUtils
+ .getSpareEmailCount(subscription);
+ int emptyNumber = freeSimCount + emptyAnr;
+
+ Log.d(TAG, "freeSimCount = " + freeSimCount);
+ String emails = null;
+ if (contactList != null) {
+ Iterator<String[]> iterator = contactList.iterator();
+ while (iterator.hasNext() && !canceled && !isAirplaneMode && isSimCardLoaded) {
+ String[] contactInfo = iterator.next();
+ String name = "";
+ ArrayList<String> arrayNumber = new ArrayList<String>();
+ ArrayList<String> arrayEmail = new ArrayList<String>();
+
+ Uri dataUri = Uri.withAppendedPath(
+ ContentUris.withAppendedId(Contacts.CONTENT_URI,
+ Long.parseLong(contactInfo[1])),
+ Contacts.Data.CONTENT_DIRECTORY);
+ final String[] projection = new String[] {
+ Contacts._ID, Contacts.Data.MIMETYPE, Contacts.Data.DATA1,
+ };
+ Cursor c = mPeople.getContentResolver().query(dataUri, projection, null,
+ null, null);
+
+ if (c != null && c.moveToFirst()) {
+ do {
+ String mimeType = c.getString(1);
+ if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ String number = c.getString(2);
+ if (!TextUtils.isEmpty(number) && emptyNumber-- >0) {
+ arrayNumber.add(number);
+ }
+ } else if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ name = c.getString(2);
+ }
+ if (canSaveEmail) {
+ if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ String email = c.getString(2);
+ if (!TextUtils.isEmpty(email) && emptyEmail-- > 0) {
+ arrayEmail.add(email);
+ }
+ }
+ }
+ } while (c.moveToNext());
+ }
+ if (c != null) {
+ c.close();
+ }
+
+ if (freeSimCount > 0 && 0 == arrayNumber.size()
+ && 0 == arrayEmail.size()) {
+ mToastHandler.sendMessage(mToastHandler.obtainMessage(
+ TOAST_EXPORT_NO_PHONE_OR_EMAIL, name));
+ continue;
+ }
+
+ int phoneCountInOneSimContact = 1;
+ int emailCountInOneSimContact = 0;
+ if (canSaveAnr) {
+ int num = MoreContactUtils.getOneSimAnrCount(subscription);
+ phoneCountInOneSimContact = num > 1 ? (num + 1) : 2;
+ }
+ if (canSaveEmail) {
+ emailCountInOneSimContact = MoreContactUtils
+ .getOneSimEmailCount(subscription);
+ }
+ int nameCount = (name != null && !name.equals("")) ? 1 : 0;
+ int groupNumCount = (arrayNumber.size() % phoneCountInOneSimContact) != 0 ?
+ (arrayNumber.size() / phoneCountInOneSimContact + 1)
+ : (arrayNumber.size() / phoneCountInOneSimContact);
+ int groupEmailCount = emailCountInOneSimContact == 0 ? 0
+ : ((arrayEmail.size() % emailCountInOneSimContact) != 0 ? (
+ arrayEmail.size() / emailCountInOneSimContact + 1)
+ : (arrayEmail.size() / emailCountInOneSimContact));
+ //recalute the group when spare anr is not enough
+ if (canSaveAnr && emptyAnr <= groupNumCount) {
+ groupNumCount = arrayNumber.size() - emptyAnr;
+ }
+ int groupCount = Math.max(groupEmailCount,
+ Math.max(nameCount, groupNumCount));
+
+ Uri result = null;
+ if (DEBUG) {
+ Log.d(TAG, "GroupCount = " + groupCount);
+ }
+ for (int i = 0; i < groupCount; i++) {
+ if (freeSimCount > 0) {
+ String num = arrayNumber.size() > 0 ? arrayNumber.remove(0) : null;
+ StringBuilder anrNum = new StringBuilder();
+ StringBuilder email = new StringBuilder();
+ if (canSaveAnr && emptyAnr-- > 0) {
+ for (int j = 1; j < phoneCountInOneSimContact; j++) {
+ if (arrayNumber.size() > 0 && emptyAnr-- > 0 ) {
+ String s = arrayNumber.remove(0);
+ if (s.length() > MoreContactUtils
+ .MAX_LENGTH_NUMBER_IN_SIM) {
+ s = s.substring(0,
+ MoreContactUtils.MAX_LENGTH_NUMBER_IN_SIM);
+ }
+ anrNum.append(s);
+ anrNum.append(",");
+ }
+ }
+ }
+ if (canSaveEmail) {
+ for (int j = 0; j < emailCountInOneSimContact; j++) {
+ if (arrayEmail.size() > 0) {
+ String s = arrayEmail.remove(0);
+ if (s.length() > MoreContactUtils
+ .MAX_LENGTH_EMAIL_IN_SIM) {
+ s = s.substring(0,
+ MoreContactUtils.MAX_LENGTH_EMAIL_IN_SIM);
+ }
+ email.append(s);
+ email.append(",");
+ }
+ }
+ }
+
+ result = MoreContactUtils.insertToCard(mPeople, name, num,
+ email.toString(), anrNum.toString(), subscription);
+
+ if (null == result) {
+ // add toast handler when sim card is full
+ if ((MoreContactUtils.getAdnCount(subscription) > 0)
+ && (MoreContactUtils.getSimFreeCount(mPeople,
+ subscription) == 0)) {
+ isSimCardFull = true;
+ mToastHandler.sendEmptyMessage(TOAST_SIM_CARD_FULL);
+ break;
+ } else {
+ isAirplaneMode = MoreContactUtils
+ .isAPMOnAndSIMPowerDown(mPeople);
+ if (isAirplaneMode) {
+ mToastHandler.sendEmptyMessage(TOAST_EXPORT_FAILED);
+ break;
+ } else {
+ continue;
+ }
+ }
+ } else {
+ if (DEBUG) {
+ Log.d(TAG, "Exported contact [" + name + ", "
+ + contactInfo[0] + ", " + contactInfo[1]
+ + "] to sub " + subscription);
+ }
+ insertCount++;
+ freeSimCount--;
+ }
+ } else {
+ if (MoreContactUtils.getAdnCount(subscription) == 0) {
+ isSimCardLoaded = false;
+ mToastHandler.sendEmptyMessage(
+ TOAST_SIM_CARD_NOT_LOAD_COMPLETE);
+ } else {
+ isSimCardFull = true;
+ mToastHandler.sendEmptyMessage(TOAST_SIM_CARD_FULL);
+ }
+ break;
+ }
+ }
+
+ if (isSimCardFull) {
+ break;
+ }
+ }
+ }
+ if (mExportProgressDlg != null) {
+ mExportProgressDlg.dismiss();
+ mExportProgressDlg = null;
+ }
+
+ if (!isAirplaneMode && !isSimCardFull) {
+ // if canceled, show toast indicating export is interrupted.
+ if (canceled) {
+ mToastHandler.sendMessage(mToastHandler.obtainMessage(TOAST_EXPORT_CANCELED,
+ insertCount, 0));
+ } else {
+ mToastHandler.sendEmptyMessage(TOAST_EXPORT_FINISHED);
+ }
+ }
+ isExportingToSIM = false;
+ Intent intent = new Intent(SimContactsConstants.INTENT_EXPORT_COMPLETE);
+ mPeople.sendBroadcast(intent);
+ }
+
+ private Handler mToastHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case TOAST_EXPORT_FAILED:
+ Toast.makeText(mPeople, R.string.export_failed, Toast.LENGTH_SHORT).show();
+ break;
+ case TOAST_EXPORT_FINISHED:
+ Toast.makeText(mPeople, R.string.export_finished, Toast.LENGTH_SHORT)
+ .show();
+ break;
+
+ // add toast handler when sim card is full
+ case TOAST_SIM_CARD_FULL:
+ Toast.makeText(mPeople, R.string.sim_card_full, Toast.LENGTH_SHORT).show();
+ break;
+
+ //add the max count limit of Chinese code or not
+ case TOAST_CONTACT_NAME_TOO_LONG:
+ Toast.makeText(mPeople, R.string.tag_too_long, Toast.LENGTH_SHORT).show();
+ break;
+
+ // add toast handler when export is canceled
+ case TOAST_EXPORT_CANCELED:
+ String text = mPeople.getResources().getQuantityString(
+ R.plurals.export_cancelled, msg.arg1, msg.arg1);
+ Toast.makeText(mPeople, text, Toast.LENGTH_SHORT).show();
+ break;
+
+ // add toast handler when no phone or email
+ case TOAST_EXPORT_NO_PHONE_OR_EMAIL:
+ String name = (String) msg.obj;
+ Toast.makeText(mPeople,
+ mPeople.getString(R.string.export_no_phone_or_email, name),
+ Toast.LENGTH_SHORT).show();
+ break;
+ case TOAST_SIM_CARD_NOT_LOAD_COMPLETE:
+ Toast.makeText(mPeople, R.string.sim_contacts_not_loaded,
+ Toast.LENGTH_SHORT).show();
+ break;
+ }
+ }
+ };
+
+ public void showExportProgressDialog(Activity activity){
+ mPeople = activity;
+ mExportProgressDlg = new ProgressDialog(mPeople);
+ mExportProgressDlg.setTitle(R.string.export_to_sim);
+ mExportProgressDlg.setOnCancelListener(new OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ Log.d(TAG, "Cancel exporting contacts");
+ canceled = true;
+ }
+ });
+ mExportProgressDlg.setMessage(mPeople.getString(R.string.exporting));
+ mExportProgressDlg.setProgressNumberFormat(mPeople.getString(
+ R.string.reading_vcard_files));
+ mExportProgressDlg.setMax(contactList.size());
+ //mExportProgressDlg.setProgress(insertCount);
+
+ // set cancel dialog by touching outside disabled.
+ mExportProgressDlg.setCanceledOnTouchOutside(false);
+
+ // add a cancel button to let user cancel explicitly.
+ mExportProgressDlg.setButton(DialogInterface.BUTTON_NEGATIVE,
+ mPeople.getString(android.R.string.cancel),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (DEBUG) {
+ Log.d(TAG, "Cancel exporting contacts by click button");
+ }
+ canceled = true;
+ }
+ });
+
+ mExportProgressDlg.show();
+ }
+ }
+
+ public ImportFromSimSelectListener listener;
+ /**
+ * Create a {@link Dialog} that allows the user to pick from a bulk import
+ * or bulk export task across all contacts.
+ */
+ private Dialog displayImportExportDialog(int id, Bundle bundle) {
+ Dialog diag;
+ switch (id) {
+ case R.string.import_from_sim_select: {
+ listener = new ImportFromSimSelectListener();
+ showSimSelectDialog();
+ break;
+ }
+ case R.string.export_to_sim: {
+ String[] items = new String[TelephonyManager.getDefault().getPhoneCount()];
+ for (int i = 0; i < items.length; i++) {
+ items[i] = getString(R.string.export_to_sim) + ": "
+ + MoreContactUtils.getMultiSimAliasesName(mActivity, i);
+ }
+ mExportSub = SimContactsConstants.SUB_1;
+ ExportToSimSelectListener listener = new ExportToSimSelectListener();
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.export_to_sim)
+ .setPositiveButton(android.R.string.ok, listener)
+ .setSingleChoiceItems(items, 0, listener).create();
+ }
+ }
+ return null;
+ }
+
+ public void showSimSelectDialog() {
+ AccountSelectionUtil.setImportSubscription(SimContactsConstants.SUB_1);
+ // item is for sim account to show
+ String[] items = new String[TelephonyManager.getDefault().getPhoneCount()];
+ for (int i = 0; i < items.length; i++) {
+ items[i] = getString(R.string.import_from_sim) + ": "
+ + MoreContactUtils.getMultiSimAliasesName(mActivity, i);
+ }
+ new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.import_from_sim)
+ .setPositiveButton(android.R.string.ok, listener)
+ .setSingleChoiceItems(items, 0, listener).create().show();
+ }
+
+ private void handleExportToSimRequest(int Id) {
+ if (MoreContactUtils.getEnabledSimCount() >1) {
+ //has two enalbed sim cards, prompt dialog to select one
+ displayImportExportDialog(Id, null).show();
+ } else {
+ mExportSub = getEnabledIccCard();
+ Intent pickPhoneIntent = new Intent(
+ SimContactsConstants.ACTION_MULTI_PICK, Contacts.CONTENT_URI);
+ // do not show the contacts in SIM card
+ pickPhoneIntent.putExtra(AccountFilterActivity.KEY_EXTRA_CONTACT_LIST_FILTER,
+ ContactListFilter
+ .createFilterWithType(ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS));
+ pickPhoneIntent.putExtra(EXT_NOT_SHOW_SIM_FLAG, true);
+ pickPhoneIntent.putExtra(SimContactsConstants.IS_CONTACT,true);
+ mActivity.startActivityForResult(pickPhoneIntent, SUBACTIVITY_MULTI_PICK_CONTACT);
+ }
+ }
+
+ private boolean hasEnabledIccCard(int subscription) {
+ return TelephonyManager.getDefault().hasIccCard(subscription)
+ && TelephonyManager.getDefault().getSimState(subscription)
+ == TelephonyManager.SIM_STATE_READY;
+ }
+
+ private int getEnabledIccCard() {
+ for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+ if (hasEnabledIccCard(i)) {
+ return i;
+ }
+ }
+ return SimContactsConstants.SUB_1;
+ }
+
private CharSequence getSubDescription(SubscriptionInfo record) {
CharSequence name = record.getDisplayName();
if (TextUtils.isEmpty(record.getNumber())) {
diff --git a/src/com/android/contacts/common/interactions/ImportSIMContactsDialogFragment.java b/src/com/android/contacts/common/interactions/ImportSIMContactsDialogFragment.java
new file mode 100644
index 00000000..a54f791a
--- /dev/null
+++ b/src/com/android/contacts/common/interactions/ImportSIMContactsDialogFragment.java
@@ -0,0 +1,36 @@
+package com.android.contacts.common.interactions;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import com.android.contacts.common.R;
+
+/**
+ * An dialog invoked to import/export contacts.
+ */
+public class ImportSIMContactsDialogFragment extends DialogFragment {
+ public static final String TAG = "ImportSIMContactsDialogFragment";
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ // Use the Builder class for convenient dialog construction
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setMessage(R.string.import_contacts_sim)
+ .setPositiveButton(android.R.string.ok,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ ImportExportDialogFragment.show(getFragmentManager(),
+ false, ImportSIMContactsDialogFragment.class);
+ }})
+ .setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ // Nothing to do
+ dismiss();
+ }});
+ // Create the AlertDialog object and return it
+ return builder.create();
+ }
+}
diff --git a/src/com/android/contacts/common/lettertiles/LetterTileDrawable.java b/src/com/android/contacts/common/lettertiles/LetterTileDrawable.java
index e62d4218..34d3d457 100644
--- a/src/com/android/contacts/common/lettertiles/LetterTileDrawable.java
+++ b/src/com/android/contacts/common/lettertiles/LetterTileDrawable.java
@@ -16,6 +16,8 @@
package com.android.contacts.common.lettertiles;
+import android.accounts.Account;
+import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
@@ -28,8 +30,11 @@ import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
+import android.telephony.TelephonyManager;
import android.util.Log;
+import com.android.contacts.common.MoreContactUtils;
+import com.android.contacts.common.model.account.SimAccountType;
import com.android.contacts.common.R;
import com.android.contacts.common.util.BitmapUtil;
@@ -53,6 +58,9 @@ public class LetterTileDrawable extends Drawable {
private static Bitmap DEFAULT_PERSON_AVATAR;
private static Bitmap DEFAULT_BUSINESS_AVATAR;
private static Bitmap DEFAULT_VOICEMAIL_AVATAR;
+ private static Bitmap DEFAULT_SIM_PERSON_AVATAR;
+ private static Bitmap[] DEFAULT_CUSTOMIZE_SIM_PERSON_AVATAR =
+ new Bitmap[MoreContactUtils.IC_SIM_PICTURE.length];
/** Reusable components to avoid new allocations */
private static final Paint sPaint = new Paint();
@@ -71,11 +79,17 @@ public class LetterTileDrawable extends Drawable {
private float mScale = 1.0f;
private float mOffset = 0.0f;
private boolean mIsCircle = false;
+ private Account mAccount;
+ private Context mContext;
- public LetterTileDrawable(final Resources res) {
+
+ public LetterTileDrawable(final Context context, final Account account) {
mPaint = new Paint();
mPaint.setFilterBitmap(true);
mPaint.setDither(true);
+ mAccount = account;
+ mContext = context;
+ Resources res = context.getResources();
if (sColors == null) {
sColors = res.obtainTypedArray(R.array.letter_tile_colors);
@@ -88,6 +102,13 @@ public class LetterTileDrawable extends Drawable {
R.drawable.ic_business_white_120dp);
DEFAULT_VOICEMAIL_AVATAR = BitmapFactory.decodeResource(res,
R.drawable.ic_voicemail_avatar);
+ DEFAULT_SIM_PERSON_AVATAR = BitmapFactory.decodeResource(res,
+ R.drawable.ic_contact_picture_sim);
+ for (int i = 0; i < MoreContactUtils.IC_SIM_PICTURE.length; i++) {
+ DEFAULT_CUSTOMIZE_SIM_PERSON_AVATAR[i] = BitmapFactory
+ .decodeResource(res, MoreContactUtils.IC_SIM_PICTURE[i]);
+ }
+
sPaint.setTypeface(Typeface.create(
res.getString(R.string.letter_tile_letter_font_family), Typeface.NORMAL));
sPaint.setTextAlign(Align.CENTER);
@@ -143,7 +164,9 @@ public class LetterTileDrawable extends Drawable {
}
// Draw letter/digit only if the first character is an english letter
- if (mDisplayName != null && isEnglishLetter(mDisplayName.charAt(0))) {
+ if (mDisplayName != null
+ && isEnglishLetter(mDisplayName.charAt(0))
+ && (mAccount == null || (!mAccount.type.equals(SimAccountType.ACCOUNT_TYPE)))) {
// Draw letter or digit.
sFirstChar[0] = Character.toUpperCase(mDisplayName.charAt(0));
@@ -160,9 +183,9 @@ public class LetterTileDrawable extends Drawable {
sPaint);
} else {
// Draw the default image if there is no letter/digit to be drawn
- final Bitmap bitmap = getBitmapForContactType(mContactType);
- drawBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(),
- canvas);
+ final Bitmap bitmap = getBitmapForContactType(mContactType,
+ mAccount, mContext);
+ drawBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight(), canvas);
}
}
@@ -184,7 +207,21 @@ public class LetterTileDrawable extends Drawable {
return sColors.getColor(color, sDefaultColor);
}
- private static Bitmap getBitmapForContactType(int contactType) {
+ private static Bitmap getBitmapForContactType(int contactType,
+ Account account, Context context) {
+ if (account != null && SimAccountType.ACCOUNT_TYPE.equals(account.type)) {
+ if (TelephonyManager.getDefault().isMultiSimEnabled()) {
+ final int sub = MoreContactUtils.getSubscription(
+ SimAccountType.ACCOUNT_TYPE, account.name);
+ int index = MoreContactUtils.getCurrentSimIconIndex(context, sub);
+ if (index < 0) {
+ return DEFAULT_SIM_PERSON_AVATAR;
+ }
+ return DEFAULT_CUSTOMIZE_SIM_PERSON_AVATAR[index];
+ } else {
+ return DEFAULT_SIM_PERSON_AVATAR;
+ }
+ }
switch (contactType) {
case TYPE_PERSON:
return DEFAULT_PERSON_AVATAR;
diff --git a/src/com/android/contacts/common/list/AccountFilterActivity.java b/src/com/android/contacts/common/list/AccountFilterActivity.java
index 58450c65..9dba5362 100644..100755
--- a/src/com/android/contacts/common/list/AccountFilterActivity.java
+++ b/src/com/android/contacts/common/list/AccountFilterActivity.java
@@ -120,7 +120,8 @@ public class AccountFilterActivity extends Activity implements AdapterView.OnIte
// Hide extensions with no raw_contacts.
continue;
}
- Drawable icon = accountType != null ? accountType.getDisplayIcon(context) : null;
+ Drawable icon = accountType != null ? accountType.getDisplayIcon(
+ context, account.name) : null;
accountFilters.add(ContactListFilter.createAccountFilter(
account.type, account.name, account.dataSet, icon));
}
diff --git a/src/com/android/contacts/common/list/ContactEntry.java b/src/com/android/contacts/common/list/ContactEntry.java
index 43fc19dd..66ae50d1 100644
--- a/src/com/android/contacts/common/list/ContactEntry.java
+++ b/src/com/android/contacts/common/list/ContactEntry.java
@@ -16,6 +16,7 @@
package com.android.contacts.common.list;
+import android.accounts.Account;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.provider.ContactsContract.PinnedPositions;
@@ -36,6 +37,7 @@ public class ContactEntry {
public int pinned = PinnedPositions.UNPINNED;
public boolean isFavorite = false;
public boolean isDefaultNumber = false;
+ public Account account;
public static final ContactEntry BLANK_ENTRY = new ContactEntry();
} \ No newline at end of file
diff --git a/src/com/android/contacts/common/list/ContactEntryListAdapter.java b/src/com/android/contacts/common/list/ContactEntryListAdapter.java
index 4d7eb197..26f13f3d 100644..100755
--- a/src/com/android/contacts/common/list/ContactEntryListAdapter.java
+++ b/src/com/android/contacts/common/list/ContactEntryListAdapter.java
@@ -15,6 +15,7 @@
*/
package com.android.contacts.common.list;
+import android.accounts.Account;
import android.content.Context;
import android.content.CursorLoader;
import android.content.res.Resources;
@@ -62,6 +63,7 @@ public abstract class ContactEntryListAdapter extends IndexerListAdapter {
private boolean mCircularPhotos = true;
private boolean mQuickContactEnabled;
private boolean mAdjustSelectionBoundsEnabled;
+ private boolean mQuickCallButtonEnabled;
/**
* indicates if contact queries include profile
@@ -346,6 +348,10 @@ public abstract class ContactEntryListAdapter extends IndexerListAdapter {
return mQuickContactEnabled;
}
+ public boolean isQuickCallButtonEnabled() {
+ return mQuickCallButtonEnabled;
+ }
+
public void setQuickContactEnabled(boolean quickContactEnabled) {
mQuickContactEnabled = quickContactEnabled;
}
@@ -358,6 +364,10 @@ public abstract class ContactEntryListAdapter extends IndexerListAdapter {
mAdjustSelectionBoundsEnabled = enabled;
}
+ public void setQuickCallButtonEnabled(boolean quickCallButtonEnabled) {
+ mQuickCallButtonEnabled = quickCallButtonEnabled;
+ }
+
public boolean shouldIncludeProfile() {
return mIncludeProfile;
}
@@ -710,22 +720,31 @@ public abstract class ContactEntryListAdapter extends IndexerListAdapter {
* @param contactIdColumn Index of the contact id column
* @param lookUpKeyColumn Index of the lookup key column
* @param displayNameColumn Index of the display name column
+ * @param accountTypeColumn Index of the account type column
+ * @param accountNameColumn Index of the account name column
*/
protected void bindQuickContact(final ContactListItemView view, int partitionIndex,
Cursor cursor, int photoIdColumn, int photoUriColumn, int contactIdColumn,
- int lookUpKeyColumn, int displayNameColumn) {
+ int lookUpKeyColumn,int displayNameColumn, int accountTypeColumn,
+ int accountNameColumn) {
long photoId = 0;
if (!cursor.isNull(photoIdColumn)) {
photoId = cursor.getLong(photoIdColumn);
}
+ Account account = null;
+ if (!cursor.isNull(accountTypeColumn) && !cursor.isNull(accountNameColumn)) {
+ final String accountType = cursor.getString(accountTypeColumn);
+ final String accountName = cursor.getString(accountNameColumn);
+ account = new Account(accountName, accountType);
+ }
QuickContactBadge quickContact = view.getQuickContact();
quickContact.assignContactUri(
getContactUri(partitionIndex, cursor, contactIdColumn, lookUpKeyColumn));
if (photoId != 0 || photoUriColumn == -1) {
- getPhotoLoader().loadThumbnail(quickContact, photoId, mDarkTheme, mCircularPhotos,
- null);
+ getPhotoLoader().loadThumbnail(quickContact, photoId, account,
+ mDarkTheme, mCircularPhotos, null);
} else {
final String photoUriString = cursor.getString(photoUriColumn);
final Uri photoUri = photoUriString == null ? null : Uri.parse(photoUriString);
@@ -734,8 +753,8 @@ public abstract class ContactEntryListAdapter extends IndexerListAdapter {
request = getDefaultImageRequestFromCursor(cursor, displayNameColumn,
lookUpKeyColumn);
}
- getPhotoLoader().loadPhoto(quickContact, photoUri, -1, mDarkTheme, mCircularPhotos,
- request);
+ getPhotoLoader().loadPhoto(quickContact, photoUri, account, -1,
+ mDarkTheme, mCircularPhotos, request);
}
}
diff --git a/src/com/android/contacts/common/list/ContactEntryListFragment.java b/src/com/android/contacts/common/list/ContactEntryListFragment.java
index c38e9693..c7204931 100644..100755
--- a/src/com/android/contacts/common/list/ContactEntryListFragment.java
+++ b/src/com/android/contacts/common/list/ContactEntryListFragment.java
@@ -20,9 +20,11 @@ import android.app.Activity;
import android.app.Fragment;
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.CursorLoader;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
@@ -48,6 +50,8 @@ import com.android.common.widget.CompositeCursorAdapter.Partition;
import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.preference.ContactsPreferences;
import com.android.contacts.common.util.ContactListViewUtils;
+import com.android.contacts.common.util.SchedulingUtils;
+import com.android.internal.telephony.TelephonyIntents;
import java.util.Locale;
@@ -70,6 +74,7 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
private static final String KEY_QUICK_CONTACT_ENABLED = "quickContactEnabled";
private static final String KEY_ADJUST_SELECTION_BOUNDS_ENABLED =
"adjustSelectionBoundsEnabled";
+ private static final String KEY_QUICK_CALL_BUTTON_ENABLED = "quickCallButtonEnabled";
private static final String KEY_INCLUDE_PROFILE = "includeProfile";
private static final String KEY_SEARCH_MODE = "searchMode";
private static final String KEY_VISIBLE_SCROLLBAR_ENABLED = "visibleScrollbarEnabled";
@@ -95,6 +100,7 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
private boolean mPhotoLoaderEnabled;
private boolean mQuickContactEnabled = true;
private boolean mAdjustSelectionBoundsEnabled = true;
+ private boolean mQuickCallButtonEnabled = false;
private boolean mIncludeProfile;
private boolean mSearchMode;
private boolean mVisibleScrollbarEnabled;
@@ -145,6 +151,13 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
private LoaderManager mLoaderManager;
+ private BroadcastReceiver mSIMStateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context arg0, Intent arg1) {
+ reloadData();
+ }
+ };
+
private Handler mDelayedDirectorySearchHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -229,6 +242,7 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
outState.putBoolean(KEY_PHOTO_LOADER_ENABLED, mPhotoLoaderEnabled);
outState.putBoolean(KEY_QUICK_CONTACT_ENABLED, mQuickContactEnabled);
outState.putBoolean(KEY_ADJUST_SELECTION_BOUNDS_ENABLED, mAdjustSelectionBoundsEnabled);
+ outState.putBoolean(KEY_QUICK_CALL_BUTTON_ENABLED, mQuickCallButtonEnabled);
outState.putBoolean(KEY_INCLUDE_PROFILE, mIncludeProfile);
outState.putBoolean(KEY_SEARCH_MODE, mSearchMode);
outState.putBoolean(KEY_VISIBLE_SCROLLBAR_ENABLED, mVisibleScrollbarEnabled);
@@ -251,6 +265,14 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
restoreSavedState(savedState);
mAdapter = createListAdapter();
mContactsPrefs = new ContactsPreferences(mContext);
+ restoreSavedState(savedState);
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
+ if (mContext != null) {
+ mContext.registerReceiver(mSIMStateReceiver, filter);
+ }
}
public void restoreSavedState(Bundle savedState) {
@@ -262,6 +284,7 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
mPhotoLoaderEnabled = savedState.getBoolean(KEY_PHOTO_LOADER_ENABLED);
mQuickContactEnabled = savedState.getBoolean(KEY_QUICK_CONTACT_ENABLED);
mAdjustSelectionBoundsEnabled = savedState.getBoolean(KEY_ADJUST_SELECTION_BOUNDS_ENABLED);
+ mQuickCallButtonEnabled = savedState.getBoolean(KEY_QUICK_CALL_BUTTON_ENABLED);
mIncludeProfile = savedState.getBoolean(KEY_INCLUDE_PROFILE);
mSearchMode = savedState.getBoolean(KEY_SEARCH_MODE);
mVisibleScrollbarEnabled = savedState.getBoolean(KEY_VISIBLE_SCROLLBAR_ENABLED);
@@ -315,6 +338,7 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
// Next time this method is called, we should start loading non-priority directories
mLoadPriorityDirectoriesOnly = false;
+ mAdapter.notifyDataSetChanged();
}
@Override
@@ -374,6 +398,9 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
protected void loadDirectoryPartition(int partitionIndex, DirectoryPartition partition) {
Bundle args = new Bundle();
args.putLong(DIRECTORY_ID_ARG_KEY, partition.getDirectoryId());
+ if (getLoaderManager().getLoader(partitionIndex) != null) {
+ getLoaderManager().destroyLoader(partitionIndex);
+ }
getLoaderManager().restartLoader(partitionIndex, args, this);
}
@@ -415,6 +442,11 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
}
public void onLoaderReset(Loader<Cursor> loader) {
+ if (loader.getId() >= 0) {
+ mAdapter.changeCursor(loader.getId(), null);
+ } else {
+ mAdapter.changeCursor(null);
+ }
}
protected void onPartitionLoaded(int partitionIndex, Cursor data) {
@@ -457,6 +489,14 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
mAdapter.clearPartitions();
}
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mContext != null) {
+ mContext.unregisterReceiver(mSIMStateReceiver);
+ }
+ }
+
protected void reloadData() {
removePendingDirectorySearchRequests();
mAdapter.onDataReload();
@@ -551,6 +591,10 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
mAdjustSelectionBoundsEnabled = flag;
}
+ public void setQuickCallButtonEnabled(boolean flag) {
+ this.mQuickCallButtonEnabled = flag;
+ }
+
public void setIncludeProfile(boolean flag) {
mIncludeProfile = flag;
if(mAdapter != null) {
@@ -773,6 +817,7 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
mAdapter.setQuickContactEnabled(mQuickContactEnabled);
mAdapter.setAdjustSelectionBoundsEnabled(mAdjustSelectionBoundsEnabled);
+ mAdapter.setQuickCallButtonEnabled(mQuickCallButtonEnabled);
mAdapter.setIncludeProfile(mIncludeProfile);
mAdapter.setQueryString(mQueryString);
mAdapter.setDirectorySearchMode(mDirectorySearchMode);
@@ -869,8 +914,9 @@ public abstract class ContactEntryListFragment<T extends ContactEntryListAdapter
new ContactsPreferences.ChangeListener() {
@Override
public void onChange() {
- loadPreferences();
- reloadData();
+ if(loadPreferences()) {
+ reloadData();
+ }
}
};
diff --git a/src/com/android/contacts/common/list/ContactListAdapter.java b/src/com/android/contacts/common/list/ContactListAdapter.java
index 9107d044..ea2d8539 100644..100755
--- a/src/com/android/contacts/common/list/ContactListAdapter.java
+++ b/src/com/android/contacts/common/list/ContactListAdapter.java
@@ -15,22 +15,27 @@
*/
package com.android.contacts.common.list;
+import android.accounts.Account;
import android.content.Context;
+import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Directory;
+import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.SearchSnippets;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
+import android.widget.Toast;
import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
import com.android.contacts.common.R;
import com.android.contacts.common.preference.ContactsPreferences;
+import com.android.contacts.common.model.Contact;
/**
* A cursor adapter for the {@link ContactsContract.Contacts#CONTENT_TYPE} content type.
@@ -49,6 +54,9 @@ public abstract class ContactListAdapter extends ContactEntryListAdapter {
Contacts.PHOTO_THUMBNAIL_URI, // 5
Contacts.LOOKUP_KEY, // 6
Contacts.IS_USER_PROFILE, // 7
+ RawContacts.ACCOUNT_TYPE, // 8
+ RawContacts.ACCOUNT_NAME, // 9
+ Contacts.HAS_PHONE_NUMBER, // 10
};
private static final String[] CONTACT_PROJECTION_ALTERNATIVE = new String[] {
@@ -60,6 +68,9 @@ public abstract class ContactListAdapter extends ContactEntryListAdapter {
Contacts.PHOTO_THUMBNAIL_URI, // 5
Contacts.LOOKUP_KEY, // 6
Contacts.IS_USER_PROFILE, // 7
+ RawContacts.ACCOUNT_TYPE, // 8
+ RawContacts.ACCOUNT_NAME, // 9
+ Contacts.HAS_PHONE_NUMBER, // 10
};
private static final String[] FILTER_PROJECTION_PRIMARY = new String[] {
@@ -71,7 +82,10 @@ public abstract class ContactListAdapter extends ContactEntryListAdapter {
Contacts.PHOTO_THUMBNAIL_URI, // 5
Contacts.LOOKUP_KEY, // 6
Contacts.IS_USER_PROFILE, // 7
- SearchSnippets.SNIPPET, // 8
+ RawContacts.ACCOUNT_TYPE, // 8
+ RawContacts.ACCOUNT_NAME, // 9
+ Contacts.HAS_PHONE_NUMBER, // 10
+ SearchSnippets.SNIPPET, // 11
};
private static final String[] FILTER_PROJECTION_ALTERNATIVE = new String[] {
@@ -83,7 +97,10 @@ public abstract class ContactListAdapter extends ContactEntryListAdapter {
Contacts.PHOTO_THUMBNAIL_URI, // 5
Contacts.LOOKUP_KEY, // 6
Contacts.IS_USER_PROFILE, // 7
- SearchSnippets.SNIPPET, // 8
+ RawContacts.ACCOUNT_TYPE, // 8
+ RawContacts.ACCOUNT_NAME, // 9
+ Contacts.HAS_PHONE_NUMBER, // 10
+ SearchSnippets.SNIPPET, // 11
};
public static final int CONTACT_ID = 0;
@@ -94,7 +111,10 @@ public abstract class ContactListAdapter extends ContactEntryListAdapter {
public static final int CONTACT_PHOTO_URI = 5;
public static final int CONTACT_LOOKUP_KEY = 6;
public static final int CONTACT_IS_USER_PROFILE = 7;
- public static final int CONTACT_SNIPPET = 8;
+ public static final int CONTACT_ACCOUNT_TYPE = 8;
+ public static final int CONTACT_ACCOUNT_NAME = 9;
+ public static final int CONTACT_HAS_NUMBER = 10;
+ public static final int CONTACT_SNIPPET = 11;
}
private CharSequence mUnknownNameText;
@@ -200,6 +220,7 @@ public abstract class ContactListAdapter extends ContactEntryListAdapter {
view.setUnknownNameText(mUnknownNameText);
view.setQuickContactEnabled(isQuickContactEnabled());
view.setAdjustSelectionBoundsEnabled(isAdjustSelectionBoundsEnabled());
+ view.setQuickCallButtonEnabled(isQuickCallButtonEnabled());
view.setActivatedStateSupported(isSelectionVisible());
if (mPhotoPosition != null) {
view.setPhotoPosition(mPhotoPosition);
@@ -207,6 +228,29 @@ public abstract class ContactListAdapter extends ContactEntryListAdapter {
return view;
}
+ private View.OnClickListener mClickListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ String lookup = ((ContactListItemView) view.getParent()).getQuickCallLookup();
+ Cursor cursor = mContext.getContentResolver().query(
+ ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
+ new String[] { ContactsContract.CommonDataKinds.Phone.NUMBER,
+ ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY},
+ ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY + "=?",
+ new String[] { lookup }, null);
+
+ if (cursor != null) {
+ if (cursor.moveToNext()) {
+ String phoneNumber = cursor.getString(0);
+ Uri uri = Uri.parse("tel: " + phoneNumber);
+ Intent intent = new Intent(Intent.ACTION_CALL, uri);
+ mContext.startActivity(intent);
+ }
+ cursor.close();
+ }
+ }
+ };
+
protected void bindSectionHeaderAndDivider(ContactListItemView view, int position,
Cursor cursor) {
view.setIsSectionHeaderEnabled(isSectionHeaderDisplayEnabled());
@@ -230,8 +274,15 @@ public abstract class ContactListAdapter extends ContactEntryListAdapter {
photoId = cursor.getLong(ContactQuery.CONTACT_PHOTO_ID);
}
+ Account account = null;
+ if (!cursor.isNull(ContactQuery.CONTACT_ACCOUNT_TYPE)
+ && !cursor.isNull(ContactQuery.CONTACT_ACCOUNT_NAME)) {
+ final String accountType = cursor.getString(ContactQuery.CONTACT_ACCOUNT_TYPE);
+ final String accountName = cursor.getString(ContactQuery.CONTACT_ACCOUNT_NAME);
+ account = new Account(accountName, accountType);
+ }
if (photoId != 0) {
- getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false,
+ getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, account, false,
getCircularPhotos(), null);
} else {
final String photoUriString = cursor.getString(ContactQuery.CONTACT_PHOTO_URI);
@@ -242,7 +293,7 @@ public abstract class ContactListAdapter extends ContactEntryListAdapter {
ContactQuery.CONTACT_DISPLAY_NAME,
ContactQuery.CONTACT_LOOKUP_KEY);
}
- getPhotoLoader().loadDirectoryPhoto(view.getPhotoView(), photoUri, false,
+ getPhotoLoader().loadDirectoryPhoto(view.getPhotoView(), photoUri, account, false,
getCircularPhotos(), request);
}
}
@@ -255,6 +306,12 @@ public abstract class ContactListAdapter extends ContactEntryListAdapter {
bindViewId(view, cursor, ContactQuery.CONTACT_ID);
}
+ protected void bindQuickCallView(final ContactListItemView view, Cursor cursor) {
+ view.showQuickCallView(cursor, ContactQuery.CONTACT_HAS_NUMBER,
+ ContactQuery.CONTACT_LOOKUP_KEY, ContactQuery.CONTACT_IS_USER_PROFILE);
+ view.setOnQuickCallClickListener(mClickListener);
+ }
+
protected void bindPresenceAndStatusMessage(final ContactListItemView view, Cursor cursor) {
view.showPresenceAndStatusMessage(cursor, ContactQuery.CONTACT_PRESENCE_STATUS,
ContactQuery.CONTACT_CONTACT_STATUS);
diff --git a/src/com/android/contacts/common/list/ContactListFilter.java b/src/com/android/contacts/common/list/ContactListFilter.java
index f81ea742..b48efb98 100644..100755
--- a/src/com/android/contacts/common/list/ContactListFilter.java
+++ b/src/com/android/contacts/common/list/ContactListFilter.java
@@ -45,6 +45,7 @@ public final class ContactListFilter implements Comparable<ContactListFilter>, P
* TODO: "group" filter and relevant variables are all obsolete. Remove them.
*/
private static final int FILTER_TYPE_GROUP = 1;
+ public static final int FILTER_TYPE_ALL_WITHOUT_SIM = 2;
private static final String KEY_FILTER_TYPE = "filter.type";
private static final String KEY_ACCOUNT_NAME = "filter.accountName";
diff --git a/src/com/android/contacts/common/list/ContactListFilterView.java b/src/com/android/contacts/common/list/ContactListFilterView.java
index 4cea7558..075f1fb6 100644..100755
--- a/src/com/android/contacts/common/list/ContactListFilterView.java
+++ b/src/com/android/contacts/common/list/ContactListFilterView.java
@@ -28,6 +28,8 @@ import android.widget.TextView;
import com.android.contacts.common.R;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.account.AccountType;
+import com.android.contacts.common.model.account.PhoneAccountType;
+import com.android.contacts.common.model.account.SimAccountType;
/**
* Contact list filter parameters.
@@ -113,7 +115,13 @@ public class ContactListFilterView extends LinearLayout {
break;
}
case ContactListFilter.FILTER_TYPE_ACCOUNT: {
- mAccountUserName.setVisibility(View.VISIBLE);
+ if (SimAccountType.ACCOUNT_TYPE.equals(mFilter.accountType)
+ || PhoneAccountType.ACCOUNT_TYPE
+ .equals(mFilter.accountType)) {
+ mAccountUserName.setVisibility(View.GONE);
+ } else {
+ mAccountUserName.setVisibility(View.VISIBLE);
+ }
mIcon.setVisibility(View.VISIBLE);
if (mFilter.icon != null) {
mIcon.setImageDrawable(mFilter.icon);
@@ -123,7 +131,7 @@ public class ContactListFilterView extends LinearLayout {
final AccountType accountType =
accountTypes.getAccountType(mFilter.accountType, mFilter.dataSet);
mAccountUserName.setText(mFilter.accountName);
- mAccountType.setText(accountType.getDisplayLabel(getContext()));
+ mAccountType.setText(accountType.getDisplayLabel(getContext(),mFilter.accountName));
break;
}
}
diff --git a/src/com/android/contacts/common/list/ContactListItemView.java b/src/com/android/contacts/common/list/ContactListItemView.java
index 4c561dfc..dd869b0c 100644..100755
--- a/src/com/android/contacts/common/list/ContactListItemView.java
+++ b/src/com/android/contacts/common/list/ContactListItemView.java
@@ -26,6 +26,7 @@ import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
+import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
@@ -52,6 +53,8 @@ import com.android.contacts.common.format.TextHighlighter;
import com.android.contacts.common.util.ContactDisplayUtils;
import com.android.contacts.common.util.SearchUtil;
import com.android.contacts.common.util.ViewUtil;
+import com.android.contacts.common.widget.CheckableImageView;
+import com.android.contacts.common.widget.CheckableQuickContactBadge;
import com.google.common.collect.Lists;
@@ -77,7 +80,7 @@ import java.util.regex.Pattern;
*/
public class ContactListItemView extends ViewGroup
- implements SelectionBoundsAdjuster {
+ implements SelectionBoundsAdjuster, View.OnClickListener {
// Style values for layout and appearance
// The initialized values are defaults if none is provided through xml.
@@ -136,7 +139,7 @@ public class ContactListItemView extends ViewGroup
final int layoutDirection = TextUtils.getLayoutDirectionFromLocale(locale);
switch (layoutDirection) {
case View.LAYOUT_DIRECTION_RTL:
- return (opposite ? PhotoPosition.LEFT : PhotoPosition.RIGHT);
+ return (PhotoPosition.RIGHT);
case View.LAYOUT_DIRECTION_LTR:
default:
return (opposite ? PhotoPosition.RIGHT : PhotoPosition.LEFT);
@@ -151,8 +154,10 @@ public class ContactListItemView extends ViewGroup
// The views inside the contact view
private boolean mQuickContactEnabled = true;
- private QuickContactBadge mQuickContact;
- private ImageView mPhotoView;
+ private boolean mQuickCallButtonEnabled = false;
+ private CheckableQuickContactBadge mQuickContact;
+ private ImageView mQuickCallView;
+ private CheckableImageView mPhotoView;
private TextView mNameTextView;
private TextView mPhoneticNameTextView;
private TextView mLabelView;
@@ -160,12 +165,15 @@ public class ContactListItemView extends ViewGroup
private TextView mSnippetView;
private TextView mStatusView;
private ImageView mPresenceIcon;
+ private String mQuickCallKey;
private ColorStateList mSecondaryTextColor;
-
+ private int mQuickCallViewImageId = 0;
+ private int mQuickCallViewBgId = 0;
private int mDefaultPhotoViewSize = 0;
+ private int mDefaultQuickCallViewSize = 0;
/**
* Can be effective even when {@link #mPhotoView} is null, as we want to have horizontal padding
* to align other data in this View.
@@ -177,6 +185,15 @@ public class ContactListItemView extends ViewGroup
private int mPhotoViewHeight;
/**
+ * Only effective when {@link #mQuickCallView} is null
+ */
+ private int mQuickCallViewWidth;
+ /**
+ * Only effective when {@link #mQuickCallView} is null
+ */
+ private int mQuickCallViewHeight;
+
+ /**
* Only effective when {@link #mPhotoView} is null.
* When true all the Views on the right side of the photo should have horizontal padding on
* those left assuming there is a photo.
@@ -219,6 +236,8 @@ public class ContactListItemView extends ViewGroup
private Rect mBoundsWithoutHeader = new Rect();
+ private OnClickListener mListener;
+
/** A helper used to highlight a prefix in a text field. */
private final TextHighlighter mTextHighlighter;
private CharSequence mUnknownNameText;
@@ -226,7 +245,9 @@ public class ContactListItemView extends ViewGroup
public ContactListItemView(Context context) {
super(context);
- mTextHighlighter = new TextHighlighter(Typeface.BOLD);
+ mTextHighlighter = new TextHighlighter(Typeface.BOLD,
+ context.getResources().getColor(R.color.text_highlight_color));
+
mNameHighlightSequence = new ArrayList<HighlightSequence>();
mNumberHighlightSequence = new ArrayList<HighlightSequence>();
}
@@ -254,6 +275,9 @@ public class ContactListItemView extends ViewGroup
R.styleable.ContactListItemView_list_item_presence_icon_size, mPresenceIconSize);
mDefaultPhotoViewSize = a.getDimensionPixelOffset(
R.styleable.ContactListItemView_list_item_photo_size, mDefaultPhotoViewSize);
+ mDefaultQuickCallViewSize = a.getDimensionPixelOffset(
+ R.styleable.ContactListItemView_list_item_quick_call_size,
+ mDefaultQuickCallViewSize);
mTextIndent = a.getDimensionPixelOffset(
R.styleable.ContactListItemView_list_item_text_indent, mTextIndent);
mTextOffsetTop = a.getDimensionPixelOffset(
@@ -268,6 +292,12 @@ public class ContactListItemView extends ViewGroup
mNameTextViewTextSize = (int) a.getDimension(
R.styleable.ContactListItemView_list_item_name_text_size,
(int) getResources().getDimension(R.dimen.contact_browser_list_item_text_size));
+ mQuickCallViewImageId = a.getResourceId(
+ R.styleable.ContactListItemView_list_item_quick_call_view_source,
+ R.drawable.ic_action_call);
+ mQuickCallViewBgId = a.getResourceId(
+ R.styleable.ContactListItemView_list_item_quick_call_view_background,
+ R.drawable.ic_action_call_background);
setPaddingRelative(
a.getDimensionPixelOffset(
@@ -279,7 +309,9 @@ public class ContactListItemView extends ViewGroup
a.getDimensionPixelOffset(
R.styleable.ContactListItemView_list_item_padding_bottom, 0));
- mTextHighlighter = new TextHighlighter(Typeface.BOLD);
+ mTextHighlighter = new TextHighlighter(Typeface.BOLD,
+ context.getResources().getColor(R.color.text_highlight_color));
+
a.recycle();
@@ -308,6 +340,22 @@ public class ContactListItemView extends ViewGroup
mQuickContactEnabled = flag;
}
+ public void setQuickCallButtonEnabled(boolean flag) {
+ mQuickCallButtonEnabled = flag;
+ }
+
+ public void setQuickCallLookup(String lookupKey) {
+ mQuickCallKey = lookupKey;
+ }
+
+ public void setQuickCallButtonImageResource(int resourceId) {
+ mQuickCallViewImageId = resourceId;
+ }
+
+ public void setQuickCallButtonBackgroundResource(int resourceId) {
+ mQuickCallViewBgId = resourceId;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// We will match parent's width and wrap content vertically, but make sure
@@ -324,15 +372,16 @@ public class ContactListItemView extends ViewGroup
mStatusTextViewHeight = 0;
ensurePhotoViewSize();
+ ensureQuickCallViewSize();
// Width each TextView is able to use.
int effectiveWidth;
// All the other Views will honor the photo, so available width for them may be shrunk.
if (mPhotoViewWidth > 0 || mKeepHorizontalPaddingForPhotoView) {
effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight()
- - (mPhotoViewWidth + mGapBetweenImageAndText);
+ - (mPhotoViewWidth + mGapBetweenImageAndText + mQuickCallViewWidth);
} else {
- effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight();
+ effectiveWidth = specWidth - getPaddingLeft() - getPaddingRight() - mQuickCallViewWidth;
}
if (mIsSectionHeaderEnabled) {
@@ -450,6 +499,12 @@ public class ContactListItemView extends ViewGroup
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
}
+ if (isVisible(mQuickCallView)) {
+ mQuickCallView.measure(
+ MeasureSpec.makeMeasureSpec(mQuickCallViewWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(mQuickCallViewHeight, MeasureSpec.EXACTLY));
+ }
+
setMeasuredDimension(specWidth, height);
}
@@ -551,6 +606,9 @@ public class ContactListItemView extends ViewGroup
textTopBound += mNameTextViewHeight;
}
+ // Center the photo vertically
+ final int quickCallTop = topBound + (bottomBound - topBound - mQuickCallViewHeight) / 2;
+
// Presence and status
if (isLayoutRtl) {
int statusRightBound = rightBound;
@@ -570,6 +628,13 @@ public class ContactListItemView extends ViewGroup
statusRightBound,
textTopBound + mStatusTextViewHeight);
}
+
+ if (isVisible(mQuickCallView)) {
+ mQuickCallView.layout(-width + (mQuickCallViewWidth + mPhotoViewWidth),
+ quickCallTop,
+ rightBound,
+ quickCallTop + mQuickCallViewHeight);
+ }
} else {
int statusLeftBound = leftBound;
if (isVisible(mPresenceIcon)) {
@@ -588,6 +653,13 @@ public class ContactListItemView extends ViewGroup
rightBound,
textTopBound + mStatusTextViewHeight);
}
+
+ if (isVisible(mQuickCallView)) {
+ mQuickCallView.layout(rightBound - mQuickCallView.getMeasuredWidth(),
+ quickCallTop,
+ rightBound,
+ quickCallTop + mQuickCallViewHeight);
+ }
}
if (isVisible(mStatusView) || isVisible(mPresenceIcon)) {
@@ -675,10 +747,33 @@ public class ContactListItemView extends ViewGroup
}
}
+ /**
+ * Extracts width and height from the style
+ */
+ private void ensureQuickCallViewSize() {
+ mQuickCallViewWidth = mQuickCallViewHeight = getDefaultQuickCallViewSize();
+ if (!mQuickCallButtonEnabled || mQuickCallView == null) {
+ mQuickCallViewWidth = 0;
+ mQuickCallViewHeight = 0;
+ }
+ }
+
+ protected void setDefaultPhotoViewSize(int pixels) {
+ mDefaultPhotoViewSize = pixels;
+ }
+
protected int getDefaultPhotoViewSize() {
return mDefaultPhotoViewSize;
}
+ protected void setDefaultQuickCallViewSize(int pixels) {
+ mDefaultQuickCallViewSize = pixels;
+ }
+
+ protected int getDefaultQuickCallViewSize() {
+ return mDefaultQuickCallViewSize;
+ }
+
/**
* Gets a LayoutParam that corresponds to the default photo size.
*
@@ -746,6 +841,14 @@ public class ContactListItemView extends ViewGroup
}
/**
+ * Get the quick call lookup to use with Intent.ACTION_CALL
+ * @return
+ */
+ public String getQuickCallLookup() {
+ return mQuickCallKey;
+ }
+
+ /**
* Returns the quick contact badge, creating it if necessary.
*/
public QuickContactBadge getQuickContact() {
@@ -753,7 +856,7 @@ public class ContactListItemView extends ViewGroup
throw new IllegalStateException("QuickContact is disabled for this view");
}
if (mQuickContact == null) {
- mQuickContact = new QuickContactBadge(getContext());
+ mQuickContact = new CheckableQuickContactBadge(getContext());
mQuickContact.setOverlay(null);
mQuickContact.setLayoutParams(getDefaultPhotoLayoutParams());
if (mNameTextView != null) {
@@ -767,12 +870,21 @@ public class ContactListItemView extends ViewGroup
return mQuickContact;
}
+ public void setChecked(boolean checked, boolean animate) {
+ if (mQuickContact != null) {
+ mQuickContact.setChecked(checked, animate);
+ }
+ if (mPhotoView != null) {
+ mPhotoView.setChecked(checked, animate);
+ }
+ }
+
/**
* Returns the photo view, creating it if necessary.
*/
public ImageView getPhotoView() {
if (mPhotoView == null) {
- mPhotoView = new ImageView(getContext());
+ mPhotoView = new CheckableImageView(getContext());
mPhotoView.setLayoutParams(getDefaultPhotoLayoutParams());
// Quick contact style used above will set a background - remove it
mPhotoView.setBackground(null);
@@ -783,6 +895,31 @@ public class ContactListItemView extends ViewGroup
}
/**
+ * Returns the quick call view, creating it if necessary.
+ */
+ public ImageView getQuickCallView() {
+ if (mQuickCallView == null) {
+ mQuickCallView = new ImageView(mContext);
+ mQuickCallView.setLayoutParams(getDefaultPhotoLayoutParams());
+ mQuickCallView.setImageResource(mQuickCallViewImageId);
+ mQuickCallView.setBackgroundResource(mQuickCallViewBgId);
+ mQuickCallView.setClickable(true);
+ addView(mQuickCallView);
+ }
+ return mQuickCallView;
+ }
+
+ /**
+ * Removes the quick call view.
+ */
+ public void removeQuickCallView() {
+ if (mQuickCallView != null) {
+ removeView(mQuickCallView);
+ mQuickCallView = null;
+ }
+ }
+
+ /**
* Removes the photo view.
*/
public void removePhotoView() {
@@ -1135,6 +1272,20 @@ public class ContactListItemView extends ViewGroup
}
}
+ public void showQuickCallView(Cursor cursor, int numberColumIndex, int lookUpKey,
+ int profileKey) {
+ int hasNumber = cursor.getInt(numberColumIndex);
+ boolean isProfile = cursor.getInt(profileKey) == 1;
+ if (!(hasNumber == 0) && !isProfile) {
+ getQuickCallView().setVisibility(View.VISIBLE);
+ setQuickCallLookup(cursor.getString(lookUpKey));
+ } else {
+ if (mQuickCallView != null) {
+ mQuickCallView.setVisibility(View.GONE);
+ }
+ }
+ }
+
public void setDisplayName(CharSequence name, boolean highlight) {
if (!TextUtils.isEmpty(name) && highlight) {
clearHighlightSequences();
@@ -1463,7 +1614,27 @@ public class ContactListItemView extends ViewGroup
if (mBoundsWithoutHeader.contains((int) x, (int) y) || !pointIsInView(x, y)) {
return super.onTouchEvent(event);
} else {
- return true;
+ return false;
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (mListener != null && mQuickCallButtonEnabled) {
+ if (view == mQuickCallView) {
+ mListener.onClick(view);
+ }
+ }
+ }
+
+ /**
+ * Set the a click listener for the quick call view
+ * @param listener
+ */
+ public void setOnQuickCallClickListener(OnClickListener listener) {
+ this.mListener = listener;
+ if (mListener != null && mQuickCallView != null) {
+ mQuickCallView.setOnClickListener(mListener);
}
}
diff --git a/src/com/android/contacts/common/list/ContactTileAdapter.java b/src/com/android/contacts/common/list/ContactTileAdapter.java
index 789ca026..35f9f185 100644
--- a/src/com/android/contacts/common/list/ContactTileAdapter.java
+++ b/src/com/android/contacts/common/list/ContactTileAdapter.java
@@ -15,6 +15,7 @@
*/
package com.android.contacts.common.list;
+import android.accounts.Account;
import android.content.ContentUris;
import android.content.Context;
import android.content.res.Resources;
@@ -53,6 +54,11 @@ public class ContactTileAdapter extends BaseAdapter {
protected int mNumFrequents;
/**
+ * Get the layout width.
+ */
+ private int nRTLWidth = 0;
+
+ /**
* Index of the first NON starred contact in the {@link Cursor}
* Only valid when {@link DisplayType#STREQUENT} is true
*/
@@ -66,6 +72,8 @@ public class ContactTileAdapter extends BaseAdapter {
protected int mNameIndex;
protected int mPresenceIndex;
protected int mStatusIndex;
+ private int mAccountTypeIndex;
+ private int mAccountNameIndex;
private boolean mIsQuickContactEnabled = false;
private final int mPaddingInPixels;
@@ -148,6 +156,8 @@ public class ContactTileAdapter extends BaseAdapter {
mStarredIndex = ContactTileLoaderFactory.STARRED;
mPresenceIndex = ContactTileLoaderFactory.CONTACT_PRESENCE;
mStatusIndex = ContactTileLoaderFactory.CONTACT_STATUS;
+ mAccountTypeIndex = ContactTileLoaderFactory.ACCOUNT_TYPE;
+ mAccountNameIndex = ContactTileLoaderFactory.ACCOUNT_NAME;
}
private static boolean cursorIsValid(Cursor cursor) {
@@ -186,6 +196,9 @@ public class ContactTileAdapter extends BaseAdapter {
* Else use {@link ContactTileLoaderFactory}
*/
public void setContactCursor(Cursor cursor) {
+ if (cursor == null || cursor.isClosed()) {
+ return;
+ }
mContactCursor = cursor;
mDividerPosition = getDividerPosition(cursor);
@@ -270,6 +283,13 @@ public class ContactTileAdapter extends BaseAdapter {
}
contact.status = statusMessage;
+ if (!cursor.isNull(mAccountTypeIndex) && !cursor.isNull(mAccountTypeIndex)) {
+ final String accountType = cursor.getString(mAccountTypeIndex);
+ final String accountName = cursor.getString(mAccountNameIndex);
+ contact.account = new Account(accountName, accountType);
+ } else {
+ contact.account = null;
+ }
return contact;
}
@@ -546,6 +566,7 @@ public class ContactTileAdapter extends BaseAdapter {
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
switch (mItemViewType) {
case ViewTypes.STARRED:
+ nRTLWidth = right -left;
onLayoutForTiles();
return;
default:
@@ -567,8 +588,15 @@ public class ContactTileAdapter extends BaseAdapter {
// Note MeasuredWidth includes the padding.
final int childWidth = child.getMeasuredWidth();
- child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
- childLeft += childWidth;
+
+ // Layout for RTL
+ if (child.isLayoutRtl()) {
+ child.layout(nRTLWidth -childWidth, 0, nRTLWidth, child.getMeasuredHeight());
+ nRTLWidth -= childWidth;
+ }else{
+ child.layout(childLeft, 0, childLeft + childWidth, child.getMeasuredHeight());
+ childLeft += childWidth;
+ }
}
}
diff --git a/src/com/android/contacts/common/list/ContactTileView.java b/src/com/android/contacts/common/list/ContactTileView.java
index 56552bb6..b42ab7bf 100644
--- a/src/com/android/contacts/common/list/ContactTileView.java
+++ b/src/com/android/contacts/common/list/ContactTileView.java
@@ -15,6 +15,7 @@
*/
package com.android.contacts.common.list;
+import android.accounts.Account;
import android.content.Context;
import android.graphics.Rect;
import android.net.Uri;
@@ -128,7 +129,8 @@ public abstract class ContactTileView extends FrameLayout {
DefaultImageRequest request = getDefaultImageRequest(entry.name, entry.lookupKey);
configureViewForImage(entry.photoUri == null);
if (mPhoto != null) {
- mPhotoManager.loadPhoto(mPhoto, entry.photoUri, getApproximateImageSize(),
+ mPhotoManager.loadPhoto(mPhoto, entry.photoUri,
+ entry.account, getApproximateImageSize(),
isDarkTheme(), isContactPhotoCircular(), request);
if (mQuickContact != null) {
@@ -136,7 +138,7 @@ public abstract class ContactTileView extends FrameLayout {
}
} else if (mQuickContact != null) {
mQuickContact.assignContactUri(mLookupUri);
- mPhotoManager.loadPhoto(mQuickContact, entry.photoUri,
+ mPhotoManager.loadPhoto(mQuickContact, entry.photoUri, entry.account,
getApproximateImageSize(), isDarkTheme(), isContactPhotoCircular(),
request);
}
diff --git a/src/com/android/contacts/common/list/ContactsSectionIndexer.java b/src/com/android/contacts/common/list/ContactsSectionIndexer.java
index 8d1c9e1d..bada56c2 100644
--- a/src/com/android/contacts/common/list/ContactsSectionIndexer.java
+++ b/src/com/android/contacts/common/list/ContactsSectionIndexer.java
@@ -71,8 +71,10 @@ public class ContactsSectionIndexer implements SectionIndexer {
}
public int getPositionForSection(int section) {
- if (section < 0 || section >= mSections.length) {
+ if (section < 0 || section > mSections.length) {
return -1;
+ } else if (section == mSections.length) {
+ return mCount;
}
return mPositions[section];
diff --git a/src/com/android/contacts/common/list/CustomContactListFilterActivity.java b/src/com/android/contacts/common/list/CustomContactListFilterActivity.java
index b3253cc3..5066b294 100644..100755
--- a/src/com/android/contacts/common/list/CustomContactListFilterActivity.java
+++ b/src/com/android/contacts/common/list/CustomContactListFilterActivity.java
@@ -39,6 +39,7 @@ import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.Settings;
+import android.text.TextUtils;
import android.util.Log;
import android.view.ContextMenu;
import android.view.LayoutInflater;
@@ -54,11 +55,14 @@ import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
import android.widget.TextView;
import com.android.contacts.common.R;
+import com.android.contacts.common.MoreContactUtils;
import com.android.contacts.common.model.AccountTypeManager;
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.GoogleAccountType;
+import com.android.contacts.common.model.account.PhoneAccountType;
+import com.android.contacts.common.model.account.SimAccountType;
import com.android.contacts.common.util.EmptyService;
import com.android.contacts.common.util.LocalizedNameResolver;
import com.android.contacts.common.util.WeakAsyncTask;
@@ -347,9 +351,14 @@ public class CustomContactListFilterActivity extends Activity
}
} else {
final Integer titleRes = getAsInteger(Groups.TITLE_RES);
+
if (titleRes != null) {
final String packageName = getAsString(Groups.RES_PACKAGE);
- return context.getPackageManager().getText(packageName, titleRes, null);
+ if (!TextUtils.isEmpty(packageName)) {
+ return context.getPackageManager().getText(packageName, titleRes, null);
+ } else {
+ return getAsString(Groups.TITLE);
+ }
} else {
return getAsString(Groups.TITLE);
}
@@ -584,11 +593,17 @@ public class CustomContactListFilterActivity extends Activity
final AccountType accountType = mAccountTypes.getAccountType(
account.mType, account.mDataSet);
-
- text1.setText(account.mName);
- text1.setVisibility(account.mName == null ? View.GONE : View.VISIBLE);
- text2.setText(accountType.getDisplayLabel(mContext));
-
+ if (SimAccountType.ACCOUNT_TYPE.equals(account.mType)
+ || PhoneAccountType.ACCOUNT_TYPE.equals(account.mType)) {
+ text1.setVisibility(View.VISIBLE);
+ text1.setText(accountType.getDisplayLabel(mContext, account.mName));
+ text2.setVisibility(View.GONE);
+ } else {
+ text1.setText(account.mName);
+ text1.setVisibility(account.mName == null ? View.GONE : View.VISIBLE);
+ text2.setText(accountType.getDisplayLabel(mContext, account.mName));
+ text2.setVisibility(View.VISIBLE);
+ }
return convertView;
}
diff --git a/src/com/android/contacts/common/list/DefaultContactListAdapter.java b/src/com/android/contacts/common/list/DefaultContactListAdapter.java
index 8774777c..c44e1e28 100644..100755
--- a/src/com/android/contacts/common/list/DefaultContactListAdapter.java
+++ b/src/com/android/contacts/common/list/DefaultContactListAdapter.java
@@ -26,11 +26,15 @@ import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Directory;
+import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.SearchSnippets;
import android.text.TextUtils;
import android.view.View;
+import com.android.contacts.common.model.account.SimAccountType;
import com.android.contacts.common.preference.ContactsPreferences;
+import com.android.contacts.common.MoreContactUtils;
+import com.android.contacts.common.SimContactsConstants;
import java.util.ArrayList;
import java.util.List;
@@ -47,6 +51,21 @@ public class DefaultContactListAdapter extends ContactListAdapter {
super(context);
}
+ /** append Uri QueryParameter to filter contacts in SIM card */
+ private void appendUriQueryParameterWithoutSim(CursorLoader loader,
+ String key, String value) {
+ if (null == loader || null == key || null == value) {
+ return;
+ }
+
+ Uri uri = loader.getUri();
+ if (null != uri) {
+ uri = uri.buildUpon().appendQueryParameter(key, value)
+ .appendQueryParameter(SimContactsConstants.WITHOUT_SIM_FLAG, "true").build();
+ loader.setUri(uri);
+ }
+ }
+
@Override
public void configureLoader(CursorLoader loader, long directoryId) {
if (loader instanceof ProfileAndContactsLoader) {
@@ -79,6 +98,21 @@ public class DefaultContactListAdapter extends ContactListAdapter {
loader.setUri(builder.build());
loader.setProjection(getProjection(true));
}
+ boolean isAirMode = MoreContactUtils.isAPMOnAndSIMPowerDown(getContext());
+
+ if (isAirMode
+ || (null != filter && filter.filterType ==
+ ContactListFilter.FILTER_TYPE_ALL_WITHOUT_SIM)) {
+ appendUriQueryParameterWithoutSim(loader,
+ RawContacts.ACCOUNT_TYPE, SimAccountType.ACCOUNT_TYPE);
+ } else {
+ // Do not show contacts when SIM card is disabled
+ String disabledSimFilter = MoreContactUtils.getDisabledSimFilter();
+ if (!TextUtils.isEmpty(disabledSimFilter)) {
+ appendUriQueryParameterWithoutSim(
+ loader, RawContacts.ACCOUNT_NAME, disabledSimFilter);
+ }
+ }
} else {
configureUri(loader, directoryId, filter);
loader.setProjection(getProjection(false));
@@ -139,10 +173,21 @@ public class DefaultContactListAdapter extends ContactListAdapter {
StringBuilder selection = new StringBuilder();
List<String> selectionArgs = new ArrayList<String>();
+ boolean isAirMode = MoreContactUtils.isAPMOnAndSIMPowerDown(getContext());
+ String disabledSimFilter = MoreContactUtils.getDisabledSimFilter();
+
switch (filter.filterType) {
case ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS: {
// We have already added directory=0 to the URI, which takes care of this
// filter
+ // Do not show contacts in SIM card when airplane mode is on
+ if (isAirMode) {
+ appendUriQueryParameterWithoutSim(loader, RawContacts.ACCOUNT_TYPE,
+ SimAccountType.ACCOUNT_TYPE);
+ } else if (!TextUtils.isEmpty(disabledSimFilter)) {
+ appendUriQueryParameterWithoutSim(loader, RawContacts.ACCOUNT_NAME,
+ disabledSimFilter);
+ }
break;
}
case ContactListFilter.FILTER_TYPE_SINGLE_CONTACT: {
@@ -163,12 +208,25 @@ public class DefaultContactListAdapter extends ContactListAdapter {
if (isCustomFilterForPhoneNumbersOnly()) {
selection.append(" AND " + Contacts.HAS_PHONE_NUMBER + "=1");
}
+ // Do not show contacts in SIM card when airplane mode is on
+ if (isAirMode) {
+ appendUriQueryParameterWithoutSim(loader, RawContacts.ACCOUNT_TYPE,
+ SimAccountType.ACCOUNT_TYPE);
+ } else if (!TextUtils.isEmpty(disabledSimFilter)) {
+ appendUriQueryParameterWithoutSim(loader, RawContacts.ACCOUNT_NAME,
+ disabledSimFilter);
+ }
break;
}
case ContactListFilter.FILTER_TYPE_ACCOUNT: {
// We use query parameters for account filter, so no selection to add here.
break;
}
+ case ContactListFilter.FILTER_TYPE_ALL_WITHOUT_SIM: {
+ appendUriQueryParameterWithoutSim(loader, RawContacts.ACCOUNT_TYPE,
+ SimAccountType.ACCOUNT_TYPE);
+ break;
+ }
}
loader.setSelection(selection.toString());
loader.setSelectionArgs(selectionArgs.toArray(new String[0]));
@@ -190,7 +248,8 @@ public class DefaultContactListAdapter extends ContactListAdapter {
if (isQuickContactEnabled()) {
bindQuickContact(view, partition, cursor, ContactQuery.CONTACT_PHOTO_ID,
ContactQuery.CONTACT_PHOTO_URI, ContactQuery.CONTACT_ID,
- ContactQuery.CONTACT_LOOKUP_KEY, ContactQuery.CONTACT_DISPLAY_NAME);
+ ContactQuery.CONTACT_LOOKUP_KEY, ContactQuery.CONTACT_DISPLAY_NAME,
+ ContactQuery.CONTACT_ACCOUNT_TYPE, ContactQuery.CONTACT_ACCOUNT_NAME);
} else {
if (getDisplayPhotos()) {
bindPhoto(view, partition, cursor);
@@ -198,6 +257,9 @@ public class DefaultContactListAdapter extends ContactListAdapter {
}
bindNameAndViewId(view, cursor);
+ if (isQuickCallButtonEnabled()) {
+ bindQuickCallView(view, cursor);
+ }
bindPresenceAndStatusMessage(view, cursor);
if (isSearchMode()) {
diff --git a/src/com/android/contacts/common/list/PhoneNumberListAdapter.java b/src/com/android/contacts/common/list/PhoneNumberListAdapter.java
index 8c8700c7..35ff111a 100644
--- a/src/com/android/contacts/common/list/PhoneNumberListAdapter.java
+++ b/src/com/android/contacts/common/list/PhoneNumberListAdapter.java
@@ -15,6 +15,7 @@
*/
package com.android.contacts.common.list;
+import android.accounts.Account;
import android.content.ContentUris;
import android.content.Context;
import android.content.CursorLoader;
@@ -28,6 +29,8 @@ import android.provider.ContactsContract.CommonDataKinds.SipAddress;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Directory;
+import android.provider.ContactsContract.RawContacts;
+import android.text.TextUtils;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
import android.util.Log;
@@ -41,6 +44,9 @@ import com.android.contacts.common.extensions.ExtendedPhoneDirectoriesManager;
import com.android.contacts.common.extensions.ExtensionsFactory;
import com.android.contacts.common.preference.ContactsPreferences;
import com.android.contacts.common.util.Constants;
+import com.android.contacts.common.SimContactsConstants;
+import com.android.contacts.common.MoreContactUtils;
+import com.android.contacts.common.model.account.SimAccountType;
import java.util.ArrayList;
import java.util.List;
@@ -76,6 +82,8 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter {
Phone.PHOTO_ID, // 6
Phone.DISPLAY_NAME_PRIMARY, // 7
Phone.PHOTO_THUMBNAIL_URI, // 8
+ RawContacts.ACCOUNT_TYPE, // 9
+ RawContacts.ACCOUNT_NAME, // 10
};
public static final String[] PROJECTION_ALTERNATIVE = new String[] {
@@ -88,6 +96,8 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter {
Phone.PHOTO_ID, // 6
Phone.DISPLAY_NAME_ALTERNATIVE, // 7
Phone.PHOTO_THUMBNAIL_URI, // 8
+ RawContacts.ACCOUNT_TYPE, // 9
+ RawContacts.ACCOUNT_NAME, // 10
};
public static final int PHONE_ID = 0;
@@ -99,6 +109,8 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter {
public static final int PHOTO_ID = 6;
public static final int DISPLAY_NAME = 7;
public static final int PHOTO_URI = 8;
+ public static final int PHONE_ACCOUNT_TYPE = 9;
+ public static final int PHONE_ACCOUNT_NAME = 10;
}
private static final String IGNORE_NUMBER_TOO_LONG_CLAUSE =
@@ -193,6 +205,13 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter {
// Remove duplicates when it is possible.
builder.appendQueryParameter(ContactsContract.REMOVE_DUPLICATE_ENTRIES, "true");
+
+ // Do not show contacts in disabled SIM card
+ String disabledSimFilter = MoreContactUtils.getDisabledSimFilter();
+ if (!TextUtils.isEmpty(disabledSimFilter)) {
+ String disabledSimName = getDisabledSimName(disabledSimFilter);
+ loader.setSelection(RawContacts.ACCOUNT_NAME+ "<>" + disabledSimName);
+ }
loader.setUri(builder.build());
// TODO a projection that includes the search snippet
@@ -366,7 +385,8 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter {
if (isQuickContactEnabled()) {
bindQuickContact(view, partition, cursor, PhoneQuery.PHOTO_ID,
PhoneQuery.PHOTO_URI, PhoneQuery.CONTACT_ID,
- PhoneQuery.LOOKUP_KEY, PhoneQuery.DISPLAY_NAME);
+ PhoneQuery.LOOKUP_KEY, PhoneQuery.DISPLAY_NAME,
+ PhoneQuery.PHONE_ACCOUNT_TYPE, PhoneQuery.PHONE_ACCOUNT_NAME);
} else {
if (getDisplayPhotos()) {
bindPhoto(view, partition, cursor);
@@ -436,9 +456,15 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter {
if (!cursor.isNull(PhoneQuery.PHOTO_ID)) {
photoId = cursor.getLong(PhoneQuery.PHOTO_ID);
}
-
+ Account account = null;
+ if (!cursor.isNull(PhoneQuery.PHONE_ACCOUNT_TYPE)
+ && !cursor.isNull(PhoneQuery.PHONE_ACCOUNT_NAME)) {
+ final String accountType = cursor.getString(PhoneQuery.PHONE_ACCOUNT_TYPE);
+ final String accountName = cursor.getString(PhoneQuery.PHONE_ACCOUNT_NAME);
+ account = new Account(accountName, accountType);
+ }
if (photoId != 0) {
- getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, false,
+ getPhotoLoader().loadThumbnail(view.getPhotoView(), photoId, account, false,
getCircularPhotos(), null);
} else {
final String photoUriString = cursor.getString(PhoneQuery.PHOTO_URI);
@@ -450,7 +476,7 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter {
final String lookupKey = cursor.getString(PhoneQuery.LOOKUP_KEY);
request = new DefaultImageRequest(displayName, lookupKey, getCircularPhotos());
}
- getPhotoLoader().loadDirectoryPhoto(view.getPhotoView(), photoUri, false,
+ getPhotoLoader().loadDirectoryPhoto(view.getPhotoView(), photoUri, account, false,
getCircularPhotos(), request);
}
}
@@ -541,4 +567,21 @@ public class PhoneNumberListAdapter extends ContactEntryListAdapter {
.encodedFragment(cursor.getString(lookUpKeyColumn))
.build();
}
+
+ private String getDisabledSimName(String disabledSimFilter){
+ String[] disabledSimArray = disabledSimFilter.split(",");//it will never be null
+ String disabledSimName = "";
+ for (int i = 0; i < disabledSimArray.length; i++) {
+ if (i < disabledSimArray.length -1) {
+ //If disabledSimArray[i] is not the last one of the array,
+ //add "or" after every member of the array.
+ disabledSimName = disabledSimName + "'" + disabledSimArray[i] + "'" + "or";
+ } else {
+ //If disabledSimArray[i] is the last one of the array,
+ //should not add anything after it.
+ disabledSimName = disabledSimName + "'" + disabledSimArray[i] + "'";
+ }
+ }
+ return disabledSimName;
+ }
}
diff --git a/src/com/android/contacts/common/list/PhoneNumberPickerFragment.java b/src/com/android/contacts/common/list/PhoneNumberPickerFragment.java
index 968f8db3..06a4f50c 100644
--- a/src/com/android/contacts/common/list/PhoneNumberPickerFragment.java
+++ b/src/com/android/contacts/common/list/PhoneNumberPickerFragment.java
@@ -42,6 +42,7 @@ public class PhoneNumberPickerFragment extends ContactEntryListFragment<ContactE
private static final int REQUEST_CODE_ACCOUNT_FILTER = 1;
private static final String KEY_SHORTCUT_ACTION = "shortcutAction";
+ private static final String DIRECTORY_ID_ARG_KEY = "directoryId";
private OnPhoneNumberPickerActionListener mListener;
private String mShortcutAction;
@@ -327,4 +328,16 @@ public class PhoneNumberPickerFragment extends ContactEntryListFragment<ContactE
adapter.setPhotoPosition(photoPosition);
}
}
+
+ /**
+ * Loads the directory partition.
+ */
+ protected void loadDirectoryPartition(int partitionIndex, DirectoryPartition partition) {
+ Bundle args = new Bundle();
+ args.putLong(DIRECTORY_ID_ARG_KEY, partition.getDirectoryId());
+ if (getLoaderManager().getLoader(partitionIndex) != null) {
+ getLoaderManager().destroyLoader(partitionIndex);
+ }
+ getLoaderManager().restartLoader(partitionIndex, args, this);
+ }
}
diff --git a/src/com/android/contacts/common/list/ShortcutIntentBuilder.java b/src/com/android/contacts/common/list/ShortcutIntentBuilder.java
index 6c97fd9f..53cb857b 100644
--- a/src/com/android/contacts/common/list/ShortcutIntentBuilder.java
+++ b/src/com/android/contacts/common/list/ShortcutIntentBuilder.java
@@ -15,6 +15,7 @@
*/
package com.android.contacts.common.list;
+import android.accounts.Account;
import android.app.ActivityManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -38,6 +39,7 @@ import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.support.v4.graphics.drawable.RoundedBitmapDrawable;
import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory;
+import android.provider.ContactsContract.RawContacts;
import android.telecom.PhoneAccount;
import android.text.TextPaint;
import android.text.TextUtils;
@@ -56,12 +58,16 @@ public class ShortcutIntentBuilder {
private static final String[] CONTACT_COLUMNS = {
Contacts.DISPLAY_NAME,
Contacts.PHOTO_ID,
- Contacts.LOOKUP_KEY
+ Contacts.LOOKUP_KEY,
+ RawContacts.ACCOUNT_TYPE,
+ RawContacts.ACCOUNT_NAME
};
private static final int CONTACT_DISPLAY_NAME_COLUMN_INDEX = 0;
private static final int CONTACT_PHOTO_ID_COLUMN_INDEX = 1;
private static final int CONTACT_LOOKUP_KEY_COLUMN_INDEX = 2;
+ private static final int CONTACT_ACCOUNT_TYPE_COLUMN_INDEX = 3;
+ private static final int CONTACT_ACCOUNT_NAME_COLUMN_INDEX = 4;
private static final String[] PHONE_COLUMNS = {
Phone.DISPLAY_NAME,
@@ -69,7 +75,9 @@ public class ShortcutIntentBuilder {
Phone.NUMBER,
Phone.TYPE,
Phone.LABEL,
- Phone.LOOKUP_KEY
+ Phone.LOOKUP_KEY,
+ RawContacts.ACCOUNT_TYPE,
+ RawContacts.ACCOUNT_NAME
};
private static final int PHONE_DISPLAY_NAME_COLUMN_INDEX = 0;
@@ -78,6 +86,8 @@ public class ShortcutIntentBuilder {
private static final int PHONE_TYPE_COLUMN_INDEX = 3;
private static final int PHONE_LABEL_COLUMN_INDEX = 4;
private static final int PHONE_LOOKUP_KEY_COLUMN_INDEX = 5;
+ private static final int PHONE_ACCOUNT_TYPE_COLUMN_INDEX = 6;
+ private static final int PHONE_ACCOUNT_NAME_COLUMN_INDEX = 7;
private static final String[] PHOTO_COLUMNS = {
Photo.PHOTO,
@@ -187,6 +197,8 @@ public class ShortcutIntentBuilder {
}
private final class ContactLoadingAsyncTask extends LoadingAsyncTask {
+ private Account mAccount;
+
public ContactLoadingAsyncTask(Uri uri) {
super(uri);
}
@@ -200,6 +212,13 @@ public class ShortcutIntentBuilder {
if (cursor.moveToFirst()) {
mDisplayName = cursor.getString(CONTACT_DISPLAY_NAME_COLUMN_INDEX);
mPhotoId = cursor.getLong(CONTACT_PHOTO_ID_COLUMN_INDEX);
+
+ final String accountType = cursor
+ .getString(CONTACT_ACCOUNT_TYPE_COLUMN_INDEX);
+ final String accountName = cursor
+ .getString(CONTACT_ACCOUNT_NAME_COLUMN_INDEX);
+ mAccount = new Account(accountName, accountType);
+
mLookupKey = cursor.getString(CONTACT_LOOKUP_KEY_COLUMN_INDEX);
}
} finally {
@@ -209,7 +228,8 @@ public class ShortcutIntentBuilder {
}
@Override
protected void onPostExecute(Void result) {
- createContactShortcutIntent(mUri, mContentType, mDisplayName, mLookupKey, mBitmapData);
+ createContactShortcutIntent(mUri, mContentType, mDisplayName,
+ mAccount, mLookupKey, mBitmapData);
}
}
@@ -218,6 +238,7 @@ public class ShortcutIntentBuilder {
private String mPhoneNumber;
private int mPhoneType;
private String mPhoneLabel;
+ private Account mAccount;
public PhoneNumberLoadingAsyncTask(Uri uri, String shortcutAction) {
super(uri);
@@ -236,6 +257,13 @@ public class ShortcutIntentBuilder {
mPhoneNumber = cursor.getString(PHONE_NUMBER_COLUMN_INDEX);
mPhoneType = cursor.getInt(PHONE_TYPE_COLUMN_INDEX);
mPhoneLabel = cursor.getString(PHONE_LABEL_COLUMN_INDEX);
+
+ final String accountType = cursor
+ .getString(PHONE_ACCOUNT_TYPE_COLUMN_INDEX);
+ final String accountName = cursor
+ .getString(PHONE_ACCOUNT_NAME_COLUMN_INDEX);
+ mAccount = new Account(accountName, accountType);
+
mLookupKey = cursor.getString(PHONE_LOOKUP_KEY_COLUMN_INDEX);
}
} finally {
@@ -247,23 +275,24 @@ public class ShortcutIntentBuilder {
@Override
protected void onPostExecute(Void result) {
createPhoneNumberShortcutIntent(mUri, mDisplayName, mLookupKey, mBitmapData,
- mPhoneNumber, mPhoneType, mPhoneLabel, mShortcutAction);
+ mPhoneNumber, mPhoneType, mPhoneLabel, mAccount, mShortcutAction);
}
}
- private Drawable getPhotoDrawable(byte[] bitmapData, String displayName, String lookupKey) {
+ private Drawable getPhotoDrawable(byte[] bitmapData, String displayName,
+ String lookupKey, Account account) {
if (bitmapData != null) {
Bitmap bitmap = BitmapFactory.decodeByteArray(bitmapData, 0, bitmapData.length, null);
return new BitmapDrawable(mContext.getResources(), bitmap);
} else {
- return ContactPhotoManager.getDefaultAvatarDrawableForContact(mContext.getResources(),
- false, new DefaultImageRequest(displayName, lookupKey, false));
+ return ContactPhotoManager.getDefaultAvatarDrawableForContact(mContext,
+ false, new DefaultImageRequest(displayName, lookupKey, false), account);
}
}
private void createContactShortcutIntent(Uri contactUri, String contentType, String displayName,
- String lookupKey, byte[] bitmapData) {
- Drawable drawable = getPhotoDrawable(bitmapData, displayName, lookupKey);
+ Account account, String lookupKey, byte[] bitmapData) {
+ Drawable drawable = getPhotoDrawable(bitmapData, displayName, lookupKey, account);
Intent shortcutIntent = new Intent(ContactsContract.QuickContact.ACTION_QUICK_CONTACT);
@@ -300,8 +329,8 @@ public class ShortcutIntentBuilder {
private void createPhoneNumberShortcutIntent(Uri uri, String displayName, String lookupKey,
byte[] bitmapData, String phoneNumber, int phoneType, String phoneLabel,
- String shortcutAction) {
- Drawable drawable = getPhotoDrawable(bitmapData, displayName, lookupKey);
+ Account account, String shortcutAction) {
+ Drawable drawable = getPhotoDrawable(bitmapData, displayName, lookupKey, account);
Bitmap bitmap;
Uri phoneUri;
diff --git a/src/com/android/contacts/common/model/AccountTypeManager.java b/src/com/android/contacts/common/model/AccountTypeManager.java
index 6efe8199..ba303c4d 100644
--- a/src/com/android/contacts/common/model/AccountTypeManager.java
+++ b/src/com/android/contacts/common/model/AccountTypeManager.java
@@ -38,6 +38,7 @@ import android.os.Message;
import android.os.SystemClock;
import android.provider.ContactsContract;
import android.text.TextUtils;
+import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.TimingLogger;
@@ -50,7 +51,10 @@ import com.android.contacts.common.model.account.ExchangeAccountType;
import com.android.contacts.common.model.account.ExternalAccountType;
import com.android.contacts.common.model.account.FallbackAccountType;
import com.android.contacts.common.model.account.GoogleAccountType;
+import com.android.contacts.common.model.account.PhoneAccountType;
+import com.android.contacts.common.model.account.SimAccountType;
import com.android.contacts.common.model.dataitem.DataKind;
+import com.android.contacts.common.SimContactsConstants;
import com.android.contacts.common.testing.NeededForTesting;
import com.android.contacts.common.util.Constants;
import com.google.common.annotations.VisibleForTesting;
@@ -79,6 +83,13 @@ public abstract class AccountTypeManager {
private static final Object mInitializationLock = new Object();
private static AccountTypeManager mAccountTypeManager;
+ public static final int FLAG_ALL_ACCOUNTS = 0;
+ public static final int FLAG_ALL_ACCOUNTS_WITHOUT_SIM = 1;
+ /**
+ * without sim and phone accounts
+ */
+ public static final int FLAG_ALL_ACCOUNTS_WITHOUT_LOCAL = 2;
+
/**
* Requests the singleton instance of {@link AccountTypeManager} with data bound from
* the available authenticators. This method can safely be called from the UI thread.
@@ -112,6 +123,8 @@ public abstract class AccountTypeManager {
* contact writable accounts (if contactWritableOnly is true).
*/
// TODO: Consider splitting this into getContactWritableAccounts() and getAllAccounts()
+ public abstract List<AccountWithDataSet> getAccounts(boolean contactWritableOnly, int flag);
+
public abstract List<AccountWithDataSet> getAccounts(boolean contactWritableOnly);
/**
@@ -418,6 +431,10 @@ class AccountTypeManagerImpl extends AccountTypeManager
accountType = new GoogleAccountType(mContext, auth.packageName);
} else if (ExchangeAccountType.isExchangeType(type)) {
accountType = new ExchangeAccountType(mContext, auth.packageName, type);
+ } else if (SimAccountType.ACCOUNT_TYPE.equals(type)) {
+ accountType = new SimAccountType(mContext, auth.packageName);
+ } else if (PhoneAccountType.ACCOUNT_TYPE.equals(type)) {
+ accountType = new PhoneAccountType(mContext, auth.packageName);
} else {
Log.d(TAG, "Registering external account type=" + type
+ ", packageName=" + auth.packageName);
@@ -563,15 +580,86 @@ class AccountTypeManagerImpl extends AccountTypeManager
return null;
}
+ @Override
+ public List<AccountWithDataSet> getAccounts(boolean contactWritableOnly) {
+ return getAccounts(contactWritableOnly, FLAG_ALL_ACCOUNTS);
+ }
+
/**
* Return list of all known, contact writable {@link AccountWithDataSet}'s.
*/
@Override
- public List<AccountWithDataSet> getAccounts(boolean contactWritableOnly) {
+ public List<AccountWithDataSet> getAccounts(boolean contactWritableOnly,
+ int flag) {
ensureAccountsLoaded();
+ boolean isAirMode = MoreContactUtils.isAPMOnAndSIMPowerDown(mContext);
+ switch (flag) {
+ case FLAG_ALL_ACCOUNTS:
+ return trimAccountByType(
+ contactWritableOnly ? mContactWritableAccounts : mAccounts,
+ isAirMode ? SimAccountType.ACCOUNT_TYPE : null);
+ case FLAG_ALL_ACCOUNTS_WITHOUT_LOCAL:
+ return trimAccountByType(
+ contactWritableOnly ? mContactWritableAccounts : mAccounts,
+ SimAccountType.ACCOUNT_TYPE, PhoneAccountType.ACCOUNT_TYPE);
+ case FLAG_ALL_ACCOUNTS_WITHOUT_SIM:
+ return trimAccountByType(
+ contactWritableOnly ? mContactWritableAccounts : mAccounts,
+ SimAccountType.ACCOUNT_TYPE);
+ }
return contactWritableOnly ? mContactWritableAccounts : mAccounts;
}
+ private boolean isSimStateUnknown(Account account) {
+ int subscription = SimContactsConstants.SUB_INVALID;
+ subscription = MoreContactUtils.getSubscription(account.type, account.name);
+
+ if (subscription > SimContactsConstants.SUB_INVALID
+ && TelephonyManager.getDefault().getSimState(subscription)
+ == TelephonyManager.SIM_STATE_UNKNOWN) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean isSimAccountInvalid(Account account) {
+ if ((SimContactsConstants.ACCOUNT_TYPE_SIM).equals(account.type)) {
+ if (TelephonyManager.getDefault().isMultiSimEnabled()) {
+ if (account.name.equals(SimContactsConstants.SIM_NAME))
+ return true;
+ } else {
+ if (!account.name.equals(SimContactsConstants.SIM_NAME)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private List<AccountWithDataSet> trimAccountByType(final List<AccountWithDataSet> list,
+ String... trimAccountTypes) {
+ List<AccountWithDataSet> tempList = Lists.newArrayList();
+ outer: for (AccountWithDataSet accountWithDataSet : list) {
+ if (trimAccountTypes != null && trimAccountTypes.length > 0) {
+ for (String type : trimAccountTypes) {
+ if (type != null && type.equals(accountWithDataSet.type)) {
+ continue outer;
+ }
+ }
+ }
+
+ if (isSimStateUnknown(accountWithDataSet)) {
+ continue outer;
+ }
+ if (isSimAccountInvalid(accountWithDataSet)) {
+ continue outer;
+ }
+ tempList.add(accountWithDataSet);
+ }
+ return tempList;
+ }
+
/**
* Return the list of all known, group writable {@link AccountWithDataSet}'s.
*/
diff --git a/src/com/android/contacts/common/model/RawContactDelta.java b/src/com/android/contacts/common/model/RawContactDelta.java
index 7304f023..cf5bf304 100644
--- a/src/com/android/contacts/common/model/RawContactDelta.java
+++ b/src/com/android/contacts/common/model/RawContactDelta.java
@@ -24,15 +24,20 @@ import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.BaseColumns;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Profile;
import android.provider.ContactsContract.RawContacts;
+import android.text.TextUtils;
import android.util.Log;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.ValuesDelta;
import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.common.testing.NeededForTesting;
+import com.android.contacts.common.SimContactsConstants;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -416,6 +421,139 @@ public class RawContactDelta implements Parcelable {
}
}
+ public ContentValues buildSimDiff() {
+ ContentValues values = new ContentValues();
+ ArrayList<ValuesDelta> names = getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
+ ArrayList<ValuesDelta> phones = getMimeEntries(Phone.CONTENT_ITEM_TYPE);
+ ArrayList<ValuesDelta> emails = getMimeEntries(Email.CONTENT_ITEM_TYPE);
+
+ ValuesDelta nameValuesDelta = null;
+ ValuesDelta emailValuesDelta = null;
+
+ if (getMimeEntriesCount(StructuredName.CONTENT_ITEM_TYPE, true) > 0) {
+ nameValuesDelta = names.get(0);
+ names.get(0).putNull(StructuredName.GIVEN_NAME);
+ names.get(0).putNull(StructuredName.FAMILY_NAME);
+ names.get(0).putNull(StructuredName.PREFIX);
+ names.get(0).putNull(StructuredName.MIDDLE_NAME);
+ names.get(0).putNull(StructuredName.SUFFIX);
+ names.get(0).put(StructuredName.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+ }
+ if (emails != null && emails.size() > 0) {
+ emailValuesDelta = emails.get(0);
+ }
+
+ String name = null;
+ String number = null;
+ String newName = null;
+ String newNumber = null;
+ StringBuilder email = new StringBuilder();
+ StringBuilder anr = new StringBuilder();
+ StringBuilder newEmail = new StringBuilder();
+ StringBuilder newAnr = new StringBuilder();
+
+ if (nameValuesDelta != null) {
+ if (isContactInsert()) {
+ name = nameValuesDelta.getAsString(StructuredName.DISPLAY_NAME);
+ } else {
+ if (nameValuesDelta.getBefore() != null) {
+ name = nameValuesDelta.getBefore()
+ .getAsString(StructuredName.DISPLAY_NAME);
+ }
+ if (nameValuesDelta.getAfter() != null) {
+ newName = nameValuesDelta.getAfter()
+ .getAsString(StructuredName.DISPLAY_NAME);
+ }
+ }
+ }
+
+ if (isContactInsert() && phones != null) {
+ for (ValuesDelta valuesDelta : phones) {
+ if (valuesDelta.getAfter() != null
+ && valuesDelta.getAfter().size() != 0) {
+ if (Phone.TYPE_MOBILE == valuesDelta.getAfter().getAsLong(Phone.TYPE)) {
+ if (TextUtils.isEmpty(number)) {
+ number = valuesDelta.getAfter().getAsString(Phone.NUMBER);
+ } else {
+ // don't supports to save two mobile number,so gives
+ // invalid str here
+ number = SimContactsConstants.STR_ANRS;
+ }
+ } else {
+ anr.append(valuesDelta.getAfter().getAsString(Phone.NUMBER));
+ anr.append(",");
+ }
+ }
+ }
+ } else if(phones != null) {
+ for (ValuesDelta valuesDelta : phones) {
+ if (valuesDelta.getBefore() != null
+ && valuesDelta.getBefore().size() != 0) {
+ if (Phone.TYPE_MOBILE == valuesDelta.getBefore().getAsLong(Phone.TYPE) ) {
+ number = valuesDelta.getBefore().getAsString(Phone.NUMBER);
+ } else {
+ anr.append(valuesDelta.getBefore().getAsString(Phone.NUMBER));
+ anr.append(",");
+ }
+ }
+ if (valuesDelta.getAfter() != null
+ && valuesDelta.getAfter().size() != 0) {
+ if (Phone.TYPE_MOBILE == valuesDelta.getAsLong(Phone.TYPE)) {
+ if (TextUtils.isEmpty(newNumber)) {
+ newNumber = valuesDelta.getAfter().getAsString(Phone.NUMBER);
+ } else {
+ newNumber = SimContactsConstants.STR_ANRS;
+ }
+ } else {
+ newAnr.append(valuesDelta.getAfter().getAsString(Phone.NUMBER));
+ newAnr.append(",");
+ }
+ }
+ }
+ }
+
+ if (isContactInsert() && emails != null) {
+ for (ValuesDelta valuesDelta : emails) {
+ if (valuesDelta.getAfter() != null
+ && valuesDelta.getAfter().size() != 0) {
+ email.append(valuesDelta.getAfter().getAsString(Email.DATA));
+ email.append(",");
+ }
+ }
+ } else if (emails != null) {
+ for (ValuesDelta valuesDelta : emails) {
+ if (valuesDelta.getBefore() != null
+ && valuesDelta.getBefore().size() != 0) {
+ email.append(valuesDelta.getBefore().getAsString(Email.DATA));
+ email.append(",");
+ }
+ if (valuesDelta.getAfter() != null
+ && valuesDelta.getAfter().size() != 0) {
+ newEmail.append(valuesDelta.getAfter().getAsString(Email.DATA));
+ newEmail.append(",");
+ }
+ }
+ }
+
+ if (isContactInsert()) {
+ if (name != null || number != null || anr != null || email != null) {
+ values.put(SimContactsConstants.STR_TAG, name);
+ values.put(SimContactsConstants.STR_NUMBER, number);
+ values.put(SimContactsConstants.STR_EMAILS, email.toString());
+ values.put(SimContactsConstants.STR_ANRS, anr.toString());
+ }
+ } else {
+ values.put(SimContactsConstants.STR_TAG, name);
+ values.put(SimContactsConstants.STR_NUMBER, number);
+ values.put(SimContactsConstants.STR_EMAILS, email.toString());
+ values.put(SimContactsConstants.STR_ANRS, anr.toString());
+ values.put(SimContactsConstants.STR_NEW_TAG, newName);
+ values.put(SimContactsConstants.STR_NEW_NUMBER, newNumber);
+ values.put(SimContactsConstants.STR_NEW_EMAILS, newEmail.toString());
+ values.put(SimContactsConstants.STR_NEW_ANRS, newAnr.toString());
+ }
+ return values;
+ }
/**
* Build a list of {@link ContentProviderOperation} that will transform the
* current "before" {@link Entity} state into the modified state which this
diff --git a/src/com/android/contacts/common/model/RawContactModifier.java b/src/com/android/contacts/common/model/RawContactModifier.java
index 954123ba..5ddf0f05 100644
--- a/src/com/android/contacts/common/model/RawContactModifier.java
+++ b/src/com/android/contacts/common/model/RawContactModifier.java
@@ -487,7 +487,7 @@ public class RawContactModifier {
*/
public static boolean isEmpty(ValuesDelta values, DataKind kind) {
if (Photo.CONTENT_ITEM_TYPE.equals(kind.mimeType)) {
- return values.isInsert() && values.getAsByteArray(Photo.PHOTO) == null;
+ return values.getAsByteArray(Photo.PHOTO) == null;
}
// No defined fields mean this row is always empty
diff --git a/src/com/android/contacts/common/model/ValuesDelta.java b/src/com/android/contacts/common/model/ValuesDelta.java
index e30cdd62..2db7e1c8 100644
--- a/src/com/android/contacts/common/model/ValuesDelta.java
+++ b/src/com/android/contacts/common/model/ValuesDelta.java
@@ -23,6 +23,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
+import android.provider.ContactsContract.Data;
import com.android.contacts.common.testing.NeededForTesting;
import com.google.common.collect.Sets;
@@ -61,6 +62,17 @@ public class ValuesDelta implements Parcelable {
final ValuesDelta entry = new ValuesDelta();
entry.mBefore = before;
entry.mAfter = new ContentValues();
+
+ // init data1 to mAfter map. when no operation edittext of
+ // sim phone in the UI, the mAfter init have no data1 value,
+ // it will cause the builddiff data not right.
+ if (before.containsKey(Data.DATA1)) {
+ String contactInfo = before.getAsString(Data.DATA1);
+ if (null != contactInfo && !"".equals(contactInfo)) {
+ entry.mAfter.put(Data.DATA1, contactInfo);
+ }
+ }
+
return entry;
}
@@ -83,6 +95,10 @@ public class ValuesDelta implements Parcelable {
return mAfter;
}
+ public ContentValues getBefore() {
+ return mBefore;
+ }
+
public boolean containsKey(String key) {
return ((mAfter != null && mAfter.containsKey(key)) ||
(mBefore != null && mBefore.containsKey(key)));
diff --git a/src/com/android/contacts/common/model/account/AccountType.java b/src/com/android/contacts/common/model/account/AccountType.java
index 53ab47d9..27b5bc5f 100644..100755
--- a/src/com/android/contacts/common/model/account/AccountType.java
+++ b/src/com/android/contacts/common/model/account/AccountType.java
@@ -16,19 +16,26 @@
package com.android.contacts.common.model.account;
+import android.accounts.AccountManager;
+import android.accounts.AuthenticatorDescription;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.RawContacts;
+import android.telephony.TelephonyManager;
+import android.util.Log;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
+import com.android.contacts.common.MoreContactUtils;
import com.android.contacts.common.R;
import com.android.contacts.common.model.dataitem.DataKind;
+import com.android.internal.telephony.PhoneConstants;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -39,6 +46,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Internal structure that represents constraints and styles for a specific data
@@ -51,6 +59,12 @@ public abstract class AccountType {
private static final String TAG = "AccountType";
/**
+ * Local phone-storage account
+ * @hide
+ */
+ public static final String LOCAL_ACCOUNT = "phone-local";
+
+ /**
* The {@link RawContacts#ACCOUNT_TYPE} these constraints apply to.
*/
public String accountType = null;
@@ -96,6 +110,11 @@ public abstract class AccountType {
protected boolean mIsInitialized;
+ private Map<String, AuthenticatorDescription> mTypeToAuthDescription
+ = new HashMap<String, AuthenticatorDescription>();
+
+ private AuthenticatorDescription[] mAuthDescs;
+
protected static class DefinitionException extends Exception {
public DefinitionException(String message) {
super(message);
@@ -196,12 +215,6 @@ public abstract class AccountType {
public String getViewGroupActivity() {
return null;
}
-
- public CharSequence getDisplayLabel(Context context) {
- // Note this resource is defined in the sync adapter package, not resourcePackageName.
- return getResourceText(context, syncAdapterPackageName, titleRes, accountType);
- }
-
/**
* @return resource ID for the "invite contact" action label, or -1 if not defined.
*/
@@ -276,15 +289,89 @@ public abstract class AccountType {
}
}
+ public void updateAuthDescriptions(Context context) {
+ mAuthDescs = AccountManager.get(context).getAuthenticatorTypes();
+ for (int i = 0; i < mAuthDescs.length; i++) {
+ mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]);
+ }
+ }
+ public CharSequence getDisplayLabel(Context context) {
+ CharSequence label = null;
+ updateAuthDescriptions(context);
+ if (mTypeToAuthDescription.containsKey(accountType)) {
+ try {
+ AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+ Context authContext = context.createPackageContext(desc.packageName, 0);
+ label = authContext.getResources().getText(desc.labelId);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.w(TAG, "No label name for account type " + accountType);
+ } catch (Resources.NotFoundException e) {
+ Log.w(TAG, "No label icon for account type " + accountType);
+ }
+ }
+ return label;
+ }
+
+ public CharSequence getDisplayLabel(Context context, String accountName) {
+ if ((SimAccountType.ACCOUNT_TYPE).equals(accountType)) {
+ final int slot = MoreContactUtils.getSubscription(accountType,
+ accountName);
+ return MoreContactUtils.getMultiSimAliasesName(context, slot);
+ }
+ return getDisplayLabel(context);
+ }
+
+ /**
+ * Gets an icon associated with a particular account type. If none found, return null.
+ *
+ * @param accountType the type of account
+ * @return a drawable for the icon or null if one cannot be found.
+ */
public Drawable getDisplayIcon(Context context) {
- if (this.titleRes != -1 && this.syncAdapterPackageName != null) {
- final PackageManager pm = context.getPackageManager();
- return pm.getDrawable(this.syncAdapterPackageName, this.iconRes, null);
- } else if (this.titleRes != -1) {
- return context.getResources().getDrawable(this.iconRes);
- } else {
- return null;
+ Drawable icon = null;
+ updateAuthDescriptions(context);
+ if (PhoneAccountType.ACCOUNT_TYPE.equals(accountType)) {
+ return context.getResources().getDrawable(R.drawable.phone_account);
+ }
+ if (mTypeToAuthDescription.containsKey(accountType)) {
+ try {
+ AuthenticatorDescription desc = mTypeToAuthDescription
+ .get(accountType);
+ Context authContext = context.createPackageContext(
+ desc.packageName, 0);
+ icon = authContext.getResources().getDrawable(desc.iconId);
+ } catch (PackageManager.NameNotFoundException e) {
+ } catch (Resources.NotFoundException e) {
+ }
+ }
+ if (icon == null) {
+ icon = context.getPackageManager().getDefaultActivityIcon();
+ }
+ return icon;
+ }
+
+ public Drawable getDisplayIcon(Context context, String accountName) {
+ if ((SimAccountType.ACCOUNT_TYPE).equals(accountType)) {
+ final int slot = MoreContactUtils.getSubscription(accountType,
+ accountName);
+ if (TelephonyManager.getDefault().isMultiSimEnabled()) {
+ switch (slot) {
+ case PhoneConstants.SUB1:
+ return context.getResources().getDrawable(
+ R.drawable.sim1_account);
+ case PhoneConstants.SUB2:
+ return context.getResources().getDrawable(
+ R.drawable.sim2_account);
+ default:
+ return context.getResources().getDrawable(
+ R.drawable.simcard_account);
+ }
+ } else {
+ return context.getResources().getDrawable(
+ R.drawable.simcard_account);
+ }
}
+ return getDisplayIcon(context);
}
/**
diff --git a/src/com/android/contacts/common/model/account/BaseAccountType.java b/src/com/android/contacts/common/model/account/BaseAccountType.java
index 648a6dc8..1ead103f 100644
--- a/src/com/android/contacts/common/model/account/BaseAccountType.java
+++ b/src/com/android/contacts/common/model/account/BaseAccountType.java
@@ -436,6 +436,8 @@ public abstract class BaseAccountType extends AccountType {
DataKind kind = addKind(new DataKind(GroupMembership.CONTENT_ITEM_TYPE,
R.string.groupsLabel, Weight.GROUP_MEMBERSHIP, true));
+ kind.actionHeader = new SimpleInflater(R.string.label_groups);
+ kind.actionBody = new SimpleInflater(GroupMembership.GROUP_ROW_ID);
kind.typeOverallMax = 1;
kind.fieldList = Lists.newArrayList();
kind.fieldList.add(new EditField(GroupMembership.GROUP_ROW_ID, -1, -1));
diff --git a/src/com/android/contacts/common/model/account/PhoneAccountType.java b/src/com/android/contacts/common/model/account/PhoneAccountType.java
new file mode 100644
index 00000000..7e2e1e52
--- /dev/null
+++ b/src/com/android/contacts/common/model/account/PhoneAccountType.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014, The Linux Foundation. All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.android.contacts.common.model.account;
+
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.os.SystemProperties;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.contacts.common.R;
+import com.android.contacts.common.SimContactsConstants;
+import com.android.contacts.common.model.account.AccountType.DefinitionException;
+import com.google.android.collect.Lists;
+
+
+public class PhoneAccountType extends BaseAccountType{
+ private static final String TAG = "PhoneAccountType";
+
+ public static final String ACCOUNT_TYPE = SimContactsConstants.ACCOUNT_TYPE_PHONE;
+ public static final int FLAGS_PERSON_NAME = EditorInfo.TYPE_CLASS_TEXT
+ | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS | EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME;
+ protected static final int FLAGS_PHONE = EditorInfo.TYPE_CLASS_PHONE;
+
+ public PhoneAccountType(Context context, String resPackageName) {
+ this.accountType = ACCOUNT_TYPE;
+ this.resourcePackageName = null;
+ this.syncAdapterPackageName = resPackageName;
+
+ try {
+
+ addDataKindStructuredName(context);
+ addDataKindDisplayName(context);
+ addDataKindPhoneticName(context);
+ addDataKindNickname(context);
+ addDataKindPhone(context);
+ addDataKindEmail(context);
+ addDataKindStructuredPostal(context);
+ addDataKindIm(context);
+ addDataKindOrganization(context);
+ addDataKindPhoto(context);
+ addDataKindNote(context);
+ addDataKindWebsite(context);
+ addDataKindGroupMembership(context);
+ if (context.getResources().getBoolean(
+ com.android.internal.R.bool.config_built_in_sip_phone)) {
+ addDataKindSipAddress(context);
+ }
+
+ mIsInitialized = true;
+ } catch (DefinitionException e) {
+ Log.e(TAG, "Problem building account type", e);
+ }
+
+ }
+
+ @Override
+ public boolean isGroupMembershipEditable() {
+ return true;
+ }
+
+ @Override
+ public boolean areContactsWritable() {
+ return true;
+ }
+
+}
diff --git a/src/com/android/contacts/common/model/account/SimAccountType.java b/src/com/android/contacts/common/model/account/SimAccountType.java
new file mode 100644
index 00000000..6473f2b0
--- /dev/null
+++ b/src/com/android/contacts/common/model/account/SimAccountType.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2014, The Linux Foundation. All Rights Reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package com.android.contacts.common.model.account;
+
+import android.content.Context;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.util.Log;
+import android.view.inputmethod.EditorInfo;
+import android.graphics.drawable.Drawable;
+
+import com.android.contacts.common.R;
+import com.android.contacts.common.SimContactsConstants;
+import com.android.contacts.common.model.account.AccountType.DefinitionException;
+import com.android.contacts.common.model.dataitem.DataKind;
+import com.google.android.collect.Lists;
+
+public class SimAccountType extends BaseAccountType{
+ private static final String TAG = "SimContactsType";
+
+ public static final String ACCOUNT_TYPE = SimContactsConstants.ACCOUNT_TYPE_SIM;
+ public static final int FLAGS_PERSON_NAME = EditorInfo.TYPE_CLASS_TEXT
+ | EditorInfo.TYPE_TEXT_FLAG_CAP_WORDS | EditorInfo.TYPE_TEXT_VARIATION_PERSON_NAME;
+ public static final int FLAGS_PHONETIC = EditorInfo.TYPE_CLASS_TEXT
+ | EditorInfo.TYPE_TEXT_VARIATION_PHONETIC;
+ protected static final int FLAGS_PHONE = EditorInfo.TYPE_CLASS_PHONE;
+ private static Context mContext;
+
+ public SimAccountType(Context context, String resPackageName) {
+ this.accountType = ACCOUNT_TYPE;
+ this.resourcePackageName = resPackageName;
+ this.syncAdapterPackageName = resPackageName;
+
+ this.mContext = context;
+
+ try {
+ addDataKindStructuredName(context);
+ addDataKindDisplayName(context);
+ addDataKindPhone(context);
+ addDataKindEmail(context);
+ mIsInitialized = true;
+ } catch (DefinitionException e) {
+ Log.e(TAG, "Problem building account type", e);
+ }
+ }
+
+ @Override
+ protected DataKind addDataKindStructuredName(Context context) throws DefinitionException {
+ final DataKind kind = super.addDataKindStructuredName(context);
+ kind.fieldList = Lists.newArrayList();
+ kind.fieldList.add(new EditField(StructuredName.DISPLAY_NAME, R.string.nameLabelsGroup,
+ FLAGS_PERSON_NAME));
+
+ return kind;
+ }
+
+ @Override
+ protected DataKind addDataKindPhone(Context context) throws DefinitionException {
+ final DataKind kind = super.addDataKindPhone(context);
+
+ kind.iconAltRes = R.drawable.ic_text_holo_light;
+ kind.typeOverallMax = 2;
+ kind.typeColumn = Phone.TYPE;
+ kind.typeList = Lists.newArrayList();
+ kind.typeList.add(buildPhoneType(Phone.TYPE_MOBILE));
+ kind.typeList.add(buildPhoneType(Phone.TYPE_HOME));// This is used to save ANR records
+ kind.fieldList = Lists.newArrayList();
+ kind.fieldList.add(new EditField(Phone.NUMBER, R.string.phoneLabelsGroup, FLAGS_PHONE));
+
+ return kind;
+ }
+
+ @Override
+ protected DataKind addDataKindEmail(Context context) throws DefinitionException {
+ final DataKind kind = super.addDataKindEmail(context);
+
+ kind.typeOverallMax = 1;
+ kind.typeColumn = Email.TYPE;
+ kind.fieldList = Lists.newArrayList();
+ kind.fieldList.add(new EditField(Email.ADDRESS, R.string.emailLabelsGroup, FLAGS_EMAIL));
+ return kind;
+ }
+
+
+ @Override
+ public boolean isGroupMembershipEditable() {
+ return true;
+ }
+
+ @Override
+ public boolean areContactsWritable() {
+ return true;
+ }
+
+}
diff --git a/src/com/android/contacts/common/preference/ContactsPreferences.java b/src/com/android/contacts/common/preference/ContactsPreferences.java
index 311d0075..5c07f83f 100644
--- a/src/com/android/contacts/common/preference/ContactsPreferences.java
+++ b/src/com/android/contacts/common/preference/ContactsPreferences.java
@@ -27,6 +27,7 @@ import android.provider.ContactsContract;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
+import android.text.TextUtils;
import com.android.contacts.common.R;
/**
@@ -54,6 +55,11 @@ public final class ContactsPreferences implements OnSharedPreferenceChangeListen
public static final String SORT_ORDER_KEY = "android.contacts.SORT_ORDER";
/**
+ * The values of SIMs serial numbers that have been imported
+ */
+ public static final String IMPORTED_SIMS_SNS = "android.contacts.IMPORTED_SIMS";
+
+ /**
* The value for the SORT_ORDER key corresponding to sort by family name first.
*/
public static final int SORT_ORDER_ALTERNATIVE = 2;
@@ -105,6 +111,28 @@ public final class ContactsPreferences implements OnSharedPreferenceChangeListen
editor.commit();
}
+ public String[] getImportedSims() {
+ String imported = mPreferences.getString(IMPORTED_SIMS_SNS, "");
+ if (!TextUtils.isEmpty(imported)) {
+ return imported.split("\\|");
+ } else {
+ return new String[0];
+ }
+ }
+
+ public void addImportedSims(String simSN) {
+ String imported = mPreferences.getString(IMPORTED_SIMS_SNS, "");
+ if (!TextUtils.isEmpty(imported)) {
+ imported += "|" + simSN;
+ } else {
+ imported = simSN;
+ }
+
+ final Editor editor = mPreferences.edit();
+ editor.putString(IMPORTED_SIMS_SNS, imported);
+ editor.commit();
+ }
+
public boolean isDisplayOrderUserChangeable() {
return mContext.getResources().getBoolean(R.bool.config_display_order_user_changeable);
}
diff --git a/src/com/android/contacts/common/preference/DisplayOrderPreference.java b/src/com/android/contacts/common/preference/DisplayOrderPreference.java
index 6a182c51..c053466d 100644..100755
--- a/src/com/android/contacts/common/preference/DisplayOrderPreference.java
+++ b/src/com/android/contacts/common/preference/DisplayOrderPreference.java
@@ -21,6 +21,8 @@ import android.content.Context;
import android.preference.ListPreference;
import android.provider.ContactsContract;
import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
import com.android.contacts.common.R;
import com.android.contacts.common.preference.ContactsPreferences;
@@ -89,4 +91,13 @@ public final class DisplayOrderPreference extends ListPreference {
super.onPrepareDialogBuilder(builder);
builder.setNegativeButton(null, null);
}
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ final View imageFrame = view.findViewById(com.android.internal.R.id.icon_frame);
+ if (imageFrame != null) {
+ imageFrame.setVisibility(View.GONE);
+ }
+ }
}
diff --git a/src/com/android/contacts/common/preference/SortOrderPreference.java b/src/com/android/contacts/common/preference/SortOrderPreference.java
index dfd9550b..863d9845 100644..100755
--- a/src/com/android/contacts/common/preference/SortOrderPreference.java
+++ b/src/com/android/contacts/common/preference/SortOrderPreference.java
@@ -20,6 +20,8 @@ import android.app.AlertDialog.Builder;
import android.content.Context;
import android.preference.ListPreference;
import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
import com.android.contacts.common.R;
import com.android.contacts.common.preference.ContactsPreferences;
@@ -88,4 +90,13 @@ public final class SortOrderPreference extends ListPreference {
super.onPrepareDialogBuilder(builder);
builder.setNegativeButton(null, null);
}
+
+ @Override
+ protected void onBindView(View view) {
+ super.onBindView(view);
+ final View imageFrame = view.findViewById(com.android.internal.R.id.icon_frame);
+ if (imageFrame != null) {
+ imageFrame.setVisibility(View.GONE);
+ }
+ }
}
diff --git a/src/com/android/contacts/common/util/AccountSelectionUtil.java b/src/com/android/contacts/common/util/AccountSelectionUtil.java
index 78cc2d5d..ed77da22 100644
--- a/src/com/android/contacts/common/util/AccountSelectionUtil.java
+++ b/src/com/android/contacts/common/util/AccountSelectionUtil.java
@@ -1,5 +1,7 @@
/*
* Copyright (C) 2009 The Android Open Source Project
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +25,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -32,11 +35,13 @@ import android.widget.ArrayAdapter;
import android.widget.TextView;
import com.android.contacts.common.R;
+import com.android.contacts.common.SimContactsConstants;
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.vcard.ImportVCardActivity;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -47,8 +52,14 @@ public class AccountSelectionUtil {
private static final String LOG_TAG = "AccountSelectionUtil";
public static boolean mVCardShare = false;
+ private static int SIM_ID_INVALID = -1;
+ private static int mSelectedSim = SIM_ID_INVALID;
+ // Constant value to know option is import from all SIM's
+ private static int IMPORT_FROM_ALL = 8;
public static Uri mPath;
+ // QRD enhancement: import subscription selected by user
+ private static int mImportSub = SimContactsConstants.SUB_INVALID;
public static class AccountSelectedListener
implements DialogInterface.OnClickListener {
@@ -57,7 +68,7 @@ public class AccountSelectionUtil {
final private int mResId;
final private int mSubscriptionId;
- final protected List<AccountWithDataSet> mAccountList;
+ protected List<AccountWithDataSet> mAccountList;
public AccountSelectedListener(Context context, List<AccountWithDataSet> accountList,
int resId, int subscriptionId) {
@@ -81,6 +92,19 @@ public class AccountSelectionUtil {
dialog.dismiss();
doImport(mContext, mResId, mAccountList.get(which), mSubscriptionId);
}
+ /**
+ * Reset the account list for this listener, to make sure the selected
+ * items reflect the displayed items.
+ *
+ * @param accountList The reset account list.
+ */
+ void setAccountList(List<AccountWithDataSet> accountList) {
+ mAccountList = accountList;
+ }
+ }
+
+ public static void setImportSubscription(int subscription) {
+ mImportSub = subscription;
}
public static Dialog getSelectAccountDialog(Context context, int resId) {
@@ -92,15 +116,28 @@ public class AccountSelectionUtil {
return getSelectAccountDialog(context, resId, onClickListener, null);
}
+ public static Dialog getSelectAccountDialog(Context context, int resId,
+ DialogInterface.OnClickListener onClickListener,
+ DialogInterface.OnCancelListener onCancelListener) {
+ return getSelectAccountDialog(context, resId, onClickListener,
+ onCancelListener, true);
+ }
+
/**
* When OnClickListener or OnCancelListener is null, uses a default listener.
* The default OnCancelListener just closes itself with {@link Dialog#dismiss()}.
*/
public static Dialog getSelectAccountDialog(Context context, int resId,
DialogInterface.OnClickListener onClickListener,
- DialogInterface.OnCancelListener onCancelListener) {
+ DialogInterface.OnCancelListener onCancelListener, boolean includeSIM) {
final AccountTypeManager accountTypes = AccountTypeManager.getInstance(context);
- final List<AccountWithDataSet> writableAccountList = accountTypes.getAccounts(true);
+ List<AccountWithDataSet> writableAccountList = accountTypes.getAccounts(true);
+ if (includeSIM) {
+ writableAccountList = accountTypes.getAccounts(true);
+ } else {
+ writableAccountList = accountTypes.getAccounts(true,
+ AccountTypeManager.FLAG_ALL_ACCOUNTS_WITHOUT_SIM);
+ }
Log.i(LOG_TAG, "The number of available accounts: " + writableAccountList.size());
@@ -145,6 +182,13 @@ public class AccountSelectionUtil {
AccountSelectedListener accountSelectedListener =
new AccountSelectedListener(context, writableAccountList, resId);
onClickListener = accountSelectedListener;
+ } else if (onClickListener instanceof AccountSelectedListener) {
+ // Because the writableAccountList is different if includeSIM or not, so
+ // should reset the account list for the AccountSelectedListener which
+ // is initialized with FLAG_ALL_ACCOUNTS.
+ // Reset the account list to make sure the selected account is contained
+ // in these display accounts.
+ ((AccountSelectedListener) onClickListener).setAccountList(writableAccountList);
}
if (onCancelListener == null) {
onCancelListener = new DialogInterface.OnCancelListener() {
@@ -204,4 +248,70 @@ public class AccountSelectionUtil {
mPath = null;
context.startActivity(importIntent);
}
+
+ public static class SimSelectedListener
+ implements DialogInterface.OnClickListener {
+
+ final private Context mContext;
+ final private AccountWithDataSet mAccount;
+
+ public SimSelectedListener(Context context, AccountWithDataSet account) {
+ mContext = context;
+ mAccount = account;
+ }
+
+ public void onClick(DialogInterface dialog, int which) {
+ Log.d(LOG_TAG, "onClick OK: mSelectedSim = " + mSelectedSim);
+ if (mSelectedSim != SIM_ID_INVALID) {
+ doImportFromSim(mContext, mAccount, mSelectedSim);
+ }
+ }
+ }
+
+ private static void displaySelectSimDialog(Context context,
+ SimSelectedListener simSelListner) {
+ Log.d(LOG_TAG, "displaySelectSimDialog");
+
+ mSelectedSim = SIM_ID_INVALID;
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setTitle(R.string.select_sim);
+ final int numPhones = TelephonyManager.getDefault().getPhoneCount();
+ CharSequence[] subList = new CharSequence[numPhones + 1];
+ int i;
+ for (i = 1; i <= numPhones; i++) {
+ subList[i-1] = "SIM" + i;
+ }
+ subList[i-1] = context.getString(R.string.import_contacts_from_all_cards);
+ builder.setSingleChoiceItems(subList, -1, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Log.d(LOG_TAG, "onClicked Dialog on which = " + which);
+ mSelectedSim = which;
+ if (mSelectedSim == numPhones) {
+ mSelectedSim = IMPORT_FROM_ALL;
+ }
+ }
+ });
+
+ AlertDialog dialog = builder.create();
+ dialog.setButton(DialogInterface.BUTTON_POSITIVE,
+ context.getString(com.android.internal.R.string.ok), simSelListner);
+ dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(
+ com.android.internal.R.string.cancel), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Log.d(LOG_TAG, "onClicked Cancel");
+ }
+ });
+
+ dialog.setOnDismissListener(new DialogInterface.OnDismissListener () {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ Log.d(LOG_TAG, "onDismiss");
+ Log.d(LOG_TAG, "Selected SUB = " + mSelectedSim);
+ }
+ });
+ dialog.show();
+ }
}
diff --git a/src/com/android/contacts/common/util/AccountsListAdapter.java b/src/com/android/contacts/common/util/AccountsListAdapter.java
index 84435df8..2e1c44ae 100644..100755
--- a/src/com/android/contacts/common/util/AccountsListAdapter.java
+++ b/src/com/android/contacts/common/util/AccountsListAdapter.java
@@ -29,6 +29,8 @@ import com.android.contacts.common.R;
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.model.account.PhoneAccountType;
+import com.android.contacts.common.model.account.SimAccountType;
import java.util.ArrayList;
import java.util.List;
@@ -48,7 +50,8 @@ public final class AccountsListAdapter extends BaseAdapter {
public enum AccountListFilter {
ALL_ACCOUNTS, // All read-only and writable accounts
ACCOUNTS_CONTACT_WRITABLE, // Only where the account type is contact writable
- ACCOUNTS_GROUP_WRITABLE // Only accounts where the account type is group writable
+ ACCOUNTS_GROUP_WRITABLE, // Only accounts where the account type is group writable
+ ACCOUNTS_CONTACT_WRITABLE_WITHOUT_SIM
}
public AccountsListAdapter(Context context, AccountListFilter accountListFilter) {
@@ -64,6 +67,11 @@ public final class AccountsListAdapter extends BaseAdapter {
mContext = context;
mAccountTypes = AccountTypeManager.getInstance(context);
mAccounts = getAccounts(accountListFilter);
+
+ // Add a virtual local storage account to allow user to store its contacts in the phone
+ String localAccountName = context.getString(R.string.local_storage_account);
+ mAccounts.add(0, new AccountWithDataSet(localAccountName, AccountType.LOCAL_ACCOUNT, null));
+
if (currentAccount != null
&& !mAccounts.isEmpty()
&& !mAccounts.get(0).equals(currentAccount)
@@ -75,10 +83,22 @@ public final class AccountsListAdapter extends BaseAdapter {
private List<AccountWithDataSet> getAccounts(AccountListFilter accountListFilter) {
if (accountListFilter == AccountListFilter.ACCOUNTS_GROUP_WRITABLE) {
- return new ArrayList<AccountWithDataSet>(mAccountTypes.getGroupWritableAccounts());
+ return new ArrayList<AccountWithDataSet>(mAccountTypes.getAccounts(
+ true, AccountTypeManager.FLAG_ALL_ACCOUNTS_WITHOUT_SIM));
}
- return new ArrayList<AccountWithDataSet>(mAccountTypes.getAccounts(
- accountListFilter == AccountListFilter.ACCOUNTS_CONTACT_WRITABLE));
+ final List<AccountWithDataSet> writableAccountList = mAccountTypes
+ .getAccounts(accountListFilter == AccountListFilter.ACCOUNTS_CONTACT_WRITABLE
+ || accountListFilter == AccountListFilter.ACCOUNTS_CONTACT_WRITABLE_WITHOUT_SIM);
+ List<AccountWithDataSet> deletedList = new ArrayList<AccountWithDataSet>();
+
+ if (accountListFilter == AccountListFilter.ACCOUNTS_CONTACT_WRITABLE_WITHOUT_SIM) {
+ for (AccountWithDataSet account : writableAccountList) {
+ if (SimAccountType.ACCOUNT_TYPE.equals(account.type))
+ deletedList.add(account);
+ }
+ writableAccountList.removeAll(deletedList);
+ }
+ return writableAccountList;
}
@Override
@@ -93,14 +113,20 @@ public final class AccountsListAdapter extends BaseAdapter {
final AccountWithDataSet account = mAccounts.get(position);
final AccountType accountType = mAccountTypes.getAccountType(account.type, account.dataSet);
- text1.setText(accountType.getDisplayLabel(mContext));
+ text1.setText(accountType.getDisplayLabel(mContext, account.name));
// For email addresses, we don't want to truncate at end, which might cut off the domain
// name.
+ if (SimAccountType.ACCOUNT_TYPE.equals(account.type)
+ || PhoneAccountType.ACCOUNT_TYPE.equals(account.type)) {
+ text2.setVisibility(View.GONE);
+ } else {
+ text2.setVisibility(View.VISIBLE);
+ }
text2.setText(account.name);
text2.setEllipsize(TruncateAt.MIDDLE);
- icon.setImageDrawable(accountType.getDisplayIcon(mContext));
+ icon.setImageDrawable(accountType.getDisplayIcon(mContext, account.name));
return resultView;
}
diff --git a/src/com/android/contacts/common/util/TelephonyManagerUtils.java b/src/com/android/contacts/common/util/TelephonyManagerUtils.java
index 7c322ca0..374743d1 100644
--- a/src/com/android/contacts/common/util/TelephonyManagerUtils.java
+++ b/src/com/android/contacts/common/util/TelephonyManagerUtils.java
@@ -15,12 +15,19 @@
*/
package com.android.contacts.common.util;
+import android.content.ComponentName;
import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
+import java.util.List;
import java.util.Locale;
/**
@@ -70,4 +77,70 @@ public class TelephonyManagerUtils {
// TODO: Check the telephony manager's subscriptions to see if any support video calls.
return true;
}
+
+ /**
+ * Retrieve the account metadata, but if the account does not exist or the device has only a
+ * single registered and enabled account, return null.
+ */
+ private static PhoneAccount getAccountOrNull(Context context,
+ PhoneAccountHandle phoneAccount) {
+ final TelecomManager telecomManager =
+ (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
+ final PhoneAccount account = telecomManager.getPhoneAccount(phoneAccount);
+ if (account == null || !telecomManager.hasMultipleCallCapableAccounts()) {
+ return null;
+ }
+ return account;
+ }
+
+ /**
+ * Generate account info from data in Telecomm database
+ */
+ public static PhoneAccountHandle getAccount(String componentString,
+ String accountId) {
+ if (TextUtils.isEmpty(componentString) || TextUtils.isEmpty(accountId)) {
+ return null;
+ }
+ final ComponentName componentName = ComponentName.unflattenFromString(componentString);
+ return new PhoneAccountHandle(componentName, accountId);
+ }
+
+ /**
+ * Generate account icon from data in Telecomm database
+ */
+ public static Drawable getAccountIcon(Context context, PhoneAccountHandle phoneAccount) {
+ final PhoneAccount account = getAccountOrNull(context, phoneAccount);
+ if (account == null) {
+ return null;
+ }
+ return account.createIconDrawable(context);
+ }
+
+ public static Drawable getMultiSimIcon(Context context, int subscription) {
+ if (context == null) {
+ // If the context is null, return 0 as no resource found.
+ return null;
+ }
+
+ int subId[] = SubscriptionManager.getSubId(subscription);
+ if (subId == null) {
+ return null;
+ }
+ final TelecomManager telecomManager = (TelecomManager) context
+ .getSystemService(Context.TELECOM_SERVICE);
+ List<PhoneAccountHandle> pHandles = telecomManager.getCallCapablePhoneAccounts();
+ PhoneAccountHandle phoneAccountHandle = null;
+ for (PhoneAccountHandle itorator : pHandles) {
+ if (String.valueOf(subId[0]).equals(itorator.getId())) {
+ phoneAccountHandle = itorator;
+ }
+ }
+
+ if (phoneAccountHandle == null) {
+ return null;
+ }
+ final PhoneAccount account = telecomManager
+ .getPhoneAccount(phoneAccountHandle);
+ return account.createIconDrawable(context);
+ }
}
diff --git a/src/com/android/contacts/common/vcard/ExportProcessor.java b/src/com/android/contacts/common/vcard/ExportProcessor.java
index 791f2f96..72cfa426 100644
--- a/src/com/android/contacts/common/vcard/ExportProcessor.java
+++ b/src/com/android/contacts/common/vcard/ExportProcessor.java
@@ -56,6 +56,7 @@ public class ExportProcessor extends ProcessorBase {
private volatile boolean mCanceled;
private volatile boolean mDone;
+ private String selExport = "";
public ExportProcessor(VCardService service, ExportRequest exportRequest, int jobId,
String callingActivity) {
@@ -141,7 +142,7 @@ public class ExportProcessor extends ProcessorBase {
final Uri contentUriForRawContactsEntity = RawContactsEntity.CONTENT_URI;
// TODO: should provide better selection.
if (!composer.init(Contacts.CONTENT_URI, new String[] {Contacts._ID},
- null, null,
+ selExport, null,
null, contentUriForRawContactsEntity)) {
final String errorReason = composer.getErrorReason();
Log.e(LOG_TAG, "initialization of vCard composer failed: " + errorReason);
@@ -216,6 +217,10 @@ public class ExportProcessor extends ProcessorBase {
}
}
+ public void setSelExport(String sel) {
+ selExport = sel;
+ }
+
private String translateComposerError(String errorMessage) {
final Resources resources = mService.getResources();
if (VCardComposer.FAILURE_REASON_FAILED_TO_GET_DATABASE_INFO.equals(errorMessage)) {
@@ -258,8 +263,8 @@ public class ExportProcessor extends ProcessorBase {
final Intent intent = new Intent();
intent.setClassName(mService, mCallingActivity);
final Notification notification =
- NotificationImportExportListener.constructFinishNotification(mService, title,
- description, intent);
+ NotificationImportExportListener.constructFinishNotification(mService, VCardService.TYPE_EXPORT,
+ title, description, intent);
mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG,
mJobId, notification);
}
diff --git a/src/com/android/contacts/common/vcard/ExportVCardActivity.java b/src/com/android/contacts/common/vcard/ExportVCardActivity.java
index b86845e7..029561d0 100644
--- a/src/com/android/contacts/common/vcard/ExportVCardActivity.java
+++ b/src/com/android/contacts/common/vcard/ExportVCardActivity.java
@@ -35,6 +35,7 @@ import android.text.TextDirectionHeuristics;
import android.text.TextUtils;
import android.util.Log;
+import com.android.contacts.common.MoreContactUtils;
import com.android.contacts.common.R;
import java.io.File;
@@ -50,6 +51,7 @@ public class ExportVCardActivity extends Activity implements ServiceConnection,
DialogInterface.OnClickListener, DialogInterface.OnCancelListener {
private static final String LOG_TAG = "VCardExport";
private static final boolean DEBUG = VCardService.DEBUG;
+ private String selExport = "";
/**
* Handler used when some Message has come from {@link VCardService}.
@@ -121,6 +123,8 @@ public class ExportVCardActivity extends Activity implements ServiceConnection,
// String for storing error reason temporarily.
private String mErrorReason;
+ private int mSelectedStorage = VCardService.INTERNAL_PATH;
+
private class ExportConfirmationListener implements DialogInterface.OnClickListener {
private final Uri mDestinationUri;
@@ -140,6 +144,7 @@ public class ExportVCardActivity extends Activity implements ServiceConnection,
}
final ExportRequest request = new ExportRequest(mDestinationUri);
// The connection object will call finish().
+ mService.setSelExport(selExport);
mService.handleExportRequest(request, new NotificationImportExportListener(
ExportVCardActivity.this));
}
@@ -151,27 +156,15 @@ public class ExportVCardActivity extends Activity implements ServiceConnection,
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
- // Check directory is available.
- if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- Log.w(LOG_TAG, "External storage is in state " + Environment.getExternalStorageState() +
- ". Cancelling export");
- showDialog(R.id.dialog_sdcard_not_found);
- return;
- }
-
- final File targetDirectory = Environment.getExternalStorageDirectory();
- if (!(targetDirectory.exists() &&
- targetDirectory.isDirectory() &&
- targetDirectory.canRead()) &&
- !targetDirectory.mkdirs()) {
- showDialog(R.id.dialog_sdcard_not_found);
- return;
- }
+ checkStorage();
+ }
+ private void runExportContacts() {
final String callingActivity = getIntent().getExtras()
.getString(VCardCommonArguments.ARG_CALLING_ACTIVITY);
Intent intent = new Intent(this, VCardService.class);
intent.putExtra(VCardCommonArguments.ARG_CALLING_ACTIVITY, callingActivity);
+ intent.putExtra(VCardService.STORAGE_PATH, mSelectedStorage);
if (startService(intent) == null) {
Log.e(LOG_TAG, "Failed to start vCard service");
@@ -186,6 +179,73 @@ public class ExportVCardActivity extends Activity implements ServiceConnection,
showDialog(R.id.dialog_fail_to_export_with_reason);
}
// Continued to onServiceConnected()
+ Intent selExportIntent = getIntent();
+ if(selExportIntent != null) {
+ selExport = selExportIntent.getStringExtra("SelExport");
+ }
+ }
+
+ private void checkStorage() {
+ boolean sdExist = MoreContactUtils.sdCardExist(this);
+ boolean inExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
+ if (sdExist && inExist) {
+ CharSequence[] storage_list = new CharSequence[2];
+ storage_list[VCardService.INTERNAL_PATH] = Environment.getExternalStorageDirectory()
+ .getPath();
+ storage_list[VCardService.EXTERNAL_PATH] = MoreContactUtils.getSDPath(this);
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.select_path);
+ builder.setSingleChoiceItems(storage_list, 0, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Log.d(LOG_TAG, "onClicked Dialog on which = " + which);
+ mSelectedStorage = which;
+ }
+ });
+
+ AlertDialog dialog = builder.create();
+ dialog.setButton(DialogInterface.BUTTON_POSITIVE, getString(android.R.string.ok),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ runExportContacts();
+ }
+ });
+ dialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(android.R.string.cancel),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mSelectedStorage = VCardService.INVALID_PATH;
+ }
+ });
+ dialog.show();
+ } else if (inExist) {
+ mSelectedStorage = VCardService.INTERNAL_PATH;
+
+ // Check directory is available.
+ if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
+ Log.w(LOG_TAG, "External storage is in state "
+ + Environment.getExternalStorageState() + ". Cancelling export");
+ showDialog(R.id.dialog_sdcard_not_found);
+ return;
+ }
+
+ final File targetDirectory = Environment.getExternalStorageDirectory();
+ if (!(targetDirectory.exists() &&
+ targetDirectory.isDirectory() &&
+ targetDirectory.canRead()) &&
+ !targetDirectory.mkdirs()) {
+ showDialog(R.id.dialog_sdcard_not_found);
+ return;
+ }
+
+ runExportContacts();
+ } else if (sdExist) {
+ mSelectedStorage = VCardService.EXTERNAL_PATH;
+ runExportContacts();
+ } else {
+ mSelectedStorage = VCardService.INVALID_PATH;
+ }
}
@Override
diff --git a/src/com/android/contacts/common/vcard/ImportVCardActivity.java b/src/com/android/contacts/common/vcard/ImportVCardActivity.java
index 62e8431c..d36dcaf3 100644
--- a/src/com/android/contacts/common/vcard/ImportVCardActivity.java
+++ b/src/com/android/contacts/common/vcard/ImportVCardActivity.java
@@ -45,6 +45,7 @@ import android.text.style.RelativeSizeSpan;
import android.util.Log;
import android.widget.Toast;
+import com.android.contacts.common.MoreContactUtils;
import com.android.contacts.common.R;
import com.android.contacts.common.model.AccountTypeManager;
import com.android.contacts.common.model.account.AccountWithDataSet;
@@ -122,6 +123,7 @@ public class ImportVCardActivity extends Activity {
/* package */ VCardImportExportListener mListener;
private String mErrorMessage;
+ private int mSelectedStorage = VCardService.INTERNAL_PATH;
private Handler mHandler = new Handler();
@@ -882,7 +884,60 @@ public class ImportVCardActivity extends Activity {
importVCard(uri);
} else {
Log.i(LOG_TAG, "Start vCard without Uri. The user will select vCard manually.");
+ checkStorage();
+ }
+ }
+
+ private void checkStorage() {
+ boolean sdExist = MoreContactUtils.sdCardExist(this);
+ boolean inExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
+ if (sdExist && inExist) {
+ CharSequence[] storage_list = new CharSequence[2];
+ storage_list[VCardService.INTERNAL_PATH] = Environment.getExternalStorageDirectory()
+ .getPath();
+ storage_list[VCardService.EXTERNAL_PATH] = MoreContactUtils.getSDPath(this);
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.select_path);
+ builder.setSingleChoiceItems(storage_list, 0, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Log.d(LOG_TAG, "onClicked Dialog on which = " + which);
+ mSelectedStorage = which;
+ }
+ });
+
+ AlertDialog dialog = builder.create();
+ dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ mSelectedStorage = VCardService.INVALID_PATH;
+ finish();
+ }
+ });
+ dialog.setButton(DialogInterface.BUTTON_POSITIVE, getString(android.R.string.ok),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ doScanExternalStorageAndImportVCard();
+ }
+ });
+ dialog.setButton(DialogInterface.BUTTON_NEGATIVE, getString(android.R.string.cancel),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mSelectedStorage = VCardService.INVALID_PATH;
+ finish();
+ }
+ });
+ dialog.show();
+ } else if (inExist) {
+ mSelectedStorage = VCardService.INTERNAL_PATH;
+ doScanExternalStorageAndImportVCard();
+ } else if (sdExist) {
+ mSelectedStorage = VCardService.EXTERNAL_PATH;
doScanExternalStorageAndImportVCard();
+ } else {
+ mSelectedStorage = VCardService.INVALID_PATH;
}
}
@@ -993,7 +1048,26 @@ public class ImportVCardActivity extends Activity {
*/
private void doScanExternalStorageAndImportVCard() {
// TODO: should use getExternalStorageState().
- final File file = Environment.getExternalStorageDirectory();
+ Log.i(LOG_TAG, "Import Vcard from path:" + mSelectedStorage);
+ if (mSelectedStorage == VCardService.INVALID_PATH)
+ return;
+ File file;
+ switch (mSelectedStorage) {
+ case VCardService.INTERNAL_PATH:
+ file = Environment.getExternalStorageDirectory();
+ break;
+ case VCardService.EXTERNAL_PATH:
+ final String sdcardPath = MoreContactUtils.getSDPath(this);
+ if (sdcardPath != null) {
+ file = new File(sdcardPath);
+ } else {
+ file = Environment.getExternalStorageDirectory();
+ }
+ break;
+ default:
+ file = Environment.getExternalStorageDirectory();
+ break;
+ }
if (!file.exists() || !file.isDirectory() || !file.canRead()) {
showDialog(R.id.dialog_sdcard_not_found);
} else {
diff --git a/src/com/android/contacts/common/vcard/NotificationImportExportListener.java b/src/com/android/contacts/common/vcard/NotificationImportExportListener.java
index a85825f1..63420026 100644
--- a/src/com/android/contacts/common/vcard/NotificationImportExportListener.java
+++ b/src/com/android/contacts/common/vcard/NotificationImportExportListener.java
@@ -131,7 +131,7 @@ public class NotificationImportExportListener implements VCardImportExportListen
}
final Notification notification =
NotificationImportExportListener.constructFinishNotification(mContext,
- description, null, intent);
+ VCardService.TYPE_IMPORT, description, null, intent);
mNotificationManager.notify(NotificationImportExportListener.DEFAULT_NOTIFICATION_TAG,
jobId, notification);
}
@@ -261,11 +261,13 @@ public class NotificationImportExportListener implements VCardImportExportListen
* @param intent Intent to be launched when the Notification is clicked. Can be null.
*/
/* package */ static Notification constructFinishNotification(
- Context context, String title, String description, Intent intent) {
+ Context context, int type, String title, String description, Intent intent) {
return new Notification.Builder(context)
.setAutoCancel(true)
+ .setSmallIcon(type == VCardService.TYPE_IMPORT
+ ? android.R.drawable.stat_sys_download_done
+ : android.R.drawable.stat_sys_upload_done)
.setColor(context.getResources().getColor(R.color.dialtacts_theme_color))
- .setSmallIcon(android.R.drawable.stat_sys_download_done)
.setContentTitle(title)
.setContentText(description)
.setContentIntent(PendingIntent.getActivity(context, 0,
diff --git a/src/com/android/contacts/common/vcard/SelectAccountActivity.java b/src/com/android/contacts/common/vcard/SelectAccountActivity.java
index d05810db..5ee36bc6 100644
--- a/src/com/android/contacts/common/vcard/SelectAccountActivity.java
+++ b/src/com/android/contacts/common/vcard/SelectAccountActivity.java
@@ -24,6 +24,7 @@ import android.util.Log;
import com.android.contacts.common.R;
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.util.AccountSelectionUtil;
@@ -52,30 +53,25 @@ public class SelectAccountActivity extends Activity {
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
- // There's three possibilities:
- // - more than one accounts -> ask the user
- // - just one account -> use the account without asking the user
+ // There are two possibilities:
+ // - one or more than one accounts -> ask the user (user can select phone-local also)
// - no account -> use phone-local storage without asking the user
final int resId = R.string.import_from_sdcard;
final AccountTypeManager accountTypes = AccountTypeManager.getInstance(this);
final List<AccountWithDataSet> accountList = accountTypes.getAccounts(true);
if (accountList.size() == 0) {
- Log.w(LOG_TAG, "Account does not exist");
- finish();
- return;
- } else if (accountList.size() == 1) {
- final AccountWithDataSet account = accountList.get(0);
- final Intent intent = new Intent();
- intent.putExtra(ACCOUNT_NAME, account.name);
- intent.putExtra(ACCOUNT_TYPE, account.type);
- intent.putExtra(DATA_SET, account.dataSet);
- setResult(RESULT_OK, intent);
+ Log.w(LOG_TAG, "Select phone-local storage account");
finish();
return;
}
Log.i(LOG_TAG, "The number of available accounts: " + accountList.size());
+ // Add a virtual local storage account to allow user to store its contacts in the phone
+ AccountWithDataSet localAccount = new AccountWithDataSet(
+ getString(R.string.local_storage_account), AccountType.LOCAL_ACCOUNT, null);
+ accountList.add(0, localAccount);
+
// Multiple accounts. Let users to select one.
mAccountSelectionListener =
new AccountSelectionUtil.AccountSelectedListener(
@@ -83,12 +79,15 @@ public class SelectAccountActivity extends Activity {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
- final AccountWithDataSet account = mAccountList.get(which);
- final Intent intent = new Intent();
- intent.putExtra(ACCOUNT_NAME, account.name);
- intent.putExtra(ACCOUNT_TYPE, account.type);
- intent.putExtra(DATA_SET, account.dataSet);
- setResult(RESULT_OK, intent);
+ // Position 0 contains the phone-local account
+ if (which > 0) {
+ final AccountWithDataSet account = mAccountList.get(which);
+ final Intent intent = new Intent();
+ intent.putExtra(ACCOUNT_NAME, account.name);
+ intent.putExtra(ACCOUNT_TYPE, account.type);
+ intent.putExtra(DATA_SET, account.dataSet);
+ setResult(RESULT_OK, intent);
+ }
finish();
}
};
diff --git a/src/com/android/contacts/common/vcard/VCardService.java b/src/com/android/contacts/common/vcard/VCardService.java
index 0a50becc..7b90eddb 100644
--- a/src/com/android/contacts/common/vcard/VCardService.java
+++ b/src/com/android/contacts/common/vcard/VCardService.java
@@ -31,6 +31,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
+import com.android.contacts.common.MoreContactUtils;
import com.android.contacts.common.R;
import java.io.File;
@@ -55,6 +56,10 @@ import java.util.concurrent.RejectedExecutionException;
public class VCardService extends Service {
private final static String LOG_TAG = "VCardService";
+ public final static int INTERNAL_PATH = 0;
+ public final static int EXTERNAL_PATH = 1;
+ public final static int INVALID_PATH = -1;
+ public final static String STORAGE_PATH = "storage";
/* package */ final static boolean DEBUG = false;
/* package */ static final int MSG_IMPORT_REQUEST = 1;
@@ -71,7 +76,8 @@ public class VCardService extends Service {
/* package */ static final int TYPE_EXPORT = 2;
/* package */ static final String CACHE_FILE_PREFIX = "import_tmp_";
-
+ private String selExport = "";
+ private int mStorage = INTERNAL_PATH;
private class CustomMediaScannerConnectionClient implements MediaScannerConnectionClient {
final MediaScannerConnection mConnection;
@@ -150,7 +156,16 @@ public class VCardService extends Service {
}
private void initExporterParams() {
- mTargetDirectory = Environment.getExternalStorageDirectory();
+ if (mStorage == EXTERNAL_PATH) {
+ String targetDirectory = MoreContactUtils.getSDPath(this);
+ if (targetDirectory != null) {
+ mTargetDirectory = new File(targetDirectory);
+ } else {
+ mTargetDirectory = Environment.getExternalStorageDirectory();
+ }
+ } else {
+ mTargetDirectory = Environment.getExternalStorageDirectory();
+ }
mFileNamePrefix = getString(R.string.config_export_file_prefix);
mFileNameSuffix = getString(R.string.config_export_file_suffix);
mFileNameExtension = getString(R.string.config_export_file_extension);
@@ -179,9 +194,11 @@ public class VCardService extends Service {
if (intent != null && intent.getExtras() != null) {
mCallingActivity = intent.getExtras().getString(
VCardCommonArguments.ARG_CALLING_ACTIVITY);
+ mStorage = intent.getExtras().getInt(STORAGE_PATH);
} else {
mCallingActivity = null;
}
+ initExporterParams();
return START_STICKY;
}
@@ -232,7 +249,10 @@ public class VCardService extends Service {
public synchronized void handleExportRequest(ExportRequest request,
VCardImportExportListener listener) {
- if (tryExecute(new ExportProcessor(this, request, mCurrentJobId, mCallingActivity))) {
+ ExportProcessor processor = new ExportProcessor(this, request, mCurrentJobId,
+ mCallingActivity);
+ processor.setSelExport(selExport);
+ if (tryExecute(processor)) {
final String path = request.destUri.getEncodedPath();
if (DEBUG) Log.d(LOG_TAG, "Reserve the path " + path);
if (!mReservedDestination.add(path)) {
@@ -256,6 +276,10 @@ public class VCardService extends Service {
}
}
+ public void setSelExport(String sel) {
+ selExport = sel;
+ }
+
/**
* Tries to call {@link ExecutorService#execute(Runnable)} toward a given processor.
* @return true when successful.
diff --git a/src/com/android/contacts/common/widget/CheckableFlipDrawable.java b/src/com/android/contacts/common/widget/CheckableFlipDrawable.java
new file mode 100644
index 00000000..329b665c
--- /dev/null
+++ b/src/com/android/contacts/common/widget/CheckableFlipDrawable.java
@@ -0,0 +1,300 @@
+package com.android.contacts.common.widget;
+
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.Checkable;
+import android.widget.QuickContactBadge;
+
+import com.android.contacts.common.R;
+
+public class CheckableFlipDrawable extends FlipDrawable implements
+ ValueAnimator.AnimatorUpdateListener {
+
+ private final FrontDrawable mFrontDrawable;
+ private final CheckmarkDrawable mCheckmarkDrawable;
+
+ private final ValueAnimator mCheckmarkScaleAnimator;
+ private final ValueAnimator mCheckmarkAlphaAnimator;
+
+ private static final int POST_FLIP_DURATION_MS = 150;
+
+ private static final float CHECKMARK_SCALE_BEGIN_VALUE = 0.2f;
+ private static final float CHECKMARK_ALPHA_BEGIN_VALUE = 0f;
+
+ /** Must be <= 1f since the animation value is used as a percentage. */
+ private static final float END_VALUE = 1f;
+
+ public CheckableFlipDrawable(Drawable front, final Resources res,
+ final int checkBackgroundColor, final int flipDurationMs) {
+ super(new FrontDrawable(front), new CheckmarkDrawable(res, checkBackgroundColor),
+ flipDurationMs, 0 /* preFlipDurationMs */, POST_FLIP_DURATION_MS);
+
+ mFrontDrawable = (FrontDrawable) mFront;
+ mCheckmarkDrawable = (CheckmarkDrawable) mBack;
+
+ // We will create checkmark animations that are synchronized with the
+ // flipping animation. The entire delay + duration of the checkmark animation
+ // needs to equal the entire duration of the flip animation (where delay is 0).
+
+ // The checkmark animation is in effect only when the back drawable is being shown.
+ // For the flip animation duration <pre>[_][]|[][_]<post>
+ // The checkmark animation will be |--delay--|-duration-|
+
+ // Need delay to skip the first half of the flip duration.
+ final long animationDelay = mPreFlipDurationMs + mFlipDurationMs / 2;
+ // Actual duration is the second half of the flip duration.
+ final long animationDuration = mFlipDurationMs / 2 + mPostFlipDurationMs;
+
+ mCheckmarkScaleAnimator = ValueAnimator.ofFloat(CHECKMARK_SCALE_BEGIN_VALUE, END_VALUE)
+ .setDuration(animationDuration);
+ mCheckmarkScaleAnimator.setStartDelay(animationDelay);
+ mCheckmarkScaleAnimator.addUpdateListener(this);
+
+ mCheckmarkAlphaAnimator = ValueAnimator.ofFloat(CHECKMARK_ALPHA_BEGIN_VALUE, END_VALUE)
+ .setDuration(animationDuration);
+ mCheckmarkAlphaAnimator.setStartDelay(animationDelay);
+ mCheckmarkAlphaAnimator.addUpdateListener(this);
+ }
+
+ public void setFront(Drawable front) {
+ mFrontDrawable.setInnerDrawable(front);
+ invalidateSelf();
+ }
+
+ public void setCheckMarkBackgroundColor(int color) {
+ mCheckmarkDrawable.setBackgroundColor(color);
+ invalidateSelf();
+ }
+
+ @Override
+ public void reset() {
+ super.reset();
+ if (mCheckmarkScaleAnimator == null) {
+ // Call from super's constructor. Not yet initialized.
+ return;
+ }
+ mCheckmarkScaleAnimator.cancel();
+ mCheckmarkAlphaAnimator.cancel();
+ boolean side = getSideFlippingTowards();
+ mCheckmarkDrawable.setScaleAnimatorValue(side ? CHECKMARK_SCALE_BEGIN_VALUE : END_VALUE);
+ mCheckmarkDrawable.setAlphaAnimatorValue(side ? CHECKMARK_ALPHA_BEGIN_VALUE : END_VALUE);
+ }
+
+ @Override
+ public void flip() {
+ super.flip();
+ // Keep the checkmark animators in sync with the flip animator.
+ if (mCheckmarkScaleAnimator.isStarted()) {
+ mCheckmarkScaleAnimator.reverse();
+ mCheckmarkAlphaAnimator.reverse();
+ } else {
+ if (!getSideFlippingTowards() /* front to back */) {
+ mCheckmarkScaleAnimator.start();
+ mCheckmarkAlphaAnimator.start();
+ } else /* back to front */ {
+ mCheckmarkScaleAnimator.reverse();
+ mCheckmarkAlphaAnimator.reverse();
+ }
+ }
+ }
+
+ @Override
+ public void onAnimationUpdate(final ValueAnimator animation) {
+ //noinspection ConstantConditions
+ final float value = (Float) animation.getAnimatedValue();
+
+ if (animation == mCheckmarkScaleAnimator) {
+ mCheckmarkDrawable.setScaleAnimatorValue(value);
+ } else if (animation == mCheckmarkAlphaAnimator) {
+ mCheckmarkDrawable.setAlphaAnimatorValue(value);
+ }
+ }
+
+ private static class FrontDrawable extends Drawable implements Drawable.Callback {
+ private Drawable mDrawable;
+
+ public FrontDrawable(Drawable d) {
+ mDrawable = d;
+ mDrawable.setCallback(this);
+ }
+
+ public void setInnerDrawable(Drawable d) {
+ mDrawable.setCallback(null);
+ mDrawable = d;
+ mDrawable.setCallback(this);
+ assignDrawableBounds(getBounds());
+ invalidateSelf();
+ }
+
+ @Override
+ protected void onBoundsChange(final Rect bounds) {
+ super.onBoundsChange(bounds);
+ assignDrawableBounds(bounds);
+ }
+
+ private void assignDrawableBounds(Rect bounds) {
+ int w = mDrawable.getIntrinsicWidth();
+ int h = mDrawable.getIntrinsicHeight();
+ if (w > 0 && h > 0) {
+ mDrawable.setBounds(0, 0, w, h);
+ } else {
+ mDrawable.setBounds(bounds);
+ }
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ final Rect bounds = getBounds();
+ if (!isVisible() || bounds.isEmpty()) {
+ return;
+ }
+
+ int w = mDrawable.getIntrinsicWidth();
+ int h = mDrawable.getIntrinsicHeight();
+
+ if (w <= 0 || h <= 0) {
+ mDrawable.draw(canvas);
+ } else {
+ final float widthScale = (float) bounds.width() / (float) w;
+ final float heightScale = (float) bounds.height() / (float) h;
+ final float scale = Math.max(widthScale, heightScale);
+
+ canvas.save();
+ canvas.scale(scale, scale);
+ canvas.translate(bounds.left, bounds.top);
+ mDrawable.draw(canvas);
+ canvas.restore();
+ }
+ }
+
+ @Override
+ public void setAlpha(final int alpha) {
+ mDrawable.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(final ColorFilter cf) {
+ mDrawable.setColorFilter(cf);
+ }
+
+ @Override
+ public int getOpacity() {
+ return mDrawable.getOpacity();
+ }
+
+ @Override
+ public void invalidateDrawable(final Drawable who) {
+ invalidateSelf();
+ }
+
+ @Override
+ public void scheduleDrawable(final Drawable who, final Runnable what, final long when) {
+ scheduleSelf(what, when);
+ }
+
+ @Override
+ public void unscheduleDrawable(final Drawable who, final Runnable what) {
+ unscheduleSelf(what);
+ }
+ }
+
+ private static class CheckmarkDrawable extends Drawable {
+ private static Bitmap sCheckMark;
+
+ private final Paint mPaint;
+
+ private float mScaleFraction;
+ private float mAlphaFraction;
+
+ private static final Matrix sMatrix = new Matrix();
+
+ public CheckmarkDrawable(final Resources res, int backgroundColor) {
+ if (sCheckMark == null) {
+ sCheckMark = BitmapFactory.decodeResource(res, R.drawable.ic_check_wht_24dp);
+ }
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setFilterBitmap(true);
+ mPaint.setColor(backgroundColor);
+ }
+
+ public void setBackgroundColor(int color) {
+ mPaint.setColor(color);
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ final Rect bounds = getBounds();
+ if (!isVisible() || bounds.isEmpty()) {
+ return;
+ }
+
+ canvas.drawCircle(bounds.centerX(), bounds.centerY(), bounds.width() / 2, mPaint);
+
+ // Scale the checkmark.
+ sMatrix.reset();
+ sMatrix.setScale(mScaleFraction, mScaleFraction, sCheckMark.getWidth() / 2,
+ sCheckMark.getHeight() / 2);
+ sMatrix.postTranslate(bounds.centerX() - sCheckMark.getWidth() / 2,
+ bounds.centerY() - sCheckMark.getHeight() / 2);
+
+ // Fade the checkmark.
+ final int oldAlpha = mPaint.getAlpha();
+ // Interpolate the alpha.
+ mPaint.setAlpha((int) (oldAlpha * mAlphaFraction));
+ canvas.drawBitmap(sCheckMark, sMatrix, mPaint);
+ // Restore the alpha.
+ mPaint.setAlpha(oldAlpha);
+ }
+
+ @Override
+ public void setAlpha(final int alpha) {
+ mPaint.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(final ColorFilter cf) {
+ mPaint.setColorFilter(cf);
+ }
+
+ @Override
+ public int getOpacity() {
+ // Always a gray background.
+ return PixelFormat.OPAQUE;
+ }
+
+ /**
+ * Set value as a fraction from 0f to 1f.
+ */
+ public void setScaleAnimatorValue(final float value) {
+ final float old = mScaleFraction;
+ mScaleFraction = value;
+ if (old != mScaleFraction) {
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * Set value as a fraction from 0f to 1f.
+ */
+ public void setAlphaAnimatorValue(final float value) {
+ final float old = mAlphaFraction;
+ mAlphaFraction = value;
+ if (old != mAlphaFraction) {
+ invalidateSelf();
+ }
+ }
+ }
+}
diff --git a/src/com/android/contacts/common/widget/CheckableImageView.java b/src/com/android/contacts/common/widget/CheckableImageView.java
new file mode 100644
index 00000000..57bac3e0
--- /dev/null
+++ b/src/com/android/contacts/common/widget/CheckableImageView.java
@@ -0,0 +1,96 @@
+package com.android.contacts.common.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.Checkable;
+import android.widget.ImageView;
+
+import com.android.contacts.common.R;
+
+public class CheckableImageView extends ImageView implements Checkable {
+ private boolean mChecked = false;
+ private int mCheckMarkBackgroundColor;
+ private CheckableFlipDrawable mDrawable;
+
+ public CheckableImageView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ public CheckableImageView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public CheckableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context);
+ }
+
+ public CheckableImageView(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(context);
+ }
+
+ private void init(Context context) {
+ TypedArray a = context.obtainStyledAttributes(android.R.styleable.Theme);
+ setCheckMarkBackgroundColor(a.getColor(android.R.styleable.Theme_colorPrimary,
+ context.getResources().getColor(R.color.people_app_theme_color)));
+ a.recycle();
+ }
+
+ public void setCheckMarkBackgroundColor(int color) {
+ mCheckMarkBackgroundColor = color;
+ if (mDrawable != null) {
+ mDrawable.setCheckMarkBackgroundColor(color);
+ }
+ }
+
+ public void toggle() {
+ setChecked(!mChecked);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mChecked;
+ }
+
+ @Override
+ public void setChecked(boolean checked) {
+ setChecked(checked, true);
+ }
+
+ public void setChecked(boolean checked, boolean animate) {
+ if (mChecked == checked) {
+ return;
+ }
+
+ mChecked = checked;
+ applyCheckState(animate);
+ }
+
+ @Override
+ public void setImageDrawable(Drawable d) {
+ if (d != null) {
+ if (mDrawable == null) {
+ mDrawable = new CheckableFlipDrawable(d, getResources(),
+ mCheckMarkBackgroundColor, 150);
+ applyCheckState(false);
+ } else {
+ mDrawable.setFront(d);
+ }
+ d = mDrawable;
+ }
+ super.setImageDrawable(d);
+ }
+
+ private void applyCheckState(boolean animate) {
+ mDrawable.flipTo(!mChecked);
+ if (!animate) {
+ mDrawable.reset();
+ }
+ }
+}
diff --git a/src/com/android/contacts/common/widget/CheckableQuickContactBadge.java b/src/com/android/contacts/common/widget/CheckableQuickContactBadge.java
new file mode 100644
index 00000000..27b64660
--- /dev/null
+++ b/src/com/android/contacts/common/widget/CheckableQuickContactBadge.java
@@ -0,0 +1,98 @@
+package com.android.contacts.common.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.widget.Checkable;
+import android.widget.QuickContactBadge;
+
+import com.android.contacts.common.R;
+
+public class CheckableQuickContactBadge extends QuickContactBadge implements Checkable {
+ private boolean mChecked = false;
+ private int mCheckMarkBackgroundColor;
+ private CheckableFlipDrawable mDrawable;
+
+ public CheckableQuickContactBadge(Context context) {
+ super(context);
+ init(context);
+ }
+
+ public CheckableQuickContactBadge(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public CheckableQuickContactBadge(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context);
+ }
+
+ public CheckableQuickContactBadge(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(context);
+ }
+
+ private void init(Context context) {
+ TypedArray a = context.obtainStyledAttributes(android.R.styleable.Theme);
+ setCheckMarkBackgroundColor(a.getColor(android.R.styleable.Theme_colorPrimary,
+ context.getResources().getColor(R.color.people_app_theme_color)));
+ a.recycle();
+ }
+
+ public void setCheckMarkBackgroundColor(int color) {
+ mCheckMarkBackgroundColor = color;
+ if (mDrawable != null) {
+ mDrawable.setCheckMarkBackgroundColor(color);
+ }
+ }
+
+ public void toggle() {
+ setChecked(!mChecked);
+ }
+
+ @Override
+ public boolean isChecked() {
+ return mChecked;
+ }
+
+ @Override
+ public void setChecked(boolean checked) {
+ setChecked(checked, true);
+ }
+
+ public void setChecked(boolean checked, boolean animate) {
+ if (mChecked == checked) {
+ return;
+ }
+
+ mChecked = checked;
+ if (mDrawable != null) {
+ applyCheckState(animate);
+ }
+ }
+
+ @Override
+ public void setImageDrawable(Drawable d) {
+ if (d != null) {
+ if (mDrawable == null) {
+ mDrawable = new CheckableFlipDrawable(d, getResources(),
+ mCheckMarkBackgroundColor, 150);
+ applyCheckState(false);
+ } else {
+ mDrawable.setFront(d);
+ }
+ d = mDrawable;
+ }
+ super.setImageDrawable(d);
+ }
+
+ private void applyCheckState(boolean animate) {
+ mDrawable.flipTo(!mChecked);
+ if (!animate) {
+ mDrawable.reset();
+ }
+ }
+}
diff --git a/src/com/android/contacts/common/widget/FlipDrawable.java b/src/com/android/contacts/common/widget/FlipDrawable.java
new file mode 100644
index 00000000..ba62e0fe
--- /dev/null
+++ b/src/com/android/contacts/common/widget/FlipDrawable.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.contacts.common.widget;
+
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+
+/**
+ * A drawable that wraps two other drawables and allows flipping between them. The flipping
+ * animation is a 2D rotation around the y axis.
+ *
+ * <p/>
+ * The 3 durations are: (best viewed in documentation form)
+ * <pre>
+ * &lt;pre&gt;[_][]|[][_]&lt;post&gt;
+ * | | |
+ * V V V
+ * &lt;pre>&lt; flip &gt;&lt;post&gt;
+ * </pre>
+ */
+public class FlipDrawable extends Drawable implements Drawable.Callback {
+
+ /**
+ * The inner drawables.
+ */
+ protected Drawable mFront;
+ protected final Drawable mBack;
+
+ protected final int mFlipDurationMs;
+ protected final int mPreFlipDurationMs;
+ protected final int mPostFlipDurationMs;
+ private final ValueAnimator mFlipAnimator;
+
+ private static final float END_VALUE = 2f;
+
+ /**
+ * From 0f to END_VALUE. Determines the flip progress between mFront and mBack. 0f means
+ * mFront is fully shown, while END_VALUE means mBack is fully shown.
+ */
+ private float mFlipFraction = 0f;
+
+ /**
+ * True if flipping towards front, false if flipping towards back.
+ */
+ private boolean mFlipToSide = true;
+
+ /**
+ * Create a new FlipDrawable. The front is fully shown by default.
+ *
+ * <p/>
+ * The 3 durations are: (best viewed in documentation form)
+ * <pre>
+ * &lt;pre&gt;[_][]|[][_]&lt;post&gt;
+ * | | |
+ * V V V
+ * &lt;pre>&lt; flip &gt;&lt;post&gt;
+ * </pre>
+ *
+ * @param front The front drawable.
+ * @param back The back drawable.
+ * @param flipDurationMs The duration of the actual flip. This duration includes both
+ * animating away one side and showing the other.
+ * @param preFlipDurationMs The duration before the actual flip begins. Subclasses can use this
+ * to add flourish.
+ * @param postFlipDurationMs The duration after the actual flip begins. Subclasses can use this
+ * to add flourish.
+ */
+ public FlipDrawable(final Drawable front, final Drawable back, final int flipDurationMs,
+ final int preFlipDurationMs, final int postFlipDurationMs) {
+ if (front == null || back == null) {
+ throw new IllegalArgumentException("Front and back drawables must not be null.");
+ }
+ mFront = front;
+ mBack = back;
+
+ mFront.setCallback(this);
+ mBack.setCallback(this);
+
+ mFlipDurationMs = flipDurationMs;
+ mPreFlipDurationMs = preFlipDurationMs;
+ mPostFlipDurationMs = postFlipDurationMs;
+
+ mFlipAnimator = ValueAnimator.ofFloat(0f, END_VALUE)
+ .setDuration(mPreFlipDurationMs + mFlipDurationMs + mPostFlipDurationMs);
+ mFlipAnimator.addUpdateListener(new AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(final ValueAnimator animation) {
+ final float old = mFlipFraction;
+ //noinspection ConstantConditions
+ mFlipFraction = (Float) animation.getAnimatedValue();
+ if (old != mFlipFraction) {
+ invalidateSelf();
+ }
+ }
+ });
+
+ reset();
+ }
+
+ @Override
+ protected void onBoundsChange(final Rect bounds) {
+ super.onBoundsChange(bounds);
+ if (bounds.isEmpty()) {
+ mFront.setBounds(0, 0, 0, 0);
+ mBack.setBounds(0, 0, 0, 0);
+ } else {
+ mFront.setBounds(bounds);
+ mBack.setBounds(bounds);
+ }
+ }
+
+ @Override
+ public void draw(final Canvas canvas) {
+ final Rect bounds = getBounds();
+ if (!isVisible() || bounds.isEmpty()) {
+ return;
+ }
+
+ final Drawable inner = getSideShown() /* == front */ ? mFront : mBack;
+
+ final float totalDurationMs = mPreFlipDurationMs + mFlipDurationMs + mPostFlipDurationMs;
+
+ final float scaleX;
+ if (mFlipFraction / 2 <= mPreFlipDurationMs / totalDurationMs) {
+ // During pre-flip.
+ scaleX = 1;
+ } else if (mFlipFraction / 2 >= (totalDurationMs - mPostFlipDurationMs) / totalDurationMs) {
+ // During post-flip.
+ scaleX = 1;
+ } else {
+ // During flip.
+ final float flipFraction = mFlipFraction / 2;
+ final float flipMiddle = (mPreFlipDurationMs / totalDurationMs
+ + (totalDurationMs - mPostFlipDurationMs) / totalDurationMs) / 2;
+ final float distFraction = Math.abs(flipFraction - flipMiddle);
+ final float multiplier = 1 / (flipMiddle - (mPreFlipDurationMs / totalDurationMs));
+ scaleX = distFraction * multiplier;
+ }
+
+ canvas.save();
+ // The flip is a simple 1 dimensional scale.
+ canvas.scale(scaleX, 1, bounds.exactCenterX(), bounds.exactCenterY());
+ inner.draw(canvas);
+ canvas.restore();
+ }
+
+ @Override
+ public void setAlpha(final int alpha) {
+ mFront.setAlpha(alpha);
+ mBack.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(final ColorFilter cf) {
+ mFront.setColorFilter(cf);
+ mBack.setColorFilter(cf);
+ }
+
+ @Override
+ public int getOpacity() {
+ return resolveOpacity(mFront.getOpacity(), mBack.getOpacity());
+ }
+
+ @Override
+ protected boolean onLevelChange(final int level) {
+ return mFront.setLevel(level) || mBack.setLevel(level);
+ }
+
+ @Override
+ public void invalidateDrawable(final Drawable who) {
+ invalidateSelf();
+ }
+
+ @Override
+ public void scheduleDrawable(final Drawable who, final Runnable what, final long when) {
+ scheduleSelf(what, when);
+ }
+
+ @Override
+ public void unscheduleDrawable(final Drawable who, final Runnable what) {
+ unscheduleSelf(what);
+ }
+
+ /**
+ * Stop animating the flip and reset to one side.
+ * @param side Pass true if reset to front, false if reset to back.
+ */
+ public void reset() {
+ final float old = mFlipFraction;
+ mFlipAnimator.cancel();
+ mFlipFraction = mFlipToSide ? 0f : 2f;
+ if (mFlipFraction != old) {
+ invalidateSelf();
+ }
+ }
+
+ /**
+ * Returns true if the front is shown. Returns false if the back is shown.
+ */
+ public boolean getSideShown() {
+ final float totalDurationMs = mPreFlipDurationMs + mFlipDurationMs + mPostFlipDurationMs;
+ final float middleFraction = (mPreFlipDurationMs / totalDurationMs
+ + (totalDurationMs - mPostFlipDurationMs) / totalDurationMs) / 2;
+ return mFlipFraction / 2 < middleFraction;
+ }
+
+ /**
+ * Returns true if the front is being flipped towards. Returns false if the back is being
+ * flipped towards.
+ */
+ public boolean getSideFlippingTowards() {
+ return mFlipToSide;
+ }
+
+ /**
+ * Starts an animated flip to the other side. If a flip animation is currently started,
+ * it will be reversed.
+ */
+ public void flip() {
+ mFlipToSide = !mFlipToSide;
+ if (mFlipAnimator.isStarted()) {
+ mFlipAnimator.reverse();
+ } else {
+ if (!mFlipToSide /* front to back */) {
+ mFlipAnimator.start();
+ } else /* back to front */ {
+ mFlipAnimator.reverse();
+ }
+ }
+ }
+
+ /**
+ * Start an animated flip to a side. This works regardless of whether a flip animation is
+ * currently started.
+ * @param side Pass true if flip to front, false if flip to back.
+ */
+ public void flipTo(final boolean side) {
+ if (mFlipToSide != side) {
+ flip();
+ }
+ }
+
+ /**
+ * Returns whether flipping is in progress.
+ */
+ public boolean isFlipping() {
+ return mFlipAnimator.isStarted();
+ }
+}
diff --git a/src/com/android/contacts/common/widget/FloatingActionButtonController.java b/src/com/android/contacts/common/widget/FloatingActionButtonController.java
index 679eb7b4..15d68594 100644
--- a/src/com/android/contacts/common/widget/FloatingActionButtonController.java
+++ b/src/com/android/contacts/common/widget/FloatingActionButtonController.java
@@ -25,6 +25,7 @@ import android.view.View;
import com.android.contacts.common.util.ViewUtil;
import com.android.contacts.common.R;
import com.android.phone.common.animation.AnimUtils;
+import com.android.phone.common.animation.AnimUtils.AnimationCallback;
/**
* Controls the movement and appearance of the FAB (Floating Action Button).
@@ -142,8 +143,12 @@ public class FloatingActionButtonController {
* @param delayMs The delay for the effect, in milliseconds.
*/
public void scaleIn(int delayMs) {
+ scaleIn(delayMs, null);
+ }
+
+ public void scaleIn(int delayMs, AnimationCallback callback) {
setVisible(true);
- AnimUtils.scaleIn(mFloatingActionButtonContainer, FAB_SCALE_IN_DURATION, delayMs);
+ AnimUtils.scaleIn(mFloatingActionButtonContainer, FAB_SCALE_IN_DURATION, delayMs, callback);
AnimUtils.fadeIn(mFloatingActionButton, FAB_SCALE_IN_DURATION,
delayMs + FAB_SCALE_IN_FADE_IN_DELAY, null);
}
@@ -153,10 +158,14 @@ public class FloatingActionButtonController {
* an animation for hiding the floating action button.
*/
public void scaleOut() {
- AnimUtils.scaleOut(mFloatingActionButtonContainer, mAnimationDuration);
+ scaleOut(null);
+ }
+
+ public void scaleOut(AnimationCallback callback) {
+ AnimUtils.scaleOut(mFloatingActionButtonContainer, mAnimationDuration, callback);
// Fade out the icon faster than the scale out animation, so that the icon scaling is less
// obvious. We don't want it to scale, but the resizing the container is not as performant.
- AnimUtils.fadeOut(mFloatingActionButton, FAB_ICON_FADE_OUT_DURATION, null);
+ AnimUtils.fadeOut(mFloatingActionButton, FAB_ICON_FADE_OUT_DURATION);
}
/**