aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml14
-rw-r--r--res/layout/contact_dump_activity.xml72
-rw-r--r--res/values-af/strings.xml7
-rw-r--r--res/values-am/strings.xml7
-rw-r--r--res/values-ar/strings.xml7
-rw-r--r--res/values-be/strings.xml7
-rw-r--r--res/values-bg/strings.xml7
-rw-r--r--res/values-ca/strings.xml7
-rw-r--r--res/values-cs/strings.xml7
-rw-r--r--res/values-da/strings.xml7
-rw-r--r--res/values-de/strings.xml7
-rw-r--r--res/values-el/strings.xml7
-rw-r--r--res/values-en-rGB/strings.xml7
-rw-r--r--res/values-es-rUS/strings.xml7
-rw-r--r--res/values-es/strings.xml7
-rw-r--r--res/values-et/strings.xml7
-rw-r--r--res/values-fa/strings.xml7
-rw-r--r--res/values-fi/strings.xml7
-rw-r--r--res/values-fr/strings.xml7
-rw-r--r--res/values-hi/strings.xml7
-rw-r--r--res/values-hr/strings.xml7
-rw-r--r--res/values-hu/strings.xml7
-rw-r--r--res/values-in/strings.xml19
-rw-r--r--res/values-it/strings.xml7
-rw-r--r--res/values-iw/strings.xml7
-rw-r--r--res/values-ja/strings.xml7
-rw-r--r--res/values-ko/strings.xml7
-rw-r--r--res/values-lt/strings.xml7
-rw-r--r--res/values-lv/strings.xml7
-rw-r--r--res/values-ms/strings.xml7
-rw-r--r--res/values-nb/strings.xml7
-rw-r--r--res/values-nl/strings.xml7
-rw-r--r--res/values-pl/strings.xml7
-rw-r--r--res/values-pt-rPT/strings.xml7
-rw-r--r--res/values-pt/strings.xml7
-rw-r--r--res/values-rm/strings.xml14
-rw-r--r--res/values-ro/strings.xml7
-rw-r--r--res/values-ru/strings.xml7
-rw-r--r--res/values-sk/strings.xml7
-rw-r--r--res/values-sl/strings.xml7
-rw-r--r--res/values-sr/strings.xml7
-rw-r--r--res/values-sv/strings.xml7
-rw-r--r--res/values-sw/strings.xml7
-rw-r--r--res/values-th/strings.xml7
-rw-r--r--res/values-tl/strings.xml7
-rw-r--r--res/values-tr/strings.xml7
-rw-r--r--res/values-uk/strings.xml7
-rw-r--r--res/values-vi/strings.xml7
-rw-r--r--res/values-zh-rCN/strings.xml9
-rw-r--r--res/values-zh-rTW/strings.xml7
-rw-r--r--res/values-zu/strings.xml7
-rw-r--r--res/values/strings.xml22
-rw-r--r--src/com/android/providers/contacts/AbstractContactsProvider.java43
-rw-r--r--src/com/android/providers/contacts/AccountWithDataSet.java4
-rw-r--r--src/com/android/providers/contacts/CallLogProvider.java8
-rw-r--r--src/com/android/providers/contacts/ContactDirectoryManager.java14
-rw-r--r--src/com/android/providers/contacts/ContactLocaleUtils.java4
-rw-r--r--src/com/android/providers/contacts/ContactsDatabaseHelper.java14
-rw-r--r--src/com/android/providers/contacts/ContactsProvider2.java518
-rw-r--r--src/com/android/providers/contacts/ContactsTransaction.java44
-rw-r--r--src/com/android/providers/contacts/DataRowHandler.java12
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForCommonDataKind.java4
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForCustomMimetype.java4
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForEmail.java6
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java18
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForIdentity.java4
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForIm.java6
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForNickname.java6
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForNote.java6
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForOrganization.java8
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java10
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForPhoto.java4
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForStructuredName.java6
-rw-r--r--src/com/android/providers/contacts/DataRowHandlerForStructuredPostal.java6
-rw-r--r--src/com/android/providers/contacts/DbModifierWithNotification.java10
-rw-r--r--src/com/android/providers/contacts/DefaultCallLogInsertionHelper.java9
-rw-r--r--src/com/android/providers/contacts/FastScrollingIndexCache.java7
-rw-r--r--src/com/android/providers/contacts/LegacyApiSupport.java26
-rw-r--r--src/com/android/providers/contacts/NameLookupBuilder.java4
-rw-r--r--src/com/android/providers/contacts/NameNormalizer.java4
-rw-r--r--src/com/android/providers/contacts/NameSplitter.java6
-rw-r--r--src/com/android/providers/contacts/PhotoPriorityResolver.java14
-rw-r--r--src/com/android/providers/contacts/PhotoProcessor.java79
-rw-r--r--src/com/android/providers/contacts/PhotoStore.java9
-rw-r--r--src/com/android/providers/contacts/ProfileAwareUriMatcher.java6
-rw-r--r--src/com/android/providers/contacts/ProfileDatabaseHelper.java4
-rw-r--r--src/com/android/providers/contacts/ProfileProvider.java19
-rw-r--r--src/com/android/providers/contacts/SearchIndexManager.java16
-rw-r--r--src/com/android/providers/contacts/VoicemailCleanupService.java4
-rw-r--r--src/com/android/providers/contacts/VoicemailContentProvider.java10
-rw-r--r--src/com/android/providers/contacts/VoicemailContentTable.java8
-rw-r--r--src/com/android/providers/contacts/VoicemailStatusTable.java6
-rw-r--r--src/com/android/providers/contacts/VoicemailTable.java4
-rw-r--r--src/com/android/providers/contacts/aggregation/ContactAggregator.java46
-rw-r--r--src/com/android/providers/contacts/aggregation/ProfileAggregator.java2
-rw-r--r--src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java6
-rw-r--r--src/com/android/providers/contacts/debug/ContactsDumpActivity.java142
-rw-r--r--src/com/android/providers/contacts/debug/DataExporter.java102
-rw-r--r--tests/res/drawable-nodpi/transparent_10x10.pngbin0 -> 179 bytes
-rw-r--r--tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java10
-rw-r--r--tests/src/com/android/providers/contacts/CallerInfoIntegrationTest.java4
-rw-r--r--tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java6
-rw-r--r--tests/src/com/android/providers/contacts/ContactLookupKeyTest.java4
-rw-r--r--tests/src/com/android/providers/contacts/ContactsActor.java6
-rw-r--r--tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java4
-rw-r--r--tests/src/com/android/providers/contacts/ContactsMockPackageManager.java4
-rw-r--r--tests/src/com/android/providers/contacts/ContactsMockResources.java4
-rw-r--r--tests/src/com/android/providers/contacts/ContactsProvider2Test.java24
-rw-r--r--tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java309
-rw-r--r--tests/src/com/android/providers/contacts/DirectoryTest.java2
-rw-r--r--tests/src/com/android/providers/contacts/EvenMoreAsserts.java8
-rw-r--r--tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java4
-rw-r--r--tests/src/com/android/providers/contacts/GlobalSearchSupportTest.java14
-rw-r--r--tests/src/com/android/providers/contacts/GroupsTest.java5
-rw-r--r--tests/src/com/android/providers/contacts/HanziToPinyinTest.java8
-rw-r--r--tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java2
-rw-r--r--tests/src/com/android/providers/contacts/NameLookupBuilderTest.java4
-rw-r--r--tests/src/com/android/providers/contacts/NameSplitterTest.java6
-rw-r--r--tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java4
-rw-r--r--tests/src/com/android/providers/contacts/PhotoProcessorTest.java51
-rw-r--r--tests/src/com/android/providers/contacts/PhotoStoreTest.java12
-rw-r--r--tests/src/com/android/providers/contacts/PostalSplitterForJapaneseTest.java6
-rw-r--r--tests/src/com/android/providers/contacts/PostalSplitterTest.java6
-rw-r--r--tests/src/com/android/providers/contacts/SqlInjectionDetectionTest.java2
-rw-r--r--tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java86
-rw-r--r--tests/src/com/android/providers/contacts/SynchronousProfileProvider.java1
-rw-r--r--tests/src/com/android/providers/contacts/TestUtils.java4
-rw-r--r--tests/src/com/android/providers/contacts/VCardTest.java6
-rw-r--r--tests/src/com/android/providers/contacts/VoicemailProviderTest.java4
-rw-r--r--tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java15
-rw-r--r--tests/src/com/android/providers/contacts/aggregation/util/ContactMatcherTest.java2
-rw-r--r--tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java5
-rw-r--r--tests/src/com/android/providers/contacts/util/DBQueryUtilsTest.java6
-rw-r--r--tests/src/com/android/providers/contacts/util/MockSharedPreferences.java4
-rw-r--r--tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java3
135 files changed, 1840 insertions, 569 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6f743686..4370a420 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -33,6 +33,7 @@
android:authorities="contacts;com.android.contacts"
android:label="@string/provider_label"
android:multiprocess="false"
+ android:exported="true"
android:readPermission="android.permission.READ_CONTACTS"
android:writePermission="android.permission.WRITE_CONTACTS">
<path-permission
@@ -50,6 +51,7 @@
<provider android:name="CallLogProvider"
android:authorities="call_log"
android:syncable="false" android:multiprocess="false"
+ android:exported="true"
android:readPermission="android.permission.READ_CALL_LOG"
android:writePermission="android.permission.WRITE_CALL_LOG">
</provider>
@@ -57,6 +59,7 @@
<provider android:name="VoicemailContentProvider"
android:authorities="com.android.voicemail"
android:syncable="false" android:multiprocess="false"
+ android:exported="true"
android:permission="com.android.voicemail.permission.ADD_VOICEMAIL">
</provider>
@@ -96,5 +99,16 @@
</receiver>
<service android:name="VoicemailCleanupService"/>
+
+ <activity android:name=".debug.ContactsDumpActivity"
+ android:label="@string/debug_dump_title"
+ android:theme="@android:style/Theme.Holo.Dialog"
+ >
+ <intent-filter>
+ <action android:name="com.android.providers.contacts.DUMP_DATABASE"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+
</application>
</manifest>
diff --git a/res/layout/contact_dump_activity.xml b/res/layout/contact_dump_activity.xml
new file mode 100644
index 00000000..557b5bdb
--- /dev/null
+++ b/res/layout/contact_dump_activity.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="4dp"
+ android:gravity="center_horizontal">
+
+ <!-- Message to show to use. -->
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:gravity="center_vertical|left"
+ android:layout_weight="1">
+ <TextView
+ android:id="@+id/text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="16dp"
+ android:text="@string/debug_dump_database_message"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+ </ScrollView>
+
+ <!-- Alert dialog style buttons along the bottom. -->
+ <LinearLayout
+ style="?android:attr/buttonBarStyle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:measureWithLargestChild="true">
+ <Button
+ style="?android:attr/buttonBarButtonStyle"
+ android:id="@+id/confirm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:onClick="onClick"
+ android:text="@string/debug_dump_start_button" />
+ <Button
+ style="?android:attr/buttonBarButtonStyle"
+ android:id="@+id/delete"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:onClick="onClick"
+ android:text="@string/debug_dump_delete_button"
+ android:enabled="false" />
+ <Button
+ style="?android:attr/buttonBarButtonStyle"
+ android:id="@+id/cancel"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:onClick="onClick"
+ android:text="@android:string/no" />
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 2f6562be..cb922eec 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Kry toegang tot alle stemboodskappe"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Laat die program toe om alle stemboodskappe te stoor en op te haal wat hierdie toestel kan lees."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Stemboodskap van "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopieer kontaktedatabasis"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Jy is op die punt om 1) jou databasis, wat alle kontakverwante inligting en alle oproeprekords insluit, na die SD-kaart/USB-berging te kopieer, wat deur enige program gelees kan word, en 2) dit te e-pos. Onthou om die kopie uit te vee sodra jy dit suksesvol van die toestel af gekopieer het of wanneer die e-pos ontvang is."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Vee nou uit"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Begin"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Kies \'n program om jou lêer te stuur"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Kontaktedatabasis aangeheg"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"My kontaktedatabasis met al my kontakinligting is aangeheg. Hanteer versigtig."</string>
</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 6aa55ec1..a74fb98c 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"ሁሉንም የድምፅ መልዕክቶች ድረስ"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"ትግበራ ይህ መሣሪያ መድረስ የሚችለውን የድምፅ መልዕክቶች በሙሉ ለማከማቸት እና ሰርስሮ ለማውጣት ይፈቅዳል።"</string>
<string name="voicemail_from_column" msgid="435732568832121444">"ከ....የድምፅ መልዕክት "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"የእውቂያዎች የውሂብ ጎታ ገልብጥ"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"የሚከተሉት ሊያደርጉ ነው 1) ሁሉንም ከእውቂያዎችዎ ጋር የተገናኙ መረጃዎች እና ሁሉንም የጥሪ ምዝግብ ማስታወሻ ያካተተው የውሂብ ጎታዎ ቅጂ ወደ SD ካርድ/USB ማከማቻ ሊያስቀምጡ ነው፣ ይህም በማንኛውም መተግበሪያ የሚነበብ ነው፣ እና 2) በኢሜይል ሊልኩ ነው። በተሳካ ሁኔታው ከመሣሪያው ገልብጠው ካወጡት በኋላ ወይም ኢሜይሉ ከደረሰ በኋላ ወዲያውንኑ ቅጂውን መሰረዝ እንዳለብዎት ያስታውሱ።"</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"አሁን ሰርዝ"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"ጀምር"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"ፋይልዎትን የሚልኩበት ፕሮግራም ይምረጡ"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"የእውቂያዎች የውሂብ ጎታ ተያይዟል"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"የእውቂያዎቼ የውሂብ ጎታ ከሁሉም የእውቂያዎቼ መረጃዎች ጋር አባሪ ተደርጓል። በደንብ ይጠበቅ።"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 3cd298d1..6ce18d8e 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"الوصول إلى جميع رسائل البريد الصوتي"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"للسماح للتطبيق بتخزين واسترداد جميع رسائل البريد الصوتي التي يمكن الوصول إليها عبر هذا الجهاز."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"بريد صوتي من "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"نسخ قاعدة بيانات جهات الاتصال"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"أنت على وشك إجراء ما يلي: 1) الاحتفاظ بنسخة من قاعدة البيانات والتي تتضمن جميع البيانات ذات الصلة بجهات الاتصال وجميع سجلات المكالمات على بطاقة SD/وحدة تخزين USB 2) إرسال هذه النسخة عبر البريد الإلكتروني. لا تنس حذف النسخة من الجهاز بعد نجاح نسخها مباشرة أو عندما يتم استلام البريد الإلكتروني."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"الحذف الآن"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"البداية"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"اختر أحد البرامج لإرسال الملف"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"قاعدة بيانات جهات الاتصال مرفقة"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"قاعدة بيانات جهات اتصالي والتي تحتوي على جميع المعلومات ذات الصلة بجهات الاتصال مرفقة. يرجى التعامل معها بحرص."</string>
</resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 44357c3a..c45145c1 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Доступ да ўсіх галасавых паведамленняў"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Дазваляе прыкладанню захоўваць і прайграваць усе даступныя для гэтай прылады паведамленні галасавой пошты."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Галасавое паведамленне ад "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Капiраваць базу дадзеных кантактаў"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Вы збiраецеся: 1) зрабiць копiю базы дадзеных з усiмi звесткамi пра кантакты i гiсторыю выклiкаў на SD-карту/USB-назапашвальнiк, якiя чытаюцца кожным прыкладаннем; i 2) адправiць электронны лiст. Не забудзьцеся выдалiць гэту копiю, калi вы паспяхова скапiравалi яе з прылады або атрымалi электронны лiст."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Выдаліць зараз"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Пачаць"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Выберыце праграму для адпраўкі файла"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Далучаны кантакты Dd"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Далучана база дадзеных маiх кантактаў з усёй інфармацыяй. Працуйце з ёй уважліва."</string>
</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index dee34a7a..1bb9c858 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Достъп до всички гласови съобщения"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Разрешава на приложението да съхранява и извлича всички гласови съобщения, до които това устройство има достъп."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Гласова поща от "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Копиране на базата от данни на контактите"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"На път сте 1) да направите копие в SD картата/USB хранилището на базата си от данни, коeто включва цялата свързана с контактите информация и всички списъци с обаждания, като освен това може да се чете от всяко приложение, и 2) да го изпратите по имейл. Не забравяйте да го изтриете веднага след като го копирате успешно от устройството или когато имейлът е получен."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Изтриване сега"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Начало"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Изберете програма, за да изпратите файла си"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Прикачена база от данни на контактите"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Прикачена Ви изпращам базата от данни на контактите си заедно с цялата информация за тях. Бъдете внимателни."</string>
</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index ef073fae..51bda70c 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Accés a tots els missatges de veu"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Permet que l\'aplicació emmagatzemi i recuperi totes les bústies de veu a les quals pot accedir aquest dispositiu."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Missatge de veu de "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Copia la base de dades de contactes"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Estàs a punt de 1) fer una còpia de la teva base de dades, que inclou tota la informació relacionada amb els teus contactes i tots els registres de trucades, a la targeta SD/emmagatzematge USB, que podrà llegir qualsevol aplicació i 2) d\'enviar-la per correu electrònic. Recorda que has de suprimir la còpia tan aviat com l\'hagis transferit fora del dispositiu o tan bon punt rebis el correu electrònic."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Suprimeix ara"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Inicia"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Selecciona un programa per enviar el fitxer"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Base de dades de contactes adjunta"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Aquí adjunta hi ha la meva base de dades de contactes amb tota la informació dels meus contactes. Tracta-la amb cura."</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 76335a09..ba8b3c01 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Přístup ke všem hlasovým zprávám"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Umožňuje aplikaci ukládat a načítat všechny hlasové zprávy, ke kterým má toto zařízení přístup."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Hlasová zpráva od uživatele "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopírování databáze kontaktů"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Chystáte se 1) vytvořit na kartě SD nebo úložišti USB, které je čitelné v každé aplikaci, kopii své databáze, která obsahuje všechny informace o kontaktech a protokol volání a 2) odeslat ji e-mailem. Jakmile tuto kopii zkopírujete pryč z úložiště nebo obdržíte odeslaný e-mail, nezapomeňte ji smazat."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Smazat nyní"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Spustit"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Vyberte program pro odeslání souboru."</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Databáze kontaktů v příloze"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"V příloze je databáze s informacemi o všech mých kontaktech. Zacházejte s ní opatrně."</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 7b708fb8..e959c754 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Adgang til alle telefonsvarerbeskeder"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Tillader, at applikationen gemmer og henter alle telefonsvarerbeskeder, som denne enhed kan få adgang til."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Telefonsvarerbesked fra "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopiér database med kontaktpersoner"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Du er ved at 1) lave en kopi af din database, som indeholder alle oplysninger om dine kontaktpersoner og alle opkaldslister, til SD-kortet/USB-lager, som kan læses af alle apps, og 2) sende den som e-mail. Husk at slette kopien, så snart du har kopieret den fra enheden, eller e-mailen er modtaget."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Slet nu"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Start"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Vælg et program, for at sende din fil"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Database med kontaktpersoner er vedhæftet"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Min database med kontaktpersoner med alle oplysninger om mine kontaktpersoner er vedhæftet. Brug den med omhu."</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 1f10b19b..5a2ddcad 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Zugriff auf alle Mailbox-Nachrichten"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Ermöglicht der App das Speichern und Abrufen aller Mailbox-Nachrichten, auf die dieses Gerät zugreifen kann"</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Mailbox-Nachricht von "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kontaktdatenbank kopieren"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Sie sind im Begriff, 1) eine Kopie Ihrer Datenbank mit allen Informationen zu Ihren Kontakten und dem gesamten Anrufprotokoll auf der SD-Karte/im USB-Speicher zu erstellen, die von jeder App gelesen werden kann, und 2) diese per E-Mail zu versenden. Löschen Sie die Kopie, sobald Sie sie vom Gerät kopiert haben bzw. die E-Mail eingegangen ist."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Jetzt löschen"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Starten"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Programm zum Senden der Datei auswählen"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Kontaktdatenbank angehängt"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Anbei meine Kontaktdatenbank mit allen Informationen zu meinen Kontakten. Bitte vertraulich behandeln!"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 2622515d..4c21580e 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Πρόσβαση σε όλα τα μηνύματα αυτόματου τηλεφωνητή"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Επιτρέπει στην εφαρμογή την αποθήκευση και ανάκτηση όλων των μηνυμάτων αυτόματου τηλεφωνητή, στα οποία μπορεί να έχει πρόσβαση αυτή η συσκευή."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Μήνυμα αυτόματου τηλεφωνητή από "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Αντιγραφή βάσης δεδομένων επαφών"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Πρόκειται να κάνετε τα εξής: 1) Να δημιουργήσετε ένα αντίγραφο της βάσης δεδομένων σας, η οποία περιέχει όλες τις πληροφορίες που σχετίζονται με τις επαφές και όλα τα αρχεία καταγραφής κλήσεων στην κάρτα SD/ στο χώρο αποθήκευσης USB με δυνατότητα ανάγνωσης από οποιαδήποτε εφαρμογή. 2) Να το αποστείλετε μέσω ηλεκτρονικού ταχυδρομείου. Μην ξεχάσετε να διαγράψετε το αντίγραφο μετά την επιτυχή αντιγραφή του εκτός της συσκευής ή μετά τη λήψη του μηνύματος ηλεκτρονικού ταχυδρομείου."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Διαγραφή τώρα"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Έναρξη"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Επιλέξτε ένα πρόγραμμα για να στείλετε το αρχείο σας"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Συνημμένη βάση δεδομένων επαφών"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Επισυνάπτεται η βάση δεδομένων των επαφών μου με όλες τις πληροφορίες των επαφών μου. Ο χειρισμός της πρέπει να είναι προσεκτικός."</string>
</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 9cbc783f..8f734b6b 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Access all voicemails"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Allows the app to store and retrieve all voicemails that this device can access."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Voicemail from "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Copy contacts database"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"You are about to 1) make a copy of your database which includes all contacts related information and all call log to the SD card/USB storage, which is readable by any app, and 2) email it. Remember to delete the copy as soon as you have successfully copied it off the device or the email is received."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Delete now"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Start"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Choose a programme to send your file"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Contacts Db attached"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Attached is my contacts database with all my contacts information. Handle with care."</string>
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index a3cddf24..9d242e15 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Acceder a todos los mensajes de voz"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Permite que la aplicación almacene y recupere todos los mensajes de voz a los que este dispositivo puede acceder."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Mensaje de voz de "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Copiar base de datos de contactos"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Estás a punto de 1) realizar una copia de tu base de datos, que incluye toda la información relacionada con tus contactos y el registro de todas tus llamadas, en el almacenamiento USB o en la tarjeta SD (cualquier aplicación podrá acceder a ella); y 2) enviarla por correo. Recuerda eliminar la copia inmediatamente después de que la hayas copiado en otro dispositivo o se haya recibido el correo."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Eliminar ahora"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Comenzar"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Elige un programa para enviar el archivo."</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Base de datos de contactos adjunta"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Adjunto a este correo la base de datos de mis contactos con toda la información relacionada ellos. Esta información se debe manejar con cuidado."</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index d4f7edf6..d87b6e78 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Acceder a todos los mensajes de voz"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Permite que la aplicación almacene y recupere todos los mensajes de voz a los que puede acceder este dispositivo."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Mensaje de voz de "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Copiar base de datos de contactos"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Vas a 1) hacer una copia de tu base de datos, que incluye la información relacionada con tus contactos y el registro de llamadas, en el almacenamiento USB o en la tarjeta SD y cualquier aplicación tendrá acceso a ella y a 2) enviarla por correo electrónico. No olvides eliminar la copia en cuanto la hayas copiado en otro dispositivo o hayas recibido el correo electrónico."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Eliminar ahora"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Iniciar"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Seleccionar un programa para enviar el archivo"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Base de datos de contactos adjunta"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Mi base de datos de contactos con toda la información de mis contactos va adjunta a este mensaje. Usa esta información con cuidado."</string>
</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 6fda0d5f..c597f4fb 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Juurdepääs kõigile kõnepostisõnumitele"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Võimaldab rakendusel salvestada ja vastu võtta kõik kõnepostisõnumid, mille juurde seade pääseb."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Kõnepost kontaktilt "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kontaktide andmebaasi kopeerimine"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Soovite 1) teha koopiat andmebaasist, mis sisaldab kogu kontaktidega seotud teavet ja kõnelogi, ning salvestada selle SD-kaardile/USB-salvestusvahendile, mida saab lugeda iga rakendusega ning 2) soovite selle meilida. Ärge unustage kustutada koopiat niipea, kui olete selle seadmest kopeerinud või kui meil on vastu võetud."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Kustuta kohe"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Alusta"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Valige programm faili saatmiseks"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Lisatud kontaktide andmebaas"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Lisatud on minu kontaktide andmebaas, mis sisaldab kogu kontaktidega seotud teavet. Käsitsege ettevaatlikult."</string>
</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index bcdf7107..e5812e89 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"دسترسی به تمام پست‌های صوتی"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"به برنامه اجازه ذخیره و بازیابی تمام پست‌های صوتی قابل دسترس برای این دستگاه را می‌دهد."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"پست صوتی از "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"کپی پایگاه داده مخاطبین"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"شما در حال ١) ایجاد یک نسخه از پایگاه داده خود هستید که شامل تمام اطلاعات مربوط به مخاطبین و تمام گزارش‌های تماس در کارت SD/دستگاه ذخیره‌سازی USB است و توسط هر برنامه‌ای قابل خواندن است، و ٢) ایمیل کردن آن. فراموش نکنید که بلافاصله پس از کپی کردن آن از دستگاه یا دریافت ایمیل، این نسخه را حذف کنید."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"اکنون حذف شود"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"شروع"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"یک برنامه را برای ارسال فایل خود انتخاب کنید"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"پایگاه داده مخاطبین پیوست شد"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"پایگاه داده مخاطبین من همراه با تمام اطلاعات مخاطبین پیوست شده است. با دقت از آن استفاده شود."</string>
</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index d9c341f1..7da7a992 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Kaikkien vastaajaviestien käyttäminen"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Antaa sovelluksen tallentaa ja hakea kaikki vastaajaviestit, jotka ovat laitteen käytettävissä."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Vastaajaviesti henkilöltä "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopioi kontaktitietokanta"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Olet aikeissa 1) tehdä kopion tietokannasta, joka sisältää kaikki kontakteihin liittyvät tiedot sekä kaikkien sovelluksien luettavissa olevat puhelulokit SD-kortilta tai USB-tallennustilasta, ja 2) lähettää sen sähköpostitse. Muista poistaa kopio kopioituasi sen laitteelta tai kun sähköposti on vastaanotettu."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Poista nyt"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Aloita"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Valitse ohjelma tiedoston lähettämiseen"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Kontaktitietokanta liitteenä"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Liitteenä on kontaktitietokantani, joka sisältää kaikki kontaktitietoni. Käsiteltävä varoen."</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index b25b7634..2b4e3720 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Accéder à tous les messages vocaux"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Permet à l\'application de stocker et de récupérer tous les messages vocaux auxquels cet appareil peut accéder."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Message vocal de "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Copier la base de données de contacts"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Vous êtes sur le point de 1) faire une copie de votre base de données (qui inclut toutes les données relatives aux contacts et l\'intégralité du journal d\'appels) sur une carte SD ou dans une mémoire de stockage USB, lisible par n\'importe quelle application, puis de 2) l\'envoyer par e-mail. N\'oubliez pas de supprimer la copie une fois qu\'elle a été dupliquée ou dès lors que l\'e-mail a été reçu."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Supprimer"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Commencer"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Sélectionnez un programme pour envoyer votre fichier"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Base de données de contacts ci-jointe"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Veuillez trouver ci-joint ma base de données de contacts incluant toutes les coordonnées de mes contacts. Merci de la traiter avec précaution."</string>
</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index f2d706a1..132e3cbe 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"सभी ध्‍वनि‍मेल पर पहुंचें"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"एप्‍लि‍केशन को ऐसे सभी ध्‍वनि‍मेल संग्रहीत और पुनर्प्राप्त करने देता है जि‍न पर यह उपकरण पहुंच सकता है."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"इनका ध्‍वनि‍मेल: "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"संपर्क डेटाबेस की प्रतिलिपि बनाएं"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"आप 1) अपने डेटाबेस की एक प्रति बनाने वाले हैं, जिसमें समस्त संपर्क संबंधित जानकारी और किसी भी एप्लिकेशन द्वारा पढ़े जाने योग्य SD कार्ड/USB संग्रहण के सभी कॉल लॉग शामिल होते हैं, और 2) उसे ईमेल करने वाले हैं. जब आप उपकरण से उसकी प्रतिलिपि सफलतापूर्वक बना लें या ईमेल प्राप्त हो जाने पर, जितनी जल्दी हो सके प्रतिलिपि हटाना न भूलें."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"अभी हटाएं"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"प्रारंभ करें"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"अपनी फ़ाइल भेजने के लिए कोई प्रोग्राम चुनें"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"संपर्क Db अनुलग्न है"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"मेरी समस्त संपर्क जानकारी के साथ मेरा संपर्क डेटाबेस अनुलग्न है. सावधानी से कार्य करें."</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 2b53781f..d9b68326 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Pristup svoj govornoj pošti"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Aplikaciji omogućuje pohranjivanje i dohvaćanje svih poruka govorne pošte kojoj ovaj uređaj može pristupati."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Govorna pošta od "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopiranje podatkovne baze kontakata"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Upravo ćete 1) izraditi kopiju svoje podatkovne baze koja uključuje sve informacije koje se odnose na kontakte i sve dnevnike poziva na SD kartici/USB pohrani, koju može čitati svaka aplikacija i 2) poslat ćete to e-poštom. Nemojte zaboraviti izbrisati kopiju s uređaja odmah nakon uspješnog kopiranja ili uspješnog primitka e-poruke."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Izbriši sada"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Kreni"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Odaberite program za slanje datoteke"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"U prilogu je podatkovna baza"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"U prilogu je moja podatkovna baza kontakata sa svim mojim kontaktnim informacijama. Oprezno rukujte s njom."</string>
</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 7f477e55..a2d71281 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Hozzáférés az összes hangüzenethez"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Lehetővé teszi, hogy az alkalmazás tárolja és lekérje azokat a hangüzeneteket, amelyekhez ez a készülék hozzáférhet."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Hangüzenet tőle: "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Névjegyadatbázis másolása"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Ön arra készül, hogy 1) másolatot készítsen az SD-kártyára/USB-tárhelyre az adatbázisról, amely magában foglalja az összes névjegyet és minden kapcsolódó információt, valamint a hívásnaplót, és bármely alkalmazás által olvasható, valamint 2) e-mailben elküldje azt. Ne feledje azonnal törölni a másolatot, amint sikeresen átmásolta a készülékről, vagy amint megkapta az e-mailt."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Törlés most"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Indítás"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Válasszon programot a fájl elküldéséhez."</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Névjegyadatbázis csatolva."</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Csatolva a névjegyadatbázisom, amely a névjegyeim összes adatát tartalmazza. Óvatosan kezeld."</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index f958b124..0e385dc4 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -17,15 +17,22 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="sharedUserLabel" msgid="8024311725474286801">"Apl Inti Android"</string>
- <string name="app_label" msgid="3389954322874982620">"Penyimpanan Kenalan"</string>
- <string name="provider_label" msgid="6012150850819899907">"Kenalan"</string>
- <string name="upgrade_msg" msgid="8640807392794309950">"Meningkatkan versi basis data kenalan."</string>
- <string name="upgrade_out_of_memory_notification_ticker" msgid="7638747231223520477">"Peningkatan versi kenalan memerlukan lebih banyak memori."</string>
- <string name="upgrade_out_of_memory_notification_title" msgid="8888171924684998531">"Meningkatkan versi penyimpanan untuk kenalan"</string>
+ <string name="app_label" msgid="3389954322874982620">"Penyimpanan Kontak"</string>
+ <string name="provider_label" msgid="6012150850819899907">"Kontak"</string>
+ <string name="upgrade_msg" msgid="8640807392794309950">"Meningkatkan versi basis kontak."</string>
+ <string name="upgrade_out_of_memory_notification_ticker" msgid="7638747231223520477">"Peningkatan versi kontak memerlukan lebih banyak memori."</string>
+ <string name="upgrade_out_of_memory_notification_title" msgid="8888171924684998531">"Meningkatkan versi penyimpanan untuk kontak"</string>
<string name="upgrade_out_of_memory_notification_text" msgid="8438179450336437626">"Sentuh untuk menyelesaikan peningkatan versi."</string>
- <string name="default_directory" msgid="93961630309570294">"Kenalan"</string>
+ <string name="default_directory" msgid="93961630309570294">"Kontak"</string>
<string name="local_invisible_directory" msgid="705244318477396120">"Lainnya"</string>
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Akses semua pesan suara"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Mengizinkan apl menyimpan dan mengambil semua pesan suara yang dapat diakses oleh perangkat ini."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Kotak pesan dari "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Salin basis data kontak"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Anda akan 1) membuat salinan dari basis data Anda yang mencakup semua informasi terkait kontak dan semua log panggilan ke kartu SD/penyimpanan USB yang dapat dibaca oleh aplikasi apa pun, dan 2) mengirimkannya melalui email. Jangan lupa untuk menghapus salinan segera setelah Anda berhasil menyalinnya dari perangkat atau setelah email diterima."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Hapus sekarang"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Mulai"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Pilih program untuk mengirim file Anda"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Db Kontak terlampir"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Terlampir basis data kontak saya dengan semua informasi kontak. Harap tangani dengan benar."</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index dfea4d4f..0d54a572 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Accesso a tutti i messaggi vocali"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Consente all\'applicazione di archiviare recuperare tutti i messaggi vocali a cui questo dispositivo può accedere."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Messaggio vocale da "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Copia database di contatti"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Stai per 1) creare una copia del tuo database contenente tutte le informazioni relative ai contatti e l\'intero registro chiamate sulla scheda SD/nell\'archivio USB, leggibile da qualsiasi applicazione e 2) inviarla tramite email. Ricordati di eliminare la copia non appena l\'avrai copiata dal dispositivo o in seguito alla ricezione dell\'email."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Elimina adesso"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Inizia"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Scegli un programma per inviare il file"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Database di contatti allegato"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"In allegato è presente il mio database di contatti contenente tutte le informazioni sui miei contatti. Trattare con cura."</string>
</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index c87a2f94..a547c916 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"גישה לכל הודעות הדואר הקולי"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"מאפשר ליישום לאחסן ולאחזר את כל הודעות הדואר הקולי שלמכשיר זה יש גישה אליהן."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"הודעה קולית מאת "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"העתקת מסד נתוני אנשי קשר"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"אתה עומד 1) ליצור עותק של מסד הנתונים שכולל את כל המידע הקשור לאנשי הקשר ואת כל יומני השיחות באחסון כרטיס ה-SD/ USB, אשר ניתן לקריאה על ידי כל יישום, וגם 2) לשלוח אותו בדוא\"ל. זכור למחוק את העותק מיד לאחר שתעתיק אותו בהצלחה מהמכשיר או אחרי שהודעת הדוא\"ל תתקבל."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"מחק עכשיו"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"התחל"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"בחר תוכנית לשליחת הקובץ"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"מסד נתוני אנשי קשר מצורף"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"מצורף מסד הנתונים של אנשי הקשר שלי עם כל פרטי אנשי הקשר. שמור עליו היטב."</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 74044d89..794d6bcb 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"すべてのボイスメールにアクセス"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"この端末でアクセス可能なすべてのボイスメールを保存、取得することをアプリに許可します。"</string>
<string name="voicemail_from_column" msgid="435732568832121444">"受信ボイスメール: "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"連絡先データベースをコピー"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"1)すべての連絡先関連情報とすべての通話履歴を格納したデータベースを(あらゆるアプリから読み取り可能な)SDカード/USBストレージにコピーし、2)メールで送信しようとしています。端末からのコピーが完了した時点またはメールが受信された時点ですぐにコピーを削除してください。"</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"今すぐ削除"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"開始"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"ファイルを送信するプログラムを選択"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"連絡先データベースを添付"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"添付されているのは、私のすべての連絡先情報を含む連絡先データベースです。取り扱いにご注意ください。"</string>
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 041cc0b8..5a0ae647 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"모든 음성사서함에 액세스"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"앱이 이 기기에서 액세스할 수 있는 모든 음성사서함을 저장하고 검색하도록 허용합니다."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"음성사서함 발신자 "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"주소록 데이터베이스 복사"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"모든 앱에서 읽을 수 있는 SD 카드/USB 저장소에 모든 주소록 관련 정보와 통화 기록을 포함하는 데이터베이스의 1) 사본을 만들고 2) 이메일로 보내려 합니다. 기기 이외의 장소에 사본을 만들거나 사본의 이메일 수신이 완료된 후에는 해당 사본을 즉시 삭제하시기 바랍니다."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"지금 삭제"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"시작"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"파일을 전송할 프로그램을 선택하세요."</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"주소록 DB 첨부됨"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"모든 주소록 정보가 포함된 주소록 데이터베이스가 첨부되어 있습니다. 신중하게 처리해 주세요."</string>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index b873d1f5..79e88d51 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Pasiekti visus balso pašto pranešimus"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Leidžiama programai saugoti ir nuskaityti visus balso pašto pranešimus, kuriuos gali pasiekti šis įrenginys."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Balso pašto pranešimas nuo "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopijuoti kontaktų duomenis"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Ketinate atlikti šiuos veiksmus: 1) nukopijuoti visus duomenis (į kuriuos įeina visa su kontaktais susijusi informacija ir visų skambučių žurnalas) į SD kortelę arba USB atmintį, kurias gali skaityti bet kuri programa, ir 2) išsiųsti duomenų kopiją el. paštu. Nepamirškite ištrinti kopijos, kai duomenys bus sėkmingai nukopijuoti iš įrenginio arba kai el. laiškas bus gautas."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Ištrinti dabar"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Pradėti"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Pasirinkite programą, kad išsiųstumėte failą"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Pridedami kontaktų duomenys"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Pridedami mano kontaktų duomenys su visa kontaktų informacija. Elkitės atsargiai."</string>
</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index fa1e89e3..ef86ffd7 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Piekļuve visiem balss pasta ziņojumiem"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Ļauj lietotnei glabāt un izgūt visus balss pasta ziņojumus, kuriem var piekļūt šajā ierīcē."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Balss pasta ziņojums no "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kontaktpersonu datu bāzes kopēšana"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Jūs gatavojaties veikt šādas darbības: 1) izveidot savas datu bāzes kopiju (kurā ir ietverta visa ar kontaktpersonām saistītā informācija un zvanu žurnāls) SD kartē/USB atmiņā, kur to var nolasīt jebkura lietotne; 2) nosūtīt to pa e-pastu. Dzēsiet kopiju, tiklīdz esat to veiksmīgi kopējis no ierīces vai saņēmis e-pasta ziņojumu."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Dzēst tūlīt"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Sākt"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Izvēlieties programmu, kuru izmantot faila nosūtīšanai"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Pievienota kontaktpersonu datu bāze"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Pielikumā ir pievienota mana kontaktpersonu datu bāze ar informāciju par visām manām kontaktpersonām. Rīkojieties uzmanīgi."</string>
</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 653a8d9b..fa8d0419 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Akses semua mel suara"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Membenarkan aplikasi menyimpan dan mengambil semula semua mel suara yang boleh diakses peranti ini."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Mel suara daripada "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Salin pangkalan data kenalan"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Anda akan 1) membuat salinan pangkalan data anda yang termasuk semua maklumat berkaitan kenalan dan semua log panggilan ke kad SD/storan USB yang boleh dibaca oleh sebarang apl dan 2) meng-e-melkannya. Jangan lupa memadamkan salinan sejurus selepas anda berjaya menyalinnya dari peranti atau e-mel diterima."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Padamkan sekarang"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Mula"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Pilih program untuk menghantar fail anda"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Pangkalan Data Kenalan dilampirkan"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Dilampirkan pangkalan data kenalan saya yang mengandungi semua maklumat kenalan. Sila gunakan dengan cermat."</string>
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 57758545..932bfb14 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Tilgang til alle talemeldinger"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Lar appen lagre og hente alle talepostmeldinger som denne enheten har tilgang til."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Talemelding fra "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopiér kontaktdatabasen"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Du er i ferd med å lage en kopi av databasen din på SD-kortet/USB-lagringen. Dette inkluderer all informasjonen relatert til kontaktene dine og hele samtaleloggen. Denne kopien kan leses av alle apper. Kopien sendes også på e-post. Husk å slette kopien så snart du har kopiert den fra enheten eller mottatt e-posten."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Slett nå"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Start"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Velg et program for å sende filen"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Kontaktdatabasen er vedlagt"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Vedlagt er kontaktdatabasen min med informasjon om alle kontaktene mine. Håndteres med varsomhet."</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 1a092887..b76de01b 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Toegang tot alle voicemails"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Toestaan dat de app alle voicemails opslaat en ophaalt waartoe dit apparaat toegang heeft."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Voicemail van "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Contactendatabase kopiëren"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"U staat op het punt 1) een kopie van uw database met alle contactgegevens en het gehele oproeplogbestand te maken naar de SD-kaart/USB-opslag (de kopie kan door elke app worden gelezen), en 2) de kopie per e-mail te verzenden. Verwijder de kopie zodra u deze heeft gekopieerd vanaf het apparaat of de e-mail is ontvangen."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Nu verwijderen"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Starten"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Selecteer een programma om uw bestand te verzenden"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Contactendatabase bijgevoegd"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Bijgevoegd is mijn contactendatabase met al mijn contactgegevens. Ga hier zorgvuldig mee om."</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index b598221d..9cc9cdcd 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Dostęp do wszystkich wiadomości głosowych"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Zezwala aplikacji na przechowywanie i pobieranie wszystkich wiadomości głosowych, do których ma dostęp to urządzenie."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Poczta głosowa od "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopiuj bazę danych kontaktów"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Zamierzasz 1) utworzyć na karcie SD lub w pamięci USB kopię bazy danych z informacjami dotyczącymi kontaktów i rejestrami połączeń, która będzie możliwa do odczytania przez dowolną aplikację, oraz 2) przesłać ją e-mailem. Pamiętaj, by kopię usunąć od razu po jej pomyślnym skopiowaniu na inny nośnik lub odebraniu e-maila."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Usuń teraz"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Rozpocznij"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Wybierz program, którego użyjesz do wysłania pliku"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"W załączniku baza danych kontaktów"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"W załączniku przesyłam moją bazę danych kontaktów, która zawiera wszystkie informacje o moich kontaktach. Proszę zachować ostrożność."</string>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index acdb0d2a..9a97e7db 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Acesso a todas as mensagens de correio de voz"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Permite à aplicação guardar e recuperar todas as mensagens de correio de voz a que este aparelho pode aceder."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Correio de voz de "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Copiar base de dados de contactos"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Está prestes a 1) criar uma cópia da nossa base de dados, que inclui todas as informações relacionadas com contactos e o registo de todas as chamadas, para o cartão SD/memória USB, que pode ser lido por qualquer aplicação, e a 2) enviá-la por email. Não se esqueça de eliminar a cópia assim que a tiver copiado com êxito para fora do dispositivo ou tiver recebido a mensagem de email."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Eliminar agora"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Iniciar"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Escolha um programa para enviar o ficheiro"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"BD de Contactos em anexo"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Em anexo segue a minha base de dados de contactos com todas as informações dos meus contactos. Utilize-a com cuidado."</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 5d471a1c..7c913c28 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Acessar todas as mensagens de voz"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Permite que o aplicativo armazene e recupere todas as mensagens de voz que esse dispositivo acessa."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Correio de voz de "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Copiar banco de dados de contatos"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Você está prestes a 1) fazer uma cópia de seu banco de dados que pode ser lida por qualquer aplicativo e inclui todas as informações relacionadas aos contatos e todos os registros de chamadas para o cartão SD/armazenamento USB e 2) enviá-la por e-mail. Exclua a cópia assim que copiá-la do dispositivo ou assim que o e-mail for recebido."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Excluir agora"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Iniciar"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Escolha um programa para enviar o arquivo"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"BD de contatos anexado"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Meu banco de dados de contatos está anexado, Lá estão todas as informações de meus contatos. Use-o com cuidado."</string>
</resources>
diff --git a/res/values-rm/strings.xml b/res/values-rm/strings.xml
index b0e2898d..c5762987 100644
--- a/res/values-rm/strings.xml
+++ b/res/values-rm/strings.xml
@@ -36,4 +36,18 @@
<skip />
<!-- no translation found for voicemail_from_column (435732568832121444) -->
<skip />
+ <!-- no translation found for debug_dump_title (4916885724165570279) -->
+ <skip />
+ <!-- no translation found for debug_dump_database_message (5718202172291024953) -->
+ <skip />
+ <!-- no translation found for debug_dump_delete_button (7832879421132026435) -->
+ <skip />
+ <!-- no translation found for debug_dump_start_button (2837506913757600001) -->
+ <skip />
+ <!-- no translation found for debug_dump_email_sender_picker (3534420908672176460) -->
+ <skip />
+ <!-- no translation found for debug_dump_email_subject (108188398416385976) -->
+ <skip />
+ <!-- no translation found for debug_dump_email_body (4577749800871444318) -->
+ <skip />
</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 110f166e..6fae1755 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Accesaţi toate mesajele vocale"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Permite aplicaţiei să stocheze şi să preia toate mesajele vocale pe care acest dispozitiv le poate accesa."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Mesaj vocal de la "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Copiaţi baza de date a agendei"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Sunteţi pe cale 1) să faceţi o copie a bazei dvs. de date care include toate informaţiile referitoare la agendă şi întregul jurnal de apeluri pe cardul SD/stocarea USB, iar această copie poate fi citită de orice aplicaţie, şi 2) să trimiteţi această copie prin e-mail. Nu uitaţi să ştergeţi această copie după ce aţi copiat-o de pe dispozitiv sau după ce a fost primit e-mailul."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Ştergeţi acum"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Porniţi"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Alegeţi un program pentru a trimite fişierul"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Atașată baza de date a agendei"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Vă trimit ataşată baza de date cu toate informaţiile din agenda mea. Vă rog să o gestionaţi cu atenţie."</string>
</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 45b28a08..76ebc424 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Доступ к голосовым сообщениям"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Приложение сможет сохранять и загружать все голосовые сообщения, к которым есть доступ на этом устройстве."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Голосовое сообщение от абонента "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Копирование базы данных контактов"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Вы собираетесь: 1) сохранить на SD-карте или USB-носителе копию базы данных со всеми контактами и историей звонков, которую можно открыть с помощью любого приложения, и 2) отправить ее по электронной почте. Не забудьте удалить копию после того, как она будет перенесена с накопителя или сообщение будет доставлено адресату."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Удалить"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Копировать"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Выберите приложение для отправки файла"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"К сообщению добавлена база данных контактов"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Будьте внимательны: в приложенном файле находится база данных с моими контактами."</string>
</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index e8d82c6b..aad2d53e 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Prístup ku všetkým hlasovým správam"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Umožňuje aplikácii uchovávať a načítavať všetky hlasové správy, ku ktorým má zariadenie prístup."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Hlasová správa od "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopírovanie databázy kontaktov"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Chystáte sa 1) vytvoriť na karte SD alebo úložisku USB, ktoré je čitateľné v každej aplikácii, kópiu svojej databázy, ktorá obsahuje všetky informácie o kontaktoch a denník volaní, a 2) odoslať ju e-mailom. Hneď ako túto kópiu skopírujete preč z úložiska alebo dostanete odoslaný e-mail, nezabudnite ju odstrániť."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Odstrániť"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Spustiť"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Vyberte program na odoslanie súboru"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Databáza kontaktov v prílohe"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"V prílohe je databáza s informáciami o všetkých mojich kontaktoch. Zaobchádzajte s ňou opatrne."</string>
</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index af435317..cfbcb054 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Dostop do glasovne pošte"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Programu dovoli shranjevanje in prenos sporočil v odzivniku, do katerih lahko dostopa ta naprava."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Govorna pošta s številke "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopiraj zbirko podatkov o stikih"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"S tem dejanjem boste 1) na pomnilniški kartici SD oziroma v pomnilniku USB ustvarili kopijo zbirke podatkov, ki bo vključevala vse informacije v zvezi s stiki in dnevnik klicev ter bo berljiva v vsaki aplikaciji, in 2) jo poslali po e-pošti. Kopijo izbrišite iz pomnilniške naprave, ko jo boste uspešno prekopirali v drugo napravo ali ko bo poslana e-pošta prejeta."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Izbriši zdaj"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Začni"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Izberite program za pošiljanje datoteke"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Priložena zbirka podatkov o stikih"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Priložena je zbirka podatkov z vsemi informacijami o stikih. Z e-pošto ravnajte previdno."</string>
</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index c8888db9..e2b5f565 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Приступ свим порукама говорне поште"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Дозвољава апликацији да складишти и преузима све поруке говорне поште којима овај уређај може да приступи."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Говорна пошта од "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Копирање базе података са контактима"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Управо ћете 1) направити копију базе података која обухвата све информације о контактима и све евиденције позива на SD картицу/у USB меморију, које може да чита било која апликација, и 2) послати је е-поштом. Не заборавите да избришете копију одмах након што је прекопирате са уређаја или примите поруку е-поште."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Избриши одмах"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Покрени"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Изаберите програм за слање датотеке"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"База података са контактима је у прилогу"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"У прилогу је база података са мојим контактима и свим информацијама о њима. Рукујте пажљиво."</string>
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 06ecf9a9..76c65ee2 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Åtkomst till alla röstmeddelanden"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Tillåter att appen sparar och hämtar alla röstmeddelanden som enheten har åtkomst till."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Röstmeddelande från "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopiera kontaktdatabas"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Du är på väg att 1) kopiera databasen som innehåller alla dina kontaktrelaterade uppgifter och hela samtalsloggen till SD-kortet/USB-minnet, där alla appar kan läsa den, och 2) skicka den med e-post. Kom ihåg att ta bort kopian så fort du har kopierat den från enheten eller när e-postmeddelandet har kommit fram."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Ta bort nu"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Börja"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Välj program att skicka filen med"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Kontaktdatabas bifogad"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Jag bifogar min kontaktdatabas med alla mina kontaktuppgifter. Hantera den varsamt."</string>
</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index b83c636c..6156ae56 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Fikia barua zote za sauti"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Inaruhusu programu kuhifadhi na kutoa jumbe zote za sauti ambazo kifaa hiki kinaweza kufikia."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Barua ya sauti kutoka "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Nakili hifadhidata ya anwani"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Unakaribia 1) kuunda nakala ya hifadhidata yako ambayo ni pamoja na maelezo yote yanayohusiana ya anwani na kumbukumbu zote za simu kwenye kadi ya SD/hifadhi ya USB, ambayo inasomeka kwa programu yoyote, na 2) kuituma kwa barua pepe. Kumbuka kufuta nakala pindi tu unapofanikiwa kuinakili kutoka kwenye kifaa au barua inapopokewa."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Futa sasa"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Anza"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Chagua programu ili kutuma faili yako"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Db ya anwani imeambatishwa"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Kilichoambatishwa ni hifadhidata ya anwani zangu iliyo na maelezo yote ya anwani zangu. Ishughulikie kwa uangalifu."</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 0cb6adcf..4e607d42 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"เข้าถึงข้อความเสียงทั้งหมด"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"อนุญาตให้แอปพลิเคชันจัดเก็บและเรียกข้อความเสียงทั้งหมดที่อุปกรณ์นี้สามารถเข้าถึงได้"</string>
<string name="voicemail_from_column" msgid="435732568832121444">"ข้อความเสียงจาก "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"คัดลอกฐานข้อมูลผู้ติดต่อ"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"คุณกำลังจะ 1) สร้างสำเนาฐานข้อมูลซึ่งประกอบด้วยข้อมูลที่เกี่ยวข้องกับผู้ติดต่อทั้งหมดและประวัติการโทรทั้งหมดไปยังการ์ด SD/ที่จัดเก็บข้อมูล USB ซึ่งทุกๆ แอปพลิเคชันสามารถอ่านได้ และ 2) ส่งอีเมลสำเนาฐานข้อมูล อย่าลืมลบสำเนาออกจากอุปกรณ์ทันทีที่คุณคัดลอกเสร็จแล้ว หรือเมื่อผู้รับรับอีเมลแล้ว"</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"ลบเดี๋ยวนี้"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"เริ่มต้น"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"เลือกโปรแกรมเพื่อส่งไฟล์ของคุณ"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"แนบฐานข้อมูลผู้ติดต่อมาด้วย"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"ที่แนบอยู่นี้เป็นฐานข้อมูลผู้ติดต่อซึ่งมีข้อมูลผู้ติดต่อของฉันทั้งหมด โปรดจัดการด้วยความระมัดระวัง"</string>
</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 44f6b738..cd6bcad8 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"I-access ang lahat ng voicemail"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Binibigyang-daan ang app upang iimbak at kuning muli ang lahat ng voicemail na naa-access ng device na ito."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Voicemail mula sa/kay "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopyahin ang database ng mga contact"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Ikaw ay 1) gagawa ng kopya ng iyong database na nagsasama ng lahat ng impormasyong nauugnay sa mga contact at lahat ng log ng tawag sa SD card/imbakan ng USB, na nababasa ng anumang app, at 2) i-e-email ito. Tandaang tanggalin ang kopya sa sandaling matagumpay mo nang nakopya ito sa device o natanggap ang email."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Tanggalin ngayon"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Simulan"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Pumili ng program upang ipadala ang iyong file"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Naka-attach ang Contacts Db"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Naka-attach ang aking database ng mga contact na kasama ang lahat ng impormasyon ng aking mga contact. Pangasiwaan nang may pag-iingat."</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 672288ab..46921fb1 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Tüm sesli mesajlara erişim"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Uygulamaya, bu cihazın erişebileceği tüm sesli mesajları depolama ve alma izni verir."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Sesli mesaj gönderen: "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kişiler veritabanını kopyala"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Şunu yapmak üzeresiniz: 1) kişilerle ilgili tüm bilgileri ve tüm çağrı kayıtlarını içeren veritabanınızı SD karta/USB depolama birimine her türlü uygulama tarafından okunabilecek şekilde kopyasını alma ve 2) e-postayla gönderme. Cihazdan başarıyla kopyaladıktan veya e-posta alındıktan sonra kopyayı silmeyi unutmayın."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Şimdi sil"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Başlat"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Dosyanızı göndermek için bir program seçin"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Kişiler veritabanı ektedir"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Tüm kişi bilgilerimi içeren kişiler veritabanımı ekte bulabilirsiniz. Dikkatli kullanın."</string>
</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 18292195..20d9a88d 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Доступ до всієї голосової пошти"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Дозволяє програмі зберігати й отримувати всю голосову пошту, доступ до якої має цей пристрій."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Голосова пошта від "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Копіювати базу даних контактів"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Ви збираєтеся виконати такі дії: 1) скопіювати базу даних, яка містить усю інформацію про контакти та весь журнал дзвінків, на карту SD або носій USB, які може читати будь-яка програма; 2) надіслати копію електронною поштою. Не забудьте видалити копію, щойно її буде скопійовано з пристрою або отримано електронним листом."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Видалити зараз"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Почати"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Виберіть програму для надсилання файлу"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"У вкладенні – база даних контактів"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"У вкладенні – база даних моїх контактів з усією інформацією про мої контакти. Працюйте з нею обережно."</string>
</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 431a4036..88a3708a 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Truy cập tất cả các thư thoại"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Cho phép ứng dụng lưu trữ và truy xuất tất cả thư thoại mà thiết bị này có thể truy cập."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Thư thoại từ "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Sao chép cơ sở dữ liệu người liên hệ"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Bạn sắp 1) sao chép cơ sở dữ liệu của mình bao gồm tất cả thông tin liên quan đến người liên hệ và toàn bộ nhật ký cuộc gọi sang thẻ SD/bộ lưu trữ USB mà bất kỳ ứng dụng nào đều có thể đọc những thông tin này và 2) gửi email dữ liệu. Hãy nhớ xóa bản sao ngay sau khi bạn đã sao chép thành công từ thiết bị hoặc người nhận đã nhận được email."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Xóa ngay"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Bắt đầu"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Chọn chương trình để gửi tệp của bạn"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"Đã đính kèm cơ sở dữ liệu người liên hệ"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Phần đính kèm là cơ sở dữ liệu người liên hệ với tất cả thông tin người liên hệ của tôi. Hãy cẩn trọng khi xử lý."</string>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 402b8c1c..50a797e3 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -22,10 +22,17 @@
<string name="upgrade_msg" msgid="8640807392794309950">"正在升级联系人数据库。"</string>
<string name="upgrade_out_of_memory_notification_ticker" msgid="7638747231223520477">"联系人升级需要更多的存储空间。"</string>
<string name="upgrade_out_of_memory_notification_title" msgid="8888171924684998531">"正在升级存储器以容纳更多联系人"</string>
- <string name="upgrade_out_of_memory_notification_text" msgid="8438179450336437626">"请触摸以完成升级。"</string>
+ <string name="upgrade_out_of_memory_notification_text" msgid="8438179450336437626">"触摸可完成升级。"</string>
<string name="default_directory" msgid="93961630309570294">"联系人"</string>
<string name="local_invisible_directory" msgid="705244318477396120">"其他"</string>
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"访问所有语音邮件"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"允许应用存储和检索此设备可访问的所有语音邮件。"</string>
<string name="voicemail_from_column" msgid="435732568832121444">"语音邮件发件人 "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"复制通讯录数据库"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"您将要执行以下操作:1) 在任意应用都可读取的 SD 卡/USB 存储设备中,创建包括通讯录相关信息和所有通话记录的数据库的副本;2) 通过电子邮件发送该副本。从设备中成功复制该副本或在电子邮件送达之后,请务必及时删除该副本。"</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"立即删除"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"开始"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"选择用于发送文件的程序"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"随附通讯录数据库"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"附件是我的通讯录数据库,其中包含我所有的联系人信息,因此请谨慎处理。"</string>
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index ba929c3d..49d8b80d 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"存取所有語音留言"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"允許應用程式儲存及擷取這個裝置可存取的所有語音留言。"</string>
<string name="voicemail_from_column" msgid="435732568832121444">"語音郵件寄件者: "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"複製聯絡人資料庫"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"您即將要 1) 將您的資料庫 (包含所有聯絡人相關資訊及所有通話紀錄) 複製到可供任何應用程式讀取的 SD 卡/USB 儲存裝置,以及 2) 透過電子郵件傳送副本。提醒您,當您順利複製裝置上的資料或收到電子郵件後,請儘快刪除副本。"</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"立即刪除"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"開始"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"選擇要傳送檔案的程式"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"內含聯絡人資料庫附件"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"附件是我的聯絡人資料庫,其中包含我所有的聯絡人資訊,請謹慎處理。"</string>
</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 76de636e..e7083d35 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -28,4 +28,11 @@
<string name="read_write_all_voicemail_label" msgid="4557216100818257560">"Finyelela kuwo wonke amavoyisimeyili"</string>
<string name="read_write_all_voicemail_description" msgid="8029809937805761356">"Ivumela uhlelo olusebenzayo lulonde futhi lulande wonke ama-imeyli ezwi ledivayisi engakwazi ukuwafinyelela."</string>
<string name="voicemail_from_column" msgid="435732568832121444">"Imeyili yezwi kusuka "</string>
+ <string name="debug_dump_title" msgid="4916885724165570279">"Kopisha imininingo egciniwe yoxhumana nabo"</string>
+ <string name="debug_dump_database_message" msgid="5718202172291024953">"Usuzo 1) kwenza ikhophi yemininingo egciniwe yakho okufaka phakathi lonke ulwazi oluhlobene loxhumana nabo nalo lonke irekhodi lwamakholi ekhadini le-SD/isilondolozi se-USB, esifundekayo nganoma uluphi uhlelo lokusebenza, futhi 2) ulithumele nge-imeyili. Khumbula ukususa ikhophi ngokushesha uma uqeda ukulikopisha ulisuse ngempumelelo kwenye idiayisi noma i-imeyili yamukelwe."</string>
+ <string name="debug_dump_delete_button" msgid="7832879421132026435">"Susa manje"</string>
+ <string name="debug_dump_start_button" msgid="2837506913757600001">"Qala"</string>
+ <string name="debug_dump_email_sender_picker" msgid="3534420908672176460">"Khetha uhlelo ozothumela kulo ifayela lakho"</string>
+ <string name="debug_dump_email_subject" msgid="108188398416385976">"I-Db yoxhumana nabo inamathiselwe"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Okunamathiselwe imininingo egciniwe yabaxhumana nami nalo lonke ulwazi labaxhumana nami. Kubambe ngokunakekela."</string>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index aaa7f44e..e17b5ed3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -58,4 +58,26 @@
Note that the trailing space is important, and that to achieve it we have to wrap the
string in double quotes. -->
<string name="voicemail_from_column">"Voicemail from "</string>
+
+ <!-- Debug tool - title of the dialog which copies the contact database into the external storage. [CHAR LIMIT=NONE] -->
+ <string name="debug_dump_title">Copy contacts database</string>
+
+ <!-- Debug tool - message shown to the user on the dialog which copies the contact database into the external storage. [CHAR LIMIT=NONE] -->
+ <string name="debug_dump_database_message">You are about to 1) make a copy of your database which includes all contacts related information and all call log to the SD card/USB storage, which is readable by any app, and 2) email it. Remember to delete the copy as soon as you have successfully copied it off the device or the email is received.</string>
+
+ <!-- Debug tool - dialog button- delete file now [CHAR LIMIT=NONE] -->
+ <string name="debug_dump_delete_button">Delete now</string>
+
+ <!-- Debug tool - dialog button - start copying [CHAR LIMIT=NONE] -->
+ <string name="debug_dump_start_button">Start</string>
+
+ <!-- Debug tool - email subject [CHAR LIMIT=NONE] -->
+ <string name="debug_dump_email_sender_picker">Choose a program to send your file</string>
+
+ <!-- Debug tool - email subject [CHAR LIMIT=NONE] -->
+ <string name="debug_dump_email_subject">Contacts Db attached</string>
+
+ <!-- Debug tool - email body [CHAR LIMIT=NONE] -->
+ <string name="debug_dump_email_body">Attached is my contacts database with all my contacts information. Handle with care.</string>
+
</resources>
diff --git a/src/com/android/providers/contacts/AbstractContactsProvider.java b/src/com/android/providers/contacts/AbstractContactsProvider.java
index a33320fc..226652e0 100644
--- a/src/com/android/providers/contacts/AbstractContactsProvider.java
+++ b/src/com/android/providers/contacts/AbstractContactsProvider.java
@@ -38,9 +38,12 @@ import java.util.ArrayList;
public abstract class AbstractContactsProvider extends ContentProvider
implements SQLiteTransactionListener {
- protected static final String TAG = "ContactsProvider";
+ public static final String TAG = "ContactsProvider";
- protected static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE);
+ public static final boolean VERBOSE_LOGGING = Log.isLoggable(TAG, Log.VERBOSE);
+
+ /** Set true to enable detailed transaction logging. */
+ public static final boolean ENABLE_TRANSACTION_LOG = false; // Don't submit with true.
/**
* Duration in ms to sleep after successfully yielding the lock during a batch operation.
@@ -72,14 +75,32 @@ public abstract class AbstractContactsProvider extends ContentProvider
* created by this provider will automatically retrieve a writable database from this helper
* and initiate a transaction on that database. This should be used to ensure that operations
* across multiple databases are all blocked on a single DB lock (to prevent deadlock cases).
+ *
+ * Hint: It's always {@link ContactsDatabaseHelper}.
+ *
+ * TODO Change the structure to make it obvious that it's actually always set, and is the
+ * {@link ContactsDatabaseHelper}.
*/
private SQLiteOpenHelper mSerializeOnDbHelper;
/**
* The tag corresponding to the database used for serializing transactions.
+ *
+ * Hint: It's always the contacts db helper tag.
+ *
+ * See also the TODO on {@link #mSerializeOnDbHelper}.
*/
private String mSerializeDbTag;
+ /**
+ * The transaction listener used with {@link #mSerializeOnDbHelper}.
+ *
+ * Hint: It's always {@link ContactsProvider2}.
+ *
+ * See also the TODO on {@link #mSerializeOnDbHelper}.
+ */
+ private SQLiteTransactionListener mSerializedDbTransactionListener;
+
@Override
public boolean onCreate() {
Context context = getContext();
@@ -94,12 +115,14 @@ public abstract class AbstractContactsProvider extends ContentProvider
/**
* Specifies a database helper (and corresponding tag) to serialize all transactions on.
- * @param serializeOnDbHelper The database helper to use for serializing transactions.
- * @param tag The tag for this database.
+ *
+ * See also the TODO on {@link #mSerializeOnDbHelper}.
*/
- public void setDbHelperToSerializeOn(SQLiteOpenHelper serializeOnDbHelper, String tag) {
+ public void setDbHelperToSerializeOn(SQLiteOpenHelper serializeOnDbHelper, String tag,
+ SQLiteTransactionListener listener) {
mSerializeOnDbHelper = serializeOnDbHelper;
mSerializeDbTag = tag;
+ mSerializedDbTransactionListener = listener;
}
public ContactsTransaction getCurrentTransaction() {
@@ -227,12 +250,16 @@ public abstract class AbstractContactsProvider extends ContentProvider
* @param callerIsBatch Whether the caller is operating in batch mode.
*/
private ContactsTransaction startTransaction(boolean callerIsBatch) {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "startTransaction " + getClass().getSimpleName() +
+ " callerIsBatch=" + callerIsBatch, new RuntimeException("startTransaction"));
+ }
ContactsTransaction transaction = mTransactionHolder.get();
if (transaction == null) {
transaction = new ContactsTransaction(callerIsBatch);
if (mSerializeOnDbHelper != null) {
transaction.startTransactionForDb(mSerializeOnDbHelper.getWritableDatabase(),
- mSerializeDbTag, this);
+ mSerializeDbTag, mSerializedDbTransactionListener);
}
mTransactionHolder.set(transaction);
}
@@ -245,6 +272,10 @@ public abstract class AbstractContactsProvider extends ContentProvider
* @param callerIsBatch Whether the caller is operating in batch mode.
*/
private void endTransaction(boolean callerIsBatch) {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "endTransaction " + getClass().getSimpleName() +
+ " callerIsBatch=" + callerIsBatch, new RuntimeException("endTransaction"));
+ }
ContactsTransaction transaction = mTransactionHolder.get();
if (transaction != null && (!transaction.isBatch() || callerIsBatch)) {
try {
diff --git a/src/com/android/providers/contacts/AccountWithDataSet.java b/src/com/android/providers/contacts/AccountWithDataSet.java
index 3fea8a67..b7484cd0 100644
--- a/src/com/android/providers/contacts/AccountWithDataSet.java
+++ b/src/com/android/providers/contacts/AccountWithDataSet.java
@@ -16,11 +16,11 @@
package com.android.providers.contacts;
-import com.android.internal.util.Objects;
-
import android.accounts.Account;
import android.text.TextUtils;
+import com.android.internal.util.Objects;
+
/**
* Account information that includes the data set, if any.
*/
diff --git a/src/com/android/providers/contacts/CallLogProvider.java b/src/com/android/providers/contacts/CallLogProvider.java
index 89ae591e..21a16f19 100644
--- a/src/com/android/providers/contacts/CallLogProvider.java
+++ b/src/com/android/providers/contacts/CallLogProvider.java
@@ -20,10 +20,6 @@ import static com.android.providers.contacts.util.DbQueryUtils.checkForSupported
import static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause;
import static com.android.providers.contacts.util.DbQueryUtils.getInequalityClause;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.util.SelectionBuilder;
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -38,6 +34,10 @@ import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.util.SelectionBuilder;
+import com.google.common.annotations.VisibleForTesting;
+
import java.util.HashMap;
/**
diff --git a/src/com/android/providers/contacts/ContactDirectoryManager.java b/src/com/android/providers/contacts/ContactDirectoryManager.java
index 7116ed6f..f243e79e 100644
--- a/src/com/android/providers/contacts/ContactDirectoryManager.java
+++ b/src/com/android/providers/contacts/ContactDirectoryManager.java
@@ -16,13 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
-import com.android.providers.contacts.ContactsDatabaseHelper.DirectoryColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageInfo;
@@ -41,6 +34,13 @@ import android.provider.ContactsContract.Directory;
import android.text.TextUtils;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
+import com.android.providers.contacts.ContactsDatabaseHelper.DirectoryColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
+import com.google.common.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
diff --git a/src/com/android/providers/contacts/ContactLocaleUtils.java b/src/com/android/providers/contacts/ContactLocaleUtils.java
index 2eb2ad6a..0e7b292d 100644
--- a/src/com/android/providers/contacts/ContactLocaleUtils.java
+++ b/src/com/android/providers/contacts/ContactLocaleUtils.java
@@ -16,11 +16,11 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.HanziToPinyin.Token;
-
import android.provider.ContactsContract.FullNameStyle;
import android.util.SparseArray;
+import com.android.providers.contacts.HanziToPinyin.Token;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
index 67429ca7..62f49ae1 100644
--- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
@@ -16,11 +16,6 @@
package com.android.providers.contacts;
-import com.android.common.content.SyncStateContentProviderHelper;
-import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
-import com.android.providers.contacts.util.NeededForTesting;
-import com.google.android.collect.Sets;
-
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -80,6 +75,11 @@ import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
import android.util.Log;
+import com.android.common.content.SyncStateContentProviderHelper;
+import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
+import com.android.providers.contacts.util.NeededForTesting;
+import com.google.android.collect.Sets;
+
import java.util.HashMap;
import java.util.Locale;
import java.util.Set;
@@ -779,6 +779,10 @@ public class ContactsDatabaseHelper extends SQLiteOpenHelper {
com.android.internal.R.bool.config_use_strict_phone_number_comparation);
}
+ public SQLiteDatabase getDatabase(boolean writable) {
+ return writable ? getWritableDatabase() : getReadableDatabase();
+ }
+
/**
* Clear all the cached database information and re-initialize it.
*
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index 26aac63a..ef2ea9ac 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -16,51 +16,6 @@
package com.android.providers.contacts;
-import com.android.common.content.ProjectionMap;
-import com.android.common.content.SyncStateContentProviderHelper;
-import com.android.providers.contacts.ContactLookupKey.LookupKeySegment;
-import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Clauses;
-import com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
-import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Joins;
-import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
-import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Projections;
-import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.StreamItemPhotosColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.StreamItemsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.ContactsDatabaseHelper.ViewGroupsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Views;
-import com.android.providers.contacts.SearchIndexManager.FtsQueryBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-import com.android.providers.contacts.aggregation.ContactAggregator.AggregationSuggestionParameter;
-import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
-import com.android.providers.contacts.aggregation.ProfileAggregator;
-import com.android.providers.contacts.util.Clock;
-import com.android.providers.contacts.util.DbQueryUtils;
-import com.android.providers.contacts.util.NeededForTesting;
-import com.android.vcard.VCardComposer;
-import com.android.vcard.VCardConfig;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-import com.google.android.collect.Sets;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
@@ -151,6 +106,51 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
+import com.android.common.content.ProjectionMap;
+import com.android.common.content.SyncStateContentProviderHelper;
+import com.android.providers.contacts.ContactLookupKey.LookupKeySegment;
+import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.AggregatedPresenceColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Clauses;
+import com.android.providers.contacts.ContactsDatabaseHelper.ContactsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.ContactsStatusUpdatesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
+import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Joins;
+import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
+import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Projections;
+import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.SettingsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.StreamItemPhotosColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.StreamItemsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.ContactsDatabaseHelper.ViewGroupsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Views;
+import com.android.providers.contacts.SearchIndexManager.FtsQueryBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+import com.android.providers.contacts.aggregation.ContactAggregator.AggregationSuggestionParameter;
+import com.android.providers.contacts.aggregation.ProfileAggregator;
+import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
+import com.android.providers.contacts.util.Clock;
+import com.android.providers.contacts.util.DbQueryUtils;
+import com.android.providers.contacts.util.NeededForTesting;
+import com.android.vcard.VCardComposer;
+import com.android.vcard.VCardConfig;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+import com.google.android.collect.Sets;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -1264,13 +1264,6 @@ public class ContactsProvider2 extends AbstractContactsProvider
/* package */ static final String PROFILE_DB_TAG = "profile";
/**
- * The active (thread-local) database. This will be switched between a contacts-specific
- * database and a profile-specific database, depending on what the current operation is
- * targeted to.
- */
- private final ThreadLocal<SQLiteDatabase> mActiveDb = new ThreadLocal<SQLiteDatabase>();
-
- /**
* The thread-local holder of the active transaction. Shared between this and the profile
* provider, to keep transactions on both databases synchronized.
*/
@@ -1393,7 +1386,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
mDbHelper.set(mContactsHelper);
// Set up the DB helper for keeping transactions serialized.
- setDbHelperToSerializeOn(mContactsHelper, CONTACTS_DB_TAG);
+ setDbHelperToSerializeOn(mContactsHelper, CONTACTS_DB_TAG, this);
mContactDirectoryManager = new ContactDirectoryManager(this);
mGlobalSearchSupport = new GlobalSearchSupport(this);
@@ -1413,8 +1406,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
};
// Set up the sub-provider for handling profiles.
- mProfileProvider = getProfileProvider();
- mProfileProvider.setDbHelperToSerializeOn(mContactsHelper, CONTACTS_DB_TAG);
+ mProfileProvider = newProfileProvider();
+ mProfileProvider.setDbHelperToSerializeOn(mContactsHelper, CONTACTS_DB_TAG, this);
ProviderInfo profileInfo = new ProviderInfo();
profileInfo.readPermission = "android.permission.READ_PROFILE";
profileInfo.writePermission = "android.permission.WRITE_PROFILE";
@@ -1521,6 +1514,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
protected void performBackgroundTask(int task, Object arg) {
+ // Make sure we operate on the contacts db by default.
+ switchToContactMode();
switch (task) {
case BACKGROUND_TASK_INITIALIZE: {
initForDefaultLocale();
@@ -1551,6 +1546,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
switchToProfileMode();
accountsChanged |= updateAccountsInBackground(accounts);
+ switchToContactMode();
+
updateContactsAccountCount(accounts);
updateDirectoriesInBackground(accountsChanged);
break;
@@ -1601,6 +1598,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
cleanupPhotoStore();
switchToProfileMode();
cleanupPhotoStore();
+
+ switchToContactMode(); // Switch to the default, just in case.
break;
}
}
@@ -1705,8 +1704,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
@VisibleForTesting
protected void cleanupPhotoStore() {
- SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
- mActiveDb.set(db);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
// Assemble the set of photo store file IDs that are in use, and send those to the photo
// store. Any photos that aren't in that set will be deleted, and any photos that no
@@ -1759,7 +1757,9 @@ public class ContactsProvider2 extends AbstractContactsProvider
// using internal APIs or direct DB access to avoid permission errors.
if (!missingPhotoIds.isEmpty()) {
try {
- db.beginTransactionWithListener(this);
+ // Need to set the db listener because we need to run onCommit afterwards.
+ // Make sure to use the proper listener depending on the current mode.
+ db.beginTransactionWithListener(inProfileMode() ? mProfileProvider : this);
for (long missingPhotoId : missingPhotoIds) {
if (photoFileIdToDataId.containsKey(missingPhotoId)) {
long dataId = photoFileIdToDataId.get(missingPhotoId);
@@ -1796,7 +1796,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
return mTransactionHolder;
}
- public ProfileProvider getProfileProvider() {
+ public ProfileProvider newProfileProvider() {
return new ProfileProvider(this);
}
@@ -1835,7 +1835,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
return Locale.getDefault();
}
- private boolean inProfileMode() {
+ @VisibleForTesting
+ final boolean inProfileMode() {
Boolean profileMode = mInProfileMode.get();
return profileMode != null && profileMode;
}
@@ -1921,7 +1922,10 @@ public class ContactsProvider2 extends AbstractContactsProvider
* Switches the provider's thread-local context variables to prepare for performing
* a profile operation.
*/
- protected void switchToProfileMode() {
+ private void switchToProfileMode() {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "switchToProfileMode", new RuntimeException("switchToProfileMode"));
+ }
mDbHelper.set(mProfileHelper);
mTransactionContext.set(mProfileTransactionContext);
mAggregator.set(mProfileAggregator);
@@ -1933,15 +1937,15 @@ public class ContactsProvider2 extends AbstractContactsProvider
* Switches the provider's thread-local context variables to prepare for performing
* a contacts operation.
*/
- protected void switchToContactMode() {
+ private void switchToContactMode() {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "switchToContactMode", new RuntimeException("switchToContactMode"));
+ }
mDbHelper.set(mContactsHelper);
mTransactionContext.set(mContactTransactionContext);
mAggregator.set(mContactAggregator);
mPhotoStore.set(mContactsPhotoStore);
mInProfileMode.set(false);
-
- // Clear out the active database; modification operations will set this to the contacts DB.
- mActiveDb.set(null);
}
@Override
@@ -2000,17 +2004,10 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
}
- /**
- * Replaces the current (thread-local) database to use for the operation with the given one.
- * @param db The database to use.
- */
- /* package */ void substituteDb(SQLiteDatabase db) {
- mActiveDb.set(db);
- }
-
@Override
public Bundle call(String method, String arg, Bundle extras) {
waitForAccess(mReadAccessLatch);
+ switchToContactMode();
if (method.equals(Authorization.AUTHORIZATION_METHOD)) {
Uri uri = (Uri) extras.getParcelable(Authorization.KEY_URI_TO_AUTHORIZE);
@@ -2110,13 +2107,20 @@ public class ContactsProvider2 extends AbstractContactsProvider
@Override
public void onBegin() {
- if (VERBOSE_LOGGING) {
- Log.v(TAG, "onBeginTransaction: " + (inProfileMode() ? "profile" : "contacts"));
+ onBeginTransactionInternal(false);
+ }
+
+ protected void onBeginTransactionInternal(boolean forProfile) {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "onBeginTransaction: " + (forProfile ? "profile" : "contacts"),
+ new RuntimeException("onBeginTransactionInternal"));
}
- if (inProfileMode()) {
+ if (forProfile) {
+ switchToProfileMode();
mProfileAggregator.clearPendingAggregations();
mProfileTransactionContext.clearExceptSearchIndexUpdates();
} else {
+ switchToContactMode();
mContactAggregator.clearPendingAggregations();
mContactTransactionContext.clearExceptSearchIndexUpdates();
}
@@ -2124,11 +2128,23 @@ public class ContactsProvider2 extends AbstractContactsProvider
@Override
public void onCommit() {
- if (VERBOSE_LOGGING) {
- Log.v(TAG, "beforeTransactionCommit: " + (inProfileMode() ? "profile" : "contacts"));
+ onCommitTransactionInternal(false);
+ }
+
+ protected void onCommitTransactionInternal(boolean forProfile) {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "onCommitTransactionInternal: " + (forProfile ? "profile" : "contacts"),
+ new RuntimeException("onCommitTransactionInternal"));
+ }
+ if (forProfile) {
+ switchToProfileMode();
+ } else {
+ switchToContactMode();
}
+
flushTransactionalChanges();
- mAggregator.get().aggregateInTransaction(mTransactionContext.get(), mActiveDb.get());
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ mAggregator.get().aggregateInTransaction(mTransactionContext.get(), db);
if (mVisibleTouched) {
mVisibleTouched = false;
mDbHelper.get().updateAllVisible();
@@ -2147,13 +2163,21 @@ public class ContactsProvider2 extends AbstractContactsProvider
@Override
public void onRollback() {
- if (VERBOSE_LOGGING) {
- Log.v(TAG, "beforeTransactionRollback: " + (inProfileMode() ? "profile" : "contacts"));
+ onRollbackTransactionInternal(false);
+ }
+
+ protected void onRollbackTransactionInternal(boolean forProfile) {
+ if (ENABLE_TRANSACTION_LOG) {
+ Log.i(TAG, "onRollbackTransactionInternal: " + (forProfile ? "profile" : "contacts"),
+ new RuntimeException("onRollbackTransactionInternal"));
+ }
+ if (forProfile) {
+ switchToProfileMode();
+ } else {
+ switchToContactMode();
}
- // mDbHelper may not be pointing at the "right" db helper due to a bug,
- // so we invalidate both for now.
- mContactsHelper.invalidateAllCache();
- mProfileHelper.invalidateAllCache();
+
+ mDbHelper.get().invalidateAllCache();
}
private void updateSearchIndexInTransaction() {
@@ -2167,12 +2191,13 @@ public class ContactsProvider2 extends AbstractContactsProvider
private void flushTransactionalChanges() {
if (VERBOSE_LOGGING) {
- Log.v(TAG, "flushTransactionChanges");
+ Log.v(TAG, "flushTransactionalChanges: " + (inProfileMode() ? "profile" : "contacts"));
}
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
for (long rawContactId : mTransactionContext.get().getInsertedRawContactIds()) {
- mDbHelper.get().updateRawContactDisplayName(mActiveDb.get(), rawContactId);
- mAggregator.get().onRawContactInsert(mTransactionContext.get(), mActiveDb.get(),
+ mDbHelper.get().updateRawContactDisplayName(db, rawContactId);
+ mAggregator.get().onRawContactInsert(mTransactionContext.get(), db,
rawContactId);
}
@@ -2182,7 +2207,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
mSb.append(UPDATE_RAW_CONTACT_SET_DIRTY_SQL);
appendIds(mSb, dirtyRawContacts);
mSb.append(")");
- mActiveDb.get().execSQL(mSb.toString());
+ db.execSQL(mSb.toString());
}
Set<Long> updatedRawContacts = mTransactionContext.get().getUpdatedRawContactIds();
@@ -2191,13 +2216,13 @@ public class ContactsProvider2 extends AbstractContactsProvider
mSb.append(UPDATE_RAW_CONTACT_SET_VERSION_SQL);
appendIds(mSb, updatedRawContacts);
mSb.append(")");
- mActiveDb.get().execSQL(mSb.toString());
+ db.execSQL(mSb.toString());
}
// Update sync states.
for (Map.Entry<Long, Object> entry : mTransactionContext.get().getUpdatedSyncStates()) {
long id = entry.getKey();
- if (mDbHelper.get().getSyncState().update(mActiveDb.get(), id, entry.getValue()) <= 0) {
+ if (mDbHelper.get().getSyncState().update(db, id, entry.getValue()) <= 0) {
throw new IllegalStateException(
"unable to update sync state, does it still exist?");
}
@@ -2265,10 +2290,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
Log.v(TAG, "insertInTransaction: uri=" + uri + " values=[" + values + "]");
}
- // Default active DB to the contacts DB if none has been set.
- if (mActiveDb.get() == null) {
- mActiveDb.set(mContactsHelper.getWritableDatabase());
- }
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
final boolean callerIsSyncAdapter =
readBooleanQueryParameter(uri, ContactsContract.CALLER_IS_SYNCADAPTER, false);
@@ -2279,7 +2301,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
switch (match) {
case SYNCSTATE:
case PROFILE_SYNCSTATE:
- id = mDbHelper.get().getSyncState().insert(mActiveDb.get(), values);
+ id = mDbHelper.get().getSyncState().insert(db, values);
break;
case CONTACTS: {
@@ -2506,7 +2528,9 @@ public class ContactsProvider2 extends AbstractContactsProvider
mValues.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED);
}
- long rawContactId = mActiveDb.get().insert(Tables.RAW_CONTACTS,
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
+ long rawContactId = db.insert(Tables.RAW_CONTACTS,
RawContacts.CONTACT_ID, mValues);
int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT;
if (mValues.containsKey(RawContacts.AGGREGATION_MODE)) {
@@ -2538,7 +2562,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
private Long findGroupByRawContactId(String selection, long rawContactId) {
- Cursor c = mActiveDb.get().query(Tables.GROUPS + "," + Tables.RAW_CONTACTS,
+ final SQLiteDatabase db = mDbHelper.get().getReadableDatabase();
+ Cursor c = db.query(Tables.GROUPS + "," + Tables.RAW_CONTACTS,
PROJECTION_GROUP_ID, selection,
new String[]{Long.toString(rawContactId)},
null /* groupBy */, null /* having */, null /* orderBy */);
@@ -2570,7 +2595,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
groupMembershipValues.put(GroupMembership.RAW_CONTACT_ID, rawContactId);
groupMembershipValues.put(DataColumns.MIMETYPE_ID,
mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE));
- mActiveDb.get().insert(Tables.DATA, null, groupMembershipValues);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ db.insert(Tables.DATA, null, groupMembershipValues);
}
private void deleteDataGroupMembership(long rawContactId, long groupId) {
@@ -2578,7 +2604,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
Long.toString(mDbHelper.get().getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE)),
Long.toString(groupId),
Long.toString(rawContactId)};
- mActiveDb.get().delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ db.delete(Tables.DATA, SELECTION_GROUPMEMBERSHIP_DATA, selectionArgs);
}
/**
@@ -2611,7 +2638,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
mValues.remove(Data.MIMETYPE);
DataRowHandler rowHandler = getDataRowHandler(mimeType);
- id = rowHandler.insert(mActiveDb.get(), mTransactionContext.get(), rawContactId, mValues);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ id = rowHandler.insert(db, mTransactionContext.get(), rawContactId, mValues);
if (!callerIsSyncAdapter) {
mTransactionContext.get().markRawContactDirty(rawContactId);
}
@@ -2642,7 +2670,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
mValues.remove(RawContacts.ACCOUNT_TYPE);
// Insert the new stream item.
- id = mActiveDb.get().insert(Tables.STREAM_ITEMS, null, mValues);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ id = db.insert(Tables.STREAM_ITEMS, null, mValues);
if (id == -1) {
// Insertion failed.
return 0;
@@ -2682,7 +2711,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
// Process the photo and store it.
if (processStreamItemPhoto(mValues, false)) {
// Insert the stream item photo.
- id = mActiveDb.get().insert(Tables.STREAM_ITEM_PHOTOS, null, mValues);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ id = db.insert(Tables.STREAM_ITEM_PHOTOS, null, mValues);
}
}
return id;
@@ -2734,7 +2764,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
*/
private long lookupRawContactIdForStreamId(long streamItemId) {
long rawContactId = -1;
- Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS,
+ final SQLiteDatabase db = mDbHelper.get().getReadableDatabase();
+ Cursor c = db.query(Tables.STREAM_ITEMS,
new String[]{StreamItems.RAW_CONTACT_ID},
StreamItems._ID + "=?", new String[]{String.valueOf(streamItemId)},
null, null, null);
@@ -2786,7 +2817,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
*/
private long cleanUpOldStreamItems(long rawContactId, long insertedStreamItemId) {
long postCleanupInsertedStreamId = insertedStreamItemId;
- Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS, new String[]{StreamItems._ID},
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ Cursor c = db.query(Tables.STREAM_ITEMS, new String[]{StreamItems._ID},
StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)},
null, null, StreamItems.TIMESTAMP + " DESC, " + StreamItems._ID + " DESC");
try {
@@ -2802,7 +2834,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
// The stream item just inserted is being deleted.
postCleanupInsertedStreamId = 0;
}
- deleteStreamItem(c.getLong(0));
+ deleteStreamItem(db, c.getLong(0));
c.moveToPrevious();
}
}
@@ -2818,6 +2850,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
private int deleteData(String selection, String[] selectionArgs, boolean callerIsSyncAdapter) {
int count = 0;
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// Note that the query will return data according to the access restrictions,
// so we don't need to worry about deleting data we don't have permission to read.
Uri dataUri = inProfileMode()
@@ -2830,7 +2864,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
long rawContactId = c.getLong(DataRowHandler.DataDeleteQuery.RAW_CONTACT_ID);
String mimeType = c.getString(DataRowHandler.DataDeleteQuery.MIMETYPE);
DataRowHandler rowHandler = getDataRowHandler(mimeType);
- count += rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c);
+ count += rowHandler.delete(db, mTransactionContext.get(), c);
if (!callerIsSyncAdapter) {
mTransactionContext.get().markRawContactDirty(rawContactId);
}
@@ -2847,6 +2881,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
*/
public int deleteData(long dataId, String[] allowedMimeTypes) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// Note that the query will return data according to the access restrictions,
// so we don't need to worry about deleting data we don't have permission to read.
mSelectionArgs1[0] = String.valueOf(dataId);
@@ -2872,7 +2908,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
+ Lists.newArrayList(allowedMimeTypes));
}
DataRowHandler rowHandler = getDataRowHandler(mimeType);
- return rowHandler.delete(mActiveDb.get(), mTransactionContext.get(), c);
+ return rowHandler.delete(db, mTransactionContext.get(), c);
} finally {
c.close();
}
@@ -2907,12 +2943,14 @@ public class ContactsProvider2 extends AbstractContactsProvider
mValues.put(Groups.DIRTY, 1);
}
- long result = mActiveDb.get().insert(Tables.GROUPS, Groups.TITLE, mValues);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
+ long result = db.insert(Tables.GROUPS, Groups.TITLE, mValues);
if (!callerIsSyncAdapter && isFavoritesGroup) {
// If the inserted group is a favorite group, add all starred raw contacts to it.
mSelectionArgs1[0] = Long.toString(accountId);
- Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS,
+ Cursor c = db.query(Tables.RAW_CONTACTS,
new String[]{RawContacts._ID, RawContacts.STARRED},
RawContactsColumns.CONCRETE_ACCOUNT_ID + "=?", mSelectionArgs1,
null, null, null);
@@ -2975,8 +3013,10 @@ public class ContactsProvider2 extends AbstractContactsProvider
c.close();
}
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// If we didn't find a duplicate, we're fine to insert.
- final long id = mActiveDb.get().insert(Tables.SETTINGS, null, values);
+ final long id = db.insert(Tables.SETTINGS, null, values);
if (values.containsKey(Settings.UNGROUPED_VISIBLE)) {
mVisibleTouched = true;
@@ -2993,6 +3033,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
final Integer protocol = values.getAsInteger(StatusUpdates.PROTOCOL);
String customProtocol = null;
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
if (protocol != null && protocol == Im.PROTOCOL_CUSTOM) {
customProtocol = values.getAsString(StatusUpdates.CUSTOM_PROTOCOL);
if (TextUtils.isEmpty(customProtocol)) {
@@ -3068,7 +3110,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
Cursor cursor = null;
try {
- cursor = mActiveDb.get().query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION,
+ cursor = db.query(DataContactsQuery.TABLE, DataContactsQuery.PROJECTION,
mSb.toString(), mSelectionArgs.toArray(EMPTY_STRING_ARRAY), null, null,
Clauses.CONTACT_VISIBLE + " DESC, " + Data.RAW_CONTACT_ID);
if (cursor.moveToFirst()) {
@@ -3110,7 +3152,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
values.getAsString(StatusUpdates.CHAT_CAPABILITY));
// Insert the presence update
- mActiveDb.get().replace(Tables.PRESENCE, null, mValues);
+ db.replace(Tables.PRESENCE, null, mValues);
}
@@ -3237,10 +3279,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
" selection=[" + selection + "] args=" + Arrays.toString(selectionArgs));
}
- // Default active DB to the contacts DB if none has been set.
- if (mActiveDb.get() == null) {
- mActiveDb.set(mContactsHelper.getWritableDatabase());
- }
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
flushTransactionalChanges();
final boolean callerIsSyncAdapter =
@@ -3249,14 +3288,14 @@ public class ContactsProvider2 extends AbstractContactsProvider
switch (match) {
case SYNCSTATE:
case PROFILE_SYNCSTATE:
- return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selection,
+ return mDbHelper.get().getSyncState().delete(db, selection,
selectionArgs);
case SYNCSTATE_ID: {
String selectionWithId =
(SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ (selection == null ? "" : " AND (" + selection + ")");
- return mDbHelper.get().getSyncState().delete(mActiveDb.get(), selectionWithId,
+ return mDbHelper.get().getSyncState().delete(db, selectionWithId,
selectionArgs);
}
@@ -3264,7 +3303,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
String selectionWithId =
(SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ (selection == null ? "" : " AND (" + selection + ")");
- return mProfileHelper.getSyncState().delete(mActiveDb.get(), selectionWithId,
+ return mProfileHelper.getSyncState().delete(db, selectionWithId,
selectionArgs);
}
@@ -3289,7 +3328,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
"Missing a lookup key", uri));
}
final String lookupKey = pathSegments.get(2);
- final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
+ final long contactId = lookupContactIdByLookupKey(db, lookupKey);
return deleteContact(contactId, callerIsSyncAdapter);
}
@@ -3311,7 +3350,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
args[0] = String.valueOf(contactId);
args[1] = Uri.encode(lookupKey);
lookupQb.appendWhere(Contacts._ID + "=? AND " + Contacts.LOOKUP_KEY + "=?");
- Cursor c = query(mActiveDb.get(), lookupQb, null, selection, args, null, null,
+ Cursor c = query(db, lookupQb, null, selection, args, null, null,
null, null, null);
try {
if (c.getCount() == 1) {
@@ -3335,7 +3374,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
case PROFILE_RAW_CONTACTS: {
invalidateFastScrollingIndexCache();
int numDeletes = 0;
- Cursor c = mActiveDb.get().query(Views.RAW_CONTACTS,
+ Cursor c = db.query(Views.RAW_CONTACTS,
new String[]{RawContacts._ID, RawContacts.CONTACT_ID},
appendAccountIdToSelection(uri, selection), selectionArgs,
null, null, null);
@@ -3388,7 +3427,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
case GROUPS: {
int numDeletes = 0;
- Cursor c = mActiveDb.get().query(Views.GROUPS, Projections.ID,
+ Cursor c = db.query(Views.GROUPS, Projections.ID,
appendAccountIdToSelection(uri, selection), selectionArgs,
null, null, null);
try {
@@ -3464,21 +3503,22 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
public int deleteGroup(Uri uri, long groupId, boolean callerIsSyncAdapter) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
mGroupIdCache.clear();
final long groupMembershipMimetypeId = mDbHelper.get()
.getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
- mActiveDb.get().delete(Tables.DATA, DataColumns.MIMETYPE_ID + "="
+ db.delete(Tables.DATA, DataColumns.MIMETYPE_ID + "="
+ groupMembershipMimetypeId + " AND " + GroupMembership.GROUP_ROW_ID + "="
+ groupId, null);
try {
if (callerIsSyncAdapter) {
- return mActiveDb.get().delete(Tables.GROUPS, Groups._ID + "=" + groupId, null);
+ return db.delete(Tables.GROUPS, Groups._ID + "=" + groupId, null);
} else {
mValues.clear();
mValues.put(Groups.DELETED, 1);
mValues.put(Groups.DIRTY, 1);
- return mActiveDb.get().update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId,
+ return db.update(Tables.GROUPS, mValues, Groups._ID + "=" + groupId,
null);
}
} finally {
@@ -3487,20 +3527,22 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
private int deleteSettings(Uri uri, String selection, String[] selectionArgs) {
- final int count = mActiveDb.get().delete(Tables.SETTINGS, selection, selectionArgs);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ final int count = db.delete(Tables.SETTINGS, selection, selectionArgs);
mVisibleTouched = true;
return count;
}
private int deleteContact(long contactId, boolean callerIsSyncAdapter) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
mSelectionArgs1[0] = Long.toString(contactId);
- Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID},
+ Cursor c = db.query(Tables.RAW_CONTACTS, new String[]{RawContacts._ID},
RawContacts.CONTACT_ID + "=?", mSelectionArgs1,
null, null, null);
try {
while (c.moveToNext()) {
long rawContactId = c.getLong(0);
- markRawContactAsDeleted(rawContactId, callerIsSyncAdapter);
+ markRawContactAsDeleted(db, rawContactId, callerIsSyncAdapter);
}
} finally {
c.close();
@@ -3508,36 +3550,38 @@ public class ContactsProvider2 extends AbstractContactsProvider
mProviderStatusUpdateNeeded = true;
- return mActiveDb.get().delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null);
+ return db.delete(Tables.CONTACTS, Contacts._ID + "=" + contactId, null);
}
public int deleteRawContact(long rawContactId, long contactId, boolean callerIsSyncAdapter) {
mAggregator.get().invalidateAggregationExceptionCache();
mProviderStatusUpdateNeeded = true;
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// Find and delete stream items associated with the raw contact.
- Cursor c = mActiveDb.get().query(Tables.STREAM_ITEMS,
+ Cursor c = db.query(Tables.STREAM_ITEMS,
new String[]{StreamItems._ID},
StreamItems.RAW_CONTACT_ID + "=?", new String[]{String.valueOf(rawContactId)},
null, null, null);
try {
while (c.moveToNext()) {
- deleteStreamItem(c.getLong(0));
+ deleteStreamItem(db, c.getLong(0));
}
} finally {
c.close();
}
if (callerIsSyncAdapter || rawContactIsLocal(rawContactId)) {
- mActiveDb.get().delete(Tables.PRESENCE,
+ db.delete(Tables.PRESENCE,
PresenceColumns.RAW_CONTACT_ID + "=" + rawContactId, null);
- int count = mActiveDb.get().delete(Tables.RAW_CONTACTS,
+ int count = db.delete(Tables.RAW_CONTACTS,
RawContacts._ID + "=" + rawContactId, null);
mAggregator.get().updateAggregateData(mTransactionContext.get(), contactId);
return count;
} else {
mDbHelper.get().removeContactIfSingleton(rawContactId);
- return markRawContactAsDeleted(rawContactId, callerIsSyncAdapter);
+ return markRawContactAsDeleted(db, rawContactId, callerIsSyncAdapter);
}
}
@@ -3545,7 +3589,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
* Returns whether the given raw contact ID is local (i.e. has no account associated with it).
*/
private boolean rawContactIsLocal(long rawContactId) {
- Cursor c = mActiveDb.get().query(Tables.RAW_CONTACTS, Projections.LITERAL_ONE,
+ final SQLiteDatabase db = mDbHelper.get().getReadableDatabase();
+ Cursor c = db.query(Tables.RAW_CONTACTS, Projections.LITERAL_ONE,
RawContactsColumns.CONCRETE_ID + "=? AND " +
RawContactsColumns.ACCOUNT_ID + "=" + Clauses.LOCAL_ACCOUNT_ID,
new String[] {String.valueOf(rawContactId)}, null, null, null);
@@ -3562,20 +3607,22 @@ public class ContactsProvider2 extends AbstractContactsProvider
if (VERBOSE_LOGGING) {
Log.v(TAG, "deleting data from status_updates for " + selection);
}
- mActiveDb.get().delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection),
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ db.delete(Tables.STATUS_UPDATES, getWhereClauseForStatusUpdatesTable(selection),
selectionArgs);
- return mActiveDb.get().delete(Tables.PRESENCE, selection, selectionArgs);
+ return db.delete(Tables.PRESENCE, selection, selectionArgs);
}
private int deleteStreamItems(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
int count = 0;
- final Cursor c = mActiveDb.get().query(Views.STREAM_ITEMS, Projections.ID,
+ final Cursor c = db.query(Views.STREAM_ITEMS, Projections.ID,
selection, selectionArgs, null, null, null);
try {
c.moveToPosition(-1);
while (c.moveToNext()) {
- count += deleteStreamItem(c.getLong(0));
+ count += deleteStreamItem(db, c.getLong(0));
}
} finally {
c.close();
@@ -3583,25 +3630,28 @@ public class ContactsProvider2 extends AbstractContactsProvider
return count;
}
- private int deleteStreamItem(long streamItemId) {
+ private int deleteStreamItem(SQLiteDatabase db, long streamItemId) {
deleteStreamItemPhotos(streamItemId);
- return mActiveDb.get().delete(Tables.STREAM_ITEMS, StreamItems._ID + "=?",
+ return db.delete(Tables.STREAM_ITEMS, StreamItems._ID + "=?",
new String[]{String.valueOf(streamItemId)});
}
private int deleteStreamItemPhotos(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
- return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS, selection, selectionArgs);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ return db.delete(Tables.STREAM_ITEM_PHOTOS, selection, selectionArgs);
}
private int deleteStreamItemPhotos(long streamItemId) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
// Note that this does not enforce the modifying account.
- return mActiveDb.get().delete(Tables.STREAM_ITEM_PHOTOS,
+ return db.delete(Tables.STREAM_ITEM_PHOTOS,
StreamItemPhotos.STREAM_ITEM_ID + "=?",
new String[]{String.valueOf(streamItemId)});
}
- private int markRawContactAsDeleted(long rawContactId, boolean callerIsSyncAdapter) {
+ private int markRawContactAsDeleted(SQLiteDatabase db, long rawContactId,
+ boolean callerIsSyncAdapter) {
mSyncToNetwork = true;
mValues.clear();
@@ -3610,11 +3660,11 @@ public class ContactsProvider2 extends AbstractContactsProvider
mValues.put(RawContactsColumns.AGGREGATION_NEEDED, 1);
mValues.putNull(RawContacts.CONTACT_ID);
mValues.put(RawContacts.DIRTY, 1);
- return updateRawContact(rawContactId, mValues, callerIsSyncAdapter);
+ return updateRawContact(db, rawContactId, mValues, callerIsSyncAdapter);
}
private int deleteDataUsage() {
- final SQLiteDatabase db = mActiveDb.get();
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
db.execSQL("UPDATE " + Tables.RAW_CONTACTS + " SET " +
Contacts.TIMES_CONTACTED + "=0," +
Contacts.LAST_TIME_CONTACTED + "=NULL"
@@ -3637,10 +3687,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
" values=[" + values + "]");
}
- // Default active DB to the contacts DB if none has been set.
- if (mActiveDb.get() == null) {
- mActiveDb.set(mContactsHelper.getWritableDatabase());
- }
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
int count = 0;
@@ -3657,7 +3704,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
switch(match) {
case SYNCSTATE:
case PROFILE_SYNCSTATE:
- return mDbHelper.get().getSyncState().update(mActiveDb.get(), values,
+ return mDbHelper.get().getSyncState().update(db, values,
appendAccountToSelection(uri, selection), selectionArgs);
case SYNCSTATE_ID: {
@@ -3665,7 +3712,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
String selectionWithId =
(SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ (selection == null ? "" : " AND (" + selection + ")");
- return mDbHelper.get().getSyncState().update(mActiveDb.get(), values,
+ return mDbHelper.get().getSyncState().update(db, values,
selectionWithId, selectionArgs);
}
@@ -3674,7 +3721,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
String selectionWithId =
(SyncStateContract.Columns._ID + "=" + ContentUris.parseId(uri) + " ")
+ (selection == null ? "" : " AND (" + selection + ")");
- return mProfileHelper.getSyncState().update(mActiveDb.get(), values,
+ return mProfileHelper.getSyncState().update(db, values,
selectionWithId, selectionArgs);
}
@@ -3687,7 +3734,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
case CONTACTS_ID: {
invalidateFastScrollingIndexCache();
- count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter);
+ count = updateContactOptions(db, ContentUris.parseId(uri), values,
+ callerIsSyncAdapter);
break;
}
@@ -3701,8 +3749,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
"Missing a lookup key", uri));
}
final String lookupKey = pathSegments.get(2);
- final long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
- count = updateContactOptions(contactId, values, callerIsSyncAdapter);
+ final long contactId = lookupContactIdByLookupKey(db, lookupKey);
+ count = updateContactOptions(db, contactId, values, callerIsSyncAdapter);
break;
}
@@ -3790,7 +3838,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
case AGGREGATION_EXCEPTIONS: {
- count = updateAggregationException(mActiveDb.get(), values);
+ count = updateAggregationException(db, values);
break;
}
@@ -3875,12 +3923,13 @@ public class ContactsProvider2 extends AbstractContactsProvider
private int updateStatusUpdate(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
// update status_updates table, if status is provided
// TODO should account type/name be appended to the where clause?
int updateCount = 0;
ContentValues settableValues = getSettableColumnsForStatusUpdatesTable(values);
if (settableValues.size() > 0) {
- updateCount = mActiveDb.get().update(Tables.STATUS_UPDATES,
+ updateCount = db.update(Tables.STATUS_UPDATES,
settableValues,
getWhereClauseForStatusUpdatesTable(selection),
selectionArgs);
@@ -3889,7 +3938,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
// now update the Presence table
settableValues = getSettableColumnsForPresenceTable(values);
if (settableValues.size() > 0) {
- updateCount = mActiveDb.get().update(Tables.PRESENCE, settableValues,
+ updateCount = db.update(Tables.PRESENCE, settableValues,
selection, selectionArgs);
}
// TODO updateCount is not entirely a valid count of updated rows because 2 tables could
@@ -3906,8 +3955,10 @@ public class ContactsProvider2 extends AbstractContactsProvider
values.remove(RawContacts.ACCOUNT_NAME);
values.remove(RawContacts.ACCOUNT_TYPE);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// If there's been no exception, the update should be fine.
- return mActiveDb.get().update(Tables.STREAM_ITEMS, values, selection, selectionArgs);
+ return db.update(Tables.STREAM_ITEMS, values, selection, selectionArgs);
}
private int updateStreamItemPhotos(Uri uri, ContentValues values, String selection,
@@ -3920,10 +3971,12 @@ public class ContactsProvider2 extends AbstractContactsProvider
values.remove(RawContacts.ACCOUNT_NAME);
values.remove(RawContacts.ACCOUNT_TYPE);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
// Process the photo (since we're updating, it's valid for the photo to not be present).
if (processStreamItemPhoto(values, true)) {
// If there's been no exception, the update should be fine.
- return mActiveDb.get().update(Tables.STREAM_ITEM_PHOTOS, values, selection,
+ return db.update(Tables.STREAM_ITEM_PHOTOS, values, selection,
selectionArgs);
}
return 0;
@@ -3983,7 +4036,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
String[] selectionArgs, boolean callerIsSyncAdapter) {
mGroupIdCache.clear();
- final SQLiteDatabase db = mActiveDb.get();
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
final ContactsDatabaseHelper dbHelper = mDbHelper.get();
final ContentValues updatedValues = new ContentValues();
@@ -4068,7 +4121,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
private int updateSettings(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
- final int count = mActiveDb.get().update(Tables.SETTINGS, values, selection, selectionArgs);
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ final int count = db.update(Tables.SETTINGS, values, selection, selectionArgs);
if (values.containsKey(Settings.UNGROUPED_VISIBLE)) {
mVisibleTouched = true;
}
@@ -4088,13 +4142,14 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
int count = 0;
- Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS,
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+ Cursor cursor = db.query(Views.RAW_CONTACTS,
Projections.ID, selection,
selectionArgs, null, null, null);
try {
while (cursor.moveToNext()) {
long rawContactId = cursor.getLong(0);
- updateRawContact(rawContactId, values, callerIsSyncAdapter);
+ updateRawContact(db, rawContactId, values, callerIsSyncAdapter);
count++;
}
} finally {
@@ -4104,7 +4159,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
return count;
}
- private int updateRawContact(long rawContactId, ContentValues values,
+ private int updateRawContact(SQLiteDatabase db, long rawContactId, ContentValues values,
boolean callerIsSyncAdapter) {
final String selection = RawContactsColumns.CONCRETE_ID + " = ?";
mSelectionArgs1[0] = Long.toString(rawContactId);
@@ -4127,7 +4182,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
String oldDataSet = null;
if (requestUndoDelete || isAccountChanging) {
- Cursor cursor = mActiveDb.get().query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS,
+ Cursor cursor = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS,
selection, mSelectionArgs1, null, null, null);
try {
if (cursor.moveToFirst()) {
@@ -4172,7 +4227,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT);
}
- int count = mActiveDb.get().update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1);
+ int count = db.update(Tables.RAW_CONTACTS, values, selection, mSelectionArgs1);
if (count != 0) {
if (values.containsKey(RawContacts.AGGREGATION_MODE)) {
int aggregationMode = values.getAsInteger(RawContacts.AGGREGATION_MODE);
@@ -4195,7 +4250,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
// If it is starred, add a group membership, if one doesn't already exist
// otherwise delete any matching group memberships.
if (!callerIsSyncAdapter && isAccountChanging) {
- boolean starred = 0 != DatabaseUtils.longForQuery(mActiveDb.get(),
+ boolean starred = 0 != DatabaseUtils.longForQuery(db,
SELECTION_STARRED_FROM_RAW_CONTACTS,
new String[]{Long.toString(rawContactId)});
updateFavoritesMembership(rawContactId, starred);
@@ -4209,7 +4264,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
if (values.containsKey(RawContacts.SOURCE_ID)) {
- mAggregator.get().updateLookupKeyForRawContact(mActiveDb.get(), rawContactId);
+ mAggregator.get().updateLookupKeyForRawContact(db, rawContactId);
}
if (values.containsKey(RawContacts.NAME_VERIFIED)) {
@@ -4218,7 +4273,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
if (values.getAsInteger(RawContacts.NAME_VERIFIED) != 0) {
mDbHelper.get().resetNameVerifiedForOtherRawContacts(rawContactId);
}
- mAggregator.get().updateDisplayNameForRawContact(mActiveDb.get(), rawContactId);
+ mAggregator.get().updateDisplayNameForRawContact(db, rawContactId);
}
if (requestUndoDelete && previousDeleted == 1) {
// Note before the accounts refactoring, we used to use the *old* account here,
@@ -4273,10 +4328,12 @@ public class ContactsProvider2 extends AbstractContactsProvider
return 0;
}
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
final String mimeType = c.getString(DataRowHandler.DataUpdateQuery.MIMETYPE);
DataRowHandler rowHandler = getDataRowHandler(mimeType);
boolean updated =
- rowHandler.update(mActiveDb.get(), mTransactionContext.get(), values, c,
+ rowHandler.update(db, mTransactionContext.get(), values, c,
callerIsSyncAdapter);
if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
scheduleBackgroundTask(BACKGROUND_TASK_CLEANUP_PHOTOS);
@@ -4287,13 +4344,15 @@ public class ContactsProvider2 extends AbstractContactsProvider
private int updateContactOptions(ContentValues values, String selection,
String[] selectionArgs, boolean callerIsSyncAdapter) {
int count = 0;
- Cursor cursor = mActiveDb.get().query(Views.CONTACTS,
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+
+ Cursor cursor = db.query(Views.CONTACTS,
new String[] { Contacts._ID }, selection, selectionArgs, null, null, null);
try {
while (cursor.moveToNext()) {
long contactId = cursor.getLong(0);
- updateContactOptions(contactId, values, callerIsSyncAdapter);
+ updateContactOptions(db, contactId, values, callerIsSyncAdapter);
count++;
}
} finally {
@@ -4303,7 +4362,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
return count;
}
- private int updateContactOptions(long contactId, ContentValues values,
+ private int updateContactOptions(SQLiteDatabase db, long contactId, ContentValues values,
boolean callerIsSyncAdapter) {
mValues.clear();
@@ -4329,11 +4388,11 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
mSelectionArgs1[0] = String.valueOf(contactId);
- mActiveDb.get().update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?"
+ db.update(Tables.RAW_CONTACTS, mValues, RawContacts.CONTACT_ID + "=?"
+ " AND " + RawContacts.RAW_CONTACT_IS_READ_ONLY + "=0", mSelectionArgs1);
if (mValues.containsKey(RawContacts.STARRED) && !callerIsSyncAdapter) {
- Cursor cursor = mActiveDb.get().query(Views.RAW_CONTACTS,
+ Cursor cursor = db.query(Views.RAW_CONTACTS,
new String[] { RawContacts._ID }, RawContacts.CONTACT_ID + "=?",
mSelectionArgs1, null, null, null);
try {
@@ -4361,13 +4420,13 @@ public class ContactsProvider2 extends AbstractContactsProvider
ContactsDatabaseHelper.copyLongValue(mValues, RawContacts.STARRED,
values, Contacts.STARRED);
- int rslt = mActiveDb.get().update(Tables.CONTACTS, mValues, Contacts._ID + "=?",
+ int rslt = db.update(Tables.CONTACTS, mValues, Contacts._ID + "=?",
mSelectionArgs1);
if (values.containsKey(Contacts.LAST_TIME_CONTACTED) &&
!values.containsKey(Contacts.TIMES_CONTACTED)) {
- mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1);
- mActiveDb.get().execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1);
+ db.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1);
+ db.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1);
}
return rslt;
}
@@ -4416,6 +4475,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
return 1;
}
+ @Override
public void onAccountsUpdated(Account[] accounts) {
scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS);
}
@@ -4499,7 +4559,6 @@ public class ContactsProvider2 extends AbstractContactsProvider
final ContactsDatabaseHelper dbHelper = mDbHelper.get();
final SQLiteDatabase db = dbHelper.getWritableDatabase();
- mActiveDb.set(db);
db.beginTransaction();
// WARNING: This method can be run in either contacts mode or profile mode. It is
@@ -4716,7 +4775,6 @@ public class ContactsProvider2 extends AbstractContactsProvider
// Otherwise proceed with a normal query against the contacts DB.
switchToContactMode();
- mActiveDb.set(mContactsHelper.getReadableDatabase());
String directory = getQueryParameter(uri, ContactsContract.DIRECTORY_PARAM_KEY);
if (directory == null) {
return addSnippetExtrasToCursor(uri,
@@ -4868,10 +4926,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
String[] selectionArgs, String sortOrder, final long directoryId,
final CancellationSignal cancellationSignal) {
- // Default active DB to the contacts DB if none has been set.
- if (mActiveDb.get() == null) {
- mActiveDb.set(mContactsHelper.getReadableDatabase());
- }
+ final SQLiteDatabase db = mDbHelper.get().getReadableDatabase();
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
String groupBy = null;
@@ -4886,7 +4941,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
switch (match) {
case SYNCSTATE:
case PROFILE_SYNCSTATE:
- return mDbHelper.get().getSyncState().query(mActiveDb.get(), projection, selection,
+ return mDbHelper.get().getSyncState().query(db, projection, selection,
selectionArgs, sortOrder);
case CONTACTS: {
@@ -4918,7 +4973,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder();
setTablesAndProjectionMapForContacts(lookupQb, uri, projection);
- Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri,
+ Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri,
projection, selection, selectionArgs, sortOrder, groupBy, limit,
Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey,
cancellationSignal);
@@ -4929,7 +4984,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
setTablesAndProjectionMapForContacts(qb, uri, projection);
selectionArgs = insertSelectionArg(selectionArgs,
- String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey)));
+ String.valueOf(lookupContactIdByLookupKey(db, lookupKey)));
qb.appendWhere(Contacts._ID + "=?");
break;
}
@@ -4953,7 +5008,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
lookupQb.appendWhere(" AND " + Data._ID + "=" + Contacts.PHOTO_ID);
}
lookupQb.appendWhere(" AND ");
- Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri,
+ Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri,
projection, selection, selectionArgs, sortOrder, groupBy, limit,
Data.CONTACT_ID, contactId, Data.LOOKUP_KEY, lookupKey,
cancellationSignal);
@@ -4965,7 +5020,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
setTablesAndProjectionMapForData(qb, uri, projection, false);
- long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
+ long contactId = lookupContactIdByLookupKey(db, lookupKey);
selectionArgs = insertSelectionArg(selectionArgs,
String.valueOf(contactId));
if (match == CONTACTS_LOOKUP_PHOTO || match == CONTACTS_LOOKUP_ID_PHOTO) {
@@ -4996,7 +5051,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
long contactId = Long.parseLong(pathSegments.get(3));
SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder();
setTablesAndProjectionMapForStreamItems(lookupQb);
- Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri,
+ Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri,
projection, selection, selectionArgs, sortOrder, groupBy, limit,
StreamItems.CONTACT_ID, contactId,
StreamItems.CONTACT_LOOKUP_KEY, lookupKey,
@@ -5007,7 +5062,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
setTablesAndProjectionMapForStreamItems(qb);
- long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
+ long contactId = lookupContactIdByLookupKey(db, lookupKey);
selectionArgs = insertSelectionArg(selectionArgs, String.valueOf(contactId));
qb.appendWhere(RawContacts.CONTACT_ID + "=?");
break;
@@ -5015,7 +5070,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
case CONTACTS_AS_VCARD: {
final String lookupKey = Uri.encode(uri.getPathSegments().get(2));
- long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
+ long contactId = lookupContactIdByLookupKey(db, lookupKey);
qb.setTables(Views.CONTACTS);
qb.setProjectionMap(sContactsVCardProjectionMap);
selectionArgs = insertSelectionArg(selectionArgs,
@@ -5027,7 +5082,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
case CONTACTS_AS_MULTI_VCARD: {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
String currentDateString = dateFormat.format(new Date()).toString();
- return mActiveDb.get().rawQuery(
+ return db.rawQuery(
"SELECT" +
" 'vcards_' || ? || '.vcf' AS " + OpenableColumns.DISPLAY_NAME + "," +
" NULL AS " + OpenableColumns.SIZE,
@@ -5173,7 +5228,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
System.arraycopy(selectionArgs, 0, doubledSelectionArgs, length, length);
}
- Cursor cursor = mActiveDb.get().rawQuery(unionQuery, doubledSelectionArgs);
+ Cursor cursor = db.rawQuery(unionQuery, doubledSelectionArgs);
if (cursor != null) {
cursor.setNotificationUri(getContext().getContentResolver(),
ContactsContract.AUTHORITY_URI);
@@ -5262,7 +5317,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
setTablesAndProjectionMapForEntities(lookupQb, uri, projection);
lookupQb.appendWhere(" AND ");
- Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri,
+ Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri,
projection, selection, selectionArgs, sortOrder, groupBy, limit,
Contacts.Entity.CONTACT_ID, contactId,
Contacts.Entity.LOOKUP_KEY, lookupKey,
@@ -5274,7 +5329,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
setTablesAndProjectionMapForEntities(qb, uri, projection);
selectionArgs = insertSelectionArg(selectionArgs,
- String.valueOf(lookupContactIdByLookupKey(mActiveDb.get(), lookupKey)));
+ String.valueOf(lookupContactIdByLookupKey(db, lookupKey)));
qb.appendWhere(" AND " + Contacts.Entity.CONTACT_ID + "=?");
break;
}
@@ -5734,7 +5789,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
// were returned, fall back to doing a match of the trailing 7 digits.
qb.setStrict(true);
boolean foundResult = false;
- Cursor cursor = query(mActiveDb.get(), qb, projection, selection, selectionArgs,
+ Cursor cursor = query(db, qb, projection, selection, selectionArgs,
sortOrder, groupBy, null, limit, cancellationSignal);
try {
if (cursor.getCount() > 0) {
@@ -5867,7 +5922,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
case SEARCH_SUGGESTIONS: {
return mGlobalSearchSupport.handleSearchSuggestionsQuery(
- mActiveDb.get(), uri, projection, limit);
+ db, uri, projection, limit);
}
case SEARCH_SHORTCUT: {
@@ -5875,7 +5930,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
String filter = getQueryParameter(
uri, SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA);
return mGlobalSearchSupport.handleSearchShortcutRefresh(
- mActiveDb.get(), projection, lookupKey, filter);
+ db, projection, lookupKey, filter);
}
case RAW_CONTACT_ENTITIES:
@@ -5925,11 +5980,11 @@ public class ContactsProvider2 extends AbstractContactsProvider
qb.setStrict(true);
Cursor cursor =
- query(mActiveDb.get(), qb, projection, selection, selectionArgs, sortOrder, groupBy,
+ query(db, qb, projection, selection, selectionArgs, sortOrder, groupBy,
having, limit, cancellationSignal);
if (readBooleanQueryParameter(uri, ContactCounts.ADDRESS_BOOK_INDEX_EXTRAS, false)) {
- bundleFastScrollingIndexExtras(cursor, uri, mActiveDb.get(), qb, selection,
+ bundleFastScrollingIndexExtras(cursor, uri, db, qb, selection,
selectionArgs, sortOrder, addressBookIndexerCountExpression,
cancellationSignal);
}
@@ -5990,10 +6045,6 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
private void invalidateFastScrollingIndexCache() {
- if (VERBOSE_LOGGING) {
- Log.v(TAG, "invalidatemFastScrollingIndexCache");
- }
-
// FastScrollingIndexCache is thread-safe, no need to synchronize here.
mFastScrollingIndexCache.invalidate();
}
@@ -7078,20 +7129,15 @@ public class ContactsProvider2 extends AbstractContactsProvider
public AssetFileDescriptor openAssetFileLocal(Uri uri, String mode)
throws FileNotFoundException {
- // Default active DB to the contacts DB if none has been set.
- if (mActiveDb.get() == null) {
- if (mode.equals("r")) {
- mActiveDb.set(mContactsHelper.getReadableDatabase());
- } else {
- mActiveDb.set(mContactsHelper.getWritableDatabase());
- }
- }
+ final boolean writing = mode.contains("w");
+
+ final SQLiteDatabase db = mDbHelper.get().getDatabase(writing);
int match = sUriMatcher.match(uri);
switch (match) {
case CONTACTS_ID_PHOTO: {
long contactId = Long.parseLong(uri.getPathSegments().get(1));
- return openPhotoAssetFile(mActiveDb.get(), uri, mode,
+ return openPhotoAssetFile(db, uri, mode,
Data._ID + "=" + Contacts.PHOTO_ID + " AND " +
RawContacts.CONTACT_ID + "=?",
new String[]{String.valueOf(contactId)});
@@ -7103,7 +7149,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
"Display photos retrieved by contact ID can only be read.");
}
long contactId = Long.parseLong(uri.getPathSegments().get(1));
- Cursor c = mActiveDb.get().query(Tables.CONTACTS,
+ Cursor c = db.query(Tables.CONTACTS,
new String[]{Contacts.PHOTO_FILE_ID},
Contacts._ID + "=?", new String[]{String.valueOf(contactId)},
null, null, null);
@@ -7125,7 +7171,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
throw new IllegalArgumentException(
"Display photos retrieved by contact ID can only be read.");
}
- Cursor c = mActiveDb.get().query(Tables.CONTACTS,
+ Cursor c = db.query(Tables.CONTACTS,
new String[]{Contacts.PHOTO_FILE_ID}, null, null, null, null, null);
try {
if (c.moveToFirst()) {
@@ -7163,7 +7209,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
long contactId = Long.parseLong(pathSegments.get(3));
SQLiteQueryBuilder lookupQb = new SQLiteQueryBuilder();
setTablesAndProjectionMapForContacts(lookupQb, uri, projection);
- Cursor c = queryWithContactIdAndLookupKey(lookupQb, mActiveDb.get(), uri,
+ Cursor c = queryWithContactIdAndLookupKey(lookupQb, db, uri,
projection, null, null, null, null, null,
Contacts._ID, contactId, Contacts.LOOKUP_KEY, lookupKey, null);
if (c != null) {
@@ -7175,7 +7221,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
return openDisplayPhotoForRead(photoFileId);
} else {
long photoId = c.getLong(c.getColumnIndex(Contacts.PHOTO_ID));
- return openPhotoAssetFile(mActiveDb.get(), uri, mode,
+ return openPhotoAssetFile(db, uri, mode,
Data._ID + "=?", new String[]{String.valueOf(photoId)});
}
} finally {
@@ -7186,8 +7232,8 @@ public class ContactsProvider2 extends AbstractContactsProvider
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
setTablesAndProjectionMapForContacts(qb, uri, projection);
- long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
- Cursor c = qb.query(mActiveDb.get(), projection, Contacts._ID + "=?",
+ long contactId = lookupContactIdByLookupKey(db, lookupKey);
+ Cursor c = qb.query(db, projection, Contacts._ID + "=?",
new String[]{String.valueOf(contactId)}, null, null, null);
try {
c.moveToFirst();
@@ -7196,7 +7242,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
return openDisplayPhotoForRead(photoFileId);
} else {
long photoId = c.getLong(c.getColumnIndex(Contacts.PHOTO_ID));
- return openPhotoAssetFile(mActiveDb.get(), uri, mode,
+ return openPhotoAssetFile(db, uri, mode,
Data._ID + "=?", new String[]{String.valueOf(photoId)});
}
} finally {
@@ -7213,7 +7259,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
String[] projection = new String[]{Data._ID, Photo.PHOTO_FILE_ID};
setTablesAndProjectionMapForData(qb, uri, projection, false);
long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE);
- Cursor c = qb.query(mActiveDb.get(), projection,
+ Cursor c = qb.query(db, projection,
Data.RAW_CONTACT_ID + "=? AND " + DataColumns.MIMETYPE_ID + "=?",
new String[]{String.valueOf(rawContactId), String.valueOf(photoMimetypeId)},
null, null, Data.IS_PRIMARY + " DESC");
@@ -7251,7 +7297,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
case DATA_ID: {
long dataId = Long.parseLong(uri.getPathSegments().get(1));
long photoMimetypeId = mDbHelper.get().getMimeTypeId(Photo.CONTENT_ITEM_TYPE);
- return openPhotoAssetFile(mActiveDb.get(), uri, mode,
+ return openPhotoAssetFile(db, uri, mode,
Data._ID + "=? AND " + DataColumns.MIMETYPE_ID + "=" + photoMimetypeId,
new String[]{String.valueOf(dataId)});
}
@@ -7290,7 +7336,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
inBuilder.append(",");
}
// TODO: Figure out what to do if the profile contact is in the list.
- long contactId = lookupContactIdByLookupKey(mActiveDb.get(), lookupKey);
+ long contactId = lookupContactIdByLookupKey(db, lookupKey);
inBuilder.append(contactId);
index++;
}
@@ -7959,7 +8005,6 @@ public class ContactsProvider2 extends AbstractContactsProvider
// Re-aggregation is only for the contacts DB.
switchToContactMode();
db = mContactsHelper.getWritableDatabase();
- mActiveDb.set(db);
// Start the actual process.
db.beginTransaction();
@@ -8064,7 +8109,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
rawContactIdSelect.append(")");
- final SQLiteDatabase db = mActiveDb.get();
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
mSelectionArgs1[0] = String.valueOf(currentTimeMillis);
@@ -8106,7 +8151,7 @@ public class ContactsProvider2 extends AbstractContactsProvider
/* package */ int updateDataUsageStat(
List<Long> dataIds, String type, long currentTimeMillis) {
- final SQLiteDatabase db = mActiveDb.get();
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
final String typeString = String.valueOf(getDataUsageFeedbackType(type, null));
final String currentTimeMillisString = String.valueOf(currentTimeMillis);
@@ -8279,4 +8324,15 @@ public class ContactsProvider2 extends AbstractContactsProvider
}
throw new IllegalArgumentException("Invalid usage type " + type);
}
+
+ /** Use only for debug logging */
+ @Override
+ public String toString() {
+ return "ContactsProvider2";
+ }
+
+ @NeededForTesting
+ public void switchToProfileModeForTest() {
+ switchToProfileMode();
+ }
}
diff --git a/src/com/android/providers/contacts/ContactsTransaction.java b/src/com/android/providers/contacts/ContactsTransaction.java
index 7a92cae4..c6c11d99 100644
--- a/src/com/android/providers/contacts/ContactsTransaction.java
+++ b/src/com/android/providers/contacts/ContactsTransaction.java
@@ -16,11 +16,12 @@
package com.android.providers.contacts;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteTransactionListener;
+import android.util.Log;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
import java.util.List;
import java.util.Map;
@@ -40,13 +41,16 @@ public class ContactsTransaction {
/**
* The list of databases that have been enlisted in this transaction.
+ *
+ * Note we insert elements to the head of the list, so that we endTransaction() in the reverse
+ * order.
*/
- private List<SQLiteDatabase> mDatabasesForTransaction;
+ private final List<SQLiteDatabase> mDatabasesForTransaction;
/**
* The mapping of tags to databases involved in this transaction.
*/
- private Map<String, SQLiteDatabase> mDatabaseTagMap;
+ private final Map<String, SQLiteDatabase> mDatabaseTagMap;
/**
* Whether any actual changes have been made successfully in this transaction.
@@ -97,8 +101,16 @@ public class ContactsTransaction {
*/
public void startTransactionForDb(SQLiteDatabase db, String tag,
SQLiteTransactionListener listener) {
+ if (AbstractContactsProvider.ENABLE_TRANSACTION_LOG) {
+ Log.i(AbstractContactsProvider.TAG, "startTransactionForDb: db=" + db.getPath() +
+ " tag=" + tag + " listener=" + listener +
+ " startTransaction=" + !hasDbInTransaction(tag),
+ new RuntimeException("startTransactionForDb"));
+ }
if (!hasDbInTransaction(tag)) {
- mDatabasesForTransaction.add(db);
+ // Insert a new db into the head of the list, so that we'll endTransaction() in
+ // the reverse order.
+ mDatabasesForTransaction.add(0, db);
mDatabaseTagMap.put(tag, db);
if (listener != null) {
db.beginTransactionWithListener(listener);
@@ -154,13 +166,33 @@ public class ContactsTransaction {
}
/**
+ * @return the tag for a database. Only intended to be used for logging.
+ */
+ private String getTagForDb(SQLiteDatabase db) {
+ for (String tag : mDatabaseTagMap.keySet()) {
+ if (db == mDatabaseTagMap.get(tag)) {
+ return tag;
+ }
+ }
+ return null;
+ }
+
+ /**
* Completes the transaction, ending the DB transactions for all associated databases.
* @param callerIsBatch Whether this is being performed in the context of a batch operation.
* If it is not, and the transaction is marked as batch, this call is a no-op.
*/
public void finish(boolean callerIsBatch) {
+ if (AbstractContactsProvider.ENABLE_TRANSACTION_LOG) {
+ Log.i(AbstractContactsProvider.TAG, "ContactsTransaction.finish callerIsBatch=" +
+ callerIsBatch, new RuntimeException("ContactsTransaction.finish"));
+ }
if (!mBatch || callerIsBatch) {
for (SQLiteDatabase db : mDatabasesForTransaction) {
+ if (AbstractContactsProvider.ENABLE_TRANSACTION_LOG) {
+ Log.i(AbstractContactsProvider.TAG, "ContactsTransaction.finish: " +
+ "endTransaction for " + getTagForDb(db));
+ }
// If an exception was thrown while yielding, it's possible that we no longer have
// a lock on this database, so we need to check before attempting to end its
// transaction. Otherwise, we should always expect to be in a transaction (and will
diff --git a/src/com/android/providers/contacts/DataRowHandler.java b/src/com/android/providers/contacts/DataRowHandler.java
index b98f6c77..03665322 100644
--- a/src/com/android/providers/contacts/DataRowHandler.java
+++ b/src/com/android/providers/contacts/DataRowHandler.java
@@ -15,12 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -33,6 +27,12 @@ import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Data;
import android.text.TextUtils;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handles inserts and update for a specific Data type.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForCommonDataKind.java b/src/com/android/providers/contacts/DataRowHandlerForCommonDataKind.java
index b717d31a..0bb17c28 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForCommonDataKind.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForCommonDataKind.java
@@ -15,8 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -24,6 +22,8 @@ import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
import android.text.TextUtils;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Superclass for data row handlers that deal with types (e.g. Home, Work, Other) and
* labels, which are custom types.
diff --git a/src/com/android/providers/contacts/DataRowHandlerForCustomMimetype.java b/src/com/android/providers/contacts/DataRowHandlerForCustomMimetype.java
index 0202fd64..502b8353 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForCustomMimetype.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForCustomMimetype.java
@@ -15,10 +15,10 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.Context;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
public class DataRowHandlerForCustomMimetype extends DataRowHandler {
public DataRowHandlerForCustomMimetype(Context context,
diff --git a/src/com/android/providers/contacts/DataRowHandlerForEmail.java b/src/com/android/providers/contacts/DataRowHandlerForEmail.java
index f1fa9410..38cb2e1a 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForEmail.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForEmail.java
@@ -15,15 +15,15 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.Email;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for email address data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java b/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java
index 3a4b167b..0d2427aa 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForGroupMembership.java
@@ -15,15 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.Clauses;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Projections;
-import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.ContactsProvider2.GroupIdCacheEntry;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -33,6 +24,15 @@ import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
+import com.android.providers.contacts.ContactsDatabaseHelper.Clauses;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Projections;
+import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.ContactsProvider2.GroupIdCacheEntry;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/src/com/android/providers/contacts/DataRowHandlerForIdentity.java b/src/com/android/providers/contacts/DataRowHandlerForIdentity.java
index 440e4300..48ce5e44 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForIdentity.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForIdentity.java
@@ -15,14 +15,14 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.Identity;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for Identity data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForIm.java b/src/com/android/providers/contacts/DataRowHandlerForIm.java
index 009bb890..faf10ad8 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForIm.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForIm.java
@@ -15,13 +15,13 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.provider.ContactsContract.CommonDataKinds.Im;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for IM address data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForNickname.java b/src/com/android/providers/contacts/DataRowHandlerForNickname.java
index 0fec6eeb..95f24f5a 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForNickname.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForNickname.java
@@ -15,9 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -25,6 +22,9 @@ import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.text.TextUtils;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for nickname data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForNote.java b/src/com/android/providers/contacts/DataRowHandlerForNote.java
index 317af1a6..ea73637e 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForNote.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForNote.java
@@ -15,13 +15,13 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.provider.ContactsContract.CommonDataKinds.Note;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for note data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForOrganization.java b/src/com/android/providers/contacts/DataRowHandlerForOrganization.java
index 7384ccba..44146e8f 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForOrganization.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForOrganization.java
@@ -15,10 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -27,6 +23,10 @@ import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.Data;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for organization data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java b/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java
index 99313e9b..da7d66c8 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForPhoneNumber.java
@@ -15,11 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -28,6 +23,11 @@ import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
+import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for phone number data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForPhoto.java b/src/com/android/providers/contacts/DataRowHandlerForPhoto.java
index 7560ed49..bfaa5014 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForPhoto.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForPhoto.java
@@ -15,8 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -24,6 +22,8 @@ import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.util.Log;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
import java.io.IOException;
/**
diff --git a/src/com/android/providers/contacts/DataRowHandlerForStructuredName.java b/src/com/android/providers/contacts/DataRowHandlerForStructuredName.java
index c84d2e83..01ee1bac 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForStructuredName.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForStructuredName.java
@@ -15,9 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -26,6 +23,9 @@ import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.FullNameStyle;
import android.text.TextUtils;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for email address data rows.
*/
diff --git a/src/com/android/providers/contacts/DataRowHandlerForStructuredPostal.java b/src/com/android/providers/contacts/DataRowHandlerForStructuredPostal.java
index 6898a43e..26483edb 100644
--- a/src/com/android/providers/contacts/DataRowHandlerForStructuredPostal.java
+++ b/src/com/android/providers/contacts/DataRowHandlerForStructuredPostal.java
@@ -15,9 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import com.android.providers.contacts.aggregation.ContactAggregator;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
@@ -25,6 +22,9 @@ import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.text.TextUtils;
+import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
+import com.android.providers.contacts.aggregation.ContactAggregator;
+
/**
* Handler for postal address data rows.
*/
diff --git a/src/com/android/providers/contacts/DbModifierWithNotification.java b/src/com/android/providers/contacts/DbModifierWithNotification.java
index c13f4a84..fda8321a 100644
--- a/src/com/android/providers/contacts/DbModifierWithNotification.java
+++ b/src/com/android/providers/contacts/DbModifierWithNotification.java
@@ -20,11 +20,6 @@ package com.android.providers.contacts;
import static android.Manifest.permission.ADD_VOICEMAIL;
import static com.android.providers.contacts.Manifest.permission.READ_WRITE_ALL_VOICEMAIL;
-import com.android.common.io.MoreCloseables;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.util.DbQueryUtils;
-import com.google.android.collect.Lists;
-
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -43,6 +38,11 @@ import android.provider.VoicemailContract.Status;
import android.provider.VoicemailContract.Voicemails;
import android.util.Log;
+import com.android.common.io.MoreCloseables;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.util.DbQueryUtils;
+import com.google.android.collect.Lists;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
diff --git a/src/com/android/providers/contacts/DefaultCallLogInsertionHelper.java b/src/com/android/providers/contacts/DefaultCallLogInsertionHelper.java
index 6777e43a..fcda8f1c 100644
--- a/src/com/android/providers/contacts/DefaultCallLogInsertionHelper.java
+++ b/src/com/android/providers/contacts/DefaultCallLogInsertionHelper.java
@@ -16,16 +16,15 @@
package com.android.providers.contacts;
+import android.content.ContentValues;
+import android.content.Context;
+import android.provider.CallLog.Calls;
+
import com.android.i18n.phonenumbers.NumberParseException;
import com.android.i18n.phonenumbers.PhoneNumberUtil;
import com.android.i18n.phonenumbers.Phonenumber.PhoneNumber;
import com.android.i18n.phonenumbers.geocoding.PhoneNumberOfflineGeocoder;
-import android.content.ContentValues;
-import android.content.Context;
-import android.provider.CallLog.Calls;
-import android.util.Log;
-
import java.util.Locale;
/**
diff --git a/src/com/android/providers/contacts/FastScrollingIndexCache.java b/src/com/android/providers/contacts/FastScrollingIndexCache.java
index c1c56028..f07a8556 100644
--- a/src/com/android/providers/contacts/FastScrollingIndexCache.java
+++ b/src/com/android/providers/contacts/FastScrollingIndexCache.java
@@ -16,11 +16,9 @@
package com.android.providers.contacts;
-import com.google.android.collect.Maps;
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.Context;
import android.content.SharedPreferences;
+import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
@@ -28,6 +26,9 @@ import android.provider.ContactsContract.ContactCounts;
import android.text.TextUtils;
import android.util.Log;
+import com.google.android.collect.Maps;
+import com.google.common.annotations.VisibleForTesting;
+
import java.util.Map;
import java.util.regex.Pattern;
diff --git a/src/com/android/providers/contacts/LegacyApiSupport.java b/src/com/android/providers/contacts/LegacyApiSupport.java
index 78cbc9db..9859d11e 100644
--- a/src/com/android/providers/contacts/LegacyApiSupport.java
+++ b/src/com/android/providers/contacts/LegacyApiSupport.java
@@ -15,19 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.ExtensionsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
-import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-
import android.accounts.Account;
import android.app.SearchManager;
import android.content.ContentUris;
@@ -65,6 +52,19 @@ import android.provider.ContactsContract.StatusUpdates;
import android.text.TextUtils;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.ExtensionsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
+import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.StatusUpdatesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+
import java.util.HashMap;
import java.util.Locale;
diff --git a/src/com/android/providers/contacts/NameLookupBuilder.java b/src/com/android/providers/contacts/NameLookupBuilder.java
index 5ebbcd16..8375b88d 100644
--- a/src/com/android/providers/contacts/NameLookupBuilder.java
+++ b/src/com/android/providers/contacts/NameLookupBuilder.java
@@ -16,11 +16,11 @@
package com.android.providers.contacts;
+import android.provider.ContactsContract.FullNameStyle;
+
import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
import com.android.providers.contacts.SearchIndexManager.IndexBuilder;
-import android.provider.ContactsContract.FullNameStyle;
-
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
diff --git a/src/com/android/providers/contacts/NameNormalizer.java b/src/com/android/providers/contacts/NameNormalizer.java
index d91bd7c6..c2b945e5 100644
--- a/src/com/android/providers/contacts/NameNormalizer.java
+++ b/src/com/android/providers/contacts/NameNormalizer.java
@@ -17,10 +17,10 @@ package com.android.providers.contacts;
import com.android.providers.contacts.util.Hex;
-import java.util.Locale;
-import java.text.Collator;
import java.text.CollationKey;
+import java.text.Collator;
import java.text.RuleBasedCollator;
+import java.util.Locale;
/**
* Converts a name to a normalized form by removing all non-letter characters and normalizing
diff --git a/src/com/android/providers/contacts/NameSplitter.java b/src/com/android/providers/contacts/NameSplitter.java
index fd5b0965..43743ee3 100644
--- a/src/com/android/providers/contacts/NameSplitter.java
+++ b/src/com/android/providers/contacts/NameSplitter.java
@@ -15,14 +15,14 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.util.NeededForTesting;
-
import android.content.ContentValues;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.FullNameStyle;
import android.provider.ContactsContract.PhoneticNameStyle;
-import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.text.TextUtils;
+import com.android.providers.contacts.util.NeededForTesting;
+
import java.lang.Character.UnicodeBlock;
import java.util.HashSet;
import java.util.Locale;
diff --git a/src/com/android/providers/contacts/PhotoPriorityResolver.java b/src/com/android/providers/contacts/PhotoPriorityResolver.java
index c0dc4d97..150811cc 100644
--- a/src/com/android/providers/contacts/PhotoPriorityResolver.java
+++ b/src/com/android/providers/contacts/PhotoPriorityResolver.java
@@ -16,22 +16,22 @@
package com.android.providers.contacts;
-import com.android.internal.util.XmlUtils;
-import com.google.android.collect.Maps;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.pm.ServiceInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ServiceInfo;
import android.content.res.XmlResourceParser;
import android.util.Log;
+import com.android.internal.util.XmlUtils;
+import com.google.android.collect.Maps;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.util.HashMap;
diff --git a/src/com/android/providers/contacts/PhotoProcessor.java b/src/com/android/providers/contacts/PhotoProcessor.java
index cf81ff39..1b8fc3f7 100644
--- a/src/com/android/providers/contacts/PhotoProcessor.java
+++ b/src/com/android/providers/contacts/PhotoProcessor.java
@@ -15,13 +15,18 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.util.MemoryUtils;
-
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.SystemProperties;
+import com.android.providers.contacts.util.MemoryUtils;
+import com.google.common.annotations.VisibleForTesting;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -43,6 +48,12 @@ import java.io.IOException;
/** Compression for thumbnails that also have a display photo */
private static final int COMPRESSION_THUMBNAIL_LOW = 90;
+ private static final Paint WHITE_PAINT = new Paint();
+
+ static {
+ WHITE_PAINT.setColor(Color.WHITE);
+ }
+
private static int sMaxThumbnailDim;
private static int sMaxDisplayPhotoDim;
@@ -169,43 +180,65 @@ import java.io.IOException;
if (mOriginal == null) {
throw new IOException("Invalid image file");
}
- mDisplayPhoto = getScaledBitmap(mMaxDisplayPhotoDim);
- mThumbnailPhoto = getScaledBitmap(mMaxThumbnailPhotoDim);
+ mDisplayPhoto = getNormalizedBitmap(mOriginal, mMaxDisplayPhotoDim, mForceCropToSquare);
+ mThumbnailPhoto = getNormalizedBitmap(mOriginal,mMaxThumbnailPhotoDim, mForceCropToSquare);
}
/**
* Scales down the original bitmap to fit within the given maximum width and height.
* If the bitmap already fits in those dimensions, the original bitmap will be
* returned unmodified unless the photo processor is set up to crop it to a square.
+ *
+ * Also, if the image has transparency, conevrt it to white.
+ *
+ * @param original Original bitmap
* @param maxDim Maximum width and height (in pixels) for the image.
+ * @param forceCropToSquare See {@link #PhotoProcessor(Bitmap, int, int, boolean)}
* @return A bitmap that fits the maximum dimensions.
*/
@SuppressWarnings({"SuspiciousNameCombination"})
- private Bitmap getScaledBitmap(int maxDim) {
- Bitmap scaledBitmap = mOriginal;
- int width = mOriginal.getWidth();
- int height = mOriginal.getHeight();
+ @VisibleForTesting
+ static Bitmap getNormalizedBitmap(Bitmap original, int maxDim, boolean forceCropToSquare) {
+ final boolean originalHasAlpha = original.hasAlpha();
+
+ // All cropXxx's are in the original coordinate.
+ int cropWidth = original.getWidth();
+ int cropHeight = original.getHeight();
int cropLeft = 0;
int cropTop = 0;
- if (mForceCropToSquare && width != height) {
+ if (forceCropToSquare && cropWidth != cropHeight) {
// Crop the image to the square at its center.
- if (height > width) {
- cropTop = (height - width) / 2;
- height = width;
+ if (cropHeight > cropWidth) {
+ cropTop = (cropHeight - cropWidth) / 2;
+ cropHeight = cropWidth;
} else {
- cropLeft = (width - height) / 2;
- width = height;
+ cropLeft = (cropWidth - cropHeight) / 2;
+ cropWidth = cropHeight;
}
}
- float scaleFactor = ((float) maxDim) / Math.max(width, height);
- if (scaleFactor < 1.0f || cropLeft != 0 || cropTop != 0) {
- // Need to scale or crop the photo.
- Matrix matrix = new Matrix();
- if (scaleFactor < 1.0f) matrix.setScale(scaleFactor, scaleFactor);
- scaledBitmap = Bitmap.createBitmap(
- mOriginal, cropLeft, cropTop, width, height, matrix, true);
+ // Calculate the scale factor. We don't want to scale up, so the max scale is 1f.
+ final float scaleFactor = Math.min(1f, ((float) maxDim) / Math.max(cropWidth, cropHeight));
+
+ if (scaleFactor < 1.0f || cropLeft != 0 || cropTop != 0 || originalHasAlpha) {
+ final int newWidth = (int) (cropWidth * scaleFactor);
+ final int newHeight = (int) (cropHeight * scaleFactor);
+ final Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight,
+ Bitmap.Config.ARGB_8888);
+ final Canvas c = new Canvas(scaledBitmap);
+
+ if (originalHasAlpha) {
+ c.drawRect(0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), WHITE_PAINT);
+ }
+
+ final Rect src = new Rect(cropLeft, cropTop,
+ cropLeft + cropWidth, cropTop + cropHeight);
+ final RectF dst = new RectF(0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight());
+
+ c.drawBitmap(original, src, dst, null);
+ return scaledBitmap;
+ } else {
+ return original;
}
- return scaledBitmap;
}
/**
diff --git a/src/com/android/providers/contacts/PhotoStore.java b/src/com/android/providers/contacts/PhotoStore.java
index e0b5fb42..e7be48c4 100644
--- a/src/com/android/providers/contacts/PhotoStore.java
+++ b/src/com/android/providers/contacts/PhotoStore.java
@@ -15,17 +15,16 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap;
import android.provider.ContactsContract.PhotoFiles;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.PhotoFilesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.google.common.annotations.VisibleForTesting;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
diff --git a/src/com/android/providers/contacts/ProfileAwareUriMatcher.java b/src/com/android/providers/contacts/ProfileAwareUriMatcher.java
index de5cce16..051c60e8 100644
--- a/src/com/android/providers/contacts/ProfileAwareUriMatcher.java
+++ b/src/com/android/providers/contacts/ProfileAwareUriMatcher.java
@@ -16,13 +16,13 @@
package com.android.providers.contacts;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Maps;
-
import android.content.UriMatcher;
import android.net.Uri;
import android.provider.ContactsContract;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
diff --git a/src/com/android/providers/contacts/ProfileDatabaseHelper.java b/src/com/android/providers/contacts/ProfileDatabaseHelper.java
index 9b707a38..a23e5217 100644
--- a/src/com/android/providers/contacts/ProfileDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ProfileDatabaseHelper.java
@@ -16,13 +16,13 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.util.NeededForTesting;
-
import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.Profile;
+import com.android.providers.contacts.util.NeededForTesting;
+
/**
* A separate version of the contacts database helper for storing the user's profile data.
*/
diff --git a/src/com/android/providers/contacts/ProfileProvider.java b/src/com/android/providers/contacts/ProfileProvider.java
index d97760d6..ba10e8bd 100644
--- a/src/com/android/providers/contacts/ProfileProvider.java
+++ b/src/com/android/providers/contacts/ProfileProvider.java
@@ -81,7 +81,6 @@ public class ProfileProvider extends AbstractContactsProvider {
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder, CancellationSignal cancellationSignal) {
enforceReadPermission(uri);
- mDelegate.substituteDb(getDatabaseHelper().getReadableDatabase());
return mDelegate.queryLocal(uri, projection, selection, selectionArgs, sortOrder, -1,
cancellationSignal);
}
@@ -112,10 +111,8 @@ public class ProfileProvider extends AbstractContactsProvider {
public AssetFileDescriptor openAssetFile(Uri uri, String mode) throws FileNotFoundException {
if (mode != null && mode.contains("w")) {
enforceWritePermission();
- mDelegate.substituteDb(getDatabaseHelper().getWritableDatabase());
} else {
enforceReadPermission(uri);
- mDelegate.substituteDb(getDatabaseHelper().getReadableDatabase());
}
return mDelegate.openAssetFileLocal(uri, mode);
}
@@ -124,7 +121,6 @@ public class ProfileProvider extends AbstractContactsProvider {
ContactsTransaction transaction = getCurrentTransaction();
SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
transaction.startTransactionForDb(db, ContactsProvider2.PROFILE_DB_TAG, this);
- mDelegate.substituteDb(db);
}
@Override
@@ -142,20 +138,17 @@ public class ProfileProvider extends AbstractContactsProvider {
@Override
public void onBegin() {
- mDelegate.switchToProfileMode();
- mDelegate.onBegin();
+ mDelegate.onBeginTransactionInternal(true);
}
@Override
public void onCommit() {
- mDelegate.switchToProfileMode();
- mDelegate.onCommit();
+ mDelegate.onCommitTransactionInternal(true);
}
@Override
public void onRollback() {
- mDelegate.switchToProfileMode();
- mDelegate.onRollback();
+ mDelegate.onRollbackTransactionInternal(true);
}
@Override
@@ -167,4 +160,10 @@ public class ProfileProvider extends AbstractContactsProvider {
public String getType(Uri uri) {
return mDelegate.getType(uri);
}
+
+ /** Use only for debug logging */
+ @Override
+ public String toString() {
+ return "ProfileProvider";
+ }
}
diff --git a/src/com/android/providers/contacts/SearchIndexManager.java b/src/com/android/providers/contacts/SearchIndexManager.java
index bd4e1ccb..361b5d8f 100644
--- a/src/com/android/providers/contacts/SearchIndexManager.java
+++ b/src/com/android/providers/contacts/SearchIndexManager.java
@@ -15,14 +15,6 @@
*/
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.google.android.collect.Lists;
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
@@ -37,6 +29,14 @@ import android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.SearchIndexColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.google.android.collect.Lists;
+import com.google.common.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
diff --git a/src/com/android/providers/contacts/VoicemailCleanupService.java b/src/com/android/providers/contacts/VoicemailCleanupService.java
index 39f5be5b..4ad1406a 100644
--- a/src/com/android/providers/contacts/VoicemailCleanupService.java
+++ b/src/com/android/providers/contacts/VoicemailCleanupService.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.google.common.annotations.VisibleForTesting;
-
import android.app.IntentService;
import android.content.ContentResolver;
import android.content.Intent;
@@ -25,6 +23,8 @@ import android.provider.VoicemailContract.Status;
import android.provider.VoicemailContract.Voicemails;
import android.util.Log;
+import com.google.common.annotations.VisibleForTesting;
+
/**
* A service that cleans up voicemail related data for packages that are uninstalled.
*/
diff --git a/src/com/android/providers/contacts/VoicemailContentProvider.java b/src/com/android/providers/contacts/VoicemailContentProvider.java
index 79d8f924..b2f6b1e9 100644
--- a/src/com/android/providers/contacts/VoicemailContentProvider.java
+++ b/src/com/android/providers/contacts/VoicemailContentProvider.java
@@ -19,11 +19,6 @@ import static android.provider.VoicemailContract.SOURCE_PACKAGE_FIELD;
import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
import static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.util.SelectionBuilder;
-import com.android.providers.contacts.util.TypedUriMatcherImpl;
-import com.google.common.annotations.VisibleForTesting;
-
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
@@ -38,6 +33,11 @@ import android.provider.VoicemailContract;
import android.provider.VoicemailContract.Voicemails;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.util.SelectionBuilder;
+import com.android.providers.contacts.util.TypedUriMatcherImpl;
+import com.google.common.annotations.VisibleForTesting;
+
import java.io.FileNotFoundException;
import java.util.List;
diff --git a/src/com/android/providers/contacts/VoicemailContentTable.java b/src/com/android/providers/contacts/VoicemailContentTable.java
index 3b72653a..3f00b262 100644
--- a/src/com/android/providers/contacts/VoicemailContentTable.java
+++ b/src/com/android/providers/contacts/VoicemailContentTable.java
@@ -19,10 +19,6 @@ import static com.android.providers.contacts.util.DbQueryUtils.checkForSupported
import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
import static com.android.providers.contacts.util.DbQueryUtils.getEqualityClause;
-import com.android.common.content.ProjectionMap;
-import com.android.providers.contacts.VoicemailContentProvider.UriData;
-import com.android.providers.contacts.util.CloseUtils;
-
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
@@ -38,6 +34,10 @@ import android.provider.OpenableColumns;
import android.provider.VoicemailContract.Voicemails;
import android.util.Log;
+import com.android.common.content.ProjectionMap;
+import com.android.providers.contacts.VoicemailContentProvider.UriData;
+import com.android.providers.contacts.util.CloseUtils;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
diff --git a/src/com/android/providers/contacts/VoicemailStatusTable.java b/src/com/android/providers/contacts/VoicemailStatusTable.java
index a0a61ba6..2c1861b3 100644
--- a/src/com/android/providers/contacts/VoicemailStatusTable.java
+++ b/src/com/android/providers/contacts/VoicemailStatusTable.java
@@ -18,9 +18,6 @@ package com.android.providers.contacts;
import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
-import com.android.common.content.ProjectionMap;
-import com.android.providers.contacts.VoicemailContentProvider.UriData;
-
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
@@ -32,6 +29,9 @@ import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.VoicemailContract.Status;
+import com.android.common.content.ProjectionMap;
+import com.android.providers.contacts.VoicemailContentProvider.UriData;
+
/**
* Implementation of {@link VoicemailTable.Delegate} for the voicemail status table.
*/
diff --git a/src/com/android/providers/contacts/VoicemailTable.java b/src/com/android/providers/contacts/VoicemailTable.java
index db35c982..9e6c4312 100644
--- a/src/com/android/providers/contacts/VoicemailTable.java
+++ b/src/com/android/providers/contacts/VoicemailTable.java
@@ -16,13 +16,13 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.VoicemailContentProvider.UriData;
-
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
+import com.android.providers.contacts.VoicemailContentProvider.UriData;
+
import java.io.FileNotFoundException;
/**
diff --git a/src/com/android/providers/contacts/aggregation/ContactAggregator.java b/src/com/android/providers/contacts/aggregation/ContactAggregator.java
index d3931e63..baae2e5c 100644
--- a/src/com/android/providers/contacts/aggregation/ContactAggregator.java
+++ b/src/com/android/providers/contacts/aggregation/ContactAggregator.java
@@ -16,6 +16,29 @@
package com.android.providers.contacts.aggregation;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteQueryBuilder;
+import android.database.sqlite.SQLiteStatement;
+import android.net.Uri;
+import android.provider.ContactsContract.AggregationExceptions;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Identity;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Contacts.AggregationSuggestions;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.DisplayNameSources;
+import android.provider.ContactsContract.FullNameStyle;
+import android.provider.ContactsContract.PhotoFiles;
+import android.provider.ContactsContract.RawContacts;
+import android.provider.ContactsContract.StatusUpdates;
+import android.text.TextUtils;
+import android.util.EventLog;
+import android.util.Log;
+
import com.android.providers.contacts.ContactLookupKey;
import com.android.providers.contacts.ContactsDatabaseHelper;
import com.android.providers.contacts.ContactsDatabaseHelper.AccountsColumns;
@@ -42,29 +65,6 @@ import com.android.providers.contacts.aggregation.util.ContactMatcher;
import com.android.providers.contacts.aggregation.util.ContactMatcher.MatchScore;
import com.google.android.collect.Maps;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteQueryBuilder;
-import android.database.sqlite.SQLiteStatement;
-import android.net.Uri;
-import android.provider.ContactsContract.AggregationExceptions;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Identity;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Contacts.AggregationSuggestions;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.DisplayNameSources;
-import android.provider.ContactsContract.FullNameStyle;
-import android.provider.ContactsContract.PhotoFiles;
-import android.provider.ContactsContract.RawContacts;
-import android.provider.ContactsContract.StatusUpdates;
-import android.text.TextUtils;
-import android.util.EventLog;
-import android.util.Log;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
diff --git a/src/com/android/providers/contacts/aggregation/ProfileAggregator.java b/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
index fedf5fee..276a05f2 100644
--- a/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
+++ b/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
@@ -23,11 +23,11 @@ import android.provider.ContactsContract.Contacts;
import com.android.providers.contacts.ContactLookupKey;
import com.android.providers.contacts.ContactsDatabaseHelper;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
import com.android.providers.contacts.ContactsProvider2;
import com.android.providers.contacts.NameSplitter;
import com.android.providers.contacts.PhotoPriorityResolver;
import com.android.providers.contacts.TransactionContext;
+import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
/**
* A version of the ContactAggregator for use against the profile database.
diff --git a/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java b/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java
index d6b799f0..9643d815 100644
--- a/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java
+++ b/src/com/android/providers/contacts/aggregation/util/CommonNicknameCache.java
@@ -16,13 +16,13 @@
package com.android.providers.contacts.aggregation.util;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+
import com.android.providers.contacts.ContactsDatabaseHelper.NicknameLookupColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.google.android.collect.Maps;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
-
import java.lang.ref.SoftReference;
import java.util.BitSet;
import java.util.HashMap;
diff --git a/src/com/android/providers/contacts/debug/ContactsDumpActivity.java b/src/com/android/providers/contacts/debug/ContactsDumpActivity.java
new file mode 100644
index 00000000..530e779b
--- /dev/null
+++ b/src/com/android/providers/contacts/debug/ContactsDumpActivity.java
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+
+package com.android.providers.contacts.debug;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.Window;
+import android.widget.Button;
+
+import com.android.providers.contacts.R;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Activity to export all app data files as a zip file on sdcard, and send it via email.
+ *
+ * Usage:
+ * adb shell am start -a com.android.providers.contacts.DUMP_DATABASE
+ */
+public class ContactsDumpActivity extends Activity implements OnClickListener {
+ private static String TAG = "ContactsDumpActivity";
+ private Button mConfirmButton;
+ private Button mCancelButton;
+ private Button mDeleteButton;
+
+ private static final File OUT_FILE = new File(Environment.getExternalStorageDirectory(),
+ "contacts.db.zip");
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ // Be sure to call the super class.
+ super.onCreate(savedInstanceState);
+
+ requestWindowFeature(Window.FEATURE_LEFT_ICON);
+
+ setContentView(R.layout.contact_dump_activity);
+
+ getWindow().setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
+ android.R.drawable.ic_dialog_alert);
+
+ mConfirmButton = (Button) findViewById(R.id.confirm);
+ mCancelButton = (Button) findViewById(R.id.cancel);
+ mDeleteButton = (Button) findViewById(R.id.delete);
+ updateDeleteButton();
+ }
+
+ private void updateDeleteButton() {
+ mDeleteButton.setEnabled(OUT_FILE.exists());
+ }
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.confirm:
+ mConfirmButton.setEnabled(false);
+ mCancelButton.setEnabled(false);
+ new DumpDbTask().execute();
+ break;
+ case R.id.delete:
+ cleanup();
+ updateDeleteButton();
+ break;
+ case R.id.cancel:
+ finish();
+ break;
+ }
+ }
+
+ private void cleanup() {
+ Log.i(TAG, "Deleting " + OUT_FILE);
+ OUT_FILE.delete();
+ }
+
+ private class DumpDbTask extends AsyncTask<Void, Void, Boolean> {
+ /**
+ * Starts spinner while task is running.
+ */
+ @Override
+ protected void onPreExecute() {
+ setProgressBarIndeterminateVisibility(true);
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... params) {
+ try {
+ DataExporter.exportData(getApplicationContext(), OUT_FILE);
+ return true;
+ } catch (IOException e) {
+ Log.e(TAG, "Failed to export", e);
+ return false;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Boolean success) {
+ if (success != null && success) {
+ emailFile(OUT_FILE);
+ }
+ }
+ }
+
+ private void emailFile(File file) {
+ Log.i(TAG, "Drafting email to send " + file.getAbsolutePath() +
+ " (" + file.length() + " bytes)");
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.debug_dump_email_subject));
+ intent.putExtra(Intent.EXTRA_TEXT, getString(R.string.debug_dump_email_body));
+ intent.setType(DataExporter.ZIP_MIME_TYPE);
+ intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
+ startActivityForResult(Intent.createChooser(intent,
+ getString(R.string.debug_dump_email_sender_picker)), 0);
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ updateDeleteButton();
+ mConfirmButton.setEnabled(true);
+ mCancelButton.setEnabled(true);
+ }
+}
diff --git a/src/com/android/providers/contacts/debug/DataExporter.java b/src/com/android/providers/contacts/debug/DataExporter.java
new file mode 100644
index 00000000..886314bc
--- /dev/null
+++ b/src/com/android/providers/contacts/debug/DataExporter.java
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+package com.android.providers.contacts.debug;
+
+import android.content.Context;
+import android.media.MediaScannerConnection;
+import android.util.Log;
+
+import com.google.common.io.Closeables;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * Compress all files under the app data dir into a single zip file.
+ */
+public class DataExporter {
+ private static String TAG = "DataExporter";
+
+ public static final String ZIP_MIME_TYPE = "application/zip";
+
+ /**
+ * Compress all files under the app data dir into a single zip file.
+ */
+ public static void exportData(Context context, File outFile) throws IOException {
+ outFile.delete();
+ Log.i(TAG, "Outfile=" + outFile.getAbsolutePath());
+
+ final ZipOutputStream os = new ZipOutputStream(new FileOutputStream(outFile));
+ try {
+ addDirectory(os, context.getFilesDir().getParentFile(), "contacts-files");
+ } finally {
+ Closeables.closeQuietly(os);
+ }
+ // Tell the media scanner about the new file so that it is
+ // immediately available to the user.
+ MediaScannerConnection.scanFile(context,
+ new String[] {outFile.toString()},
+ new String[] {ZIP_MIME_TYPE}, null);
+ }
+
+ /**
+ * Add all files under {@code current} to {@code os} zip stream
+ */
+ private static void addDirectory(ZipOutputStream os, File current, String storedPath)
+ throws IOException {
+ for (File child : current.listFiles()) {
+ final String childStoredPath = storedPath + "/" + child.getName();
+
+ if (child.isDirectory()) {
+ addDirectory(os, child, childStoredPath);
+ } else if (child.isFile()) {
+ addFile(os, child, childStoredPath);
+ } else {
+ // Shouldn't happen; skip.
+ }
+ }
+ }
+
+ /**
+ * Add a single file {@code current} to {@code os} zip stream using the file name
+ * {@code storedPath}.
+ */
+ private static void addFile(ZipOutputStream os, File current, String storedPath)
+ throws IOException {
+ final InputStream is = new FileInputStream(current);
+ os.putNextEntry(new ZipEntry(storedPath));
+
+ final byte[] buf = new byte[32 * 1024];
+ int totalLen = 0;
+ while (true) {
+ int len = is.read(buf);
+ if (len <= 0) {
+ break;
+ }
+ os.write(buf, 0, len);
+ totalLen += len;
+ }
+ os.closeEntry();
+ Log.i(TAG, "Added " + current.getAbsolutePath() + " as " + storedPath +
+ " (" + totalLen + " bytes)");
+ }
+}
diff --git a/tests/res/drawable-nodpi/transparent_10x10.png b/tests/res/drawable-nodpi/transparent_10x10.png
new file mode 100644
index 00000000..d11c2cd0
--- /dev/null
+++ b/tests/res/drawable-nodpi/transparent_10x10.png
Binary files differ
diff --git a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
index 1154186d..37591964 100644
--- a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
@@ -18,11 +18,6 @@ package com.android.providers.contacts;
import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.util.Hex;
-import com.android.providers.contacts.util.MockClock;
-import com.google.android.collect.Sets;
-
import android.accounts.Account;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -62,6 +57,11 @@ import android.test.MoreAsserts;
import android.test.mock.MockContentResolver;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.util.Hex;
+import com.android.providers.contacts.util.MockClock;
+import com.google.android.collect.Sets;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
diff --git a/tests/src/com/android/providers/contacts/CallerInfoIntegrationTest.java b/tests/src/com/android/providers/contacts/CallerInfoIntegrationTest.java
index 0ce9bca1..4c0d2dfd 100644
--- a/tests/src/com/android/providers/contacts/CallerInfoIntegrationTest.java
+++ b/tests/src/com/android/providers/contacts/CallerInfoIntegrationTest.java
@@ -16,14 +16,14 @@
package com.android.providers.contacts;
-import com.android.internal.telephony.CallerInfo;
-
import android.content.ContentUris;
import android.content.ContentValues;
import android.net.Uri;
import android.provider.ContactsContract.RawContacts;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.internal.telephony.CallerInfo;
+
/**
* Integration test for {@link CallerInfo} and {@link ContactsProvider2}.
*
diff --git a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
index f1ff7769..96cbb9b4 100644
--- a/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
+++ b/tests/src/com/android/providers/contacts/ContactDirectoryManagerTest.java
@@ -16,9 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
-import com.google.android.collect.Lists;
-
import android.accounts.Account;
import android.content.ContentValues;
import android.content.Context;
@@ -39,6 +36,9 @@ import android.test.mock.MockContentProvider;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
+import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
+import com.google.android.collect.Lists;
+
/**
* Unit tests for {@link ContactDirectoryManager}. Run the test like this:
*
diff --git a/tests/src/com/android/providers/contacts/ContactLookupKeyTest.java b/tests/src/com/android/providers/contacts/ContactLookupKeyTest.java
index 739b2cbe..08f3a077 100644
--- a/tests/src/com/android/providers/contacts/ContactLookupKeyTest.java
+++ b/tests/src/com/android/providers/contacts/ContactLookupKeyTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactLookupKey.LookupKeySegment;
-
import android.content.ContentUris;
import android.net.Uri;
import android.provider.ContactsContract.AggregationExceptions;
@@ -25,6 +23,8 @@ import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.RawContacts;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.providers.contacts.ContactLookupKey.LookupKeySegment;
+
import java.util.ArrayList;
/**
diff --git a/tests/src/com/android/providers/contacts/ContactsActor.java b/tests/src/com/android/providers/contacts/ContactsActor.java
index 038eb979..e75c52e8 100644
--- a/tests/src/com/android/providers/contacts/ContactsActor.java
+++ b/tests/src/com/android/providers/contacts/ContactsActor.java
@@ -16,9 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.util.MockSharedPreferences;
-import com.google.android.collect.Sets;
-
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerCallback;
@@ -59,6 +56,9 @@ import android.test.RenamingDelegatingContext;
import android.test.mock.MockContentResolver;
import android.test.mock.MockContext;
+import com.android.providers.contacts.util.MockSharedPreferences;
+import com.google.android.collect.Sets;
+
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
diff --git a/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java b/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java
index a9d8a368..faddeea6 100644
--- a/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java
+++ b/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java
@@ -16,11 +16,11 @@
package com.android.providers.contacts;
+import android.test.suitebuilder.annotation.SmallTest;
+
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.google.android.collect.Sets;
-import android.test.suitebuilder.annotation.SmallTest;
-
import java.util.Set;
@SmallTest
diff --git a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
index 69cd9fa5..694f0f3c 100644
--- a/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
+++ b/tests/src/com/android/providers/contacts/ContactsMockPackageManager.java
@@ -15,8 +15,6 @@
*/
package com.android.providers.contacts;
-import com.google.android.collect.Lists;
-
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -26,6 +24,8 @@ import android.content.res.Resources;
import android.os.Binder;
import android.test.mock.MockPackageManager;
+import com.google.android.collect.Lists;
+
import java.util.HashMap;
import java.util.List;
diff --git a/tests/src/com/android/providers/contacts/ContactsMockResources.java b/tests/src/com/android/providers/contacts/ContactsMockResources.java
index 248d6daa..6d986652 100644
--- a/tests/src/com/android/providers/contacts/ContactsMockResources.java
+++ b/tests/src/com/android/providers/contacts/ContactsMockResources.java
@@ -16,10 +16,10 @@
package com.android.providers.contacts;
-import com.google.android.collect.Maps;
-
import android.test.mock.MockResources;
+import com.google.android.collect.Maps;
+
import java.util.Map;
final class ContactsMockResources extends MockResources {
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index 57069259..80e194d6 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -18,16 +18,6 @@ package com.android.providers.contacts;
import static com.android.providers.contacts.TestUtils.cv;
-import com.android.internal.util.ArrayUtils;
-import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
-import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.tests.R;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
-
import android.accounts.Account;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
@@ -76,6 +66,16 @@ import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.LargeTest;
import android.text.TextUtils;
+import com.android.internal.util.ArrayUtils;
+import com.android.providers.contacts.ContactsDatabaseHelper.AggregationExceptionColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DataUsageStatColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.DbProperties;
+import com.android.providers.contacts.ContactsDatabaseHelper.PresenceColumns;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.tests.R;
+import com.google.android.collect.Lists;
+import com.google.android.collect.Sets;
+
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -5756,7 +5756,7 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test {
PhotoStore profilePhotoStore = provider.getProfilePhotoStore();
// Trigger an initial cleanup so another one won't happen while we're running this test.
- provider.switchToProfileMode();
+ provider.switchToProfileModeForTest();
provider.cleanupPhotoStore();
// Create the profile contact and add a photo.
@@ -5787,7 +5787,7 @@ public class ContactsProvider2Test extends BaseContactsProvider2Test {
profilePhotoStore.remove(streamItemPhotoFileId);
// Manually trigger another cleanup in the provider.
- provider.switchToProfileMode();
+ provider.switchToProfileModeForTest();
provider.cleanupPhotoStore();
// The following things should have happened.
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java b/tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java
new file mode 100644
index 00000000..6a82bf9f
--- /dev/null
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java
@@ -0,0 +1,309 @@
+/*
+ * 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.
+ */
+
+package com.android.providers.contacts;
+
+import static com.android.providers.contacts.TestUtils.cv;
+
+import com.google.android.collect.Lists;
+
+import android.content.ContentProviderOperation;
+import android.content.ContentValues;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.StructuredName;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.Profile;
+import android.provider.ContactsContract.RawContacts;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * Tests to make sure we're handling DB transactions properly in regard to two databases,
+ * the profile db and the contacts db.
+ */
+@LargeTest
+public class ContactsProvider2TransactionTest extends BaseContactsProvider2Test {
+ private SynchronousContactsProvider2 mProvider;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mProvider = (SynchronousContactsProvider2) getProvider();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ mProvider = null;
+ }
+
+ /**
+ * Make sure we start/finish transactions on the right databases for insert.
+ */
+ public void testTransactionCallback_insert() {
+
+ final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 12345);
+
+ // Insert a raw contact.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ mResolver.insert(RawContacts.CONTENT_URI, values);
+
+ // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
+ // profile db.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertNoTransactionsForProfileMode();
+
+
+ // Insert a profile raw contact.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ mResolver.insert(Profile.CONTENT_RAW_CONTACTS_URI, values);
+
+ // Even though we only touched the profile DB, we also start and finish a transaction
+ // on the contacts db. AbstractContactsProvider does that to avoid deadlocks.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+ }
+
+ /**
+ * Make sure we start/finish transactions on the right databases for update.
+ */
+ public void testTransactionCallback_update() {
+
+ final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 12345);
+
+ // Make sure to create a raw contact and a profile raw contact.
+ mResolver.insert(RawContacts.CONTENT_URI, values);
+ mResolver.insert(Profile.CONTENT_RAW_CONTACTS_URI, values);
+
+ values.clear();
+ values.put(RawContacts.LAST_TIME_CONTACTED, 99999);
+
+ // Update all raw contacts.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ assertTrue(mResolver.update(RawContacts.CONTENT_URI, values, null, null) > 0);
+
+ // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
+ // profile db.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertNoTransactionsForProfileMode();
+
+
+ // Update all profile raw contacts.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ assertTrue(mResolver.update(Profile.CONTENT_RAW_CONTACTS_URI, values, null, null) > 0);
+
+ // Even though we only touched the profile DB, we also start and finish a transaction
+ // on the contacts db. AbstractContactsProvider does that to avoid deadlocks.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+ }
+
+ /**
+ * Make sure we start/finish transactions on the right databases for delete.
+ */
+ public void testTransactionCallback_delete() {
+
+ final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 12345);
+
+ // Make sure to create a raw contact and a profile raw contact.
+ mResolver.insert(RawContacts.CONTENT_URI, values);
+ mResolver.insert(Profile.CONTENT_RAW_CONTACTS_URI, values);
+
+ // Delete all raw contacts.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ assertTrue(mResolver.delete(RawContacts.CONTENT_URI, null, null) > 0);
+
+ // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
+ // profile db.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertNoTransactionsForProfileMode();
+
+ // Delete all profile raw contact.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ assertTrue(mResolver.delete(Profile.CONTENT_RAW_CONTACTS_URI, null, null) > 0);
+
+ // Even though we only touched the profile DB, we also start and finish a transaction
+ // on the contacts db. AbstractContactsProvider does that to avoid deadlocks.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+ }
+ /**
+ * Make sure we start/finish transactions on the right databases for bulk insert.
+ */
+ public void testTransactionCallback_bulkInsert() {
+
+ final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 12345);
+
+ // Insert a raw contact.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ mResolver.bulkInsert(RawContacts.CONTENT_URI, new ContentValues[] {values});
+
+ // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
+ // profile db.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertNoTransactionsForProfileMode();
+
+
+ // Insert a profile raw contact.
+ mProvider.resetTrasactionCallbackCalledFlags();
+ mResolver.bulkInsert(Profile.CONTENT_RAW_CONTACTS_URI, new ContentValues[] {values});
+
+ // Even though we only touched the profile DB, we also start and finish a transaction
+ // on the contacts db. AbstractContactsProvider does that to avoid deadlocks.
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+ }
+
+ /**
+ * Add an operation to create a raw contact.
+ */
+ private static void addInsertContactOperations(ArrayList<ContentProviderOperation> ops) {
+ ContentProviderOperation.Builder b;
+ b = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
+ b.withValue(RawContacts.STARRED, 1);
+ b.withValue(RawContacts.TIMES_CONTACTED, 200001);
+ ops.add(b.build());
+
+ b = ContentProviderOperation.newInsert(Data.CONTENT_URI);
+ b.withValueBackReference(Data.RAW_CONTACT_ID, ops.size() - 1);
+ b.withValue(StructuredName.DISPLAY_NAME, "Regular Contact");
+ b.withValue(StructuredName.GIVEN_NAME, "Regular");
+ b.withValue(StructuredName.FAMILY_NAME, "Contact");
+ b.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+ ops.add(b.build());
+ }
+
+ /**
+ * Check for a contact created that'll be created for {@link #addInsertContactOperations}.
+ */
+ private void checkStoredContact() {
+ assertStoredValues(Contacts.CONTENT_URI, cv(
+ Contacts.DISPLAY_NAME, "Regular Contact",
+ RawContacts.TIMES_CONTACTED, 200001
+ ));
+ }
+
+ /**
+ * Add an operation to create a profile raw contact.
+ */
+ private static void addInsertProfileOperations(ArrayList<ContentProviderOperation> ops) {
+ ContentProviderOperation.Builder b;
+ b = ContentProviderOperation.newInsert(Profile.CONTENT_RAW_CONTACTS_URI);
+ b.withValue(RawContacts.STARRED, 1);
+ b.withValue(RawContacts.TIMES_CONTACTED, 100001);
+ ops.add(b.build());
+
+ b = ContentProviderOperation.newInsert(Data.CONTENT_URI);
+ b.withValueBackReference(Data.RAW_CONTACT_ID, ops.size() - 1);
+ b.withValue(StructuredName.DISPLAY_NAME, "Profile Contact");
+ b.withValue(StructuredName.GIVEN_NAME, "Profile");
+ b.withValue(StructuredName.FAMILY_NAME, "Contact");
+ b.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
+ ops.add(b.build());
+ }
+
+ /**
+ * Check for a profile contact created that'll be created for
+ * {@link #addInsertProfileOperations}.
+ */
+ private void checkStoredProfile() {
+ assertStoredValues(Profile.CONTENT_URI, cv(
+ Contacts.DISPLAY_NAME, "Profile Contact",
+ RawContacts.TIMES_CONTACTED, 100001
+ ));
+ }
+
+ public void testTransactionCallback_contactBatch() throws Exception {
+ final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+
+ addInsertContactOperations(ops);
+
+ mProvider.resetTrasactionCallbackCalledFlags();
+
+ // Execute the operations.
+ mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+
+ // Check the result
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertNoTransactionsForProfileMode();
+
+ checkStoredContact();
+ }
+
+ public void testTransactionCallback_profileBatch() throws Exception {
+ final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+
+ addInsertProfileOperations(ops);
+
+ mProvider.resetTrasactionCallbackCalledFlags();
+
+ // Execute the operations.
+ mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+
+ // Check the result
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+
+ checkStoredProfile();
+ }
+
+ public void testTransactionCallback_mixedBatch() throws Exception {
+ final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+
+ // Create a raw contact and a profile raw contact in a single batch.
+
+ addInsertContactOperations(ops);
+ addInsertProfileOperations(ops);
+
+ mProvider.resetTrasactionCallbackCalledFlags();
+
+ // Execute the operations.
+ mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+
+ // Check the result
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+
+ checkStoredProfile();
+ checkStoredContact();
+ }
+
+ public void testTransactionCallback_mixedBatchReversed() throws Exception {
+ final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
+
+ // Create a profile raw contact and a raw contact in a single batch.
+
+ addInsertProfileOperations(ops);
+ addInsertContactOperations(ops);
+
+ mProvider.resetTrasactionCallbackCalledFlags();
+
+ // Execute the operations.
+ mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+
+ // Check the result
+ mProvider.assertCommitTransactionCalledForContactMode();
+ mProvider.assertCommitTransactionCalledForProfileMode();
+
+ checkStoredProfile();
+ checkStoredContact();
+ }
+}
diff --git a/tests/src/com/android/providers/contacts/DirectoryTest.java b/tests/src/com/android/providers/contacts/DirectoryTest.java
index e9592c1c..c62824b7 100644
--- a/tests/src/com/android/providers/contacts/DirectoryTest.java
+++ b/tests/src/com/android/providers/contacts/DirectoryTest.java
@@ -26,7 +26,7 @@ import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.Directory;
-import android.test.suitebuilder.annotation.MediumTest;;
+import android.test.suitebuilder.annotation.MediumTest;
/**
diff --git a/tests/src/com/android/providers/contacts/EvenMoreAsserts.java b/tests/src/com/android/providers/contacts/EvenMoreAsserts.java
index c73128af..1fc15f22 100644
--- a/tests/src/com/android/providers/contacts/EvenMoreAsserts.java
+++ b/tests/src/com/android/providers/contacts/EvenMoreAsserts.java
@@ -16,19 +16,19 @@
package com.android.providers.contacts;
-import com.google.android.collect.Sets;
-
import android.content.Context;
import android.graphics.BitmapFactory;
+import com.google.android.collect.Sets;
+
+import junit.framework.Assert;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Set;
-import junit.framework.Assert;
-
/**
* Contains additional assertion methods not found in Junit or MoreAsserts.
*/
diff --git a/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java b/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java
index 7ca2a877..281834f1 100644
--- a/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java
+++ b/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.util.MockSharedPreferences;
-
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.ContactCounts;
@@ -27,6 +25,8 @@ import android.test.AndroidTestCase;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.providers.contacts.util.MockSharedPreferences;
+
@SmallTest
public class FastScrollingIndexCacheTest extends AndroidTestCase {
private MockSharedPreferences mPrefs;
diff --git a/tests/src/com/android/providers/contacts/GlobalSearchSupportTest.java b/tests/src/com/android/providers/contacts/GlobalSearchSupportTest.java
index c7761095..f63845f4 100644
--- a/tests/src/com/android/providers/contacts/GlobalSearchSupportTest.java
+++ b/tests/src/com/android/providers/contacts/GlobalSearchSupportTest.java
@@ -116,20 +116,6 @@ public class GlobalSearchSupportTest extends BaseContactsProvider2Test {
"Deer Dough").expectedText2("1-800-4664-411").build().test();
}
- public void assertCreateContactSuggestion(Cursor c, String number) {
- ContentValues values = new ContentValues();
- values.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "Create contact");
- values.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "using "+ number);
- values.put(SearchManager.SUGGEST_COLUMN_ICON_1,
- String.valueOf(com.android.internal.R.drawable.create_contact));
- values.put(SearchManager.SUGGEST_COLUMN_INTENT_ACTION,
- Intents.SEARCH_SUGGESTION_CREATE_CONTACT_CLICKED);
- values.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA, "tel:" + number);
- values.put(SearchManager.SUGGEST_COLUMN_SHORTCUT_ID,
- SearchManager.SUGGEST_NEVER_MAKE_SHORTCUT);
- assertCursorValues(c, values);
- }
-
/**
* Tests that the quick search suggestion returns the expected contact
* information.
diff --git a/tests/src/com/android/providers/contacts/GroupsTest.java b/tests/src/com/android/providers/contacts/GroupsTest.java
index 3d85064a..15cfc719 100644
--- a/tests/src/com/android/providers/contacts/GroupsTest.java
+++ b/tests/src/com/android/providers/contacts/GroupsTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.google.android.collect.Lists;
-
import android.accounts.Account;
import android.content.ContentProviderOperation;
import android.content.ContentUris;
@@ -32,9 +30,10 @@ import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.Settings;
-import android.test.suitebuilder.annotation.LargeTest;
import android.test.suitebuilder.annotation.MediumTest;
+import com.google.android.collect.Lists;
+
import java.util.ArrayList;
/**
diff --git a/tests/src/com/android/providers/contacts/HanziToPinyinTest.java b/tests/src/com/android/providers/contacts/HanziToPinyinTest.java
index 78088ee9..c08bf86c 100644
--- a/tests/src/com/android/providers/contacts/HanziToPinyinTest.java
+++ b/tests/src/com/android/providers/contacts/HanziToPinyinTest.java
@@ -16,18 +16,18 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.HanziToPinyin.Token;
-
import android.test.suitebuilder.annotation.SmallTest;
import android.text.TextUtils;
+import com.android.providers.contacts.HanziToPinyin.Token;
+
+import junit.framework.TestCase;
+
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
-import junit.framework.TestCase;
-
@SmallTest
public class HanziToPinyinTest extends TestCase {
private final static String ONE_HANZI = "\u675C";
diff --git a/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java b/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java
index e515af2f..c752e4e0 100644
--- a/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java
+++ b/tests/src/com/android/providers/contacts/LegacyContactsProviderTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.tests.*;
-
import android.app.SearchManager;
import android.content.ContentProvider;
import android.content.ContentUris;
diff --git a/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java b/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
index a5cff7aa..a54193e3 100644
--- a/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
+++ b/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
@@ -19,12 +19,12 @@ package com.android.providers.contacts;
import android.provider.ContactsContract.FullNameStyle;
import android.test.suitebuilder.annotation.SmallTest;
+import junit.framework.TestCase;
+
import java.text.Collator;
import java.util.Arrays;
import java.util.Locale;
-import junit.framework.TestCase;
-
/**
* Unit tests for {@link NameLookupBuilder}.
*
diff --git a/tests/src/com/android/providers/contacts/NameSplitterTest.java b/tests/src/com/android/providers/contacts/NameSplitterTest.java
index 785fb01d..d9007fc1 100644
--- a/tests/src/com/android/providers/contacts/NameSplitterTest.java
+++ b/tests/src/com/android/providers/contacts/NameSplitterTest.java
@@ -16,16 +16,16 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.NameSplitter.Name;
-
import android.provider.ContactsContract.FullNameStyle;
import android.provider.ContactsContract.PhoneticNameStyle;
import android.test.suitebuilder.annotation.SmallTest;
-import java.util.Locale;
+import com.android.providers.contacts.NameSplitter.Name;
import junit.framework.TestCase;
+import java.util.Locale;
+
/**
* Tests for {@link NameSplitter}.
*
diff --git a/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java b/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java
index 20058ad9..4b159a8e 100644
--- a/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java
+++ b/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java
@@ -16,12 +16,12 @@
package com.android.providers.contacts;
-import com.google.android.collect.Maps;
-
import android.content.res.Resources;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import com.google.android.collect.Maps;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
diff --git a/tests/src/com/android/providers/contacts/PhotoProcessorTest.java b/tests/src/com/android/providers/contacts/PhotoProcessorTest.java
new file mode 100644
index 00000000..b34dd86d
--- /dev/null
+++ b/tests/src/com/android/providers/contacts/PhotoProcessorTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package com.android.providers.contacts;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.providers.contacts.tests.R;
+
+
+/**
+ * Tests for {@link PhotoProcessor}.
+ *
+ * Most of tests are covered by {@link PhotoStoreTest}.
+ */
+@SmallTest
+public class PhotoProcessorTest extends AndroidTestCase {
+
+ public void testTransparency() {
+ final Drawable source = getTestContext().getResources().getDrawable(
+ R.drawable.transparent_10x10);
+ final Bitmap sourceBitmap = ((BitmapDrawable) source).getBitmap();
+
+ final Bitmap normalized = PhotoProcessor.getNormalizedBitmap(sourceBitmap, 50, false);
+
+ // Make sure it's not scaled up.
+ assertEquals(10, normalized.getWidth());
+ assertEquals(10, normalized.getHeight());
+
+ // Make sure the transparent pixel is now 100% white.
+ assertEquals(Color.argb(255, 255, 255, 255), normalized.getPixel(0, 0));
+ }
+}
diff --git a/tests/src/com/android/providers/contacts/PhotoStoreTest.java b/tests/src/com/android/providers/contacts/PhotoStoreTest.java
index 1550d0b5..4e797f75 100644
--- a/tests/src/com/android/providers/contacts/PhotoStoreTest.java
+++ b/tests/src/com/android/providers/contacts/PhotoStoreTest.java
@@ -16,9 +16,7 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.tests.R;
-import com.android.providers.contacts.util.Hex;
+import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
@@ -26,17 +24,17 @@ import android.provider.ContactsContract;
import android.provider.ContactsContract.PhotoFiles;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+import com.android.providers.contacts.tests.R;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
-import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
-
/**
* Tests for {@link PhotoStore}.
*/
@@ -81,7 +79,7 @@ public class PhotoStoreTest extends PhotoLoadingTestCase {
public void testStoreNonSquare300x200Photo() throws IOException {
// The longer side should be downscaled to the target size
- runStorageTestForResource(R.drawable.earth_300x200, 256, 171);
+ runStorageTestForResource(R.drawable.earth_300x200, 256, 170);
}
public void testStoreNonSquare300x200PhotoWithCrop() throws IOException {
diff --git a/tests/src/com/android/providers/contacts/PostalSplitterForJapaneseTest.java b/tests/src/com/android/providers/contacts/PostalSplitterForJapaneseTest.java
index b4be1731..eba9d535 100644
--- a/tests/src/com/android/providers/contacts/PostalSplitterForJapaneseTest.java
+++ b/tests/src/com/android/providers/contacts/PostalSplitterForJapaneseTest.java
@@ -16,14 +16,14 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.PostalSplitter.Postal;
-
import android.test.suitebuilder.annotation.SmallTest;
-import java.util.Locale;
+import com.android.providers.contacts.PostalSplitter.Postal;
import junit.framework.TestCase;
+import java.util.Locale;
+
/**
* Tests for {@link PostalSplitter}, especially for ja_JP locale.
* This class depends on the assumption that all the tests in {@link NameSplitterTest} pass.
diff --git a/tests/src/com/android/providers/contacts/PostalSplitterTest.java b/tests/src/com/android/providers/contacts/PostalSplitterTest.java
index 6778b79b..d12b3f3d 100644
--- a/tests/src/com/android/providers/contacts/PostalSplitterTest.java
+++ b/tests/src/com/android/providers/contacts/PostalSplitterTest.java
@@ -16,14 +16,14 @@
package com.android.providers.contacts;
-import com.android.providers.contacts.PostalSplitter.Postal;
-
import android.test.suitebuilder.annotation.SmallTest;
-import java.util.Locale;
+import com.android.providers.contacts.PostalSplitter.Postal;
import junit.framework.TestCase;
+import java.util.Locale;
+
/**
* Tests for {@link PostalSplitter}, especially for en_US locale.
*
diff --git a/tests/src/com/android/providers/contacts/SqlInjectionDetectionTest.java b/tests/src/com/android/providers/contacts/SqlInjectionDetectionTest.java
index f4b8babe..7b3fe951 100644
--- a/tests/src/com/android/providers/contacts/SqlInjectionDetectionTest.java
+++ b/tests/src/com/android/providers/contacts/SqlInjectionDetectionTest.java
@@ -27,8 +27,6 @@ import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.test.suitebuilder.annotation.MediumTest;
-import junit.framework.Assert;
-
/**
* Unit tests for {@link ContactsProvider2}, to make sure the queries don't allow sql injection.
*
diff --git a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
index 3d28ad1f..1d127c7d 100644
--- a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
+++ b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
@@ -19,6 +19,9 @@ package com.android.providers.contacts;
import android.accounts.Account;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
+import android.util.Log;
+
+import junit.framework.Assert;
import java.util.Locale;
@@ -46,7 +49,7 @@ public class SynchronousContactsProvider2 extends ContactsProvider2 {
}
@Override
- public ProfileProvider getProfileProvider() {
+ public ProfileProvider newProfileProvider() {
return new SynchronousProfileProvider(this);
}
@@ -202,6 +205,7 @@ public class SynchronousContactsProvider2 extends ContactsProvider2 {
@Override
public void wipeData() {
+ Log.i(TAG, "wipeData");
super.wipeData();
SQLiteDatabase db = getDatabaseHelper(getContext()).getWritableDatabase();
db.execSQL("replace into SQLITE_SEQUENCE (name,seq) values('raw_contacts', 42)");
@@ -210,4 +214,84 @@ public class SynchronousContactsProvider2 extends ContactsProvider2 {
getContactDirectoryManagerForTest().scanAllPackages();
}
+
+ // Flags to remember which transaction callback has been called for which mode.
+ private boolean mOnBeginTransactionInternalCalledInProfileMode;
+ private boolean mOnCommitTransactionInternalCalledInProfileMode;
+ private boolean mOnRollbackTransactionInternalCalledInProfileMode;
+
+ private boolean mOnBeginTransactionInternalCalledInContactMode;
+ private boolean mOnCommitTransactionInternalCalledInContactMode;
+ private boolean mOnRollbackTransactionInternalCalledInContactMode;
+
+ public void resetTrasactionCallbackCalledFlags() {
+ mOnBeginTransactionInternalCalledInProfileMode = false;
+ mOnCommitTransactionInternalCalledInProfileMode = false;
+ mOnRollbackTransactionInternalCalledInProfileMode = false;
+
+ mOnBeginTransactionInternalCalledInContactMode = false;
+ mOnCommitTransactionInternalCalledInContactMode = false;
+ mOnRollbackTransactionInternalCalledInContactMode = false;
+ }
+
+ @Override
+ protected void onBeginTransactionInternal(boolean forProfile) {
+ super.onBeginTransactionInternal(forProfile);
+ if (forProfile) {
+ mOnBeginTransactionInternalCalledInProfileMode = true;
+ } else {
+ mOnBeginTransactionInternalCalledInContactMode = true;
+ }
+ }
+
+ @Override
+ protected void onCommitTransactionInternal(boolean forProfile) {
+ super.onCommitTransactionInternal(forProfile);
+ if (forProfile) {
+ mOnCommitTransactionInternalCalledInProfileMode = true;
+ } else {
+ mOnCommitTransactionInternalCalledInContactMode = true;
+ }
+ }
+
+ @Override
+ protected void onRollbackTransactionInternal(boolean forProfile) {
+ super.onRollbackTransactionInternal(forProfile);
+ if (forProfile) {
+ mOnRollbackTransactionInternalCalledInProfileMode = true;
+ } else {
+ mOnRollbackTransactionInternalCalledInContactMode = true;
+ }
+ }
+
+ public void assertCommitTransactionCalledForProfileMode() {
+ Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInProfileMode);
+ Assert.assertTrue("commit", mOnCommitTransactionInternalCalledInProfileMode);
+ Assert.assertFalse("rollback", mOnRollbackTransactionInternalCalledInProfileMode);
+ }
+
+ public void assertRollbackTransactionCalledForProfileMode() {
+ Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInProfileMode);
+ Assert.assertFalse("commit", mOnCommitTransactionInternalCalledInProfileMode);
+ Assert.assertTrue("rollback", mOnRollbackTransactionInternalCalledInProfileMode);
+ }
+
+ public void assertNoTransactionsForProfileMode() {
+ Assert.assertFalse("begin", mOnBeginTransactionInternalCalledInProfileMode);
+ Assert.assertFalse("commit", mOnCommitTransactionInternalCalledInProfileMode);
+ Assert.assertFalse("rollback", mOnRollbackTransactionInternalCalledInProfileMode);
+ }
+
+
+ public void assertCommitTransactionCalledForContactMode() {
+ Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInContactMode);
+ Assert.assertTrue("commit", mOnCommitTransactionInternalCalledInContactMode);
+ Assert.assertFalse("rollback", mOnRollbackTransactionInternalCalledInContactMode);
+ }
+
+ public void assertRollbackTransactionCalledForContactMode() {
+ Assert.assertTrue("begin", mOnBeginTransactionInternalCalledInContactMode);
+ Assert.assertFalse("commit", mOnCommitTransactionInternalCalledInContactMode);
+ Assert.assertTrue("rollback", mOnRollbackTransactionInternalCalledInContactMode);
+ }
}
diff --git a/tests/src/com/android/providers/contacts/SynchronousProfileProvider.java b/tests/src/com/android/providers/contacts/SynchronousProfileProvider.java
index 93ad70f7..308e67a5 100644
--- a/tests/src/com/android/providers/contacts/SynchronousProfileProvider.java
+++ b/tests/src/com/android/providers/contacts/SynchronousProfileProvider.java
@@ -16,7 +16,6 @@
package com.android.providers.contacts;
-import android.accounts.Account;
import android.content.Context;
import java.util.Locale;
diff --git a/tests/src/com/android/providers/contacts/TestUtils.java b/tests/src/com/android/providers/contacts/TestUtils.java
index 00789bf6..b6d6a271 100644
--- a/tests/src/com/android/providers/contacts/TestUtils.java
+++ b/tests/src/com/android/providers/contacts/TestUtils.java
@@ -21,12 +21,12 @@ import android.content.Context;
import android.database.Cursor;
import android.util.Log;
+import junit.framework.Assert;
+
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-import junit.framework.Assert;
-
public class TestUtils {
private TestUtils() {
}
diff --git a/tests/src/com/android/providers/contacts/VCardTest.java b/tests/src/com/android/providers/contacts/VCardTest.java
index b022ebd0..820c2635 100644
--- a/tests/src/com/android/providers/contacts/VCardTest.java
+++ b/tests/src/com/android/providers/contacts/VCardTest.java
@@ -16,12 +16,12 @@
package com.android.providers.contacts;
-import com.android.vcard.VCardComposer;
-import com.android.vcard.VCardConfig;
-
import android.content.ContentResolver;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.vcard.VCardComposer;
+import com.android.vcard.VCardConfig;
+
/**
* Tests (or integration tests) verifying if vCard library works well with {@link ContentResolver}.
*
diff --git a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
index 74195b5f..8fdbccf1 100644
--- a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
+++ b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
@@ -16,8 +16,6 @@
package com.android.providers.contacts;
-import com.android.common.io.MoreCloseables;
-
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
@@ -30,6 +28,8 @@ import android.provider.VoicemailContract.Voicemails;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.common.io.MoreCloseables;
+
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
diff --git a/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java b/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java
index 795ea9c6..16d06c89 100644
--- a/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java
+++ b/tests/src/com/android/providers/contacts/aggregation/ContactAggregatorTest.java
@@ -16,25 +16,15 @@
package com.android.providers.contacts.aggregation;
-import com.android.providers.contacts.BaseContactsProvider2Test;
-import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
-import com.android.providers.contacts.ContactsProvider2;
-import com.android.providers.contacts.TestUtils;
-import com.android.providers.contacts.tests.R;
-import com.google.android.collect.Lists;
-
import android.accounts.Account;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
-import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
-import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.provider.ContactsContract.AggregationExceptions;
-import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
@@ -46,6 +36,11 @@ import android.provider.ContactsContract.StatusUpdates;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.providers.contacts.BaseContactsProvider2Test;
+import com.android.providers.contacts.TestUtils;
+import com.android.providers.contacts.tests.R;
+import com.google.android.collect.Lists;
+
/**
* Unit tests for {@link ContactAggregator}.
*
diff --git a/tests/src/com/android/providers/contacts/aggregation/util/ContactMatcherTest.java b/tests/src/com/android/providers/contacts/aggregation/util/ContactMatcherTest.java
index 97faacda..301902a4 100644
--- a/tests/src/com/android/providers/contacts/aggregation/util/ContactMatcherTest.java
+++ b/tests/src/com/android/providers/contacts/aggregation/util/ContactMatcherTest.java
@@ -18,7 +18,9 @@ package com.android.providers.contacts.aggregation.util;
import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+@SmallTest
public class ContactMatcherTest extends AndroidTestCase {
public void testMatchName_invalidHexDecimal() {
diff --git a/tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java b/tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java
index 7f9f0538..b8332204 100644
--- a/tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java
+++ b/tests/src/com/android/providers/contacts/aggregation/util/NameDistanceTest.java
@@ -16,12 +16,11 @@
package com.android.providers.contacts.aggregation.util;
+import android.test.suitebuilder.annotation.SmallTest;
+
import com.android.providers.contacts.NameNormalizer;
-import com.android.providers.contacts.aggregation.util.NameDistance;
import com.android.providers.contacts.util.Hex;
-import android.test.suitebuilder.annotation.SmallTest;
-
import junit.framework.TestCase;
/**
diff --git a/tests/src/com/android/providers/contacts/util/DBQueryUtilsTest.java b/tests/src/com/android/providers/contacts/util/DBQueryUtilsTest.java
index 43f7c06d..7769b492 100644
--- a/tests/src/com/android/providers/contacts/util/DBQueryUtilsTest.java
+++ b/tests/src/com/android/providers/contacts/util/DBQueryUtilsTest.java
@@ -19,13 +19,13 @@ package com.android.providers.contacts.util;
import static com.android.providers.contacts.util.DbQueryUtils.checkForSupportedColumns;
import static com.android.providers.contacts.util.DbQueryUtils.concatenateClauses;
-import com.android.common.content.ProjectionMap;
-import com.android.providers.contacts.EvenMoreAsserts;
-
import android.content.ContentValues;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
+import com.android.common.content.ProjectionMap;
+import com.android.providers.contacts.EvenMoreAsserts;
+
/**
* Unit tests for the {@link DbQueryUtils} class.
* Run the test like this:
diff --git a/tests/src/com/android/providers/contacts/util/MockSharedPreferences.java b/tests/src/com/android/providers/contacts/util/MockSharedPreferences.java
index d00e7110..574ce19a 100644
--- a/tests/src/com/android/providers/contacts/util/MockSharedPreferences.java
+++ b/tests/src/com/android/providers/contacts/util/MockSharedPreferences.java
@@ -16,10 +16,10 @@
package com.android.providers.contacts.util;
-import com.google.android.collect.Maps;
-
import android.content.SharedPreferences;
+import com.google.android.collect.Maps;
+
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
diff --git a/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java b/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java
index 48bd6087..329e6e2b 100644
--- a/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java
+++ b/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java
@@ -20,9 +20,6 @@ import android.net.Uri;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import com.android.providers.contacts.util.TypedUriMatcherImpl;
-import com.android.providers.contacts.util.UriType;
-
/**
* Unit tests for {@link TypedUriMatcherImpl}.
* Run the test like this: