am 0160b3bd: Reconcile with jb-mr0-release
* commit '0160b3bd9eb2de45f56bcac3a5c27e4e5b183feb':
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6f74368..f2aeac9 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -96,5 +96,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 0000000..557b5bd
--- /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 2f6562b..cb922ee 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 6aa55ec..a74fb98 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 3cd298d..6ce18d8 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 44357c3..c45145c 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 dee34a7..1d2b334 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 ef073fa..82a533d 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 76335a0..ba8b3c0 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 7b708fb..e959c75 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 1f10b19..5a2ddca 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 2622515..4c21580 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 9cbc783..8f734b6 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 a3cddf2..7df66be 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; la cual incluye toda la información relacionada con tus contactos y el registro de todas tus llamadas y puede ser leída por cualquier aplicación; en el almacenamiento USB o en la tarjeta SD y 2) enviarla por correo. Recuerda eliminar la copia inmediatamente después de guardarla correctamente fuera del dispositivo o de que 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 tu 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 d4f7edf..d87b6e7 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 6fda0d5..c597f4f 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 bcdf710..e5812e8 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 d9c341f..7da7a99 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 b25b763..2b4e372 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 f2d706a..130eeca 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 2b53781..d9b6832 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 7f477e5..19c2cf8 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 f958b12..0e385dc 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 dfea4d4..54f5b0f 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">"È allegato 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 c87a2f9..a547c91 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 74044d8..794d6bc 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 041cc0b..5a0ae64 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 b873d1f..79e88d5 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 fa1e89e..ef86ffd 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 653a8d9..fa8d041 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 5775854..932bfb1 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 1a09288..b76de01 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 b598221..9cc9cdc 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 acdb0d2..9a97e7d 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 5d471a1..bd52184 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, contendo 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 b0e2898..c576298 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 110f166..7143885 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, copie care pot 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">"Bază de date a agendei ataşată"</string>
+ <string name="debug_dump_email_body" msgid="4577749800871444318">"Vă trimit ataşată baza de date a agendei mele cu toate informaţiile referitoare la agendă. 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 45b28a0..76ebc42 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 e8d82c6..aad2d53 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 af43531..cfbcb05 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 c8888db..3469cdf 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 06ecf9a..76c65ee 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 b83c636..72034ac 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">"Ambatisho lililipo ni la hifadhidata ya anwani zangu iliyo na maelezo yote ya anwani zangu. Ishughulikie kimakini."</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 0cb6adc..4e607d4 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 44f6b73..cd6bcad 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 672288a..46921fb 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 1829219..30ca84f 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 431a403..473de91 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, 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 402b8c1..dc019e9 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 ba929c3..f3d0998 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 76de636..e7083d3 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 aaa7f44..e17b5ed 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 a33320f..226652e 100644
--- a/src/com/android/providers/contacts/AbstractContactsProvider.java
+++ b/src/com/android/providers/contacts/AbstractContactsProvider.java
@@ -38,9 +38,12 @@
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 @@
* 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 @@
/**
* 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 @@
* @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 @@
* @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 3fea8a6..b7484cd 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 89ae591..21a16f1 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.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.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 7116ed6..f243e79 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.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 2eb2ad6..0e7b292 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 67429ca..62f49ae 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.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 @@
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 26aac63..ef2ea9a 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.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 @@
/* 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 @@
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 @@
};
// 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 @@
}
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 @@
switchToProfileMode();
accountsChanged |= updateAccountsInBackground(accounts);
+ switchToContactMode();
+
updateContactsAccountCount(accounts);
updateDirectoriesInBackground(accountsChanged);
break;
@@ -1601,6 +1598,8 @@
cleanupPhotoStore();
switchToProfileMode();
cleanupPhotoStore();
+
+ switchToContactMode(); // Switch to the default, just in case.
break;
}
}
@@ -1705,8 +1704,7 @@
@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 @@
// 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 @@
return mTransactionHolder;
}
- public ProfileProvider getProfileProvider() {
+ public ProfileProvider newProfileProvider() {
return new ProfileProvider(this);
}
@@ -1835,7 +1835,8 @@
return Locale.getDefault();
}
- private boolean inProfileMode() {
+ @VisibleForTesting
+ final boolean inProfileMode() {
Boolean profileMode = mInProfileMode.get();
return profileMode != null && profileMode;
}
@@ -1921,7 +1922,10 @@
* 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 @@
* 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 @@
}
}
- /**
- * 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 @@
@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 @@
@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 @@
@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"));
}
- // mDbHelper may not be pointing at the "right" db helper due to a bug,
- // so we invalidate both for now.
- mContactsHelper.invalidateAllCache();
- mProfileHelper.invalidateAllCache();
+ if (forProfile) {
+ switchToProfileMode();
+ } else {
+ switchToContactMode();
+ }
+
+ mDbHelper.get().invalidateAllCache();
}
private void updateSearchIndexInTransaction() {
@@ -2167,12 +2191,13 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
*/
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 @@
*/
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 @@
// 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 @@
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 @@
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 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 @@
+ 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
" 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 @@
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 @@
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 @@
"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 @@
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 @@
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 @@
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 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 @@
}
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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
" 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 @@
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 @@
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 @@
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 @@
case CONTACTS_ID: {
invalidateFastScrollingIndexCache();
- count = updateContactOptions(ContentUris.parseId(uri), values, callerIsSyncAdapter);
+ count = updateContactOptions(db, ContentUris.parseId(uri), values,
+ callerIsSyncAdapter);
break;
}
@@ -3701,8 +3749,8 @@
"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 @@
}
case AGGREGATION_EXCEPTIONS: {
- count = updateAggregationException(mActiveDb.get(), values);
+ count = updateAggregationException(db, values);
break;
}
@@ -3875,12 +3923,13 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
return 1;
}
+ @Override
public void onAccountsUpdated(Account[] accounts) {
scheduleBackgroundTask(BACKGROUND_TASK_UPDATE_ACCOUNTS);
}
@@ -4499,7 +4559,6 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
case SEARCH_SUGGESTIONS: {
return mGlobalSearchSupport.handleSearchSuggestionsQuery(
- mActiveDb.get(), uri, projection, limit);
+ db, uri, projection, limit);
}
case SEARCH_SHORTCUT: {
@@ -5875,7 +5930,7 @@
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 @@
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 @@
}
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 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 @@
"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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
rawContactIdSelect.append(")");
- final SQLiteDatabase db = mActiveDb.get();
+ final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
mSelectionArgs1[0] = String.valueOf(currentTimeMillis);
@@ -8106,7 +8151,7 @@
/* 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 @@
}
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 7a92cae..c6c11d9 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 @@
/**
* 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 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 @@
}
/**
+ * @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 b98f6c7..0366532 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.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 b717d31..0bb17c2 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.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 0202fd6..502b835 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 f1fa941..38cb2e1 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 3a4b167..0d2427a 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.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 440e430..48ce5e4 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 009bb89..faf10ad 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 0fec6ee..95f24f5 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.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 317af1a..ea73637 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 7384ccb..44146e8 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.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 99313e9..da7d66c 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.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 7560ed4..bfaa501 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.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 c84d2e8..01ee1ba 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.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 6898a43..26483ed 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.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 c13f4a8..fda8321 100644
--- a/src/com/android/providers/contacts/DbModifierWithNotification.java
+++ b/src/com/android/providers/contacts/DbModifierWithNotification.java
@@ -20,11 +20,6 @@
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.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 6777e43..fcda8f1 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 c1c5602..f07a855 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.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 78cbc9d..9859d11 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.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 5ebbcd1..8375b88 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 d91bd7c..c2b945e 100644
--- a/src/com/android/providers/contacts/NameNormalizer.java
+++ b/src/com/android/providers/contacts/NameNormalizer.java
@@ -17,10 +17,10 @@
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 fd5b096..43743ee 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 c0dc4d9..150811c 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 cf81ff3..1b8fc3f 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 @@
/** 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 @@
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 e0b5fb4..e7be48c 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 de5cce1..051c60e 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 9b707a3..a23e521 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 d97760d..ba10e8b 100644
--- a/src/com/android/providers/contacts/ProfileProvider.java
+++ b/src/com/android/providers/contacts/ProfileProvider.java
@@ -81,7 +81,6 @@
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 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 @@
ContactsTransaction transaction = getCurrentTransaction();
SQLiteDatabase db = getDatabaseHelper().getWritableDatabase();
transaction.startTransactionForDb(db, ContactsProvider2.PROFILE_DB_TAG, this);
- mDelegate.substituteDb(db);
}
@Override
@@ -142,20 +138,17 @@
@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 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 bd4e1cc..361b5d8 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.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 39f5be5..4ad1406 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.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 79d8f92..b2f6b1e 100644
--- a/src/com/android/providers/contacts/VoicemailContentProvider.java
+++ b/src/com/android/providers/contacts/VoicemailContentProvider.java
@@ -19,11 +19,6 @@
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.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 3b72653..3f00b26 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.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.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 a0a61ba..2c1861b 100644
--- a/src/com/android/providers/contacts/VoicemailStatusTable.java
+++ b/src/com/android/providers/contacts/VoicemailStatusTable.java
@@ -18,9 +18,6 @@
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.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 db35c98..9e6c431 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 d3931e6..baae2e5 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.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 fedf5fe..276a05f 100644
--- a/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
+++ b/src/com/android/providers/contacts/aggregation/ProfileAggregator.java
@@ -23,11 +23,11 @@
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 d6b799f..9643d81 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 0000000..530e779
--- /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 0000000..886314b
--- /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 0000000..d11c2cd
--- /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 1154186..3759196 100644
--- a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
@@ -18,11 +18,6 @@
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.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 0ce9bca..4c0d2df 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 f1ff776..96cbb9b 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.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 739b2cb..08f3a07 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.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 038eb97..e75c52e 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.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 a9d8a36..faddeea 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 69cd9fa..694f0f3 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.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 248d6da..6d98665 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 5706925..80e194d 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -18,16 +18,6 @@
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.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 @@
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 @@
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 0000000..6a82bf9
--- /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 e9592c1..c62824b 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.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 c73128a..1fc15f2 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 7ca2a87..281834f 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.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/GroupsTest.java b/tests/src/com/android/providers/contacts/GroupsTest.java
index 3d85064..15cfc71 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.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 7ffb855..d1433ce 100644
--- a/tests/src/com/android/providers/contacts/HanziToPinyinTest.java
+++ b/tests/src/com/android/providers/contacts/HanziToPinyinTest.java
@@ -16,17 +16,17 @@
package com.android.providers.contacts;
+import android.test.suitebuilder.annotation.SmallTest;
+
import com.android.providers.contacts.HanziToPinyin.Token;
-import android.test.suitebuilder.annotation.SmallTest;
+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 e515af2..c752e4e 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 a5cff7a..a54193e 100644
--- a/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
+++ b/tests/src/com/android/providers/contacts/NameLookupBuilderTest.java
@@ -19,12 +19,12 @@
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 785fb01..d9007fc 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 20058ad..4b159a8 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 0000000..b34dd86
--- /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 1550d0b..4e797f7 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.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 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 b4be173..eba9d53 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 6778b79..d12b3f3 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 f4b8bab..7b3fe95 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.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 3d28ad1..1d127c7 100644
--- a/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
+++ b/tests/src/com/android/providers/contacts/SynchronousContactsProvider2.java
@@ -19,6 +19,9 @@
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 @@
}
@Override
- public ProfileProvider getProfileProvider() {
+ public ProfileProvider newProfileProvider() {
return new SynchronousProfileProvider(this);
}
@@ -202,6 +205,7 @@
@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 @@
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 93ad70f..308e67a 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 00789bf..b6d6a27 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.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 b022ebd..820c263 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 74195b5..8fdbccf 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.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 795ea9c..16d06c8 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.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 97faacd..301902a 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 @@
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 7f9f053..b833220 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 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 com.android.providers.contacts.NameNormalizer;
+import com.android.providers.contacts.util.Hex;
+
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 43f7c06..7769b49 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 @@
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 d00e711..574ce19 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 48bd608..329e6e2 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.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: