DO NOT MERGE - Merge Android 10 into master

Bug: 139893257
Change-Id: I705adb517bc5cdd70c4f45fa627a274e4503dd2c
diff --git a/Android.bp b/Android.bp
index d340304..8991628 100644
--- a/Android.bp
+++ b/Android.bp
@@ -13,6 +13,7 @@
         "com.android.vcard",
         "guava",
     ],
+
     // The Jacoco tool analyzes code coverage when running unit tests on the
     // application. This configuration line selects which packages will be analyzed,
     // leaving out code which is tested by other means (e.g. static libraries) that
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 559e60f..2da56fc 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -16,6 +16,7 @@
     <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
     <uses-permission android:name="android.permission.WRITE_CONTACTS" />
     <uses-permission android:name="android.permission.USE_RESERVED_DISK" />
+    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
 
     <permission
             android:name="android.permission.SEND_CALL_LOG_CHANGE"
diff --git a/README-tests.md b/README-tests.md
new file mode 100644
index 0000000..8351c6c
--- /dev/null
+++ b/README-tests.md
@@ -0,0 +1,7 @@
+# Running tests
+
+Use the following command to run the unit tests.
+
+```
+atest ContactsProviderTests ContactsProviderTests2
+```
\ No newline at end of file
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
new file mode 100644
index 0000000..1576ba2
--- /dev/null
+++ b/res/values-as/strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="sharedUserLabel" msgid="8024311725474286801">"Android Core এপসমূহ"</string>
+    <string name="app_label" msgid="3389954322874982620">"সম্পৰ্কসমূহৰ সঞ্চয়াগাৰ"</string>
+    <string name="provider_label" msgid="6012150850819899907">"সম্পর্কবোৰ"</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="2581831842693151968">"আপগ্ৰেড প্ৰক্ৰিয়া সম্পূৰ্ণ কৰিবলৈ টিপক।"</string>
+    <string name="default_directory" msgid="93961630309570294">"সম্পর্কসূচী"</string>
+    <string name="local_invisible_directory" msgid="705244318477396120">"অন্যান্য"</string>
+    <string name="voicemail_from_column" msgid="435732568832121444">"ইয়াৰ পৰা অহা ভইচমেল "</string>
+    <string name="debug_dump_title" msgid="4916885724165570279">"সম্পৰ্কসূচীৰ ডেটাবেছ প্ৰতিলিপি কৰক"</string>
+    <string name="debug_dump_database_message" msgid="406438635002392290">"আপুনি এই কাৰ্যবোৰ কৰিবলৈ লৈছে ১) সকলো সম্পৰ্ক সম্বন্ধীয় তথ্য় আৰু কল লগ সন্নিবিষ্ট থকা আপোনাৰ ডেটাবেছক আভ্য়ন্তৰীণ সঞ্চয়াগাৰলৈ প্ৰতিলিপি কৰা আৰু ২) ইয়াক ইমেইল কৰা। ডিভাইচৰ পৰা সফলতাৰে প্ৰতিলিপি কৰাৰ বা ইমেইল পোৱাৰ পিছত উক্ত প্ৰতিলিপি মচিবলৈ নাপাহৰিব।"</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-cs/strings.xml b/res/values-cs/strings.xml
index 489b5b7..47fc931 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -27,7 +27,7 @@
     <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="406438635002392290">"Chystáte se 1) vytvořit v interním úložišti kopii databáze obsahující všechny informace o kontaktech a veškerou historii hovorů a 2) odeslat ji e-mailem. Po úspěšném zkopírování ze zařízení nebo přijetí e-mailem ji nezapomeňte ihned odstranit."</string>
-    <string name="debug_dump_delete_button" msgid="7832879421132026435">"Smazat nyní"</string>
+    <string name="debug_dump_delete_button" msgid="7832879421132026435">"Smazat teď"</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>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index fde3a2f..af92fe7 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -18,18 +18,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="sharedUserLabel" msgid="8024311725474286801">"Android-kerneapplikationer"</string>
     <string name="app_label" msgid="3389954322874982620">"Lagring af kontakter"</string>
-    <string name="provider_label" msgid="6012150850819899907">"Kontaktpersoner"</string>
-    <string name="upgrade_out_of_memory_notification_ticker" msgid="7638747231223520477">"Opgradering af kontaktpersoner kræver mere hukommelse."</string>
-    <string name="upgrade_out_of_memory_notification_title" msgid="8888171924684998531">"Opgraderer lagring af kontaktpersoner"</string>
+    <string name="provider_label" msgid="6012150850819899907">"Kontakter"</string>
+    <string name="upgrade_out_of_memory_notification_ticker" msgid="7638747231223520477">"Opgradering af kontakter kræver mere hukommelse."</string>
+    <string name="upgrade_out_of_memory_notification_title" msgid="8888171924684998531">"Opgraderer lagring af kontakter"</string>
     <string name="upgrade_out_of_memory_notification_text" msgid="2581831842693151968">"Tryk for at gennemføre opgraderingen."</string>
-    <string name="default_directory" msgid="93961630309570294">"Kontaktpersoner"</string>
+    <string name="default_directory" msgid="93961630309570294">"Kontakter"</string>
     <string name="local_invisible_directory" msgid="705244318477396120">"Andre"</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="406438635002392290">"Du er ved at 1) lave en kopi af din database, som indeholder alle oplysninger om dine kontaktpersoner og alle opkaldslister, til det interne lager, 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_title" msgid="4916885724165570279">"Kopiér database med kontakter"</string>
+    <string name="debug_dump_database_message" msgid="406438635002392290">"Du er ved at 1) lave en kopi af din database, som indeholder alle oplysninger om dine kontakter og alle opkaldslister, til det interne lager, og 2) sende den som mail. Husk at slette kopien, så snart du har kopieret den fra enheden, eller 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>
+    <string name="debug_dump_email_subject" msgid="108188398416385976">"Database med kontakter er vedhæftet"</string>
+    <string name="debug_dump_email_body" msgid="4577749800871444318">"Min database med kontakter med alle oplysninger om mine kontakter er vedhæftet. Brug den med omhu."</string>
 </resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 3266571..4af29ec 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -26,7 +26,7 @@
     <string name="local_invisible_directory" msgid="705244318477396120">"سایر موارد"</string>
     <string name="voicemail_from_column" msgid="435732568832121444">"پست صوتی از "</string>
     <string name="debug_dump_title" msgid="4916885724165570279">"کپی پایگاه داده مخاطبین"</string>
-    <string name="debug_dump_database_message" msgid="406438635002392290">"شما در شرف ۱) ایجاد یک کپی از پایگاه داده‌ در حافظه داخلی هستید، این کپی حاوی همه اطلاعات مربوط به مخاطبین و همه گزارشات تماس است و همچنین می‌خواهید ۲) آنرا رایانامه کنید. به خاطر داشته باشید که به محض کپی کردن این نسخه در دستگاه یا دریافت رایانامه، آنرا حذف کنید."</string>
+    <string name="debug_dump_database_message" msgid="406438635002392290">"شما در شرف ۱) ایجاد یک کپی از پایگاه داده‌ در حافظه داخلی هستید، این کپی حاوی همه اطلاعات مربوط به مخاطبین و همه گزارشات تماس است و همچنین می‌خواهید ۲) آنرا ایمیل کنید. به خاطر داشته باشید که به محض کپی کردن این نسخه در دستگاه یا دریافت ایمیل، آنرا حذف کنید."</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>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 4e7a44c..1756ab8 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -26,7 +26,7 @@
     <string name="local_invisible_directory" msgid="705244318477396120">"その他"</string>
     <string name="voicemail_from_column" msgid="435732568832121444">"受信ボイスメール: "</string>
     <string name="debug_dump_title" msgid="4916885724165570279">"連絡先データベースをコピー"</string>
-    <string name="debug_dump_database_message" msgid="406438635002392290">"1)すべての連絡先関連情報とすべての通話履歴を格納したデータベースを内部ストレージにコピーし、2)メールで送信しようとしています。デバイスからのコピーが完了した時点またはメールが受信された時点ですぐにコピーを削除してください。"</string>
+    <string name="debug_dump_database_message" msgid="406438635002392290">"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>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index a4f324e..67014ca 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -26,10 +26,10 @@
     <string name="local_invisible_directory" msgid="705244318477396120">"इतर"</string>
     <string name="voicemail_from_column" msgid="435732568832121444">"कडून व्हॉईसमेल "</string>
     <string name="debug_dump_title" msgid="4916885724165570279">"संपर्क डेटाबेस कॉपी करा"</string>
-    <string name="debug_dump_database_message" msgid="406438635002392290">"आपण 1) आपल्‍या डेटाबेसची प्रत बनवणार आहात जिच्‍यामध्‍ये सर्व संपर्कांसंबंधी माहिती आणि अंतर्गत संचयनावरील कॉल लॉग समाविष्‍ट असतात आणि 2) ती ईमेल करणार आहात. आपण डिव्‍हाइसवरून यशस्‍वीरित्‍या प्रत कॉपी केल्‍यानंतर किंवा ईमेल प्राप्त केल्‍यानंतर लगेच ती हटविण्‍याचे लक्षात ठेवा."</string>
+    <string name="debug_dump_database_message" msgid="406438635002392290">"तुम्ही 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_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-my/strings.xml b/res/values-my/strings.xml
index a8f2cb9..02cb4d5 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -20,7 +20,7 @@
     <string name="app_label" msgid="3389954322874982620">"လိပ်စာများသိမ်းဆည်းသောအပ်ပလီကေးရှင်း"</string>
     <string name="provider_label" msgid="6012150850819899907">"အဆက်အသွယ်များ"</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_title" msgid="8888171924684998531">"အဆယ်အသွယ်များ သိမ်းရန် နေရာ အဆင့်မြှင့်ခြင်း"</string>
     <string name="upgrade_out_of_memory_notification_text" msgid="2581831842693151968">"အဆင့်မြှင့်တင်ခြင်းပြီးမြောက်ရန် တို့ပါ။"</string>
     <string name="default_directory" msgid="93961630309570294">"အဆက်အသွယ်များ"</string>
     <string name="local_invisible_directory" msgid="705244318477396120">"တစ်ခြား"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
new file mode 100644
index 0000000..c6bfa21
--- /dev/null
+++ b/res/values-or/strings.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="sharedUserLabel" msgid="8024311725474286801">"Android କୋର୍ ଆପ୍"</string>
+    <string name="app_label" msgid="3389954322874982620">"ଯୋଗାଯୋଗ ଷ୍ଟୋରେଜ୍"</string>
+    <string name="provider_label" msgid="6012150850819899907">"ଯୋଗାଯୋଗ"</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="2581831842693151968">"ଅପଗ୍ରେଡ୍ ସମ୍ପୂର୍ଣ୍ଣ କରିବା ପାଇଁ ଟାପ୍ କରନ୍ତୁ।"</string>
+    <string name="default_directory" msgid="93961630309570294">"ଯୋଗାଯୋଗ"</string>
+    <string name="local_invisible_directory" msgid="705244318477396120">"ଅନ୍ୟାନ୍ୟ"</string>
+    <string name="voicemail_from_column" msgid="435732568832121444">"ଏହାଙ୍କଠାରୁ ଭଏସମେଲ୍‌ "</string>
+    <string name="debug_dump_title" msgid="4916885724165570279">"ଯୋଗାଯୋଗ ଡାଟାବେସ୍ କପୀ କରନ୍ତୁ"</string>
+    <string name="debug_dump_database_message" msgid="406438635002392290">"ଆପଣ 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-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index f259d83..decb5b6 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -26,7 +26,7 @@
     <string name="local_invisible_directory" msgid="705244318477396120">"其他"</string>
     <string name="voicemail_from_column" msgid="435732568832121444">"語音郵件寄件者: "</string>
     <string name="debug_dump_title" msgid="4916885724165570279">"複製聯絡人資料庫"</string>
-    <string name="debug_dump_database_message" msgid="406438635002392290">"您即將要 1) 將您的資料庫 (包含所有聯絡人相關資訊及所有通話紀錄) 複製到內部儲存空間,以及 2) 透過電子郵件傳送副本。提醒您,當您順利複製裝置上的資料或收到電子郵件後,請儘快刪除副本。"</string>
+    <string name="debug_dump_database_message" msgid="406438635002392290">"您即將要 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>
diff --git a/run-all-tests.sh b/run-all-tests.sh
deleted file mode 100755
index 84a2ce3..0000000
--- a/run-all-tests.sh
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2016 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.
-#
-
-set -e
-
-cd $ANDROID_BUILD_TOP
-
-. build/envsetup.sh
-
-mmm -j32 packages/providers/ContactsProvider
-adb install -t -r -g $ANDROID_PRODUCT_OUT/system/priv-app/ContactsProvider/ContactsProvider.apk
-adb install -t -r -g $ANDROID_PRODUCT_OUT/data/app/ContactsProviderTests/ContactsProviderTests.apk
-adb install -t -r -g $ANDROID_PRODUCT_OUT/data/app/ContactsProviderTests2/ContactsProviderTests2.apk
-
-runtest() {
-    log=/tmp/$$.log
-    adb shell am instrument -w "${@}" |& tee $log
-    if grep -q FAILURES $log || ! grep -P -q 'OK \([1-9]' $log ; then
-        return 1
-    else
-        return 0
-    fi
-
-}
-
-runtest com.android.providers.contacts.tests
-runtest com.android.providers.contacts.tests2
\ No newline at end of file
diff --git a/src/com/android/providers/contacts/ContactsDatabaseHelper.java b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
index caea55d..91a2a91 100644
--- a/src/com/android/providers/contacts/ContactsDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ContactsDatabaseHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.providers.contacts;
 
+import com.android.internal.R.bool;
 import com.android.providers.contacts.sqlite.DatabaseAnalyzer;
 import com.android.providers.contacts.sqlite.SqlChecker;
 import com.android.providers.contacts.sqlite.SqlChecker.InvalidSqlException;
@@ -30,7 +31,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.UserInfo;
-import android.content.res.Resources;
 import android.database.CharArrayBuffer;
 import android.database.Cursor;
 import android.database.DatabaseUtils;
@@ -84,6 +84,7 @@
 import android.provider.ContactsContract.StatusUpdates;
 import android.provider.ContactsContract.StreamItemPhotos;
 import android.provider.ContactsContract.StreamItems;
+import android.provider.DeviceConfig;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -104,11 +105,16 @@
 import com.android.providers.contacts.database.MoreDatabaseUtils;
 import com.android.providers.contacts.util.NeededForTesting;
 
+import java.io.PrintWriter;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.ArrayList;
 import java.util.Locale;
 import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Database helper for contacts. Designed as a singleton to make sure that all
@@ -136,9 +142,10 @@
      *   1100-1199 N
      *   1200-1299 O
      *   1300-1399 P
+     *   1400-1499 Q
      * </pre>
      */
-    static final int DATABASE_VERSION = 1300;
+    static final int DATABASE_VERSION = 1400;
     private static final int MINIMUM_SUPPORTED_VERSION = 700;
 
     @VisibleForTesting
@@ -146,6 +153,18 @@
 
     private static final int IDLE_CONNECTION_TIMEOUT_MS = 30000;
 
+    private static final String USE_STRICT_PHONE_NUMBER_COMPARISON_KEY
+            = "use_strict_phone_number_comparison";
+
+    private static final String USE_STRICT_PHONE_NUMBER_COMPARISON_FOR_RUSSIA_KEY
+            = "use_strict_phone_number_comparison_for_russia";
+
+    private static final String USE_STRICT_PHONE_NUMBER_COMPARISON_FOR_KAZAKHSTAN_KEY
+            = "use_strict_phone_number_comparison_for_kazakhstan";
+
+    private static final String RUSSIA_COUNTRY_CODE = "RU";
+    private static final String KAZAKHSTAN_COUNTRY_CODE = "KZ";
+
     public interface Tables {
         public static final String CONTACTS = "contacts";
         public static final String DELETED_CONTACTS = "deleted_contacts";
@@ -333,9 +352,6 @@
         public static final String RAW_ENTITIES = "view_raw_entities";
         public static final String GROUPS = "view_groups";
 
-        /** The data_usage_stat table joined with other tables. */
-        public static final String DATA_USAGE_STAT = "view_data_usage_stat";
-
         /** The data_usage_stat table with the low-res columns. */
         public static final String DATA_USAGE_LR = "view_data_usage";
         public static final String STREAM_ITEMS = "view_stream_items";
@@ -422,11 +438,6 @@
         public static final String CONCRETE_PHOTO_FILE_ID = Tables.CONTACTS + "."
                 + Contacts.PHOTO_FILE_ID;
 
-        public static final String CONCRETE_RAW_TIMES_CONTACTED = Tables.CONTACTS + "."
-                + Contacts.RAW_TIMES_CONTACTED;
-        public static final String CONCRETE_RAW_LAST_TIME_CONTACTED = Tables.CONTACTS + "."
-                + Contacts.RAW_LAST_TIME_CONTACTED;
-
         public static final String CONCRETE_STARRED = Tables.CONTACTS + "." + Contacts.STARRED;
         public static final String CONCRETE_PINNED = Tables.CONTACTS + "." + Contacts.PINNED;
         public static final String CONCRETE_CUSTOM_RINGTONE = Tables.CONTACTS + "."
@@ -471,10 +482,6 @@
                 Tables.RAW_CONTACTS + "." + RawContacts.CUSTOM_RINGTONE;
         public static final String CONCRETE_SEND_TO_VOICEMAIL =
                 Tables.RAW_CONTACTS + "." + RawContacts.SEND_TO_VOICEMAIL;
-        public static final String CONCRETE_RAW_LAST_TIME_CONTACTED =
-                Tables.RAW_CONTACTS + "." + RawContacts.RAW_LAST_TIME_CONTACTED;
-        public static final String CONCRETE_RAW_TIMES_CONTACTED =
-                Tables.RAW_CONTACTS + "." + RawContacts.RAW_TIMES_CONTACTED;
         public static final String CONCRETE_STARRED =
                 Tables.RAW_CONTACTS + "." + RawContacts.STARRED;
         public static final String CONCRETE_PINNED =
@@ -748,18 +755,6 @@
         public static final String RAW_TIMES_USED = Data.RAW_TIMES_USED;
         public static final String LR_TIMES_USED = Data.LR_TIMES_USED;
 
-        public static final String CONCRETE_RAW_LAST_TIME_USED =
-                Tables.DATA_USAGE_STAT + "." + RAW_LAST_TIME_USED;
-
-        public static final String CONCRETE_RAW_TIMES_USED =
-                Tables.DATA_USAGE_STAT + "." + RAW_TIMES_USED;
-
-        public static final String CONCRETE_LR_LAST_TIME_USED =
-                Tables.DATA_USAGE_STAT + "." + LR_LAST_TIME_USED;
-
-        public static final String CONCRETE_LR_TIMES_USED =
-                Tables.DATA_USAGE_STAT + "." + LR_TIMES_USED;
-
         /** type: INTEGER */
         public static final String USAGE_TYPE_INT = "usage_type";
         public static final String CONCRETE_USAGE_TYPE =
@@ -928,60 +923,6 @@
         }
     }
 
-    /** Placeholder for the methods to build the "low-res" SQL expressions. */
-    @VisibleForTesting
-    interface LowRes {
-        /** To be replaced with a real column name.  Only used within this interface. */
-        String TEMPLATE_PLACEHOLDER = "XX";
-
-        /**
-         * To be replaced with a constant in the expression.
-         * Only used within this interface.
-         */
-        String CONSTANT_PLACEHOLDER = "YY";
-
-        /** Only used within this interface. */
-        int TIMES_USED_GRANULARITY = 10;
-
-        /** Only used within this interface. */
-        int LAST_TIME_USED_GRANULARITY = 24 * 60 * 60;
-
-        /**
-         * Template to build the "low-res times used/contacted".  Only used within this interface.
-         * The outermost cast is needed to tell SQLite that the result is of the integer type.
-         */
-        String TEMPLATE_TIMES_USED =
-                ("cast(ifnull((case when (XX) <= 0 then 0"
-                + " when (XX) < (YY) then (XX)"
-                + " else (cast((XX) as int) / (YY)) * (YY) end), 0) as int)")
-                .replaceAll(CONSTANT_PLACEHOLDER, String.valueOf(TIMES_USED_GRANULARITY));
-
-        /**
-         * Template to build the "low-res last time used/contacted".
-         * Only used within this interface.
-         * The outermost cast is needed to tell SQLite that the result is of the integer type.
-         */
-        String TEMPLATE_LAST_TIME_USED =
-                ("cast((cast((XX) as int) / (YY)) * (YY) as int)")
-                .replaceAll(CONSTANT_PLACEHOLDER, String.valueOf(LAST_TIME_USED_GRANULARITY));
-
-        /**
-         * Build the SQL expression for the "low-res times used/contacted" expression from the
-         * give column name.
-         */
-        static String getTimesUsedExpression(String column) {
-            return TEMPLATE_TIMES_USED.replaceAll(TEMPLATE_PLACEHOLDER, column);
-        }
-
-        /**
-         * Build the SQL expression for the "low-res last time used/contacted" expression from the
-         * give column name.
-         */
-        static String getLastTimeUsedExpression(String column) {
-            return TEMPLATE_LAST_TIME_USED.replaceAll(TEMPLATE_PLACEHOLDER, column);
-        }
-    }
-
     private static final String TAG = "ContactsDatabaseHelper";
 
     private static final String DATABASE_NAME = "contacts2.db";
@@ -1033,7 +974,14 @@
         }
     }
 
-    private boolean mUseStrictPhoneNumberComparison;
+    // We access it from multiple threads, so mark as volatile.
+    private volatile boolean mUseStrictPhoneNumberComparison;
+
+    // They're basically accessed only in one method, as well as in dump(), so technically
+    // they should be volatile too, but it's not really needed in practice.
+    private boolean mUseStrictPhoneNumberComparisonBase;
+    private boolean mUseStrictPhoneNumberComparisonForRussia;
+    private boolean mUseStrictPhoneNumberComparisonForKazakhstan;
     private int mMinMatch;
 
     private String[] mSelectionArgs1 = new String[1];
@@ -1041,6 +989,9 @@
     private CharArrayBuffer mCharArrayBuffer = new CharArrayBuffer(128);
     private NameSplitter mNameSplitter;
 
+    private final Executor mLazilyCreatedExecutor =
+            new ThreadPoolExecutor(0, 1, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
+
     public static synchronized ContactsDatabaseHelper getInstance(Context context) {
         if (sSingleton == null) {
             sSingleton = new ContactsDatabaseHelper(context, DATABASE_NAME, true,
@@ -1071,16 +1022,67 @@
         setIdleConnectionTimeout(IDLE_CONNECTION_TIMEOUT_MS);
         mDatabaseOptimizationEnabled = optimizationEnabled;
         mIsTestInstance = isTestInstance;
-        Resources resources = context.getResources();
         mContext = context;
         mSyncState = new SyncStateContentProviderHelper();
-        mCountryMonitor = new CountryMonitor(context);
-        mUseStrictPhoneNumberComparison = resources.getBoolean(
-                com.android.internal.R.bool.config_use_strict_phone_number_comparation);
+
+        mCountryMonitor = new CountryMonitor(context, this::updateUseStrictPhoneNumberComparison);
+
+        startListeningToDeviceConfigUpdates();
+
+        updateUseStrictPhoneNumberComparison();
+    }
+
+    protected void startListeningToDeviceConfigUpdates() {
+        // Note we override this method in the profile helper to skip it.
+
+        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_CONTACTS_PROVIDER,
+                mLazilyCreatedExecutor, (props) -> onDeviceConfigUpdated());
+    }
+
+    private void onDeviceConfigUpdated() {
+        updateUseStrictPhoneNumberComparison();
+    }
+
+    protected void updateUseStrictPhoneNumberComparison() {
+        // Note we override this method in the profile helper to skip it.
+
+        final String country = getCurrentCountryIso();
+
+        Log.i(TAG, "updateUseStrictPhoneNumberComparison: " + country);
+
+        // Load all the configs so we can show them in dumpsys.
+        mUseStrictPhoneNumberComparisonBase = getConfig(
+                USE_STRICT_PHONE_NUMBER_COMPARISON_KEY,
+                bool.config_use_strict_phone_number_comparation);
+
+        mUseStrictPhoneNumberComparisonForRussia = getConfig(
+                USE_STRICT_PHONE_NUMBER_COMPARISON_FOR_RUSSIA_KEY,
+                bool.config_use_strict_phone_number_comparation_for_russia);
+
+        mUseStrictPhoneNumberComparisonForKazakhstan = getConfig(
+                USE_STRICT_PHONE_NUMBER_COMPARISON_FOR_KAZAKHSTAN_KEY,
+                bool.config_use_strict_phone_number_comparation_for_kazakhstan);
+
+        if (RUSSIA_COUNTRY_CODE.equals(country)) {
+            mUseStrictPhoneNumberComparison = mUseStrictPhoneNumberComparisonForRussia;
+
+        } else if (KAZAKHSTAN_COUNTRY_CODE.equals(country)) {
+            mUseStrictPhoneNumberComparison = mUseStrictPhoneNumberComparisonForKazakhstan;
+
+        } else {
+            mUseStrictPhoneNumberComparison = mUseStrictPhoneNumberComparisonBase;
+        }
+
         mMinMatch = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_phonenumber_compare_min_match);
     }
 
+    private boolean getConfig(String configKey, int defaultResId) {
+        return DeviceConfig.getBoolean(
+                DeviceConfig.NAMESPACE_CONTACTS_PROVIDER, configKey,
+                mContext.getResources().getBoolean(defaultResId));
+    }
+
     public SQLiteDatabase getDatabase(boolean writable) {
         return writable ? getWritableDatabase() : getReadableDatabase();
     }
@@ -1898,7 +1900,7 @@
         db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_CONTACTS + ";");
         db.execSQL("DROP VIEW IF EXISTS " + Views.RAW_ENTITIES + ";");
         db.execSQL("DROP VIEW IF EXISTS " + Views.ENTITIES + ";");
-        db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_USAGE_STAT + ";");
+        db.execSQL("DROP VIEW IF EXISTS view_data_usage_stat;");
         db.execSQL("DROP VIEW IF EXISTS " + Views.DATA_USAGE_LR + ";");
         db.execSQL("DROP VIEW IF EXISTS " + Views.STREAM_ITEMS + ";");
         db.execSQL("DROP VIEW IF EXISTS " + Views.METADATA_SYNC_STATE + ";");
@@ -1974,15 +1976,11 @@
                 + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
                         + " AS " + Contacts.SEND_TO_VOICEMAIL + ","
 
-                + ContactsColumns.CONCRETE_RAW_LAST_TIME_CONTACTED
-                        + " AS " + Contacts.RAW_LAST_TIME_CONTACTED + ","
-                + ContactsColumns.CONCRETE_RAW_TIMES_CONTACTED
-                        + " AS " + Contacts.RAW_TIMES_CONTACTED + ","
+                + "0 AS " + Contacts.RAW_LAST_TIME_CONTACTED + ","
+                + "0 AS " + Contacts.RAW_TIMES_CONTACTED + ","
 
-                + LowRes.getLastTimeUsedExpression(ContactsColumns.CONCRETE_RAW_LAST_TIME_CONTACTED)
-                        + " AS " + Contacts.LR_LAST_TIME_CONTACTED + ","
-                + LowRes.getTimesUsedExpression(ContactsColumns.CONCRETE_RAW_TIMES_CONTACTED)
-                        + " AS " + Contacts.LR_TIMES_CONTACTED + ","
+                + "0 AS " + Contacts.LR_LAST_TIME_CONTACTED + ","
+                + "0 AS " + Contacts.LR_TIMES_CONTACTED + ","
 
                 + ContactsColumns.CONCRETE_STARRED
                         + " AS " + Contacts.STARRED + ","
@@ -2053,12 +2051,10 @@
         String rawContactOptionColumns =
                 RawContacts.CUSTOM_RINGTONE + ","
                 + RawContacts.SEND_TO_VOICEMAIL + ","
-                + RawContacts.RAW_LAST_TIME_CONTACTED + ","
-                + LowRes.getLastTimeUsedExpression(RawContacts.RAW_LAST_TIME_CONTACTED)
-                        + " AS " + RawContacts.LR_LAST_TIME_CONTACTED + ","
-                + RawContacts.RAW_TIMES_CONTACTED + ","
-                + LowRes.getTimesUsedExpression(RawContacts.RAW_TIMES_CONTACTED)
-                        + " AS " + RawContacts.LR_TIMES_CONTACTED + ","
+                + "0 AS " + RawContacts.RAW_LAST_TIME_CONTACTED + ","
+                + "0 AS " + RawContacts.LR_LAST_TIME_CONTACTED + ","
+                + "0 AS " + RawContacts.RAW_TIMES_CONTACTED + ","
+                + "0 AS " + RawContacts.LR_TIMES_CONTACTED + ","
                 + RawContacts.STARRED + ","
                 + RawContacts.PINNED;
 
@@ -2096,10 +2092,8 @@
                 + contactNameColumns + ", "
                 + baseContactColumns + ", "
 
-                + ContactsColumns.CONCRETE_RAW_LAST_TIME_CONTACTED
-                        + " AS " + Contacts.RAW_LAST_TIME_CONTACTED + ", "
-                + LowRes.getLastTimeUsedExpression(ContactsColumns.CONCRETE_RAW_LAST_TIME_CONTACTED)
-                        + " AS " + Contacts.LR_LAST_TIME_CONTACTED + ", "
+                + "0 AS " + Contacts.RAW_LAST_TIME_CONTACTED + ", "
+                + "0 AS " + Contacts.LR_LAST_TIME_CONTACTED + ", "
 
                 + ContactsColumns.CONCRETE_SEND_TO_VOICEMAIL
                         + " AS " + Contacts.SEND_TO_VOICEMAIL + ", "
@@ -2108,10 +2102,8 @@
                 + ContactsColumns.CONCRETE_PINNED
                 + " AS " + Contacts.PINNED + ", "
 
-                + ContactsColumns.CONCRETE_RAW_TIMES_CONTACTED
-                        + " AS " + Contacts.RAW_TIMES_CONTACTED + ", "
-                + LowRes.getTimesUsedExpression(ContactsColumns.CONCRETE_RAW_TIMES_CONTACTED)
-                        + " AS " + Contacts.LR_TIMES_CONTACTED;
+                + "0 AS " + Contacts.RAW_TIMES_CONTACTED + ", "
+                + "0 AS " + Contacts.LR_TIMES_CONTACTED;
 
         String contactsSelect = "SELECT "
                 + ContactsColumns.CONCRETE_ID + " AS " + Contacts._ID + ","
@@ -2201,44 +2193,22 @@
         db.execSQL("CREATE VIEW " + Views.ENTITIES + " AS "
                 + entitiesSelect);
 
-        // Data usage view, with the low res columns, with no joins.
+        // View on top of DATA_USAGE_STAT, which is always empty.
         final String dataUsageViewSelect = "SELECT "
                 + DataUsageStatColumns._ID + ", "
                 + DataUsageStatColumns.DATA_ID + ", "
                 + DataUsageStatColumns.USAGE_TYPE_INT + ", "
-                + DataUsageStatColumns.RAW_TIMES_USED + ", "
-                + DataUsageStatColumns.RAW_LAST_TIME_USED + ","
-                + LowRes.getTimesUsedExpression(DataUsageStatColumns.RAW_TIMES_USED)
-                    + " AS " + DataUsageStatColumns.LR_TIMES_USED + ","
-                + LowRes.getLastTimeUsedExpression(DataUsageStatColumns.RAW_LAST_TIME_USED)
-                    + " AS " + DataUsageStatColumns.LR_LAST_TIME_USED
-                + " FROM " + Tables.DATA_USAGE_STAT;
+                + "0 AS " + DataUsageStatColumns.RAW_TIMES_USED + ", "
+                + "0 AS " + DataUsageStatColumns.RAW_LAST_TIME_USED + ","
+                + "0 AS " + DataUsageStatColumns.LR_TIMES_USED + ","
+                + "0 AS " + DataUsageStatColumns.LR_LAST_TIME_USED
+                + " FROM " + Tables.DATA_USAGE_STAT
+                + " WHERE 0";
 
         // When the data_usage_stat table is needed with the low-res columns, use this, which is
         // faster than the DATA_USAGE_STAT view since it doesn't involve joins.
         db.execSQL("CREATE VIEW " + Views.DATA_USAGE_LR + " AS " + dataUsageViewSelect);
 
-        String dataUsageStatSelect = "SELECT "
-                + DataUsageStatColumns.CONCRETE_ID + " AS " + DataUsageStatColumns._ID + ", "
-                + DataUsageStatColumns.DATA_ID + ", "
-                + RawContactsColumns.CONCRETE_CONTACT_ID + " AS " + RawContacts.CONTACT_ID + ", "
-                + MimetypesColumns.CONCRETE_MIMETYPE + " AS " + Data.MIMETYPE + ", "
-                + DataUsageStatColumns.USAGE_TYPE_INT + ", "
-                + DataUsageStatColumns.RAW_TIMES_USED + ", "
-                + DataUsageStatColumns.RAW_LAST_TIME_USED + ", "
-                + DataUsageStatColumns.LR_TIMES_USED + ", "
-                + DataUsageStatColumns.LR_LAST_TIME_USED
-                + " FROM " + Views.DATA_USAGE_LR + " AS " + Tables.DATA_USAGE_STAT
-                + " JOIN " + Tables.DATA + " ON ("
-                +   DataColumns.CONCRETE_ID + "=" + DataUsageStatColumns.CONCRETE_DATA_ID + ")"
-                + " JOIN " + Tables.RAW_CONTACTS + " ON ("
-                +   RawContactsColumns.CONCRETE_ID + "=" + DataColumns.CONCRETE_RAW_CONTACT_ID
-                    + " )"
-                + " JOIN " + Tables.MIMETYPES + " ON ("
-                +   MimetypesColumns.CONCRETE_ID + "=" + DataColumns.CONCRETE_MIMETYPE_ID + ")";
-
-        db.execSQL("CREATE VIEW " + Views.DATA_USAGE_STAT + " AS " + dataUsageStatSelect);
-
         String streamItemSelect = "SELECT " +
                 StreamItemsColumns.CONCRETE_ID + ", " +
                 ContactsColumns.CONCRETE_ID + " AS " + StreamItems.CONTACT_ID + ", " +
@@ -2679,6 +2649,12 @@
             oldVersion = 1300;
         }
 
+        if (isUpgradeRequired(oldVersion, newVersion, 1400)) {
+            ContactsProvider2.deleteDataUsage(db);
+            upgradeViewsAndTriggers = true;
+            oldVersion = 1400;
+        }
+
         // We extracted "calls" and "voicemail_status" at this point, but we can't remove them here
         // yet, until CallLogDatabaseHelper moves the data.
 
@@ -4970,6 +4946,9 @@
     }
 
     public String getCurrentCountryIso() {
+        // For debugging.
+        // String injected = android.os.SystemProperties.get("debug.cp2.injectedCountryIso");
+        // if (!TextUtils.isEmpty(injected)) return injected;
         return mCountryMonitor.getCountryIso();
     }
 
@@ -5133,4 +5112,23 @@
             Slog.wtfStack(TAG, message);
         }
     }
+
+    public void dump(PrintWriter pw) {
+        pw.print("CountryISO: ");
+        pw.println(getCurrentCountryIso());
+
+        pw.print("UseStrictPhoneNumberComparison: ");
+        pw.println(mUseStrictPhoneNumberComparison);
+
+        pw.print("UseStrictPhoneNumberComparisonBase: ");
+        pw.println(mUseStrictPhoneNumberComparisonBase);
+
+        pw.print("UseStrictPhoneNumberComparisonRU: ");
+        pw.println(mUseStrictPhoneNumberComparisonForRussia);
+
+        pw.print("UseStrictPhoneNumberComparisonKZ: ");
+        pw.println(mUseStrictPhoneNumberComparisonForKazakhstan);
+
+        pw.println();
+    }
 }
diff --git a/src/com/android/providers/contacts/ContactsProvider2.java b/src/com/android/providers/contacts/ContactsProvider2.java
index 9dd5cfd..dbf6bea 100644
--- a/src/com/android/providers/contacts/ContactsProvider2.java
+++ b/src/com/android/providers/contacts/ContactsProvider2.java
@@ -216,15 +216,6 @@
     private static final String WRITE_PERMISSION = "android.permission.WRITE_CONTACTS";
     private static final String INTERACT_ACROSS_USERS = "android.permission.INTERACT_ACROSS_USERS";
 
-    /* package */ static final String UPDATE_TIMES_CONTACTED_CONTACTS_TABLE =
-          "UPDATE " + Tables.CONTACTS + " SET " + Contacts.RAW_TIMES_CONTACTED + "=" +
-          " ifnull(" + Contacts.RAW_TIMES_CONTACTED + ",0)+1" +
-          " WHERE " + Contacts._ID + "=?";
-
-    /* package */ static final String UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE =
-          "UPDATE " + Tables.RAW_CONTACTS + " SET " + RawContacts.RAW_TIMES_CONTACTED + "=" +
-          " ifnull(" + RawContacts.RAW_TIMES_CONTACTED + ",0)+1 " +
-          " WHERE " + RawContacts.CONTACT_ID + "=?";
 
     /* package */ static final String PHONEBOOK_COLLATOR_NAME = "PHONEBOOK";
 
@@ -296,9 +287,6 @@
     public static final ProfileAwareUriMatcher sUriMatcher =
             new ProfileAwareUriMatcher(UriMatcher.NO_MATCH);
 
-    private static final String FREQUENT_ORDER_BY = DataUsageStatColumns.RAW_TIMES_USED + " DESC,"
-            + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
-
     public static final int CONTACTS = 1000;
     public static final int CONTACTS_ID = 1001;
     public static final int CONTACTS_LOOKUP = 1002;
@@ -581,36 +569,6 @@
             " WHERE " + RawContacts.CONTACT_ID + " = ?1 AND " + Contacts.PINNED + " <= " +
             PinnedPositions.DEMOTED;
 
-    // Contacts contacted within the last 3 days (in seconds)
-    private static final long LAST_TIME_USED_3_DAYS_SEC = 3L * 24 * 60 * 60;
-
-    // Contacts contacted within the last 7 days (in seconds)
-    private static final long LAST_TIME_USED_7_DAYS_SEC = 7L * 24 * 60 * 60;
-
-    // Contacts contacted within the last 14 days (in seconds)
-    private static final long LAST_TIME_USED_14_DAYS_SEC = 14L * 24 * 60 * 60;
-
-    // Contacts contacted within the last 30 days (in seconds)
-    private static final long LAST_TIME_USED_30_DAYS_SEC = 30L * 24 * 60 * 60;
-
-    private static final String RAW_TIME_SINCE_LAST_USED_SEC =
-            "(strftime('%s', 'now') - " + DataUsageStatColumns.RAW_LAST_TIME_USED + "/1000)";
-
-    private static final String LR_TIME_SINCE_LAST_USED_SEC =
-            "(strftime('%s', 'now') - " + DataUsageStatColumns.LR_LAST_TIME_USED + "/1000)";
-
-    private static final String SORT_BY_DATA_USAGE =
-            "(CASE WHEN " + RAW_TIME_SINCE_LAST_USED_SEC + " < " + LAST_TIME_USED_3_DAYS_SEC +
-            " THEN 0 " +
-                    " WHEN " + RAW_TIME_SINCE_LAST_USED_SEC + " < " + LAST_TIME_USED_7_DAYS_SEC +
-            " THEN 1 " +
-                    " WHEN " + RAW_TIME_SINCE_LAST_USED_SEC + " < " + LAST_TIME_USED_14_DAYS_SEC +
-            " THEN 2 " +
-                    " WHEN " + RAW_TIME_SINCE_LAST_USED_SEC + " < " + LAST_TIME_USED_30_DAYS_SEC +
-            " THEN 3 " +
-            " ELSE 4 END), " +
-            DataUsageStatColumns.RAW_TIMES_USED + " DESC";
-
     /*
      * Sorting order for email address suggestions: first starred, then the rest.
      * Within the two groups:
@@ -623,7 +581,6 @@
     private static final String EMAIL_FILTER_SORT_ORDER =
         Contacts.STARRED + " DESC, "
         + Data.IS_SUPER_PRIMARY + " DESC, "
-        + SORT_BY_DATA_USAGE + ", "
         + Contacts.IN_VISIBLE_GROUP + " DESC, "
         + Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC, "
         + Data.CONTACT_ID + ", "
@@ -662,7 +619,7 @@
             .add(Contacts.DISPLAY_NAME_SOURCE)
             .add(Contacts.IN_DEFAULT_DIRECTORY)
             .add(Contacts.IN_VISIBLE_GROUP)
-            .add(Contacts.LR_LAST_TIME_CONTACTED)
+            .add(Contacts.LR_LAST_TIME_CONTACTED, "0")
             .add(Contacts.LOOKUP_KEY)
             .add(Contacts.PHONETIC_NAME)
             .add(Contacts.PHONETIC_NAME_STYLE)
@@ -679,7 +636,7 @@
             .add(ContactsColumns.PHONEBOOK_BUCKET_ALTERNATIVE)
             .add(Contacts.STARRED)
             .add(Contacts.PINNED)
-            .add(Contacts.LR_TIMES_CONTACTED)
+            .add(Contacts.LR_TIMES_CONTACTED, "0")
             .add(Contacts.HAS_PHONE_NUMBER)
             .add(Contacts.CONTACT_LAST_UPDATED_TIMESTAMP)
             .build();
@@ -782,8 +739,8 @@
             .build();
 
     private static final ProjectionMap sDataUsageColumns = ProjectionMap.builder()
-            .add(Data.LR_TIMES_USED, Tables.DATA_USAGE_STAT + "." + Data.LR_TIMES_USED)
-            .add(Data.LR_LAST_TIME_USED, Tables.DATA_USAGE_STAT + "." + Data.LR_LAST_TIME_USED)
+            .add(Data.LR_TIMES_USED, "0")
+            .add(Data.LR_LAST_TIME_USED, "0")
             .build();
 
     /** Contains just BaseColumns._COUNT */
@@ -816,12 +773,8 @@
 
     private static final ProjectionMap sStrequentFrequentProjectionMap = ProjectionMap.builder()
             .addAll(sContactsProjectionMap)
-            // Note this should ideally be "lowres(SUM)" rather than "SUM(lowres)", but we do it
-            // this way for performance reasons.
-            .add(DataUsageStatColumns.LR_TIMES_USED,
-                    "SUM(" + DataUsageStatColumns.CONCRETE_LR_TIMES_USED + ")")
-            .add(DataUsageStatColumns.LR_LAST_TIME_USED,
-                    "MAX(" + DataUsageStatColumns.CONCRETE_LR_LAST_TIME_USED + ")")
+            .add(DataUsageStatColumns.LR_TIMES_USED, "0")
+            .add(DataUsageStatColumns.LR_LAST_TIME_USED, "0")
             .build();
 
     /**
@@ -833,8 +786,8 @@
     private static final ProjectionMap sStrequentPhoneOnlyProjectionMap
             = ProjectionMap.builder()
             .addAll(sContactsProjectionMap)
-            .add(DataUsageStatColumns.LR_TIMES_USED)
-            .add(DataUsageStatColumns.LR_LAST_TIME_USED)
+            .add(DataUsageStatColumns.LR_TIMES_USED, "0")
+            .add(DataUsageStatColumns.LR_LAST_TIME_USED, "0")
             .add(Phone.NUMBER)
             .add(Phone.TYPE)
             .add(Phone.LABEL)
@@ -3686,7 +3639,7 @@
             }
 
             case CONTACTS_DELETE_USAGE: {
-                return deleteDataUsage();
+                return deleteDataUsage(db);
             }
 
             case RAW_CONTACTS:
@@ -3990,8 +3943,7 @@
                 /* callerIsMetadataSyncAdapter =*/false);
     }
 
-    private int deleteDataUsage() {
-        final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
+    static int deleteDataUsage(SQLiteDatabase db) {
         db.execSQL("UPDATE " + Tables.RAW_CONTACTS + " SET " +
                 Contacts.RAW_TIMES_CONTACTED + "=0," +
                 Contacts.RAW_LAST_TIME_CONTACTED + "=NULL");
@@ -4235,7 +4187,7 @@
             }
 
             case DATA_USAGE_FEEDBACK_ID: {
-                count = handleDataUsageFeedback(uri) ? 1 : 0;
+                count = 0;
                 break;
             }
 
@@ -4509,21 +4461,20 @@
      * LAST_TIME_CONTACTED.
      */
     private ContentValues fixUpUsageColumnsForEdit(ContentValues cv) {
-        if (!cv.containsKey(Contacts.LR_LAST_TIME_CONTACTED)
-                && !cv.containsKey(Contacts.LR_TIMES_CONTACTED)) {
+        final boolean hasLastTime = cv.containsKey(Contacts.LR_LAST_TIME_CONTACTED);
+        final boolean hasTimes = cv.containsKey(Contacts.LR_TIMES_CONTACTED);
+        if (!hasLastTime && !hasTimes) {
             return cv;
         }
         final ContentValues ret = new ContentValues(cv);
-
-        ContactsDatabaseHelper.copyLongValue(
-                ret, Contacts.RAW_LAST_TIME_CONTACTED,
-                ret, Contacts.LR_LAST_TIME_CONTACTED);
-        ContactsDatabaseHelper.copyLongValue(
-                ret, Contacts.RAW_TIMES_CONTACTED,
-                ret, Contacts.LR_TIMES_CONTACTED);
-
-        ret.remove(Contacts.LR_LAST_TIME_CONTACTED);
-        ret.remove(Contacts.LR_TIMES_CONTACTED);
+        if (hasLastTime) {
+            ret.putNull(Contacts.RAW_LAST_TIME_CONTACTED);
+            ret.remove(Contacts.LR_LAST_TIME_CONTACTED);
+        }
+        if (hasTimes) {
+            ret.put(Contacts.RAW_TIMES_CONTACTED, 0);
+            ret.remove(Contacts.LR_TIMES_CONTACTED);
+        }
         return ret;
     }
 
@@ -4785,12 +4736,12 @@
         ContactsDatabaseHelper.copyLongValue(
                 values, RawContacts.SEND_TO_VOICEMAIL,
                 inputValues, Contacts.SEND_TO_VOICEMAIL);
-        ContactsDatabaseHelper.copyLongValue(
-                values, RawContacts.RAW_LAST_TIME_CONTACTED,
-                inputValues, Contacts.RAW_LAST_TIME_CONTACTED);
-        ContactsDatabaseHelper.copyLongValue(
-                values, RawContacts.RAW_TIMES_CONTACTED,
-                inputValues, Contacts.RAW_TIMES_CONTACTED);
+        if (inputValues.containsKey(RawContacts.RAW_LAST_TIME_CONTACTED)) {
+            values.putNull(RawContacts.RAW_LAST_TIME_CONTACTED);
+        }
+        if (inputValues.containsKey(RawContacts.RAW_TIMES_CONTACTED)) {
+            values.put(RawContacts.RAW_TIMES_CONTACTED, 0);
+        }
         ContactsDatabaseHelper.copyLongValue(
                 values, RawContacts.STARRED,
                 inputValues, Contacts.STARRED);
@@ -4850,12 +4801,12 @@
         ContactsDatabaseHelper.copyLongValue(
                 values, RawContacts.SEND_TO_VOICEMAIL,
                 inputValues, Contacts.SEND_TO_VOICEMAIL);
-        ContactsDatabaseHelper.copyLongValue(
-                values, RawContacts.RAW_LAST_TIME_CONTACTED,
-                inputValues, Contacts.RAW_LAST_TIME_CONTACTED);
-        ContactsDatabaseHelper.copyLongValue(
-                values, RawContacts.RAW_TIMES_CONTACTED,
-                inputValues, Contacts.RAW_TIMES_CONTACTED);
+        if (inputValues.containsKey(RawContacts.RAW_LAST_TIME_CONTACTED)) {
+            values.putNull(RawContacts.RAW_LAST_TIME_CONTACTED);
+        }
+        if (inputValues.containsKey(RawContacts.RAW_TIMES_CONTACTED)) {
+            values.put(RawContacts.RAW_TIMES_CONTACTED, 0);
+        }
         ContactsDatabaseHelper.copyLongValue(
                 values, RawContacts.STARRED,
                 inputValues, Contacts.STARRED);
@@ -4869,11 +4820,6 @@
         int rslt = db.update(Tables.CONTACTS, values, Contacts._ID + "=?",
                 mSelectionArgs1);
 
-        if (inputValues.containsKey(Contacts.RAW_LAST_TIME_CONTACTED) &&
-                !inputValues.containsKey(Contacts.RAW_TIMES_CONTACTED)) {
-            db.execSQL(UPDATE_TIMES_CONTACTED_CONTACTS_TABLE, mSelectionArgs1);
-            db.execSQL(UPDATE_TIMES_CONTACTED_RAWCONTACTS_TABLE, mSelectionArgs1);
-        }
         return rslt;
     }
 
@@ -5100,20 +5046,6 @@
                         dataValues, null, null, /* callerIsSyncAdapter =*/true,
                         /* callerIsMetadataSyncAdapter =*/true);
 
-                // Update UsageStats.
-                for (int j = 0; j < fieldData.mUsageStatsList.size(); j++) {
-                    final UsageStats usageStats = fieldData.mUsageStatsList.get(j);
-                    final String usageType = usageStats.mUsageType;
-                    final int typeInt = getDataUsageFeedbackType(usageType.toLowerCase(), null);
-                    final long lastTimeUsed = usageStats.mLastTimeUsed;
-                    final int timesUsed = usageStats.mTimesUsed;
-                    ContentValues usageStatsValues = new ContentValues();
-                    usageStatsValues.put(DataUsageStatColumns.DATA_ID, dataId);
-                    usageStatsValues.put(DataUsageStatColumns.USAGE_TYPE_INT, typeInt);
-                    usageStatsValues.put(DataUsageStatColumns.RAW_LAST_TIME_USED, lastTimeUsed);
-                    usageStatsValues.put(DataUsageStatColumns.RAW_TIMES_USED, timesUsed);
-                    updateDataUsageStats(db, usageStatsValues);
-                }
             }
         }
 
@@ -5987,11 +5919,8 @@
             }
             case CONTACTS_STREQUENT_FILTER:
             case CONTACTS_STREQUENT: {
-                // Basically the resultant SQL should look like this:
-                // (SQL for listing starred items)
-                // UNION ALL
-                // (SQL for listing frequently contacted items)
-                // ORDER BY ...
+                // Note we used to use a union query to merge starred contacts and frequent
+                // contacts. Since we no longer have frequent contacts, we don't use union any more.
 
                 final boolean phoneOnly = readBooleanQueryParameter(
                         uri, ContactsContract.STREQUENT_PHONE_ONLY, false);
@@ -6014,9 +5943,6 @@
                 // String that will store the query for starred contacts. For phone only queries,
                 // these will return a list of all phone numbers that belong to starred contacts.
                 final String starredInnerQuery;
-                // String that will store the query for frequents. These JOINS can be very slow
-                // if assembled in the wrong order. Be sure to test changes against huge databases.
-                final String frequentInnerQuery;
 
                 if (phoneOnly) {
                     final StringBuilder tableBuilder = new StringBuilder();
@@ -6054,7 +5980,7 @@
                             phoneMimeTypeId + ", " + sipMimeTypeId + ")) AND (" +
                             RawContacts.CONTACT_ID + " IN " + Tables.DEFAULT_DIRECTORY + ")"));
                     starredInnerQuery = qb.buildQuery(subProjection, null, null,
-                        null, Data.IS_SUPER_PRIMARY + " DESC," + SORT_BY_DATA_USAGE, null);
+                        null, Data.IS_SUPER_PRIMARY + " DESC", null);
 
                     qb = new SQLiteQueryBuilder();
                     qb.setStrict(true);
@@ -6082,9 +6008,6 @@
                             DataColumns.MIMETYPE_ID + " IN (" +
                             phoneMimeTypeId + ", " + sipMimeTypeId + ")) AND (" +
                             RawContacts.CONTACT_ID + " IN " + Tables.DEFAULT_DIRECTORY + ")"));
-                    frequentInnerQuery = qb.buildQuery(subProjection, null, null, null,
-                            SORT_BY_DATA_USAGE, "25");
-
                 } else {
                     // Build the first query for starred contacts
                     qb.setStrict(true);
@@ -6095,53 +6018,9 @@
                             DbQueryUtils.concatenateClauses(selection, Contacts.STARRED + "=1"),
                             Contacts._ID, null, Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC",
                             null);
-
-                    // Reset the builder, and build the second query for frequents contacts
-                    qb = new SQLiteQueryBuilder();
-                    qb.setStrict(true);
-
-                    setTablesAndProjectionMapForContacts(qb, projection, true);
-                    qb.setProjectionMap(sStrequentFrequentProjectionMap);
-                    qb.appendWhere(DbQueryUtils.concatenateClauses(
-                            selection,
-                            "(" + Contacts.STARRED + " =0 OR " + Contacts.STARRED + " IS NULL)"));
-                    // Note frequentInnerQuery is a grouping query, so the "IN default_directory"
-                    // selection needs to be in HAVING, not in WHERE.
-                    final String HAVING =
-                            RawContacts.CONTACT_ID + " IN " + Tables.DEFAULT_DIRECTORY;
-                    frequentInnerQuery = qb.buildQuery(subProjection,
-                            null, Contacts._ID, HAVING, SORT_BY_DATA_USAGE, "25");
                 }
 
-                // We need to wrap the inner queries in an extra select, because they contain
-                // their own SORT and LIMIT
-
-                // Phone numbers that were used more than 30 days ago are dropped from frequents
-                final String frequentQuery = "SELECT * FROM (" + frequentInnerQuery + ") WHERE " +
-                        LR_TIME_SINCE_LAST_USED_SEC + "<" + LAST_TIME_USED_30_DAYS_SEC;
-                final String starredQuery = "SELECT * FROM (" + starredInnerQuery + ")";
-
-                // Put them together
-                final String unionQuery =
-                        qb.buildUnionQuery(new String[] {starredQuery, frequentQuery}, null, null);
-
-                // Here, we need to use selection / selectionArgs (supplied from users) "twice",
-                // as we want them both for starred items and for frequently contacted items.
-                //
-                // e.g. if the user specify selection = "starred =?" and selectionArgs = "0",
-                // the resultant SQL should be like:
-                // SELECT ... WHERE starred =? AND ...
-                // UNION ALL
-                // SELECT ... WHERE starred =? AND ...
-                String[] doubledSelectionArgs = null;
-                if (selectionArgs != null) {
-                    final int length = selectionArgs.length;
-                    doubledSelectionArgs = new String[length * 2];
-                    System.arraycopy(selectionArgs, 0, doubledSelectionArgs, 0, length);
-                    System.arraycopy(selectionArgs, 0, doubledSelectionArgs, length, length);
-                }
-
-                Cursor cursor = db.rawQuery(unionQuery, doubledSelectionArgs);
+                Cursor cursor = db.rawQuery(starredInnerQuery, selectionArgs);
                 if (cursor != null) {
                     cursor.setNotificationUri(
                             getContext().getContentResolver(), ContactsContract.AUTHORITY_URI);
@@ -6153,12 +6032,8 @@
                 setTablesAndProjectionMapForContacts(qb, projection, true);
                 qb.setProjectionMap(sStrequentFrequentProjectionMap);
                 groupBy = Contacts._ID;
-                having = Contacts._ID + " IN " + Tables.DEFAULT_DIRECTORY;
-                if (!TextUtils.isEmpty(sortOrder)) {
-                    sortOrder = FREQUENT_ORDER_BY + ", " + sortOrder;
-                } else {
-                    sortOrder = FREQUENT_ORDER_BY;
-                }
+                selection = "(0)";
+                selectionArgs = null;
                 break;
             }
 
@@ -8029,17 +7904,20 @@
             SQLiteQueryBuilder qb, String[] projection, boolean includeDataUsageStat) {
         StringBuilder sb = new StringBuilder();
         if (includeDataUsageStat) {
-            sb.append(Views.DATA_USAGE_STAT + " AS " + Tables.DATA_USAGE_STAT);
+            // The result will always be empty, but we still need the columns.
+            sb.append(Tables.DATA_USAGE_STAT);
             sb.append(" INNER JOIN ");
         }
 
         sb.append(Views.CONTACTS);
 
         // Just for frequently contacted contacts in Strequent URI handling.
+        // We no longer support frequent, so we do "(0)", but we still need to execute the query
+        // for the columns.
         if (includeDataUsageStat) {
             sb.append(" ON (" +
                     DbQueryUtils.concatenateClauses(
-                            DataUsageStatColumns.CONCRETE_RAW_TIMES_USED + " > 0",
+                            "(0)",
                             RawContacts.CONTACT_ID + "=" + Views.CONTACTS + "." + Contacts._ID) +
                     ")");
         }
@@ -8425,38 +8303,20 @@
     }
 
     private void appendDataUsageStatJoin(StringBuilder sb, int usageType, String dataIdColumn) {
-        if (usageType != USAGE_TYPE_ALL) {
-            sb.append(" LEFT OUTER JOIN " + Views.DATA_USAGE_LR +
-                    " as " + Tables.DATA_USAGE_STAT +
-                    " ON (" + DataUsageStatColumns.CONCRETE_DATA_ID + "=");
-            sb.append(dataIdColumn);
-            sb.append(" AND " + DataUsageStatColumns.CONCRETE_USAGE_TYPE + "=");
-            sb.append(usageType);
-            sb.append(")");
-        } else {
-            sb.append(
-                    " LEFT OUTER JOIN " +
-                        "(SELECT " +
-                            DataUsageStatColumns.DATA_ID + " as STAT_DATA_ID," +
-                            " SUM(ifnull(" + DataUsageStatColumns.RAW_TIMES_USED +
-                                ",0)) as " + DataUsageStatColumns.RAW_TIMES_USED + ", " +
-                            " MAX(ifnull(" + DataUsageStatColumns.RAW_LAST_TIME_USED +
-                                ",0)) as " + DataUsageStatColumns.RAW_LAST_TIME_USED + "," +
-
-                            // Note this is not ideal -- we should use "lowres(sum(LR_TIMES_USED))"
-                            // here, but for performance reasons we just do it simple.
-                            " SUM(ifnull(" + DataUsageStatColumns.LR_TIMES_USED +
-                                ",0)) as " + DataUsageStatColumns.LR_TIMES_USED + ", " +
-
-                            " MAX(ifnull(" + DataUsageStatColumns.LR_LAST_TIME_USED +
-                                ",0)) as " + DataUsageStatColumns.LR_LAST_TIME_USED +
-                        " FROM " + Views.DATA_USAGE_LR + " GROUP BY " +
-                            DataUsageStatColumns.DATA_ID + ") as " + Tables.DATA_USAGE_STAT
-                    );
-            sb.append(" ON (STAT_DATA_ID=");
-            sb.append(dataIdColumn);
-            sb.append(")");
-        }
+        sb.append(
+                // 0 rows, just populate the columns.
+                " LEFT OUTER JOIN " +
+                "(SELECT " +
+                "0 as STAT_DATA_ID," +
+                "0 as " + DataUsageStatColumns.RAW_TIMES_USED + ", " +
+                "0 as " + DataUsageStatColumns.RAW_LAST_TIME_USED + "," +
+                "0 as " + DataUsageStatColumns.LR_TIMES_USED + ", " +
+                "0 as " + DataUsageStatColumns.LR_LAST_TIME_USED +
+                " where 0) as " + Tables.DATA_USAGE_STAT
+        );
+        sb.append(" ON (STAT_DATA_ID=");
+        sb.append(dataIdColumn);
+        sb.append(")");
     }
 
     private void appendContactPresenceJoin(
@@ -9831,181 +9691,6 @@
         db.execSQL(UNDEMOTE_RAW_CONTACT, arg);
     }
 
-    private boolean handleDataUsageFeedback(Uri uri) {
-        final long currentTimeMillis = Clock.getInstance().currentTimeMillis();
-        final String usageType = uri.getQueryParameter(DataUsageFeedback.USAGE_TYPE);
-        final String[] ids = uri.getLastPathSegment().trim().split(",");
-        final ArrayList<Long> dataIds = new ArrayList<Long>(ids.length);
-
-        for (String id : ids) {
-            dataIds.add(Long.valueOf(id));
-        }
-        final boolean successful;
-        if (TextUtils.isEmpty(usageType)) {
-            Log.w(TAG, "Method for data usage feedback isn't specified. Ignoring.");
-            successful = false;
-        } else {
-            successful = updateDataUsageStat(dataIds, usageType, currentTimeMillis) > 0;
-        }
-
-        // Handle old API. This doesn't affect the result of this entire method.
-        final StringBuilder rawContactIdSelect = new StringBuilder();
-        rawContactIdSelect.append("SELECT " + Data.RAW_CONTACT_ID + " FROM " + Tables.DATA +
-                " WHERE " + Data._ID + " IN (");
-        for (int i = 0; i < ids.length; i++) {
-            if (i > 0) {
-                rawContactIdSelect.append(",");
-            }
-            rawContactIdSelect.append(ids[i]);
-        }
-        rawContactIdSelect.append(")");
-
-        final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
-
-        final Set<Long> rawContactIds = new ArraySet<>();
-        final Cursor cursor = db.rawQuery(rawContactIdSelect.toString(), null);
-        try {
-            cursor.moveToPosition(-1);
-            while (cursor.moveToNext()) {
-                final long rid =   cursor.getLong(0);
-                mTransactionContext.get().markRawContactMetadataDirty(rid,
-                        /* isMetadataSyncAdapter =*/false);
-                rawContactIds.add(rid);
-            }
-        } finally {
-            cursor.close();
-        }
-
-        mSelectionArgs1[0] = String.valueOf(currentTimeMillis);
-        final String rids = TextUtils.join(",", rawContactIds);
-
-        db.execSQL("UPDATE " + Tables.RAW_CONTACTS +
-                " SET " + RawContacts.RAW_LAST_TIME_CONTACTED + "=?" +
-                "," + RawContacts.RAW_TIMES_CONTACTED + "=" +
-                    "ifnull(" + RawContacts.RAW_TIMES_CONTACTED + ",0) + 1" +
-                " WHERE " + RawContacts._ID + " IN (" + rids + ")"
-                , mSelectionArgs1);
-        db.execSQL("UPDATE " + Tables.CONTACTS +
-                " SET " + Contacts.RAW_LAST_TIME_CONTACTED + "=?1" +
-                "," + Contacts.RAW_TIMES_CONTACTED + "=" +
-                    "ifnull(" + Contacts.RAW_TIMES_CONTACTED + ",0) + 1" +
-                "," + Contacts.CONTACT_LAST_UPDATED_TIMESTAMP + "=?1" +
-                " WHERE " + Contacts._ID + " IN (SELECT " + RawContacts.CONTACT_ID +
-                    " FROM " + Tables.RAW_CONTACTS +
-                    " WHERE " + RawContacts._ID + " IN (" + rids + "))"
-                , mSelectionArgs1);
-
-        return successful;
-    }
-
-    private interface DataUsageStatQuery {
-        String TABLE = Tables.DATA_USAGE_STAT;
-        String[] COLUMNS = new String[] {DataUsageStatColumns._ID};
-        int ID = 0;
-        String SELECTION = DataUsageStatColumns.DATA_ID + " =? AND "
-                + DataUsageStatColumns.USAGE_TYPE_INT + " =?";
-    }
-
-    /**
-     * Update {@link Tables#DATA_USAGE_STAT}.
-     *
-     * @return the number of rows affected.
-     */
-    @VisibleForTesting
-    /* package */ int updateDataUsageStat(
-            List<Long> dataIds, String type, long currentTimeMillis) {
-
-        final SQLiteDatabase db = mDbHelper.get().getWritableDatabase();
-
-        final String typeString = String.valueOf(getDataUsageFeedbackType(type, null));
-        final String currentTimeMillisString = String.valueOf(currentTimeMillis);
-
-        for (long dataId : dataIds) {
-            final String dataIdString = String.valueOf(dataId);
-            mSelectionArgs2[0] = dataIdString;
-            mSelectionArgs2[1] = typeString;
-            final Cursor cursor = db.query(DataUsageStatQuery.TABLE,
-                    DataUsageStatQuery.COLUMNS, DataUsageStatQuery.SELECTION,
-                    mSelectionArgs2, null, null, null);
-            try {
-                if (cursor.moveToFirst()) {
-                    final long id = cursor.getLong(DataUsageStatQuery.ID);
-
-                    mSelectionArgs2[0] = currentTimeMillisString;
-                    mSelectionArgs2[1] = String.valueOf(id);
-
-                    db.execSQL("UPDATE " + Tables.DATA_USAGE_STAT +
-                            " SET " + DataUsageStatColumns.RAW_TIMES_USED + "=" +
-                                "ifnull(" + DataUsageStatColumns.RAW_TIMES_USED +",0)+1" +
-                            "," + DataUsageStatColumns.RAW_LAST_TIME_USED + "=?" +
-                            " WHERE " + DataUsageStatColumns._ID + "=?",
-                            mSelectionArgs2);
-                } else {
-                    mSelectionArgs4[0] = dataIdString;
-                    mSelectionArgs4[1] = typeString;
-                    mSelectionArgs4[2] = "1"; // times used
-                    mSelectionArgs4[3] = currentTimeMillisString;
-                    db.execSQL("INSERT INTO " + Tables.DATA_USAGE_STAT +
-                            "(" + DataUsageStatColumns.DATA_ID +
-                            "," + DataUsageStatColumns.USAGE_TYPE_INT +
-                            "," + DataUsageStatColumns.RAW_TIMES_USED +
-                            "," + DataUsageStatColumns.RAW_LAST_TIME_USED +
-                            ") VALUES (?,?,?,?)",
-                            mSelectionArgs4);
-                }
-            } finally {
-                cursor.close();
-            }
-        }
-
-        return dataIds.size();
-    }
-
-    /**
-     * Directly update {@link Tables#DATA_USAGE_STAT}; used for metadata sync.
-     * Update or insert usageType, lastTimeUsed, and timesUsed for specific dataId.
-     */
-    private void updateDataUsageStats(SQLiteDatabase db, ContentValues values) {
-        final String dataId = values.getAsString(DataUsageStatColumns.DATA_ID);
-        final String type = values.getAsString(DataUsageStatColumns.USAGE_TYPE_INT);
-        final String lastTimeUsed = values.getAsString(DataUsageStatColumns.RAW_LAST_TIME_USED);
-        final String timesUsed = values.getAsString(DataUsageStatColumns.RAW_TIMES_USED);
-
-        mSelectionArgs2[0] = dataId;
-        mSelectionArgs2[1] = type;
-        final Cursor cursor = db.query(DataUsageStatQuery.TABLE,
-                DataUsageStatQuery.COLUMNS, DataUsageStatQuery.SELECTION,
-                mSelectionArgs2, null, null, null);
-
-        try {
-            if (cursor.moveToFirst()) {
-                final long id = cursor.getLong(DataUsageStatQuery.ID);
-
-                mSelectionArgs3[0] = lastTimeUsed;
-                mSelectionArgs3[1] = timesUsed;
-                mSelectionArgs3[2] = String.valueOf(id);
-                db.execSQL("UPDATE " + Tables.DATA_USAGE_STAT +
-                        " SET " + DataUsageStatColumns.RAW_LAST_TIME_USED + "=?" +
-                        "," + DataUsageStatColumns.RAW_TIMES_USED + "=?" +
-                        " WHERE " + DataUsageStatColumns._ID + "=?",
-                        mSelectionArgs3);
-            } else {
-                mSelectionArgs4[0] = dataId;
-                mSelectionArgs4[1] = type;
-                mSelectionArgs4[2] = timesUsed;
-                mSelectionArgs4[3] = lastTimeUsed;
-                db.execSQL("INSERT INTO " + Tables.DATA_USAGE_STAT +
-                        "(" + DataUsageStatColumns.DATA_ID +
-                        "," + DataUsageStatColumns.USAGE_TYPE_INT +
-                        "," + DataUsageStatColumns.RAW_TIMES_USED +
-                        "," + DataUsageStatColumns.RAW_LAST_TIME_USED +
-                        ") VALUES (?,?,?,?)",
-                        mSelectionArgs4);
-            }
-        } finally {
-            cursor.close();
-        }
-    }
 
     /**
      * Returns a sort order String for promoting data rows (email addresses, phone numbers, etc.)
@@ -10162,7 +9847,10 @@
                         mFastScrollingIndexCacheRequestCount),
                 safeDiv(mTotalTimeFastScrollingIndexGenerate, mFastScrollingIndexCacheMissCount));
         pw.println();
-        pw.println();
+
+        if (mContactsHelper != null) {
+            mContactsHelper.dump(pw);
+        }
 
         // DB queries may be blocked and timed out, so do it at the end.
 
diff --git a/src/com/android/providers/contacts/CountryMonitor.java b/src/com/android/providers/contacts/CountryMonitor.java
index 7796849..134a4ef 100644
--- a/src/com/android/providers/contacts/CountryMonitor.java
+++ b/src/com/android/providers/contacts/CountryMonitor.java
@@ -16,6 +16,8 @@
 
 package com.android.providers.contacts;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
 import android.location.Country;
 import android.location.CountryDetector;
@@ -32,10 +34,20 @@
  */
 public class CountryMonitor {
     private String mCurrentCountryIso;
-    private Context mContext;
 
-    public CountryMonitor(Context context) {
+    @NonNull
+    private final Context mContext;
+
+    @Nullable
+    private final Runnable mUpdateCallback;
+
+    public CountryMonitor(@NonNull Context context) {
+        this(context, null);
+    }
+
+    public CountryMonitor(@NonNull Context context, @Nullable Runnable updateCallback) {
         mContext = context;
+        mUpdateCallback = updateCallback;
     }
 
     /**
@@ -56,11 +68,14 @@
             }
 
             mCurrentCountryIso = country.getCountryIso();
-                countryDetector.addCountryListener(new CountryListener() {
-                    public void onCountryDetected(Country country) {
-                        mCurrentCountryIso = country.getCountryIso();
+            countryDetector.addCountryListener(new CountryListener() {
+                public void onCountryDetected(Country country) {
+                    mCurrentCountryIso = country.getCountryIso();
+                    if (mUpdateCallback != null) {
+                        mUpdateCallback.run();
                     }
-                }, Looper.getMainLooper());
+                }
+            }, Looper.getMainLooper());
         }
         return mCurrentCountryIso;
     }
diff --git a/src/com/android/providers/contacts/NameSplitter.java b/src/com/android/providers/contacts/NameSplitter.java
index 50b50fb..ddd294f 100644
--- a/src/com/android/providers/contacts/NameSplitter.java
+++ b/src/com/android/providers/contacts/NameSplitter.java
@@ -945,33 +945,6 @@
             bestGuess = guess;
         }
 
-        guess = guessFullNameStyle(name.middleName);
-        if (guess != FullNameStyle.UNDEFINED) {
-            if (guess != FullNameStyle.CJK && guess != FullNameStyle.WESTERN) {
-                name.fullNameStyle = guess;
-                return;
-            }
-            bestGuess = guess;
-        }
-
-        guess = guessFullNameStyle(name.prefix);
-        if (guess != FullNameStyle.UNDEFINED) {
-            if (guess != FullNameStyle.CJK && guess != FullNameStyle.WESTERN) {
-                name.fullNameStyle = guess;
-                return;
-            }
-            bestGuess = guess;
-        }
-
-        guess = guessFullNameStyle(name.suffix);
-        if (guess != FullNameStyle.UNDEFINED) {
-            if (guess != FullNameStyle.CJK && guess != FullNameStyle.WESTERN) {
-                name.fullNameStyle = guess;
-                return;
-            }
-            bestGuess = guess;
-        }
-
         name.fullNameStyle = bestGuess;
     }
 
diff --git a/src/com/android/providers/contacts/ProfileDatabaseHelper.java b/src/com/android/providers/contacts/ProfileDatabaseHelper.java
index 966ee7e..7cb0ff7 100644
--- a/src/com/android/providers/contacts/ProfileDatabaseHelper.java
+++ b/src/com/android/providers/contacts/ProfileDatabaseHelper.java
@@ -88,4 +88,14 @@
     protected void loadDatabaseCreationTime(SQLiteDatabase db) {
         // We don't need the creation time for the profile DB.
     }
+
+    @Override
+    protected void startListeningToDeviceConfigUpdates() {
+        // Do nothing for the profile DB.
+    }
+
+    @Override
+    protected void updateUseStrictPhoneNumberComparison() {
+        // Do nothing for the profile DB.
+    }
 }
diff --git a/src/com/android/providers/contacts/VoicemailPermissions.java b/src/com/android/providers/contacts/VoicemailPermissions.java
index ed3815d..7e409ea 100644
--- a/src/com/android/providers/contacts/VoicemailPermissions.java
+++ b/src/com/android/providers/contacts/VoicemailPermissions.java
@@ -124,8 +124,7 @@
                 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
         String[] packages = mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
         for (String packageName : packages) {
-            if (tm.checkCarrierPrivilegesForPackageAnyPhone(packageName)
-                    == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+            if (packageHasCarrierPrivileges(tm, packageName)) {
                 return true;
             }
         }
@@ -136,6 +135,11 @@
     private boolean packageHasCarrierPrivileges(String packageName) {
         TelephonyManager tm =
                 (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
-        return tm.getPackagesWithCarrierPrivileges().contains(packageName);
+        return packageHasCarrierPrivileges(tm, packageName);
+    }
+
+    private static boolean packageHasCarrierPrivileges(TelephonyManager tm, String packageName) {
+        return tm.checkCarrierPrivilegesForPackageAnyPhone(packageName)
+                == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
     }
 }
diff --git a/test_common/Android.bp b/test_common/Android.bp
index db2e709..b30e2e3 100644
--- a/test_common/Android.bp
+++ b/test_common/Android.bp
@@ -17,7 +17,7 @@
     srcs: ["src/**/*.java"],
     libs: [
         "android.test.runner",
-        "android-support-test",
+        "androidx.test.rules",
         "mockito-target-minus-junit4",
     ],
 }
diff --git a/tests/Android.bp b/tests/Android.bp
index c687b63..b15ded4 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -2,7 +2,7 @@
     name: "ContactsProviderTests",
     static_libs: [
         "ContactsProviderTestUtils",
-        "android-support-test",
+        "androidx.test.rules",
         "mockito-target-minus-junit4",
     ],
     libs: [
@@ -10,6 +10,7 @@
         "android.test.base",
         "android.test.mock",
     ],
+
     // Only compile source java files in this apk.
     srcs: ["src/**/*.java"],
     platform_apis: true,
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 15a90fa..4d81c5f 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -36,14 +36,8 @@
         </service>
     </application>
 
-    <!--
-    The test declared in this instrumentation will be run along with tests declared by
-    all other applications via the command: "adb shell itr".
-    The "itr" command will find all tests declared by all applications. If you want to run just these
-    tests on their own then use the command:
-    "adb shell am instrument -w com.android.providers.contacts.tests/android.test.InstrumentationTestRunner"
-    -->
-    <instrumentation android:name="android.test.InstrumentationTestRunner"
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.providers.contacts"
         android:label="Contacts Provider Tests">
     </instrumentation>
diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml
index 3c4a3ab..cdf0c7d 100644
--- a/tests/AndroidTest.xml
+++ b/tests/AndroidTest.xml
@@ -20,9 +20,8 @@
 
     <option name="test-suite-tag" value="apct" />
     <option name="test-tag" value="ContactsProviderTests" />
-    <test class="com.android.tradefed.testtype.InstrumentationTest" >
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.providers.contacts.tests" />
-        <option name="runner" value="android.test.InstrumentationTestRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
index 74642cb..91a76a3 100644
--- a/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/BaseContactsProvider2Test.java
@@ -1234,14 +1234,13 @@
     private static final String[] DATA_USAGE_PROJECTION =
             new String[] {Data.DATA1, Data.TIMES_USED, Data.LAST_TIME_USED};
 
-    protected void assertDataUsageCursorContains(Uri uri, String data1, int timesUsed,
-            int lastTimeUsed) {
+    protected void assertDataUsageZero(Uri uri, String data1) {
         final Cursor cursor = mResolver.query(uri, DATA_USAGE_PROJECTION, null, null,
                 null);
         try {
             dumpCursor(cursor);
-            assertCursorHasAnyRecordMatch(cursor, cv(Data.DATA1, data1, Data.TIMES_USED, timesUsed,
-                    Data.LAST_TIME_USED, lastTimeUsed));
+            assertCursorHasAnyRecordMatch(cursor, cv(Data.DATA1, data1, Data.TIMES_USED, 0,
+                    Data.LAST_TIME_USED, 0));
         } finally {
             cursor.close();
         }
diff --git a/tests/src/com/android/providers/contacts/BaseDatabaseHelperUpgradeTest.java b/tests/src/com/android/providers/contacts/BaseDatabaseHelperUpgradeTest.java
index 0eb12ad..ae12f1b 100644
--- a/tests/src/com/android/providers/contacts/BaseDatabaseHelperUpgradeTest.java
+++ b/tests/src/com/android/providers/contacts/BaseDatabaseHelperUpgradeTest.java
@@ -17,7 +17,6 @@
 
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
-import android.test.AndroidTestCase;
 
 import junit.framework.AssertionFailedError;
 
@@ -29,7 +28,7 @@
  * Run the test like this: <code> runtest -c com.android.providers.contacts.BaseDatabaseHelperUpgradeTest
  * contactsprov </code>
  */
-public abstract class BaseDatabaseHelperUpgradeTest extends AndroidTestCase {
+public abstract class BaseDatabaseHelperUpgradeTest extends FixedAndroidTestCase {
 
     protected static final String INTEGER = "INTEGER";
     protected static final String TEXT = "TEXT";
diff --git a/tests/src/com/android/providers/contacts/CallLogInsertionHelperTest.java b/tests/src/com/android/providers/contacts/CallLogInsertionHelperTest.java
index 7bb88a8..6122ff0 100644
--- a/tests/src/com/android/providers/contacts/CallLogInsertionHelperTest.java
+++ b/tests/src/com/android/providers/contacts/CallLogInsertionHelperTest.java
@@ -19,12 +19,10 @@
 import android.content.ContentValues;
 import android.provider.CallLog.Calls;
 
-import android.test.AndroidTestCase;
-
 /**
  * Test cases for {@link com.android.providers.contacts.DefaultCallLogInsertionHelper}.
  */
-public class CallLogInsertionHelperTest extends AndroidTestCase {
+public class CallLogInsertionHelperTest extends FixedAndroidTestCase {
 
     /**
      * The default insertion helper under test.
diff --git a/tests/src/com/android/providers/contacts/CallLogMigrationTest.java b/tests/src/com/android/providers/contacts/CallLogMigrationTest.java
index 3cbecb8..767b62f 100644
--- a/tests/src/com/android/providers/contacts/CallLogMigrationTest.java
+++ b/tests/src/com/android/providers/contacts/CallLogMigrationTest.java
@@ -18,7 +18,6 @@
 import android.content.Context;
 import android.database.DatabaseUtils;
 import android.database.sqlite.SQLiteDatabase;
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 
 import java.io.File;
@@ -28,7 +27,7 @@
 import java.io.OutputStream;
 
 @LargeTest
-public class CallLogMigrationTest extends AndroidTestCase {
+public class CallLogMigrationTest extends FixedAndroidTestCase {
 
     private void writeAssetFileToDisk(String assetName, File diskPath) throws IOException {
         final Context context = getTestContext();
diff --git a/tests/src/com/android/providers/contacts/ContactLocaleUtilsTest.java b/tests/src/com/android/providers/contacts/ContactLocaleUtilsTest.java
index 8e71bef..a19a2f2 100644
--- a/tests/src/com/android/providers/contacts/ContactLocaleUtilsTest.java
+++ b/tests/src/com/android/providers/contacts/ContactLocaleUtilsTest.java
@@ -17,11 +17,8 @@
 package com.android.providers.contacts;
 
 import android.provider.ContactsContract.FullNameStyle;
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
 
-import java.text.Collator;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -30,7 +27,7 @@
 import java.util.Locale;
 
 @SmallTest
-public class ContactLocaleUtilsTest extends AndroidTestCase {
+public class ContactLocaleUtilsTest extends FixedAndroidTestCase {
     private static final String TAG = "ContactLocaleUtilsTest";
 
     private static final String PHONE_NUMBER_1 = "+1 (650) 555-1212";
diff --git a/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java b/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java
index 8cf9ea4..a9867c5 100644
--- a/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java
+++ b/tests/src/com/android/providers/contacts/ContactsDatabaseHelperTest.java
@@ -29,12 +29,11 @@
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
 
-import com.android.providers.contacts.ContactsDatabaseHelper.LowRes;
 import com.android.providers.contacts.ContactsDatabaseHelper.MimetypesColumns;
 import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
 import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
+
 import com.google.android.collect.Sets;
 
 import java.util.HashSet;
@@ -455,48 +454,6 @@
         }
     }
 
-    private Integer checkGetTimesUsedExpression(Integer value) {
-        return getIntegerFromExpression(LowRes.getTimesUsedExpression(
-                value == null ? "NULL" : String.valueOf(value)));
-    }
-
-    public void testGetTimesUsedExpression() {
-        assertEquals((Object) 0, checkGetTimesUsedExpression(null));
-        assertEquals((Object) 0, checkGetTimesUsedExpression(-1));
-        assertEquals((Object) 0, checkGetTimesUsedExpression(-10));
-        assertEquals((Object) 0, checkGetTimesUsedExpression(0));
-        for (int i = 1; i < 10; i++) {
-            assertEquals("value=" + i, (Object) i, checkGetTimesUsedExpression(i));
-        }
-        for (int i = 10; i < 20; i++) {
-            assertEquals("value=" + i, (Object) 10, checkGetTimesUsedExpression(i));
-        }
-        for (int i = 20; i < 30; i++) {
-            assertEquals("value=" + i, (Object) 20, checkGetTimesUsedExpression(i));
-        }
-
-        assertEquals((Object) 123450, checkGetTimesUsedExpression(123456));
-    }
-
-    private Integer checkGetLastTimeUsedExpression(Integer value) {
-        return getIntegerFromExpression(LowRes.getLastTimeUsedExpression(
-                value == null ? "NULL" : String.valueOf(value)));
-    }
-
-    public void testGetLastTimeUsedExpression() {
-        assertEquals((Object) null, checkGetLastTimeUsedExpression(null));
-        assertEquals((Object) 0, checkGetLastTimeUsedExpression(0));
-        assertEquals((Object) 0, checkGetLastTimeUsedExpression(1));
-        assertEquals((Object) 0, checkGetLastTimeUsedExpression(86399));
-        assertEquals((Object) 86400, checkGetLastTimeUsedExpression(86400));
-
-        for (int i = 1; i < 3; i++) {
-            assertEquals((Object) (86400 * i), checkGetLastTimeUsedExpression(86400 * i));
-            assertEquals((Object) (86400 * i), checkGetLastTimeUsedExpression(86400 * i + 1));
-            assertEquals((Object) (86400 * i), checkGetLastTimeUsedExpression(86400 * i + 86399));
-        }
-    }
-
     public void testNotifyProviderStatusChange() throws Exception {
         final AtomicReference<Uri> calledUri = new AtomicReference<>();
 
diff --git a/tests/src/com/android/providers/contacts/ContactsIcuTest.java b/tests/src/com/android/providers/contacts/ContactsIcuTest.java
index 16583ae..7d3bdcf 100644
--- a/tests/src/com/android/providers/contacts/ContactsIcuTest.java
+++ b/tests/src/com/android/providers/contacts/ContactsIcuTest.java
@@ -17,14 +17,13 @@
 
 import android.icu.text.AlphabeticIndex;
 import android.icu.text.AlphabeticIndex.ImmutableIndex;
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.Suppress;
 import android.util.Log;
 
 import java.util.Arrays;
 import java.util.Locale;
 
-public class ContactsIcuTest extends AndroidTestCase {
+public class ContactsIcuTest extends FixedAndroidTestCase {
     private static final String TAG = "ContactsIcuTest";
 
     private static ImmutableIndex buildIndex(String... localeTags) {
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
index f29526c..6421c8f 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2Test.java
@@ -1015,11 +1015,10 @@
         Uri rowUri = mResolver.insert(RawContacts.CONTENT_URI, values);
         long rawContactId = ContentUris.parseId(rowUri);
 
-        values.put(RawContacts.LAST_TIME_CONTACTED, 86400);
-        values.put(RawContacts.TIMES_CONTACTED, 10);
+        values.put(RawContacts.LAST_TIME_CONTACTED, 0);
+        values.put(RawContacts.TIMES_CONTACTED, 0);
 
         assertStoredValues(rowUri, values);
-        assertSelection(RawContacts.CONTENT_URI, values, RawContacts._ID, rawContactId);
         assertNetworkNotified(true);
     }
 
@@ -1364,12 +1363,11 @@
         values.put(Contacts.DISPLAY_NAME, "Meghan Knox");
         values.put(Contacts.CUSTOM_RINGTONE, "d");
         values.put(Contacts.SEND_TO_VOICEMAIL, 1);
-        values.put(Contacts.LAST_TIME_CONTACTED, 86400);
-        values.put(Contacts.TIMES_CONTACTED, 54320);
+        values.put(Contacts.LAST_TIME_CONTACTED, 0);
+        values.put(Contacts.TIMES_CONTACTED, 0);
         values.put(Contacts.STARRED, 1);
 
         assertStoredValues(ContentUris.withAppendedId(Phone.CONTENT_URI, phoneId), values);
-        assertSelection(Phone.CONTENT_URI, values, Data._ID, phoneId);
     }
 
     public void testPhonesWithMergedContacts() {
@@ -2549,13 +2547,12 @@
         values.put(Contacts.DISPLAY_NAME, "Meghan Knox");
         values.put(Contacts.CUSTOM_RINGTONE, "d");
         values.put(Contacts.SEND_TO_VOICEMAIL, 1);
-        values.put(Contacts.LAST_TIME_CONTACTED, 86400);
-        values.put(Contacts.TIMES_CONTACTED, 54320);
+        values.put(Contacts.LAST_TIME_CONTACTED, 0);
+        values.put(Contacts.TIMES_CONTACTED, 0);
         values.put(Contacts.STARRED, 1);
 
         assertStoredValues(Email.CONTENT_URI, values);
         assertStoredValues(ContentUris.withAppendedId(Email.CONTENT_URI, emailId), values);
-        assertSelection(Email.CONTENT_URI, values, Data._ID, emailId);
 
         // Check if the provider detects duplicated email addresses.
         final Uri emailUri2 = insertEmail(rawContactId, "meghan@acme.com");
@@ -2748,12 +2745,6 @@
         assertStoredValuesOrderly(filterUri, v3, v1, v2);
     }
 
-    /**
-     * Test primary emails are sorted below emails used last.
-     *
-     * primary may be set without super primary.  Only super primary indicates "default" in the
-     * contact ui.
-     */
     public void testEmailFilterUsageOverPrimarySort() {
         final long rawContactId = RawContactUtil.createRawContact(mResolver, TestUtil.ACCOUNT_1);
         final Uri emailUri1 = insertEmail(rawContactId, "account1@testemail.com");
@@ -2769,9 +2760,9 @@
         final ContentValues v2 = cv(Email.ADDRESS, "account2@testemail.com");
         final ContentValues v3 = cv(Email.ADDRESS, "account3@testemail.com");
 
-        // Test that account 3 is first even though account 1 and 2 have higher usage.
+        // No usage stats any more, so v3 is still the first.
         Uri filterUri = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "acc");
-        assertStoredValuesOrderly(filterUri, v1, v2, v3);
+        assertStoredValuesOrderly(filterUri, v3, v1, v2);
     }
 
     /** Tests {@link DataUsageFeedback} correctly promotes a data row instead of a raw contact. */
@@ -2818,13 +2809,13 @@
                         RawContacts.TIMES_CONTACTED, 0
                         ),
                 cv(RawContacts._ID, rawContactId2,
-                        RawContacts.TIMES_CONTACTED, 1
+                        RawContacts.TIMES_CONTACTED, 0
                         )
                 );
 
-        // account3@email.com should be the first.
-        assertStoredValuesOrderly(filterUri1, new ContentValues[] { v3, v1, v2 });
-        assertStoredValuesOrderly(filterUri3, new ContentValues[] { v3, v1, v2 });
+        // No more interaction counter, so the order doesn't change.
+        assertStoredValuesOrderly(filterUri1, new ContentValues[] { v1, v2, v3 });
+        assertStoredValuesOrderly(filterUri3, new ContentValues[] { v1, v2, v3 });
     }
 
     public void testAddQueryParametersFromUri() {
@@ -2903,71 +2894,6 @@
         }
     }
 
-    /**
-     * Tests {@link DataUsageFeedback} correctly bucketize contacts using each
-     * {@link DataUsageStatColumns#RAW_LAST_TIME_USED}
-     */
-    public void testEmailFilterSortOrderWithOldHistory() {
-        long rawContactId1 = RawContactUtil.createRawContact(mResolver);
-        long dataId1 = ContentUris.parseId(insertEmail(rawContactId1, "address1@email.com"));
-        long dataId2 = ContentUris.parseId(insertEmail(rawContactId1, "address2@email.com"));
-        long dataId3 = ContentUris.parseId(insertEmail(rawContactId1, "address3@email.com"));
-        long dataId4 = ContentUris.parseId(insertEmail(rawContactId1, "address4@email.com"));
-
-        Uri filterUri1 = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, "address");
-
-        ContentValues v1 = new ContentValues();
-        v1.put(Email.ADDRESS, "address1@email.com");
-        ContentValues v2 = new ContentValues();
-        v2.put(Email.ADDRESS, "address2@email.com");
-        ContentValues v3 = new ContentValues();
-        v3.put(Email.ADDRESS, "address3@email.com");
-        ContentValues v4 = new ContentValues();
-        v4.put(Email.ADDRESS, "address4@email.com");
-
-        final ContactsProvider2 provider = (ContactsProvider2) getProvider();
-
-        long nowInMillis = System.currentTimeMillis();
-        long yesterdayInMillis = (nowInMillis - 24 * 60 * 60 * 1000);
-        long sevenDaysAgoInMillis = (nowInMillis - 7 * 24 * 60 * 60 * 1000);
-        long oneYearAgoInMillis = (nowInMillis - 365L * 24 * 60 * 60 * 1000);
-
-        // address4 is contacted just once yesterday.
-        provider.updateDataUsageStat(Arrays.asList(dataId4),
-                DataUsageFeedback.USAGE_TYPE_LONG_TEXT, yesterdayInMillis);
-
-        // address3 is contacted twice 1 week ago.
-        provider.updateDataUsageStat(Arrays.asList(dataId3),
-                DataUsageFeedback.USAGE_TYPE_LONG_TEXT, sevenDaysAgoInMillis);
-        provider.updateDataUsageStat(Arrays.asList(dataId3),
-                DataUsageFeedback.USAGE_TYPE_LONG_TEXT, sevenDaysAgoInMillis);
-
-        // address2 is contacted three times 1 year ago.
-        provider.updateDataUsageStat(Arrays.asList(dataId2),
-                DataUsageFeedback.USAGE_TYPE_LONG_TEXT, oneYearAgoInMillis);
-        provider.updateDataUsageStat(Arrays.asList(dataId2),
-                DataUsageFeedback.USAGE_TYPE_LONG_TEXT, oneYearAgoInMillis);
-        provider.updateDataUsageStat(Arrays.asList(dataId2),
-                DataUsageFeedback.USAGE_TYPE_LONG_TEXT, oneYearAgoInMillis);
-
-        // auto-complete should prefer recently contacted methods
-        assertStoredValuesOrderly(filterUri1, new ContentValues[] { v4, v3, v2, v1 });
-
-        // Pretend address2 is contacted right now
-        provider.updateDataUsageStat(Arrays.asList(dataId2),
-                DataUsageFeedback.USAGE_TYPE_LONG_TEXT, nowInMillis);
-
-        // Now address2 is the most recently used address
-        assertStoredValuesOrderly(filterUri1, new ContentValues[] { v2, v4, v3, v1 });
-
-        // Pretend address1 is contacted right now
-        provider.updateDataUsageStat(Arrays.asList(dataId1),
-                DataUsageFeedback.USAGE_TYPE_LONG_TEXT, nowInMillis);
-
-        // address2 is preferred to address1 as address2 is used 4 times in total
-        assertStoredValuesOrderly(filterUri1, new ContentValues[] { v2, v1, v4, v3 });
-    }
-
     public void testUpdateFromMetadataEntry() {
         String accountType1 = "accountType1";
         String accountName1 = "accountName1";
@@ -3060,8 +2986,7 @@
         assertStoredValue(dataUri2, Data.IS_SUPER_PRIMARY, 0);
         final Uri dataUriWithUsageType = Data.CONTENT_URI.buildUpon().appendQueryParameter(
                 DataUsageFeedback.USAGE_TYPE, usageTypeString).build();
-        assertDataUsageCursorContains(dataUriWithUsageType, emailAddress, 5,
-                1111111 / 86400 * 86400);
+        assertDataUsageZero(dataUriWithUsageType, emailAddress);
 
         // Update AggregationException table.
         RawContactInfo aggregationContact = new RawContactInfo(
@@ -3526,9 +3451,8 @@
                 StatusUpdates.CAPABILITY_HAS_CAMERA | StatusUpdates.CAPABILITY_HAS_VIDEO);
         Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
 
-        values.put(Contacts.TIMES_CONTACTED, 4);
+        values.put(Contacts.TIMES_CONTACTED, 0);
         assertStoredValues(contactUri, values);
-        assertSelection(Contacts.CONTENT_URI, values, Contacts._ID, contactId);
     }
 
     public void testQueryContactWithStatusUpdate() {
@@ -3540,10 +3464,9 @@
         values.put(Contacts.CONTACT_CHAT_CAPABILITY, StatusUpdates.CAPABILITY_HAS_CAMERA);
         Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
 
-        values.put(Contacts.TIMES_CONTACTED, 4);
+        values.put(Contacts.TIMES_CONTACTED, 0);
 
         assertStoredValuesWithProjection(contactUri, values);
-        assertSelectionWithProjection(Contacts.CONTENT_URI, values, Contacts._ID, contactId);
     }
 
     public void testQueryContactFilterByName() {
@@ -3564,7 +3487,7 @@
         values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE);
 
         Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "goulash");
-        values.put(Contacts.TIMES_CONTACTED, 4);
+        values.put(Contacts.TIMES_CONTACTED, 0);
         assertStoredValuesWithProjection(filterUri1, values);
 
         assertContactFilter(contactId, "goolash");
@@ -3599,7 +3522,7 @@
         values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE);
 
         Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "goog411@acme.com");
-        values.put(Contacts.TIMES_CONTACTED, 4);
+        values.put(Contacts.TIMES_CONTACTED, 0);
         assertStoredValuesWithProjection(filterUri1, values);
 
         assertContactFilter(contactId, "goog");
@@ -3626,7 +3549,7 @@
         values.put(Contacts.CONTACT_PRESENCE, StatusUpdates.INVISIBLE);
 
         Uri filterUri1 = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI, "18004664411");
-        values.put(Contacts.TIMES_CONTACTED, 4);
+        values.put(Contacts.TIMES_CONTACTED, 0);
         assertStoredValuesWithProjection(filterUri1, values);
 
         assertContactFilter(contactId, "18004664411");
@@ -3641,7 +3564,7 @@
 
     /**
      * Checks ContactsProvider2 works well with strequent Uris. The provider should return starred
-     * contacts and frequently used contacts.
+     * contacts.
      */
     public void testQueryContactStrequent() {
         ContentValues values1 = new ContentValues();
@@ -3674,20 +3597,20 @@
         // Send feedback for the 3rd phone number, pretending we called that person via phone.
         sendFeedback(phoneNumber3, DataUsageFeedback.USAGE_TYPE_CALL, values3);
 
-        values3.put(Contacts.TIMES_CONTACTED, 10); // Low res.
+        values3.put(Contacts.TIMES_CONTACTED, 0);
 
         // After the feedback, 3rd contact should be shown after starred one.
         assertStoredValuesOrderly(Contacts.CONTENT_STREQUENT_URI,
-                new ContentValues[] { values4, values3 });
+                new ContentValues[] { values4 });
 
         sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values1);
         // Twice.
         sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values1);
 
         // After the feedback, 1st and 3rd contacts should be shown after starred one.
-        values1.put(Contacts.TIMES_CONTACTED, 2);
+        values1.put(Contacts.TIMES_CONTACTED, 0);
         assertStoredValuesOrderly(Contacts.CONTENT_STREQUENT_URI,
-                new ContentValues[] { values4, values1, values3 });
+                new ContentValues[] { values4 });
 
         // With phone-only parameter, 1st and 4th contacts shouldn't be returned because:
         // 1st: feedbacks are only about email, not about phone call.
@@ -3695,48 +3618,7 @@
         Uri phoneOnlyStrequentUri = Contacts.CONTENT_STREQUENT_URI.buildUpon()
                 .appendQueryParameter(ContactsContract.STREQUENT_PHONE_ONLY, "true")
                 .build();
-        assertStoredValuesOrderly(phoneOnlyStrequentUri, new ContentValues[] { values3 });
-
-        // Now the 4th contact has three phone numbers, one of which is called twice and
-        // the other once
-        final String phoneNumber4 = "18004664414";
-        final String phoneNumber5 = "18004664415";
-        final String phoneNumber6 = "18004664416";
-        insertPhoneNumber(rawContactId4, phoneNumber4);
-        insertPhoneNumber(rawContactId4, phoneNumber5);
-        insertPhoneNumber(rawContactId4, phoneNumber6);
-        values3.put(Phone.NUMBER, phoneNumber3);
-        values4.put(Phone.NUMBER, phoneNumber4);
-
-        sendFeedback(phoneNumber5, DataUsageFeedback.USAGE_TYPE_CALL, values4);
-        sendFeedback(phoneNumber5, DataUsageFeedback.USAGE_TYPE_CALL, values4);
-        sendFeedback(phoneNumber6, DataUsageFeedback.USAGE_TYPE_CALL, values4);
-
-        // Create a ContentValues object representing the second phone number of contact 4
-        final ContentValues values5 = new ContentValues(values4);
-        values5.put(Phone.NUMBER, phoneNumber5);
-
-        // Create a ContentValues object representing the third phone number of contact 4
-        final ContentValues values6 = new ContentValues(values4);
-        values6.put(Phone.NUMBER, phoneNumber6);
-
-        // Phone only strequent should return all phone numbers belonging to the 4th contact,
-        // and then contact 3.
-        assertStoredValuesOrderly(phoneOnlyStrequentUri, new ContentValues[] {values5, values6,
-                values4, values3});
-
-        // Send feedback for the 2rd phone number, pretending we send the person a SMS message.
-        sendFeedback(phoneNumber2, DataUsageFeedback.USAGE_TYPE_SHORT_TEXT, values1);
-
-        values1.put(Contacts.TIMES_CONTACTED, 1); // Low res.
-
-        // SMS feedback shouldn't affect phone-only results.
-        assertStoredValuesOrderly(phoneOnlyStrequentUri, new ContentValues[] {values5, values6,
-                values4, values3});
-
-        values4.remove(Phone.NUMBER);
-        Uri filterUri = Uri.withAppendedPath(Contacts.CONTENT_STREQUENT_FILTER_URI, "fay");
-        assertStoredValues(filterUri, values4);
+        assertStoredValuesOrderly(phoneOnlyStrequentUri, new ContentValues[] { });
     }
 
     public void testQueryContactStrequentFrequentOrder() {
@@ -3834,27 +3716,14 @@
         // before cid5 and cid6, which were contacted at the same time.
         // cid2 will not show up because it was contacted more than 30 days ago
 
-        assertStoredValuesOrderly(Contacts.CONTENT_STREQUENT_URI,
-                cv(Contacts._ID, cid8),
-                cv(Contacts._ID, cid7),
-                cv(Contacts._ID, cid1),
-                cv(Contacts._ID, cid5),
-                cv(Contacts._ID, cid6),
-                cv(Contacts._ID, cid3),
-                cv(Contacts._ID, cid4));
+        assertStoredValuesOrderly(Contacts.CONTENT_STREQUENT_URI);
 
         // Check the order -- phone only frequent, which is data based.
         // Note this is based on data, and only looks at phone numbers, so the order is different
         // now.
         // did1, did2 will not show up because they were used to make calls more than 30 days ago.
         assertStoredValuesOrderly(Contacts.CONTENT_STREQUENT_URI.buildUpon()
-                    .appendQueryParameter(ContactsContract.STREQUENT_PHONE_ONLY, "1").build(),
-                cv(Data._ID, did8),
-                cv(Data._ID, did7),
-                cv(Data._ID, did5),
-                cv(Data._ID, did6),
-                cv(Data._ID, did3),
-                cv(Data._ID, did4));
+                    .appendQueryParameter(ContactsContract.STREQUENT_PHONE_ONLY, "1").build());
     }
 
     /**
@@ -3880,32 +3749,32 @@
 
         sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values1);
 
-        assertStoredValues(Contacts.CONTENT_FREQUENT_URI, values1);
+        assertStoredValues(Contacts.CONTENT_FREQUENT_URI);
 
         // Pretend email was sent to the address twice.
         sendFeedback(email2, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values2);
         sendFeedback(email2, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values2);
 
-        values1.put(Contacts.TIMES_CONTACTED, 1);
-        values2.put(Contacts.TIMES_CONTACTED, 2);
-        assertStoredValues(Contacts.CONTENT_FREQUENT_URI, new ContentValues[] {values2, values1});
+        values1.put(Contacts.TIMES_CONTACTED, 0);
+        values2.put(Contacts.TIMES_CONTACTED, 0);
+        assertStoredValues(Contacts.CONTENT_FREQUENT_URI);
 
         for (int i = 0; i < 10; i++) {
             sendFeedback(phoneNumber3, DataUsageFeedback.USAGE_TYPE_CALL, values3);
         }
 
-        values3.put(Contacts.TIMES_CONTACTED, 10); // low res.
+        values3.put(Contacts.TIMES_CONTACTED, 0);
 
-        assertStoredValues(Contacts.CONTENT_FREQUENT_URI,
-                new ContentValues[] {values3, values2, values1});
+        assertStoredValues(Contacts.CONTENT_FREQUENT_URI);
+
 
         // Test it works with selection/selectionArgs
         assertStoredValues(Contacts.CONTENT_FREQUENT_URI,
-                Contacts.STARRED + "=?", new String[] {"0"},
-                new ContentValues[] {values2, values1});
+                Contacts.STARRED + "=?", new String[] {"0"}
+                );
         assertStoredValues(Contacts.CONTENT_FREQUENT_URI,
-                Contacts.STARRED + "=?", new String[] {"1"},
-                new ContentValues[] {values3});
+                Contacts.STARRED + "=?", new String[] {"1"}
+                );
 
         values3.put(Contacts.STARRED, 0);
         assertEquals(1,
@@ -3913,11 +3782,11 @@
                         String.valueOf(contactId3)),
                 values3, null, null));
         assertStoredValues(Contacts.CONTENT_FREQUENT_URI,
-                Contacts.STARRED + "=?", new String[] {"0"},
-                new ContentValues[] {values3, values2, values1});
+                Contacts.STARRED + "=?", new String[] {"0"}
+                );
         assertStoredValues(Contacts.CONTENT_FREQUENT_URI,
-                Contacts.STARRED + "=?", new String[] {"1"},
-                new ContentValues[] {});
+                Contacts.STARRED + "=?", new String[] {"1"}
+                );
     }
 
     public void testQueryContactFrequentExcludingInvisible() {
@@ -3934,17 +3803,19 @@
         sendFeedback(email2, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values2);
 
         // First, we have two contacts in frequent.
-        assertStoredValues(Contacts.CONTENT_FREQUENT_URI, new ContentValues[] {values2, values1});
+        assertStoredValues(Contacts.CONTENT_FREQUENT_URI);
 
         // Contact 2 goes invisible.
         markInvisible(cid2);
 
         // Now we have only 1 frequent.
-        assertStoredValues(Contacts.CONTENT_FREQUENT_URI, new ContentValues[] {values1});
+        assertStoredValues(Contacts.CONTENT_FREQUENT_URI);
 
     }
 
     public void testQueryDataUsageStat() {
+        // Now all data usage stats are zero as of Q.
+
         ContentValues values1 = new ContentValues();
         final String email1 = "a@acme.com";
         final long cid1 = createContact(values1, "Noah", "Tever", "18004664411",
@@ -3955,51 +3826,48 @@
 
         sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values1);
 
-        assertDataUsageCursorContains(Data.CONTENT_URI, "a@acme.com", 1, 0);
+        assertDataUsageZero(Data.CONTENT_URI, "a@acme.com");
 
         sMockClock.setCurrentTimeMillis(86400 + 123);
         sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_LONG_TEXT, values1);
 
-        assertDataUsageCursorContains(Data.CONTENT_URI, "a@acme.com", 2, 86400);
+        assertDataUsageZero(Data.CONTENT_URI, "a@acme.com");
 
         sMockClock.setCurrentTimeMillis(86400 * 3 + 123);
         for (int i = 0; i < 11; i++) {
             sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_SHORT_TEXT, values1);
         }
 
-        // Note here, "a@acme.com" has two data stats rows, 2 and 11.  What we get here's the sum
-        // of the lowres values, so # times will be 12, instead of 10 (which is the lowres of the
-        // sum).
-        assertDataUsageCursorContains(Data.CONTENT_URI, "a@acme.com", 12, 86400 * 3);
+        assertDataUsageZero(Data.CONTENT_URI, "a@acme.com");
 
         final Uri dataUriWithUsageTypeLongText = Data.CONTENT_URI.buildUpon().appendQueryParameter(
                 DataUsageFeedback.USAGE_TYPE, DataUsageFeedback.USAGE_TYPE_LONG_TEXT).build();
 
-        assertDataUsageCursorContains(dataUriWithUsageTypeLongText, "a@acme.com", 2, 86400 * 1);
+        assertDataUsageZero(dataUriWithUsageTypeLongText, "a@acme.com");
 
         sMockClock.setCurrentTimeMillis(86400 * 4 + 123);
         sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_CALL, values1);
         sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_CALL, values1);
         sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_CALL, values1);
 
-        assertDataUsageCursorContains(Data.CONTENT_URI, "a@acme.com", 15, 86400 * 4);
+        assertDataUsageZero(Data.CONTENT_URI, "a@acme.com");
 
         sMockClock.setCurrentTimeMillis(86400 * 5 + 123);
         for (int i = 0; i < 10; i++) {
             sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_CALL, values1);
         }
-        assertDataUsageCursorContains(Data.CONTENT_URI, "a@acme.com", 22, 86400 * 5);
+        assertDataUsageZero(Data.CONTENT_URI, "a@acme.com");
 
         sMockClock.setCurrentTimeMillis(86400 * 6 + 123);
         for (int i = 0; i < 10; i++) {
             sendFeedback(email1, DataUsageFeedback.USAGE_TYPE_CALL, values1);
         }
-        assertDataUsageCursorContains(Data.CONTENT_URI, "a@acme.com", 32, 86400 * 6);
+        assertDataUsageZero(Data.CONTENT_URI, "a@acme.com");
 
         final Uri dataUriWithUsageTypeCall = Data.CONTENT_URI.buildUpon().appendQueryParameter(
                 DataUsageFeedback.USAGE_TYPE, DataUsageFeedback.USAGE_TYPE_CALL).build();
 
-        assertDataUsageCursorContains(dataUriWithUsageTypeCall, "a@acme.com", 20, 86400 * 6);
+        assertDataUsageZero(dataUriWithUsageTypeCall, "a@acme.com");
     }
 
     public void testQueryContactGroup() {
@@ -4201,11 +4069,10 @@
         long nonProfileRawContactId = createBasicNonProfileContact(nonProfileValues);
         long nonProfileContactId = queryContactId(nonProfileRawContactId);
 
-        nonProfileValues.put(Contacts.TIMES_CONTACTED, 4);
-        profileValues.put(Contacts.TIMES_CONTACTED, 4);
+        nonProfileValues.put(Contacts.TIMES_CONTACTED, 0);
+        profileValues.put(Contacts.TIMES_CONTACTED, 0);
 
         assertStoredValues(Contacts.CONTENT_URI, nonProfileValues);
-        assertSelection(Contacts.CONTENT_URI, nonProfileValues, Contacts._ID, nonProfileContactId);
 
         assertStoredValues(Profile.CONTENT_URI, profileValues);
     }
@@ -4217,7 +4084,7 @@
         // Create a non-profile contact - this should be returned.
         ContentValues nonProfileValues = new ContentValues();
         createBasicNonProfileContact(nonProfileValues);
-        nonProfileValues.put(Contacts.TIMES_CONTACTED, 4);
+        nonProfileValues.put(Contacts.TIMES_CONTACTED, 0);
         assertStoredValues(Contacts.CONTENT_URI, new ContentValues[] {nonProfileValues});
     }
 
@@ -4225,7 +4092,7 @@
         ContentValues profileValues = new ContentValues();
         createBasicProfileContact(profileValues);
 
-        profileValues.put(Contacts.TIMES_CONTACTED, 4);
+        profileValues.put(Contacts.TIMES_CONTACTED, 0);
         assertStoredValues(Profile.CONTENT_URI, profileValues);
     }
 
@@ -4274,7 +4141,7 @@
 
         // The raw contact view doesn't include the photo ID.
         profileValues.remove(Contacts.PHOTO_ID);
-        profileValues.put(Contacts.TIMES_CONTACTED, 4);
+        profileValues.put(Contacts.TIMES_CONTACTED, 0);
         assertStoredValues(Profile.CONTENT_RAW_CONTACTS_URI, profileValues);
     }
 
@@ -4284,7 +4151,7 @@
 
         // The raw contact view doesn't include the photo ID.
         profileValues.remove(Contacts.PHOTO_ID);
-        profileValues.put(Contacts.TIMES_CONTACTED, 4);
+        profileValues.put(Contacts.TIMES_CONTACTED, 0);
         assertStoredValues(ContentUris.withAppendedId(
                 Profile.CONTENT_RAW_CONTACTS_URI, profileRawContactId), profileValues);
     }
@@ -7221,7 +7088,7 @@
         assertMetadataNetworkNotified(true);
     }
 
-    public void testMarkAsMetadataDirtyForUsageStatsChange() {
+    public void testMarkAsMetadataNotDirtyForUsageStatsChange() {
         // Enable metadataSync flag.
         final ContactsProvider2 cp = (ContactsProvider2) getProvider();
         cp.setMetadataSyncForTest(true);
@@ -7230,9 +7097,9 @@
         final long did1a = ContentUris.parseId(insertEmail(rid1, "email_1_a@email.com"));
         updateDataUsageFeedback(DataUsageFeedback.USAGE_TYPE_LONG_TEXT, did1a);
 
-        assertMetadataDirty(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rid1),
-                true);
-        assertMetadataNetworkNotified(true);
+        // Usage feedback no longer works, so "false".
+        assertMetadataDirty(ContentUris.withAppendedId(RawContacts.CONTENT_URI, rid1), false);
+        assertMetadataNetworkNotified(false);
     }
 
     public void testMarkAsMetadataDirtyForDataPrimarySettingInsert() {
@@ -8851,7 +8718,7 @@
         }
     }
 
-    public void testMarkMetadataDirtyWhenDataUsageUpdate() {
+    public void testMarkMetadataNotDirtyWhenDataUsageUpdate() {
         // Enable metadataSync flag.
         final ContactsProvider2 cp = (ContactsProvider2) getProvider();
         cp.setMetadataSyncForTest(true);
@@ -8864,9 +8731,10 @@
         updateDataUsageFeedback(DataUsageFeedback.USAGE_TYPE_LONG_TEXT, did1a);
 
         assertDirty(rawContactUri, false);
-        assertMetadataDirty(rawContactUri, true);
+        // Usage feedback no longer works, so "false".
+        assertMetadataDirty(rawContactUri, false);
         assertNetworkNotified(false);
-        assertMetadataNetworkNotified(true);
+        assertMetadataNetworkNotified(false);
     }
 
     public void testDataUsageFeedbackAndDelete() {
@@ -8912,24 +8780,24 @@
         // Test 1. touch data 1a
         updateDataUsageFeedback(DataUsageFeedback.USAGE_TYPE_LONG_TEXT, did1a);
 
-        // Now, there's a single frequent.  (contact 1)
-        assertRowCount(1, Contacts.CONTENT_STREQUENT_URI, null, null);
+        // (We no longer populate frequent, so 0.)
+        assertRowCount(0, Contacts.CONTENT_STREQUENT_URI, null, null);
 
         sMockClock.advanceDay();
 
         // Test 2. touch data 1a, 2a and 3a
         updateDataUsageFeedback(DataUsageFeedback.USAGE_TYPE_LONG_TEXT, did1a, did2a, did3a);
 
-        // Now, contact 1 and 3 are in frequent.
-        assertRowCount(2, Contacts.CONTENT_STREQUENT_URI, null, null);
+        // (We no longer populate frequent, so 0.)
+        assertRowCount(0, Contacts.CONTENT_STREQUENT_URI, null, null);
 
         sMockClock.advanceDay();
 
         // Test 2. touch data 2p (call)
         updateDataUsageFeedback(DataUsageFeedback.USAGE_TYPE_CALL, did2p);
 
-        // There're still two frequent.
-        assertRowCount(2, Contacts.CONTENT_STREQUENT_URI, null, null);
+        // (We no longer populate frequent, so 0.)
+        assertRowCount(0, Contacts.CONTENT_STREQUENT_URI, null, null);
 
         sMockClock.advanceDay();
 
@@ -8937,68 +8805,32 @@
         updateDataUsageFeedback(DataUsageFeedback.USAGE_TYPE_SHORT_TEXT, did2p, did3p);
 
         // Let's check the tables.
-// TODO more tests?
+
         // Fist, check the data_usage_stat table, which has no public URI.
         assertStoredValuesDb("SELECT " + DataUsageStatColumns.DATA_ID +
                 "," + DataUsageStatColumns.USAGE_TYPE_INT +
                 "," + DataUsageStatColumns.RAW_TIMES_USED +
                 "," + DataUsageStatColumns.RAW_LAST_TIME_USED +
-                " FROM " + Tables.DATA_USAGE_STAT, null,
-                cv(DataUsageStatColumns.DATA_ID, did1a,
-                        DataUsageStatColumns.USAGE_TYPE_INT,
-                            DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT,
-                        DataUsageStatColumns.RAW_TIMES_USED, 2,
-                        DataUsageStatColumns.RAW_LAST_TIME_USED, startTime + 86400
-                        ),
-                cv(DataUsageStatColumns.DATA_ID, did2a,
-                        DataUsageStatColumns.USAGE_TYPE_INT,
-                            DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT,
-                        DataUsageStatColumns.RAW_TIMES_USED, 1,
-                        DataUsageStatColumns.RAW_LAST_TIME_USED, startTime + 86400
-                        ),
-                cv(DataUsageStatColumns.DATA_ID, did3a,
-                        DataUsageStatColumns.USAGE_TYPE_INT,
-                            DataUsageStatColumns.USAGE_TYPE_INT_LONG_TEXT,
-                        DataUsageStatColumns.RAW_TIMES_USED, 1,
-                        DataUsageStatColumns.RAW_LAST_TIME_USED, startTime + 86400
-                        ),
-                cv(DataUsageStatColumns.DATA_ID, did2p,
-                        DataUsageStatColumns.USAGE_TYPE_INT,
-                            DataUsageStatColumns.USAGE_TYPE_INT_CALL,
-                        DataUsageStatColumns.RAW_TIMES_USED, 1,
-                        DataUsageStatColumns.RAW_LAST_TIME_USED, startTime + 86400 * 2
-                        ),
-                cv(DataUsageStatColumns.DATA_ID, did2p,
-                        DataUsageStatColumns.USAGE_TYPE_INT,
-                            DataUsageStatColumns.USAGE_TYPE_INT_SHORT_TEXT,
-                        DataUsageStatColumns.RAW_TIMES_USED, 1,
-                        DataUsageStatColumns.RAW_LAST_TIME_USED, startTime + 86400 * 3
-                        ),
-                cv(DataUsageStatColumns.DATA_ID, did3p,
-                        DataUsageStatColumns.USAGE_TYPE_INT,
-                            DataUsageStatColumns.USAGE_TYPE_INT_SHORT_TEXT,
-                        DataUsageStatColumns.RAW_TIMES_USED, 1,
-                        DataUsageStatColumns.RAW_LAST_TIME_USED, startTime + 86400 * 3
-                        )
+                " FROM " + Tables.DATA_USAGE_STAT, null
                 );
 
         // Next, check the raw_contacts table
         assertStoredValuesWithProjection(RawContacts.CONTENT_URI,
                 cv(RawContacts._ID, rid1,
-                        RawContacts.TIMES_CONTACTED, 2,
-                        RawContacts.LAST_TIME_CONTACTED, (startTime + 86400) / 86400 * 86400
+                        RawContacts.TIMES_CONTACTED, 0,
+                        RawContacts.LAST_TIME_CONTACTED, 0
                         ),
                 cv(RawContacts._ID, rid2,
-                        RawContacts.TIMES_CONTACTED, 3,
-                        RawContacts.LAST_TIME_CONTACTED, (startTime + 86400 * 3) / 86400 * 86400
+                        RawContacts.TIMES_CONTACTED, 0,
+                        RawContacts.LAST_TIME_CONTACTED, 0
                         ),
                 cv(RawContacts._ID, rid3,
-                        RawContacts.TIMES_CONTACTED, 2,
-                        RawContacts.LAST_TIME_CONTACTED, (startTime + 86400 * 3) / 86400 * 86400
+                        RawContacts.TIMES_CONTACTED, 0,
+                        RawContacts.LAST_TIME_CONTACTED, 0
                         ),
                 cv(RawContacts._ID, rid4,
                         RawContacts.TIMES_CONTACTED, 0,
-                        RawContacts.LAST_TIME_CONTACTED, null // 4 wasn't touched.
+                        RawContacts.LAST_TIME_CONTACTED, 0
                         )
                 );
 
@@ -9009,12 +8841,12 @@
         // at once.
         assertStoredValuesWithProjection(Contacts.CONTENT_URI,
                 cv(Contacts._ID, cid1,
-                        Contacts.TIMES_CONTACTED, 4,
-                        Contacts.LAST_TIME_CONTACTED, (startTime + 86400 * 3) / 86400 * 86400
+                        Contacts.TIMES_CONTACTED, 0,
+                        Contacts.LAST_TIME_CONTACTED, 0
                         ),
                 cv(Contacts._ID, cid3,
-                        Contacts.TIMES_CONTACTED, 2,
-                        Contacts.LAST_TIME_CONTACTED, (startTime + 86400 * 3) / 86400 * 86400
+                        Contacts.TIMES_CONTACTED, 0,
+                        Contacts.LAST_TIME_CONTACTED, 0
                         ),
                 cv(Contacts._ID, cid4,
                         Contacts.TIMES_CONTACTED, 0,
@@ -9967,7 +9799,7 @@
     private void sendFeedback(String data1, String usageType, ContentValues values) {
         final long dataId = getStoredLongValue(Data.CONTENT_URI,
                 Data.DATA1 + "=?", new String[] { data1 }, Data._ID);
-        MoreAsserts.assertNotEqual(0, updateDataUsageFeedback(usageType, dataId));
+        assertEquals(0, updateDataUsageFeedback(usageType, dataId));
         if (values != null && values.containsKey(Contacts.TIMES_CONTACTED)) {
             values.put(Contacts.TIMES_CONTACTED, values.getAsInteger(Contacts.TIMES_CONTACTED) + 1);
         }
@@ -9976,7 +9808,7 @@
     private void updateDataUsageFeedback(String usageType, Uri resultUri) {
         final long id = ContentUris.parseId(resultUri);
         final boolean successful = updateDataUsageFeedback(usageType, id) > 0;
-        assertTrue(successful);
+        assertFalse(successful); // shouldn't succeed
     }
 
     private int updateDataUsageFeedback(String usageType, long... ids) {
diff --git a/tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java b/tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java
index 03c9e75..d7b78d6 100644
--- a/tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java
+++ b/tests/src/com/android/providers/contacts/ContactsProvider2TransactionTest.java
@@ -197,7 +197,7 @@
     private void checkStoredContact() {
         assertStoredValues(Contacts.CONTENT_URI, cv(
                 Contacts.DISPLAY_NAME, "Regular Contact",
-                RawContacts.LAST_TIME_CONTACTED, 86400 * 21
+                RawContacts.LAST_TIME_CONTACTED, 0
                 ));
     }
 
@@ -227,7 +227,7 @@
     private void checkStoredProfile() {
         assertStoredValues(Profile.CONTENT_URI, cv(
                 Contacts.DISPLAY_NAME, "Profile Contact",
-                RawContacts.LAST_TIME_CONTACTED, 86400 * 11
+                RawContacts.LAST_TIME_CONTACTED, 0
                 ));
     }
 
diff --git a/tests/src/com/android/providers/contacts/ContactsTaskSchedulerTest.java b/tests/src/com/android/providers/contacts/ContactsTaskSchedulerTest.java
index df7196d..fe53c28 100644
--- a/tests/src/com/android/providers/contacts/ContactsTaskSchedulerTest.java
+++ b/tests/src/com/android/providers/contacts/ContactsTaskSchedulerTest.java
@@ -15,7 +15,6 @@
  */
 package com.android.providers.contacts;
 
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 
 import java.util.ArrayList;
@@ -25,7 +24,7 @@
 import java.util.concurrent.TimeUnit;
 
 @LargeTest
-public class ContactsTaskSchedulerTest extends AndroidTestCase {
+public class ContactsTaskSchedulerTest extends FixedAndroidTestCase {
     private static final int SHUTDOWN_SECONDS = 3;
 
     private static class MyContactsTaskScheduler extends ContactsTaskScheduler {
diff --git a/tests/src/com/android/providers/contacts/EnterpriseContactsCursorWrapperTest.java b/tests/src/com/android/providers/contacts/EnterpriseContactsCursorWrapperTest.java
index 66cebfc..7ae7b57 100644
--- a/tests/src/com/android/providers/contacts/EnterpriseContactsCursorWrapperTest.java
+++ b/tests/src/com/android/providers/contacts/EnterpriseContactsCursorWrapperTest.java
@@ -19,7 +19,6 @@
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.provider.ContactsContract.PhoneLookup;
-import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -27,7 +26,7 @@
 
 
 @SmallTest
-public class EnterpriseContactsCursorWrapperTest extends AndroidTestCase {
+public class EnterpriseContactsCursorWrapperTest extends FixedAndroidTestCase {
 
     public void testWrappedResults() {
         final String[] projection = new String[] {
diff --git a/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java b/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java
index 4580ce1..08625cd 100644
--- a/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java
+++ b/tests/src/com/android/providers/contacts/FastScrollingIndexCacheTest.java
@@ -20,14 +20,13 @@
 import android.os.Bundle;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.RawContacts;
-import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.providers.contacts.util.MockSharedPreferences;
 
 @SmallTest
-public class FastScrollingIndexCacheTest extends AndroidTestCase {
+public class FastScrollingIndexCacheTest extends FixedAndroidTestCase {
     private MockSharedPreferences mPrefs;
     private FastScrollingIndexCache mCache;
 
diff --git a/tests/src/com/android/providers/contacts/FixedAndroidTestCase.java b/tests/src/com/android/providers/contacts/FixedAndroidTestCase.java
new file mode 100644
index 0000000..5f0bda5
--- /dev/null
+++ b/tests/src/com/android/providers/contacts/FixedAndroidTestCase.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 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.content.Context;
+import android.test.AndroidTestCase;
+
+import androidx.test.InstrumentationRegistry;
+
+/**
+ * {@link FixedAndroidTestCase#getTestContext} isn't set when executed on the support test runner. This
+ * class works around that.
+ */
+public class FixedAndroidTestCase extends AndroidTestCase {
+    @Override
+    public Context getTestContext() {
+        return InstrumentationRegistry.getContext();
+    }
+}
diff --git a/tests/src/com/android/providers/contacts/MetadataEntryParserTest.java b/tests/src/com/android/providers/contacts/MetadataEntryParserTest.java
index be4df57..fe6ed13 100644
--- a/tests/src/com/android/providers/contacts/MetadataEntryParserTest.java
+++ b/tests/src/com/android/providers/contacts/MetadataEntryParserTest.java
@@ -17,7 +17,6 @@
 package com.android.providers.contacts;
 
 import android.content.Context;
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 import com.android.providers.contacts.MetadataEntryParser.AggregationData;
 import com.android.providers.contacts.MetadataEntryParser.FieldData;
@@ -41,7 +40,7 @@
  * </code>
  */
 @SmallTest
-public class MetadataEntryParserTest extends AndroidTestCase {
+public class MetadataEntryParserTest extends FixedAndroidTestCase {
 
     public void testErrorForEmptyInput() {
         try {
diff --git a/tests/src/com/android/providers/contacts/NameSplitterTest.java b/tests/src/com/android/providers/contacts/NameSplitterTest.java
index d9007fc..e0e5753 100644
--- a/tests/src/com/android/providers/contacts/NameSplitterTest.java
+++ b/tests/src/com/android/providers/contacts/NameSplitterTest.java
@@ -233,6 +233,25 @@
         assertFullNameStyle(FullNameStyle.CHINESE, "\uFF5C--(\u675C\u9D51)");
     }
 
+    public void testGuessFullNameStyleChineseMixed() {
+        createNameSplitter(Locale.CHINA);
+        // Both first and last names are Chinese.
+        assertFullNameStyle(FullNameStyle.CHINESE, "\u675C \u9D51");
+        // Last name is Chinese, first name is English.
+        assertFullNameStyle(FullNameStyle.CHINESE, "\u675C Juan");
+        // Last name is English, first name is Chinese.
+        assertFullNameStyle(FullNameStyle.CHINESE, "Du \u9D51");
+        // Both first and last names are English, prefix, middle, suffix are all Chinese.
+        Name name = new Name();
+        name.prefix = "\u524D";
+        name.givenNames = "Du";
+        name.middleName = "\u5C0F";
+        name.familyName = "Juan";
+        name.suffix = "\u540E";
+        mNameSplitter.guessNameStyle(name);
+        // guessFullNameStyle() only look at last and first name.
+        assertEquals(FullNameStyle.WESTERN, name.fullNameStyle);
+    }
 
     public void testGuessPhoneticNameStyle() {
 
diff --git a/tests/src/com/android/providers/contacts/PhoneLookupWithStarPrefixTest.java b/tests/src/com/android/providers/contacts/PhoneLookupWithStarPrefixTest.java
index cd86a42..d595580 100644
--- a/tests/src/com/android/providers/contacts/PhoneLookupWithStarPrefixTest.java
+++ b/tests/src/com/android/providers/contacts/PhoneLookupWithStarPrefixTest.java
@@ -16,12 +16,11 @@
 
 package com.android.providers.contacts;
 
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.SmallTest;
 
 @LargeTest
-public class PhoneLookupWithStarPrefixTest extends AndroidTestCase {
+public class PhoneLookupWithStarPrefixTest extends FixedAndroidTestCase {
 
     @SmallTest
     public void testNormalizeNumberWithStar() {
diff --git a/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java b/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java
index 4b159a8..4b199c6 100644
--- a/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java
+++ b/tests/src/com/android/providers/contacts/PhotoLoadingTestCase.java
@@ -17,7 +17,6 @@
 package com.android.providers.contacts;
 
 import android.content.res.Resources;
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.google.android.collect.Maps;
@@ -31,7 +30,7 @@
  * Adds support for loading photo files easily from test resources.
  */
 @SmallTest
-public class PhotoLoadingTestCase extends AndroidTestCase {
+public class PhotoLoadingTestCase extends FixedAndroidTestCase {
 
     private Map<Integer, PhotoEntry> photoResourceCache = Maps.newHashMap();
     protected static enum PhotoSize {
diff --git a/tests/src/com/android/providers/contacts/PhotoPriorityResolverTest.java b/tests/src/com/android/providers/contacts/PhotoPriorityResolverTest.java
index b105595..a2dd81d 100644
--- a/tests/src/com/android/providers/contacts/PhotoPriorityResolverTest.java
+++ b/tests/src/com/android/providers/contacts/PhotoPriorityResolverTest.java
@@ -16,7 +16,6 @@
 
 package com.android.providers.contacts;
 
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.MediumTest;
 
 /**
@@ -29,7 +28,7 @@
  * </code>
  */
 @MediumTest
-public class PhotoPriorityResolverTest extends AndroidTestCase {
+public class PhotoPriorityResolverTest extends FixedAndroidTestCase {
 
     public void testLoadPicturePriorityFromXml() {
         PhotoPriorityResolver resolver = new PhotoPriorityResolver(getContext());
diff --git a/tests/src/com/android/providers/contacts/PhotoProcessorTest.java b/tests/src/com/android/providers/contacts/PhotoProcessorTest.java
index 4b59be9..ab7b7fc 100644
--- a/tests/src/com/android/providers/contacts/PhotoProcessorTest.java
+++ b/tests/src/com/android/providers/contacts/PhotoProcessorTest.java
@@ -20,7 +20,6 @@
 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;
@@ -34,7 +33,7 @@
  * Most of tests are covered by {@link PhotoStoreTest}.
  */
 @SmallTest
-public class PhotoProcessorTest extends AndroidTestCase {
+public class PhotoProcessorTest extends FixedAndroidTestCase {
 
     public void testTransparency() throws IOException {
         final Drawable source = getTestContext().getResources().getDrawable(
diff --git a/tests/src/com/android/providers/contacts/TestUtils.java b/tests/src/com/android/providers/contacts/TestUtils.java
index 322e5b4..689ea7c 100644
--- a/tests/src/com/android/providers/contacts/TestUtils.java
+++ b/tests/src/com/android/providers/contacts/TestUtils.java
@@ -20,15 +20,16 @@
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
 import android.os.FileUtils;
 import android.provider.ContactsContract.Contacts;
 import android.provider.ContactsContract.Profile;
 import android.provider.ContactsContract.RawContacts;
-import android.support.annotation.Nullable;
-import android.database.sqlite.SQLiteDatabase;
-import android.net.Uri;
 import android.util.Log;
 
+import androidx.annotation.Nullable;
+
 import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
 
 import junit.framework.Assert;
diff --git a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
index d20b9b3..9f9ef00 100644
--- a/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
+++ b/tests/src/com/android/providers/contacts/VoicemailProviderTest.java
@@ -21,10 +21,8 @@
 
 import android.content.ContentUris;
 import android.content.ContentValues;
-import android.database.ContentObserver;
 import android.database.Cursor;
 import android.net.Uri;
-import android.os.Handler;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.provider.CallLog;
@@ -741,28 +739,6 @@
         assertStoredValues(uri, values);
     }
 
-    public void testStatusUpdate_observerNotified() throws Exception {
-        Uri uri = insertTestStatusEntry();
-        ContentValues values = getTestStatusValues();
-        values.put(Status.DATA_CHANNEL_STATE, Status.DATA_CHANNEL_STATE_NO_CONNECTION);
-        values.put(Status.NOTIFICATION_CHANNEL_STATE,
-            Status.NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING);
-        values.put(Status.SOURCE_TYPE,
-            "vvm_type_test2");
-        Boolean[] observerTriggered = new Boolean[]{false};
-        mResolver.registerContentObserver(Status.CONTENT_URI, true,
-            new ContentObserver(new Handler()) {
-                @Override
-                public void onChange(boolean selfChange, Uri uri) {
-                    observerTriggered[0] = true;
-                }
-            });
-
-        mResolver.update(uri, values, null, null);
-
-        assertTrue(observerTriggered[0]);
-    }
-
     public void testStatusUpsert() throws Exception {
         ContentValues values = getTestStatusValues();
         mResolver.insert(statusUri(), values);
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 301902a..09a0b78 100644
--- a/tests/src/com/android/providers/contacts/aggregation/util/ContactMatcherTest.java
+++ b/tests/src/com/android/providers/contacts/aggregation/util/ContactMatcherTest.java
@@ -16,12 +16,12 @@
 package com.android.providers.contacts.aggregation.util;
 
 import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
+import com.android.providers.contacts.FixedAndroidTestCase;
 
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
 @SmallTest
-public class ContactMatcherTest extends AndroidTestCase {
+public class ContactMatcherTest extends FixedAndroidTestCase {
 
     public void testMatchName_invalidHexDecimal() {
         final ContactMatcher matcher = new ContactMatcher();
diff --git a/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java b/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java
index 99ff9a1..c068459 100644
--- a/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java
+++ b/tests/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuardTest.java
@@ -24,7 +24,6 @@
 import android.os.UserManager;
 import android.provider.ContactsContract;
 import android.provider.ContactsContract.Directory;
-import android.test.AndroidTestCase;
 import android.test.mock.MockContext;
 import android.test.suitebuilder.annotation.SmallTest;
 
@@ -36,12 +35,14 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import com.android.providers.contacts.FixedAndroidTestCase;
+
 
 /**
  * Unit tests for {@link EnterprisePolicyGuard}.
  */
 @SmallTest
-public class EnterprisePolicyGuardTest extends AndroidTestCase {
+public class EnterprisePolicyGuardTest extends FixedAndroidTestCase {
     private static final String SYSTEM_PROPERTY_DEXMAKER_DEXCACHE = "dexmaker.dexcache";
 
     private static final int CONTACT_ID = 10;
diff --git a/tests/src/com/android/providers/contacts/sqlite/DatabaseAnalyzerTest.java b/tests/src/com/android/providers/contacts/sqlite/DatabaseAnalyzerTest.java
index 568e1e8..8367ef5 100644
--- a/tests/src/com/android/providers/contacts/sqlite/DatabaseAnalyzerTest.java
+++ b/tests/src/com/android/providers/contacts/sqlite/DatabaseAnalyzerTest.java
@@ -16,14 +16,14 @@
 
 package com.android.providers.contacts.sqlite;
 
-import android.test.AndroidTestCase;
 
 import com.android.providers.contacts.ContactsDatabaseHelper;
+import com.android.providers.contacts.FixedAndroidTestCase;
 import com.android.providers.contacts.TestUtils;
 
 import java.util.List;
 
-public class DatabaseAnalyzerTest extends AndroidTestCase {
+public class DatabaseAnalyzerTest extends FixedAndroidTestCase {
     public void testFindTableViewsAllowingColumns() {
         final ContactsDatabaseHelper dbh =
                 ContactsDatabaseHelper.getNewInstanceForTest(getContext(),
diff --git a/tests/src/com/android/providers/contacts/sqlite/SqlCheckerTest.java b/tests/src/com/android/providers/contacts/sqlite/SqlCheckerTest.java
index ee2b5be..b69b427 100644
--- a/tests/src/com/android/providers/contacts/sqlite/SqlCheckerTest.java
+++ b/tests/src/com/android/providers/contacts/sqlite/SqlCheckerTest.java
@@ -15,16 +15,16 @@
  */
 package com.android.providers.contacts.sqlite;
 
-import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
 
+import com.android.providers.contacts.FixedAndroidTestCase;
 import com.android.providers.contacts.sqlite.SqlChecker.InvalidSqlException;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-public class SqlCheckerTest extends AndroidTestCase {
+public class SqlCheckerTest extends FixedAndroidTestCase {
     private ArrayList<String> getTokens(String sql) {
         final ArrayList<String> tokens = new ArrayList<>();
 
diff --git a/tests/src/com/android/providers/contacts/util/SelectionBuilderTest.java b/tests/src/com/android/providers/contacts/util/SelectionBuilderTest.java
index 7adbeca..4615fbd 100644
--- a/tests/src/com/android/providers/contacts/util/SelectionBuilderTest.java
+++ b/tests/src/com/android/providers/contacts/util/SelectionBuilderTest.java
@@ -16,14 +16,15 @@
 
 package com.android.providers.contacts.util;
 
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.providers.contacts.FixedAndroidTestCase;
+
 /**
  * Unit tests for {@link SelectionBuilder}.
  */
 @SmallTest
-public class SelectionBuilderTest extends AndroidTestCase {
+public class SelectionBuilderTest extends FixedAndroidTestCase {
     public void testEmptyClauses() {
         assertEquals(null, new SelectionBuilder(null).build());
         assertEquals(null, new SelectionBuilder("").build());
diff --git a/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java b/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java
index 329e6e2..d2a7b14 100644
--- a/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java
+++ b/tests/src/com/android/providers/contacts/util/TypedUriMatcherImplTest.java
@@ -17,9 +17,10 @@
 package com.android.providers.contacts.util;
 
 import android.net.Uri;
-import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import com.android.providers.contacts.FixedAndroidTestCase;
+
 /**
  * Unit tests for {@link TypedUriMatcherImpl}.
  * Run the test like this:
@@ -28,7 +29,7 @@
  * </code>
  */
 @SmallTest
-public class TypedUriMatcherImplTest extends AndroidTestCase {
+public class TypedUriMatcherImplTest extends FixedAndroidTestCase {
     /** URI type used for testing. */
     private static enum TestUriType implements UriType {
         NO_MATCH(null),
diff --git a/tests/src/com/android/providers/contacts/util/UserUtilsTest.java b/tests/src/com/android/providers/contacts/util/UserUtilsTest.java
index 611ad3f..93613cf 100644
--- a/tests/src/com/android/providers/contacts/util/UserUtilsTest.java
+++ b/tests/src/com/android/providers/contacts/util/UserUtilsTest.java
@@ -15,21 +15,19 @@
  */
 package com.android.providers.contacts.util;
 
-import com.android.providers.contacts.ContactsActor;
-import com.android.providers.contacts.ContactsActor.MockUserManager;
-import com.android.providers.contacts.SynchronousContactsProvider2;
-
-import android.content.ContentProvider;
-import android.content.Context;
-import android.os.UserManager;
-import android.provider.ContactsContract;
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-
 import static com.android.providers.contacts.ContactsActor.PACKAGE_GREY;
 
+import android.content.Context;
+import android.provider.ContactsContract;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.providers.contacts.ContactsActor;
+import com.android.providers.contacts.ContactsActor.MockUserManager;
+import com.android.providers.contacts.FixedAndroidTestCase;
+import com.android.providers.contacts.SynchronousContactsProvider2;
+
 @SmallTest
-public class UserUtilsTest extends AndroidTestCase {
+public class UserUtilsTest extends FixedAndroidTestCase {
 
     protected ContactsActor mActor;
 
diff --git a/tests2/Android.bp b/tests2/Android.bp
index b214ac0..9a2351a 100644
--- a/tests2/Android.bp
+++ b/tests2/Android.bp
@@ -18,7 +18,7 @@
     name: "ContactsProviderTests2",
     static_libs: [
         "ContactsProviderTestUtils",
-        "android-support-test",
+        "androidx.test.rules",
         "mockito-target-minus-junit4",
     ],
     libs: [
diff --git a/tests2/AndroidManifest.xml b/tests2/AndroidManifest.xml
index 7678bd2..fc00251 100644
--- a/tests2/AndroidManifest.xml
+++ b/tests2/AndroidManifest.xml
@@ -30,6 +30,6 @@
     </application>
 
     <instrumentation
-        android:name="android.support.test.runner.AndroidJUnitRunner"
+        android:name="androidx.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.providers.contacts.tests2" />
 </manifest>
diff --git a/tests2/AndroidTest.xml b/tests2/AndroidTest.xml
index 29fdc83..957350b 100644
--- a/tests2/AndroidTest.xml
+++ b/tests2/AndroidTest.xml
@@ -20,9 +20,8 @@
 
     <option name="test-suite-tag" value="apct" />
     <option name="test-tag" value="ContactsProviderTests2" />
-    <test class="com.android.tradefed.testtype.InstrumentationTest" >
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.providers.contacts.tests2" />
-        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
 </configuration>
diff --git a/tests2/src/com/android/providers/contacts/tests2/AllUriTest.java b/tests2/src/com/android/providers/contacts/tests2/AllUriTest.java
index 2aa6a61..30fd3be 100644
--- a/tests2/src/com/android/providers/contacts/tests2/AllUriTest.java
+++ b/tests2/src/com/android/providers/contacts/tests2/AllUriTest.java
@@ -371,14 +371,18 @@
     public void testSelect() {
         for (String[] path : URIs) {
             if (!supportsQuery(path)) continue;
-            final Uri uri = getUri(path);
+            try {
+                final Uri uri = getUri(path);
 
-            checkQueryExecutable(uri, // uri
-                    null, // projection
-                    null, // selection
-                    null, // selection args
-                    null // sort order
-                    );
+                checkQueryExecutable(uri, // uri
+                        null, // projection
+                        null, // selection
+                        null, // selection args
+                        null // sort order
+                        );
+            } catch (Throwable th) {
+                addFailure("Failed: URI=" + path[0] + " Message=" + th.getMessage(), th);
+            }
         }
         failIfFailed();
     }
@@ -386,12 +390,16 @@
     public void testNoHiddenColumns() {
         for (String[] path : URIs) {
             if (!supportsQuery(path)) continue;
-            final Uri uri = getUri(path);
+            try {
+                final Uri uri = getUri(path);
 
-            for (String column : getColumns(uri)) {
-                if (column.toLowerCase().startsWith(ContactsContract.HIDDEN_COLUMN_PREFIX)) {
-                    addFailure("Uri " + uri + " returned hidden column " + column, null);
+                for (String column : getColumns(uri)) {
+                    if (column.toLowerCase().startsWith(ContactsContract.HIDDEN_COLUMN_PREFIX)) {
+                        addFailure("Uri " + uri + " returned hidden column " + column, null);
+                    }
                 }
+            } catch (Throwable th) {
+                addFailure("Failed: URI=" + path[0] + " Message=" + th.getMessage(), th);
             }
         }
         failIfFailed();
@@ -649,41 +657,45 @@
         for (String[] path : URIs) {
             final Uri uri = getUri(path);
 
-            cv.clear();
-            if (supportsQuery(path)) {
-                cv.put(getColumns(uri)[0], 1);
-            } else {
-                cv.put("_id", 1);
-            }
-            if (uri.toString().contains("syncstate")) {
-                cv.put(SyncState.ACCOUNT_NAME, "abc");
-                cv.put(SyncState.ACCOUNT_TYPE, "def");
-            }
-
-            checkExecutable("insert", uri, supportsInsert(path), () -> {
-                final Uri newUri = mResolver.insert(uri, cv);
-                if (newUri == null) {
-                    addFailure("Insert for '" + uri + "' returned null.", null);
+            try {
+                cv.clear();
+                if (supportsQuery(path)) {
+                    cv.put(getColumns(uri)[0], 1);
                 } else {
-                    // "profile/raw_contacts/#" is missing update support.  too late to add, so
-                    // just skip.
-                    if (!newUri.toString().startsWith(
-                            "content://com.android.contacts/profile/raw_contacts/")) {
-                        checkExecutable("insert -> update", newUri, true, () -> {
-                            mResolver.update(newUri, cv, null, null);
+                    cv.put("_id", 1);
+                }
+                if (uri.toString().contains("syncstate")) {
+                    cv.put(SyncState.ACCOUNT_NAME, "abc");
+                    cv.put(SyncState.ACCOUNT_TYPE, "def");
+                }
+
+                checkExecutable("insert", uri, supportsInsert(path), () -> {
+                    final Uri newUri = mResolver.insert(uri, cv);
+                    if (newUri == null) {
+                        addFailure("Insert for '" + uri + "' returned null.", null);
+                    } else {
+                        // "profile/raw_contacts/#" is missing update support.  too late to add, so
+                        // just skip.
+                        if (!newUri.toString().startsWith(
+                                "content://com.android.contacts/profile/raw_contacts/")) {
+                            checkExecutable("insert -> update", newUri, true, () -> {
+                                mResolver.update(newUri, cv, null, null);
+                            });
+                        }
+                        checkExecutable("insert -> delete", newUri, true, () -> {
+                            mResolver.delete(newUri, null, null);
                         });
                     }
-                    checkExecutable("insert -> delete", newUri, true, () -> {
-                        mResolver.delete(newUri, null, null);
-                    });
-                }
-            });
-            checkExecutable("update", uri, supportsUpdate(path), () -> {
-                mResolver.update(uri, cv, "1=2", null);
-            });
-            checkExecutable("delete", uri, supportsDelete(path), () -> {
-                mResolver.delete(uri, "1=2", null);
-            });
+                });
+                checkExecutable("update", uri, supportsUpdate(path), () -> {
+                    mResolver.update(uri, cv, "1=2", null);
+                });
+                checkExecutable("delete", uri, supportsDelete(path), () -> {
+                    mResolver.delete(uri, "1=2", null);
+                });
+            } catch (Throwable th) {
+                addFailure("Failed: URI=" + uri + " Message=" + th.getMessage(), th);
+            }
         }
         failIfFailed();
     }