Merge mainline-release 6664920 to master - DO NOT MERGE

Merged-In: Ie5bbc8016e0bbb155e411f164c755f1905d49295
Change-Id: I3aa42cc7bd77e7ee42ed7bdbd267e346b691f923
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7c57599..327d0a2 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -15,80 +15,75 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-        package="com.android.server.telecom"
-        coreApp="true"
-        android:sharedUserId="android.uid.system">
+     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+     package="com.android.server.telecom"
+     coreApp="true"
+     android:sharedUserId="android.uid.system">
 
-    <protected-broadcast android:name="android.intent.action.SHOW_MISSED_CALLS_NOTIFICATION" />
-    <protected-broadcast android:name="com.android.server.telecom.MESSAGE_SENT" />
+    <protected-broadcast android:name="android.intent.action.SHOW_MISSED_CALLS_NOTIFICATION"/>
+    <protected-broadcast android:name="com.android.server.telecom.MESSAGE_SENT"/>
 
 
     <!-- Prevents the activity manager from delaying any activity-start
          requests by this package, including requests immediately after
          the user presses "home". -->
-    <uses-permission android:name="android.permission.BIND_CONNECTION_SERVICE" />
-    <uses-permission android:name="android.permission.BIND_INCALL_SERVICE" />
-    <uses-permission android:name="android.permission.BLUETOOTH" />
-    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
-    <uses-permission android:name="android.permission.BROADCAST_CALLLOG_INFO" />
-    <uses-permission android:name="android.permission.BROADCAST_PHONE_ACCOUNT_REGISTRATION" />
-    <uses-permission android:name="android.permission.CALL_PRIVILEGED" />
-    <uses-permission android:name="android.permission.HANDLE_CALL_INTENT" />
-    <uses-permission android:name="android.permission.HANDLE_CAR_MODE_CHANGES" />
-    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
-    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
-    <uses-permission android:name="android.permission.MANAGE_USERS" />
-    <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
-    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.BIND_CONNECTION_SERVICE"/>
+    <uses-permission android:name="android.permission.BIND_INCALL_SERVICE"/>
+    <uses-permission android:name="android.permission.BLUETOOTH"/>
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+    <uses-permission android:name="android.permission.BROADCAST_CALLLOG_INFO"/>
+    <uses-permission android:name="android.permission.BROADCAST_PHONE_ACCOUNT_REGISTRATION"/>
+    <uses-permission android:name="android.permission.CALL_PRIVILEGED"/>
+    <uses-permission android:name="android.permission.HANDLE_CALL_INTENT"/>
+    <uses-permission android:name="android.permission.HANDLE_CAR_MODE_CHANGES"/>
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS"/>
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
+    <uses-permission android:name="android.permission.MANAGE_USERS"/>
+    <uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS"/>
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
     <!-- Required to determine source of ongoing audio recordings. -->
-    <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
-    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
-    <uses-permission android:name="android.permission.READ_CALL_LOG" />
-    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-    <uses-permission android:name="android.permission.SEND_SMS" />
-    <uses-permission android:name="android.permission.STOP_APP_SWITCHES" />
-    <uses-permission android:name="android.permission.VIBRATE" />
-    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.READ_BLOCKED_NUMBERS" />
-    <uses-permission android:name="android.permission.WRITE_BLOCKED_NUMBERS" />
-    <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING"/>
+    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.READ_CALL_LOG"/>
+    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG"/>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.SEND_SMS"/>
+    <uses-permission android:name="android.permission.STOP_APP_SWITCHES"/>
+    <uses-permission android:name="android.permission.VIBRATE"/>
+    <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
+    <uses-permission android:name="android.permission.WAKE_LOCK"/>
+    <uses-permission android:name="android.permission.READ_BLOCKED_NUMBERS"/>
+    <uses-permission android:name="android.permission.WRITE_BLOCKED_NUMBERS"/>
+    <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME"/>
 
-    <permission
-            android:name="android.permission.BROADCAST_CALLLOG_INFO"
-            android:label="Broadcast the call type/duration information"
-            android:protectionLevel="signature|system"/>
+    <permission android:name="android.permission.BROADCAST_CALLLOG_INFO"
+         android:label="Broadcast the call type/duration information"
+         android:protectionLevel="signature|system"/>
 
-    <permission
-            android:name="android.permission.PROCESS_CALLLOG_INFO"
-            android:label="Register to handle the broadcasted call type/duration information"
-            android:protectionLevel="signature|system"/>
+    <permission android:name="android.permission.PROCESS_CALLLOG_INFO"
+         android:label="Register to handle the broadcasted call type/duration information"
+         android:protectionLevel="signature|system"/>
 
-    <permission
-            android:name="android.permission.BROADCAST_PHONE_ACCOUNT_REGISTRATION"
-            android:label="Broadcast phone account registration"
-            android:protectionLevel="signature|system"/>
+    <permission android:name="android.permission.BROADCAST_PHONE_ACCOUNT_REGISTRATION"
+         android:label="Broadcast phone account registration"
+         android:protectionLevel="signature|system"/>
 
-    <permission
-            android:name="android.permission.PROCESS_PHONE_ACCOUNT_REGISTRATION"
-            android:label="Process phone account registration"
-            android:protectionLevel="signature|system"/>
+    <permission android:name="android.permission.PROCESS_PHONE_ACCOUNT_REGISTRATION"
+         android:label="Process phone account registration"
+         android:protectionLevel="signature|system"/>
 
-    <permission
-            android:name="android.permission.HANDLE_CALL_INTENT"
-            android:label="Protects handling the call intent via the TelecomManager API."
-            android:protectionLevel="signature|system"/>
+    <permission android:name="android.permission.HANDLE_CALL_INTENT"
+         android:label="Protects handling the call intent via the TelecomManager API."
+         android:protectionLevel="signature|system"/>
 
     <application android:label="@string/telecommAppLabel"
-            android:icon="@mipmap/ic_launcher_phone"
-            android:allowBackup="false"
-            android:supportsRtl="true"
-            android:process="system"
-            android:usesCleartextTraffic="false"
-            android:defaultToDeviceProtectedStorage="true"
-            android:directBootAware="true">
+         android:icon="@mipmap/ic_launcher_phone"
+         android:allowBackup="false"
+         android:supportsRtl="true"
+         android:process="system"
+         android:usesCleartextTraffic="false"
+         android:defaultToDeviceProtectedStorage="true"
+         android:directBootAware="true">
 
         <!-- CALL vs CALL_PRIVILEGED vs CALL_EMERGENCY
              We have three different intents through which a call can be initiated each with its
@@ -104,60 +99,61 @@
 
         <!-- Activity that displays UI for managing blocked numbers. -->
         <activity android:name=".settings.BlockedNumbersActivity"
-                  android:label="@string/blocked_numbers"
-                  android:configChanges="orientation|screenSize|keyboardHidden"
-                  android:theme="@style/Theme.Telecom.BlockedNumbers"
-                  android:process=":ui"
-                  android:exported="true">
+             android:label="@string/blocked_numbers"
+             android:configChanges="orientation|screenSize|keyboardHidden"
+             android:theme="@style/Theme.Telecom.BlockedNumbers"
+             android:process=":ui"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.telecom.action.MANAGE_BLOCKED_NUMBERS" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.telecom.action.MANAGE_BLOCKED_NUMBERS"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
 
         <activity android:name=".settings.CallBlockDisabledActivity"
-                android:configChanges="keyboardHidden|orientation|screenSize"
-                android:excludeFromRecents="true"
-                android:launchMode="singleInstance"
-                android:theme="@style/Theme.Telecomm.Transparent"
-                android:process=":ui">
+             android:configChanges="keyboardHidden|orientation|screenSize"
+             android:excludeFromRecents="true"
+             android:launchMode="singleInstance"
+             android:theme="@style/Theme.Telecomm.Transparent"
+             android:process=":ui">
         </activity>
 
         <!-- Activity that starts the outgoing call process by listening to CALL intent which
-             contain contact information in the intent's data. CallActivity handles any data
-             URL with the schemes "tel", "sip", and "voicemail". It also handles URLs linked to
-             contacts provider entries. Any data not fitting the schema described is ignored. -->
+                         contain contact information in the intent's data. CallActivity handles any data
+                         URL with the schemes "tel", "sip", and "voicemail". It also handles URLs linked to
+                         contacts provider entries. Any data not fitting the schema described is ignored. -->
         <activity android:name=".components.UserCallActivity"
-                android:label="@string/userCallActivityLabel"
-                android:theme="@style/Theme.Telecomm.Transparent"
-                android:permission="android.permission.CALL_PHONE"
-                android:excludeFromRecents="true"
-                android:process=":ui">
+             android:label="@string/userCallActivityLabel"
+             android:theme="@style/Theme.Telecomm.Transparent"
+             android:permission="android.permission.CALL_PHONE"
+             android:excludeFromRecents="true"
+             android:process=":ui"
+             android:exported="true">
             <!-- CALL action intent filters for the various ways of initiating an outgoing call. -->
             <intent-filter>
-                <action android:name="android.intent.action.CALL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="tel" />
+                <action android:name="android.intent.action.CALL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="tel"/>
             </intent-filter>
             <!-- Specify an icon for SIP calls so that quick contacts widget shows a special SIP
-                 icon for calls to SIP addresses. -->
+                                 icon for calls to SIP addresses. -->
             <intent-filter android:icon="@drawable/ic_launcher_sip_call">
-                <action android:name="android.intent.action.CALL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="sip" />
+                <action android:name="android.intent.action.CALL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="sip"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.CALL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="voicemail" />
+                <action android:name="android.intent.action.CALL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="voicemail"/>
             </intent-filter>
             <!-- Omit default category below so that all Intents sent to this filter must be
-                 explicit. -->
+                                 explicit. -->
             <intent-filter>
-                <action android:name="android.intent.action.CALL" />
-                <data android:mimeType="vnd.android.cursor.item/phone" />
-                <data android:mimeType="vnd.android.cursor.item/phone_v2" />
-                <data android:mimeType="vnd.android.cursor.item/person" />
+                <action android:name="android.intent.action.CALL"/>
+                <data android:mimeType="vnd.android.cursor.item/phone"/>
+                <data android:mimeType="vnd.android.cursor.item/phone_v2"/>
+                <data android:mimeType="vnd.android.cursor.item/person"/>
             </intent-filter>
         </activity>
 
@@ -167,30 +163,30 @@
              processed. High priority of 1000 is used in all intent filters to prevent anything but
              the system from processing this intent (b/8871505). -->
         <activity-alias android:name="PrivilegedCallActivity"
-                android:targetActivity=".components.UserCallActivity"
-                android:permission="android.permission.CALL_PRIVILEGED"
-                android:process=":ui">
+             android:targetActivity=".components.UserCallActivity"
+             android:permission="android.permission.CALL_PRIVILEGED"
+             android:process=":ui">
             <intent-filter android:priority="1000">
-                <action android:name="android.intent.action.CALL_PRIVILEGED" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="tel" />
+                <action android:name="android.intent.action.CALL_PRIVILEGED"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="tel"/>
             </intent-filter>
             <intent-filter android:priority="1000"
-                    android:icon="@drawable/ic_launcher_sip_call">
-                <action android:name="android.intent.action.CALL_PRIVILEGED" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="sip" />
+                 android:icon="@drawable/ic_launcher_sip_call">
+                <action android:name="android.intent.action.CALL_PRIVILEGED"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="sip"/>
             </intent-filter>
             <intent-filter android:priority="1000">
-                <action android:name="android.intent.action.CALL_PRIVILEGED" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="voicemail" />
+                <action android:name="android.intent.action.CALL_PRIVILEGED"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="voicemail"/>
             </intent-filter>
             <intent-filter android:priority="1000">
-                <action android:name="android.intent.action.CALL_PRIVILEGED" />
-                <data android:mimeType="vnd.android.cursor.item/phone" />
-                <data android:mimeType="vnd.android.cursor.item/phone_v2" />
-                <data android:mimeType="vnd.android.cursor.item/person" />
+                <action android:name="android.intent.action.CALL_PRIVILEGED"/>
+                <data android:mimeType="vnd.android.cursor.item/phone"/>
+                <data android:mimeType="vnd.android.cursor.item/phone_v2"/>
+                <data android:mimeType="vnd.android.cursor.item/person"/>
             </intent-filter>
         </activity-alias>
 
@@ -200,123 +196,129 @@
              1000 is used in all intent filters to prevent anything but the system from processing
              this intent (b/8871505). -->
         <!-- TODO: Is there really a notion of an emergency SIP number? If not, can
-             that scheme be removed from this activity? -->
+                         that scheme be removed from this activity? -->
         <activity-alias android:name="EmergencyCallActivity"
-                android:targetActivity=".components.UserCallActivity"
-                android:permission="android.permission.CALL_PRIVILEGED"
-                android:process=":ui">
+             android:targetActivity=".components.UserCallActivity"
+             android:permission="android.permission.CALL_PRIVILEGED"
+             android:process=":ui">
             <intent-filter android:priority="1000">
-                <action android:name="android.intent.action.CALL_EMERGENCY" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="tel" />
+                <action android:name="android.intent.action.CALL_EMERGENCY"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="tel"/>
             </intent-filter>
             <intent-filter android:priority="1000"
-                    android:icon="@drawable/ic_launcher_sip_call">
-                <action android:name="android.intent.action.CALL_EMERGENCY" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="sip" />
+                 android:icon="@drawable/ic_launcher_sip_call">
+                <action android:name="android.intent.action.CALL_EMERGENCY"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="sip"/>
             </intent-filter>
             <intent-filter android:priority="1000">
-                <action android:name="android.intent.action.CALL_EMERGENCY" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="voicemail" />
+                <action android:name="android.intent.action.CALL_EMERGENCY"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="voicemail"/>
             </intent-filter>
             <intent-filter android:priority="1000">
-                <action android:name="android.intent.action.CALL_EMERGENCY" />
-                <data android:mimeType="vnd.android.cursor.item/phone" />
-                <data android:mimeType="vnd.android.cursor.item/phone_v2" />
-                <data android:mimeType="vnd.android.cursor.item/person" />
+                <action android:name="android.intent.action.CALL_EMERGENCY"/>
+                <data android:mimeType="vnd.android.cursor.item/phone"/>
+                <data android:mimeType="vnd.android.cursor.item/phone_v2"/>
+                <data android:mimeType="vnd.android.cursor.item/person"/>
             </intent-filter>
         </activity-alias>
 
-        <receiver android:name=".components.TelecomBroadcastReceiver" android:exported="false"
-                android:process="system">
+        <receiver android:name=".components.TelecomBroadcastReceiver"
+             android:exported="false"
+             android:process="system">
             <intent-filter>
-                <action android:name="com.android.server.telecom.ACTION_CLEAR_MISSED_CALLS" />
-                <action android:name="com.android.server.telecom.ACTION_CALL_BACK_FROM_NOTIFICATION" />
-                <action android:name="com.android.server.telecom.ACTION_SEND_SMS_FROM_NOTIFICATION" />
-                <action android:name="com.android.server.telecom.ACTION_ANSWER_FROM_NOTIFICATION" />
-                <action android:name="com.android.server.telecom.ACTION_REJECT_FROM_NOTIFICATION" />
-                <action android:name="com.android.server.telecom.PROCEED_WITH_CALL" />
-                <action android:name="com.android.server.telecom.CANCEL_CALL" />
-                <action android:name="com.android.server.telecom.PROCEED_WITH_REDIRECTED_CALL" />
-                <action android:name="com.android.server.telecom.CANCEL_REDIRECTED_CALL" />
+                <action android:name="com.android.server.telecom.ACTION_CLEAR_MISSED_CALLS"/>
+                <action android:name="com.android.server.telecom.ACTION_CALL_BACK_FROM_NOTIFICATION"/>
+                <action android:name="com.android.server.telecom.ACTION_SEND_SMS_FROM_NOTIFICATION"/>
+                <action android:name="com.android.server.telecom.ACTION_ANSWER_FROM_NOTIFICATION"/>
+                <action android:name="com.android.server.telecom.ACTION_REJECT_FROM_NOTIFICATION"/>
+                <action android:name="com.android.server.telecom.PROCEED_WITH_CALL"/>
+                <action android:name="com.android.server.telecom.CANCEL_CALL"/>
+                <action android:name="com.android.server.telecom.PROCEED_WITH_REDIRECTED_CALL"/>
+                <action android:name="com.android.server.telecom.CANCEL_REDIRECTED_CALL"/>
             </intent-filter>
         </receiver>
 
         <receiver android:name=".components.AppUninstallBroadcastReceiver"
-                android:process="system">
+             android:process="system"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
-                <data android:scheme="package" />
+                <action android:name="android.intent.action.PACKAGE_FULLY_REMOVED"/>
+                <data android:scheme="package"/>
             </intent-filter>
         </receiver>
 
         <activity android:name=".RespondViaSmsSettings"
-                  android:label="@string/respond_via_sms_setting_title"
-                  android:configChanges="orientation|screenSize|keyboardHidden"
-                  android:theme="@style/Theme.Telecom.DialerSettings"
-                  android:process=":ui">
+             android:label="@string/respond_via_sms_setting_title"
+             android:configChanges="orientation|screenSize|keyboardHidden"
+             android:theme="@style/Theme.Telecom.DialerSettings"
+             android:process=":ui"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <action android:name="android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.intent.action.MAIN"/>
+                <action android:name="android.telecom.action.SHOW_RESPOND_VIA_SMS_SETTINGS"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
 
         <activity android:name=".settings.EnableAccountPreferenceActivity"
-                  android:label="@string/enable_account_preference_title"
-                  android:configChanges="orientation|screenSize|keyboardHidden"
-                  android:theme="@style/Theme.Telecom.DialerSettings"
-                  android:process=":ui">
+             android:label="@string/enable_account_preference_title"
+             android:configChanges="orientation|screenSize|keyboardHidden"
+             android:theme="@style/Theme.Telecom.DialerSettings"
+             android:process=":ui"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
 
         <activity android:name=".components.ErrorDialogActivity"
-                android:configChanges="orientation|screenSize|keyboardHidden"
-                android:excludeFromRecents="true"
-                android:launchMode="singleInstance"
-                android:theme="@style/Theme.Telecomm.Transparent"
-                android:process=":ui">
+             android:configChanges="orientation|screenSize|keyboardHidden"
+             android:excludeFromRecents="true"
+             android:launchMode="singleInstance"
+             android:theme="@style/Theme.Telecomm.Transparent"
+             android:process=":ui">
         </activity>
 
         <activity android:name=".ui.ConfirmCallDialogActivity"
-                android:configChanges="orientation|screenSize|keyboardHidden"
-                android:excludeFromRecents="true"
-                android:launchMode="singleInstance"
-                android:theme="@style/Theme.Telecomm.Transparent"
-                android:process=":ui">
+             android:configChanges="orientation|screenSize|keyboardHidden"
+             android:excludeFromRecents="true"
+             android:launchMode="singleInstance"
+             android:theme="@style/Theme.Telecomm.Transparent"
+             android:process=":ui">
         </activity>
 
         <activity android:name=".ui.CallRedirectionTimeoutDialogActivity"
-                  android:configChanges="orientation|screenSize|keyboardHidden"
-                  android:excludeFromRecents="true"
-                  android:launchMode="singleInstance"
-                  android:theme="@style/Theme.Telecomm.Transparent"
-                  android:process=":ui">
+             android:configChanges="orientation|screenSize|keyboardHidden"
+             android:excludeFromRecents="true"
+             android:launchMode="singleInstance"
+             android:theme="@style/Theme.Telecomm.Transparent"
+             android:process=":ui">
         </activity>
 
         <activity android:name=".ui.TelecomDeveloperMenu"
-                  android:label="@string/developer_title"
-                  android:exported="false"
-                  android:process=":ui" />
+             android:label="@string/developer_title"
+             android:exported="false"
+             android:process=":ui"/>
 
         <service android:name=".components.BluetoothPhoneService"
-                android:singleUser="true"
-                android:process="system">
+             android:singleUser="true"
+             android:process="system"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.bluetooth.IBluetoothHeadsetPhone" />
+                <action android:name="android.bluetooth.IBluetoothHeadsetPhone"/>
             </intent-filter>
         </service>
 
         <service android:name=".components.TelecomService"
-                android:singleUser="true"
-                android:process="system">
+             android:singleUser="true"
+             android:process="system"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.telecom.ITelecomService" />
+                <action android:name="android.telecom.ITelecomService"/>
             </intent-filter>
         </service>
 
diff --git a/OWNERS b/OWNERS
index 94409ef..39be2c1 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,6 @@
 breadley@google.com
 hallliu@google.com
 tgunn@google.com
-paulye@google.com
+xiaotonj@google.com
+shuoq@google.com
+rgreenwalt@google.com
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 75feeb6..02bd056 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -15,6 +15,14 @@
           "exclude-annotation": "androidx.test.filters.FlakyTest"
         }
       ]
+    },
+    {
+      "name": "CtsTelecomTestCases",
+      "options": [
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        }
+      ]
     }
   ]
 }
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 87bde1c..c434ecc 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -47,7 +47,7 @@
     <string name="respond_via_sms_failure_format" msgid="5198680980054596391">"Fehler beim Senden der Nachricht an <xliff:g id="PHONE_NUMBER">%s</xliff:g>"</string>
     <string name="enable_account_preference_title" msgid="6949224486748457976">"Anrufkonten"</string>
     <string name="outgoing_call_not_allowed_user_restriction" msgid="3424338207838851646">"Es sind nur Notrufe erlaubt."</string>
-    <string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"Diese App darf ohne die Berechtigung \"Standard-App für Telefonie\" keine ausgehenden Anrufe tätigen."</string>
+    <string name="outgoing_call_not_allowed_no_permission" msgid="8590468836581488679">"Diese App darf ohne die Berechtigung \"Telefon-App\" keine ausgehenden Anrufe tätigen."</string>
     <string name="outgoing_call_error_no_phone_number_supplied" msgid="7665135102566099778">"Gib eine gültige Nummer ein."</string>
     <string name="duplicate_video_call_not_allowed" msgid="5754746140185781159">"Der Anruf kann momentan nicht hinzugefügt werden."</string>
     <string name="no_vm_number" msgid="2179959110602180844">"Fehlende Mailbox-Nummer"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 3acab47..e157655 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -112,7 +112,7 @@
     <string name="phone_settings_private_num_summary_txt" msgid="6755758240544021037">"番号非通知の発信者をブロック"</string>
     <string name="phone_settings_payphone_txt" msgid="5003987966052543965">"公衆電話"</string>
     <string name="phone_settings_payphone_summary_txt" msgid="3936631076065563665">"公衆電話からの着信をブロック"</string>
-    <string name="phone_settings_unknown_txt" msgid="3577926178354772728">"不明"</string>
+    <string name="phone_settings_unknown_txt" msgid="3577926178354772728">"不明な発信者"</string>
     <string name="phone_settings_unknown_summary_txt" msgid="5446657192535779645">"不明な発信者からの着信をブロック"</string>
     <string name="phone_strings_call_blocking_turned_off_notification_title_txt" msgid="2895809176537908791">"着信のブロック"</string>
     <string name="phone_strings_call_blocking_turned_off_notification_text_txt" msgid="1713632946174016619">"着信のブロックを無効にしました"</string>
diff --git a/res/xml/activity_blocked_numbers.xml b/res/xml/activity_blocked_numbers.xml
index f884ec9..df1a759 100644
--- a/res/xml/activity_blocked_numbers.xml
+++ b/res/xml/activity_blocked_numbers.xml
@@ -75,7 +75,7 @@
                     <TextView
                             android:id="@+id/add_blocked"
                             android:layout_width="wrap_content"
-                            android:layout_height="wrap_content"
+                            android:layout_height="48dp"
                             android:text="@string/block_number"
                             android:layout_marginBottom="@dimen/blocked_numbers_button_bottom_margin"
                             android:paddingTop="@dimen/blocked_numbers_button_large_padding"
diff --git a/res/xml/enhanced_call_blocking_settings.xml b/res/xml/enhanced_call_blocking_settings.xml
index 32c4c5d..73ed2af 100644
--- a/res/xml/enhanced_call_blocking_settings.xml
+++ b/res/xml/enhanced_call_blocking_settings.xml
@@ -41,8 +41,4 @@
         android:persistent="false"
         android:defaultValue="false"/>
     <!--Add divider to separate this enhanced call blocking settings from other settings-->
-    <Preference
-        android:key="enhanced_call_blocking_divider"
-        android:persistent="false"
-        android:layout="@xml/layout_divider"/>
 </PreferenceScreen>
\ No newline at end of file
diff --git a/src/com/android/server/telecom/Call.java b/src/com/android/server/telecom/Call.java
old mode 100755
new mode 100644
index df6322c..0785502
--- a/src/com/android/server/telecom/Call.java
+++ b/src/com/android/server/telecom/Call.java
@@ -545,7 +545,7 @@
     private ParcelFileDescriptor[] mConnectionServiceToInCallStreams;
 
     /**
-     * True if we're supposed to start this call with RTT, either due to the master switch or due
+     * True if we're supposed to start this call with RTT, either due to the settings switch or due
      * to an extra.
      */
     private boolean mDidRequestToStartWithRtt = false;
@@ -1124,6 +1124,12 @@
                 case CallState.ANSWERED:
                     event = LogUtils.Events.SET_ANSWERED;
                     break;
+                case CallState.AUDIO_PROCESSING:
+                    event = LogUtils.Events.SET_AUDIO_PROCESSING;
+                    break;
+                case CallState.SIMULATED_RINGING:
+                    event = LogUtils.Events.SET_SIMULATED_RINGING;
+                    break;
             }
             if (event != null) {
                 // The string data should be just the tag.
diff --git a/src/com/android/server/telecom/CallAudioRouteStateMachine.java b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
index a562021..69a870f 100644
--- a/src/com/android/server/telecom/CallAudioRouteStateMachine.java
+++ b/src/com/android/server/telecom/CallAudioRouteStateMachine.java
@@ -413,6 +413,8 @@
                     return HANDLED;
                 case SWITCH_SPEAKER:
                 case USER_SWITCH_SPEAKER:
+                    setSpeakerphoneOn(true);
+                    // fall through
                 case SPEAKER_ON:
                     transitionTo(mActiveSpeakerRoute);
                     return HANDLED;
@@ -459,6 +461,8 @@
             switch (msg.what) {
                 case SWITCH_EARPIECE:
                 case USER_SWITCH_EARPIECE:
+                case SPEAKER_ON:
+                    // Ignore speakerphone state changes outside of calls.
                 case SPEAKER_OFF:
                     // Nothing to do here
                     return HANDLED;
@@ -484,7 +488,6 @@
                     return HANDLED;
                 case SWITCH_SPEAKER:
                 case USER_SWITCH_SPEAKER:
-                case SPEAKER_ON:
                     transitionTo(mQuiescentSpeakerRoute);
                     return HANDLED;
                 case SWITCH_FOCUS:
@@ -533,6 +536,7 @@
                     // This may be sent as a confirmation by the BT stack after switch off BT.
                     return HANDLED;
                 case CONNECT_DOCK:
+                    setSpeakerphoneOn(true);
                     sendInternalMessage(SWITCH_SPEAKER);
                     return HANDLED;
                 case DISCONNECT_DOCK:
@@ -611,6 +615,8 @@
                     return HANDLED;
                 case SWITCH_SPEAKER:
                 case USER_SWITCH_SPEAKER:
+                    setSpeakerphoneOn(true);
+                    // fall through
                 case SPEAKER_ON:
                     transitionTo(mActiveSpeakerRoute);
                     return HANDLED;
@@ -677,12 +683,13 @@
                     return HANDLED;
                 case SWITCH_HEADSET:
                 case USER_SWITCH_HEADSET:
+                case SPEAKER_ON:
+                    // Ignore speakerphone state changes outside of calls.
                 case SPEAKER_OFF:
                     // Nothing to do
                     return HANDLED;
                 case SWITCH_SPEAKER:
                 case USER_SWITCH_SPEAKER:
-                case SPEAKER_ON:
                     transitionTo(mQuiescentSpeakerRoute);
                     return HANDLED;
                 case SWITCH_FOCUS:
@@ -725,6 +732,7 @@
                     return HANDLED;
                 case DISCONNECT_WIRED_HEADSET:
                     if (mWasOnSpeaker) {
+                        setSpeakerphoneOn(true);
                         sendInternalMessage(SWITCH_SPEAKER);
                     } else {
                         sendInternalMessage(SWITCH_BASELINE_ROUTE, INCLUDE_BLUETOOTH_IN_BASELINE);
@@ -796,6 +804,7 @@
                     transitionTo(mActiveHeadsetRoute);
                     break;
                 case SWITCH_SPEAKER:
+                    setSpeakerphoneOn(true);
                     transitionTo(mActiveSpeakerRoute);
                     break;
                 default:
@@ -852,6 +861,8 @@
                     mHasUserExplicitlyLeftBluetooth = true;
                     // fall through
                 case SWITCH_SPEAKER:
+                    setSpeakerphoneOn(true);
+                    // fall through
                 case SPEAKER_ON:
                     setBluetoothOff();
                     transitionTo(mActiveSpeakerRoute);
@@ -947,6 +958,8 @@
                     mHasUserExplicitlyLeftBluetooth = true;
                     // fall through
                 case SWITCH_SPEAKER:
+                    setSpeakerphoneOn(true);
+                    // fall through
                 case SPEAKER_ON:
                     transitionTo(mActiveSpeakerRoute);
                     return HANDLED;
@@ -1012,6 +1025,8 @@
                     return HANDLED;
                 case SWITCH_BLUETOOTH:
                 case USER_SWITCH_BLUETOOTH:
+                case SPEAKER_ON:
+                    // Ignore speakerphone state changes outside of calls.
                 case SPEAKER_OFF:
                     // Nothing to do
                     return HANDLED;
@@ -1025,7 +1040,6 @@
                     return HANDLED;
                 case SWITCH_SPEAKER:
                 case USER_SWITCH_SPEAKER:
-                case SPEAKER_ON:
                     transitionTo(mQuiescentSpeakerRoute);
                     return HANDLED;
                 case SWITCH_FOCUS:
@@ -1105,8 +1119,9 @@
         @Override
         public void enter() {
             super.enter();
+            // Don't set speakerphone on here -- we might end up in this state by following
+            // the speaker state that some other app commanded.
             mWasOnSpeaker = true;
-            setSpeakerphoneOn(true);
             CallAudioState newState = new CallAudioState(mIsMuted, ROUTE_SPEAKER,
                     mAvailableRoutes, null, mBluetoothRouteManager.getConnectedDevices());
             setSystemAudioState(newState, true);
@@ -1593,12 +1608,8 @@
     }
 
     private void setSpeakerphoneOn(boolean on) {
-        if (mAudioManager.isSpeakerphoneOn() != on) {
-            Log.i(this, "turning speaker phone %s", on);
-            mAudioManager.setSpeakerphoneOn(on);
-        } else {
-            Log.i(this, "Ignoring speakerphone request -- already %s", on);
-        }
+        Log.i(this, "turning speaker phone %s", on);
+        mAudioManager.setSpeakerphoneOn(on);
         mStatusBarNotifier.notifySpeakerphone(on);
     }
 
diff --git a/src/com/android/server/telecom/CallIdMapper.java b/src/com/android/server/telecom/CallIdMapper.java
index da2c199..2cd5c79 100644
--- a/src/com/android/server/telecom/CallIdMapper.java
+++ b/src/com/android/server/telecom/CallIdMapper.java
@@ -20,6 +20,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 
+import java.util.Collection;
 import java.util.Map;
 
 /** Utility to map {@link Call} objects to unique IDs. IDs are generated when a call is added. */
@@ -71,6 +72,10 @@
             return mSecondaryMap.get(value);
         }
 
+        public Collection<V> getValues() {
+            return mPrimaryMap.values();
+        }
+
         public void clear() {
             mPrimaryMap.clear();
             mSecondaryMap.clear();
@@ -132,6 +137,10 @@
         return mCalls.getValue(callId);
     }
 
+    Collection<Call> getCalls() {
+        return mCalls.getValues();
+    }
+
     void clear() {
         mCalls.clear();
     }
diff --git a/src/com/android/server/telecom/CallLogManager.java b/src/com/android/server/telecom/CallLogManager.java
index 7a5af14..b19e269 100755
--- a/src/com/android/server/telecom/CallLogManager.java
+++ b/src/com/android/server/telecom/CallLogManager.java
@@ -605,7 +605,8 @@
             for (int i = 0; i < result.length; i++) {
                 Uri uri = result[i];
                 /*
-                 Performs a simple sanity check to make sure the call was written in the database.
+                 Performs a simple correctness check to make sure the call was written in the
+                 database.
                  Typically there is only one result per call so it is easy to identify which one
                  failed.
                  */
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index 1c46209..ff3122f 100755
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -3975,7 +3975,7 @@
                 + " livecall = " + liveCall);
 
         if (emergencyCall == liveCall) {
-            // Not likely, but a good sanity check.
+            // Not likely, but a good correctness check.
             return true;
         }
 
@@ -3989,7 +3989,7 @@
                 return true;
             }
             if (outgoingCall.getState() == CallState.SELECT_PHONE_ACCOUNT) {
-                // Sanity check: if there is an orphaned emergency call in the
+                // Correctness check: if there is an orphaned emergency call in the
                 // {@link CallState#SELECT_PHONE_ACCOUNT} state, just disconnect it since the user
                 // has explicitly started a new call.
                 emergencyCall.getAnalytics().setCallIsAdditional(true);
diff --git a/src/com/android/server/telecom/CarModeTracker.java b/src/com/android/server/telecom/CarModeTracker.java
index 0ec4917..e64ef5d 100644
--- a/src/com/android/server/telecom/CarModeTracker.java
+++ b/src/com/android/server/telecom/CarModeTracker.java
@@ -28,6 +28,7 @@
 import java.util.Comparator;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.PriorityQueue;
 import java.util.stream.Collectors;
 
@@ -144,6 +145,28 @@
     }
 
     /**
+     * Force-removes a package from the car mode tracking list, no matter at which priority.
+     *
+     * This handles the case where packages are disabled or uninstalled. In those case, remove them
+     * from the tracking list so they don't cause a leak.
+     * @param packageName Package name of the app to force-remove
+     */
+    public void forceExitCarMode(@NonNull String packageName) {
+        Optional<CarModeApp> forcedApp = mCarModeApps.stream()
+                .filter(c -> c.getPackageName().equals(packageName))
+                .findAny();
+        if (forcedApp.isPresent()) {
+            String logString = String.format("forceExitCarMode: packageName=%s, was at priority=%s",
+                    packageName, forcedApp.get().getPriority());
+            Log.i(this, logString);
+            mCarModeChangeLog.log(logString);
+            mCarModeApps.removeIf(c -> c.getPackageName().equals(packageName));
+        } else {
+            Log.i(this, "Package %s is not tracked as requesting car mode", packageName);
+        }
+    }
+
+    /**
      * Retrieves a list of the apps which are currently in car mode, ordered by priority such that
      * the highest priority app is first.
      * @return List of apps in car mode.
diff --git a/src/com/android/server/telecom/ConnectionServiceWrapper.java b/src/com/android/server/telecom/ConnectionServiceWrapper.java
index 01acdd1..72c3f24 100755
--- a/src/com/android/server/telecom/ConnectionServiceWrapper.java
+++ b/src/com/android/server/telecom/ConnectionServiceWrapper.java
@@ -91,6 +91,7 @@
                             mServiceInterface.createConnectionComplete(callId,
                                     Log.getExternalSession());
                         } catch (RemoteException e) {
+                            logOutgoing("createConnectionComplete remote exception=%s", e);
                         }
                     }
                 }
@@ -1206,6 +1207,10 @@
                 mPendingResponses.put(callId, response);
 
                 Bundle extras = call.getIntentExtras();
+                if (extras == null) {
+                    extras = new Bundle();
+                }
+                extras.putString(Connection.EXTRA_ORIGINAL_CONNECTION_ID, callId);
 
                 Log.addEvent(call, LogUtils.Events.START_CONFERENCE,
                         Log.piiHandle(call.getHandle()));
diff --git a/src/com/android/server/telecom/CreateConnectionProcessor.java b/src/com/android/server/telecom/CreateConnectionProcessor.java
index 700dac7..2221cb9 100644
--- a/src/com/android/server/telecom/CreateConnectionProcessor.java
+++ b/src/com/android/server/telecom/CreateConnectionProcessor.java
@@ -438,7 +438,10 @@
                             mPhoneAccountRegistrar.getOutgoingPhoneAccountForSchemeOfCurrentUser(
                                     mCall.getHandle() == null
                                             ? null : mCall.getHandle().getScheme()));
-                    if (!mAttemptRecords.contains(callAttemptRecord)) {
+                    // If the target phone account is null, we'll run into a NPE during the retry
+                    // process, so skip it now if it's null.
+                    if (callAttemptRecord.targetPhoneAccount != null
+                            && !mAttemptRecords.contains(callAttemptRecord)) {
                         Log.i(this, "Will try Connection Manager account %s for emergency",
                                 callManager);
                         mAttemptRecords.add(callAttemptRecord);
diff --git a/src/com/android/server/telecom/CreateConnectionTimeout.java b/src/com/android/server/telecom/CreateConnectionTimeout.java
index 399c28a..14e5bf0 100644
--- a/src/com/android/server/telecom/CreateConnectionTimeout.java
+++ b/src/com/android/server/telecom/CreateConnectionTimeout.java
@@ -69,7 +69,7 @@
         }
 
         // Timeout is only supported for SIM call managers that are set by the carrier.
-        if (!Objects.equals(connectionManager.getComponentName(),
+        if (connectionManager != null && !Objects.equals(connectionManager.getComponentName(),
                 mPhoneAccountRegistrar.getSystemSimCallManagerComponent())) {
             Log.d(this, "isTimeoutNeededForCall, not a system sim call manager");
             return false;
diff --git a/src/com/android/server/telecom/DefaultDialerCache.java b/src/com/android/server/telecom/DefaultDialerCache.java
index c2b78ee..a4a0242 100644
--- a/src/com/android/server/telecom/DefaultDialerCache.java
+++ b/src/com/android/server/telecom/DefaultDialerCache.java
@@ -217,6 +217,12 @@
         return mSystemDialerComponentName;
     }
 
+    public ComponentName getDialtactsSystemDialerComponent() {
+        final Resources resources = mContext.getResources();
+        return new ComponentName(getSystemDialerApplication(),
+                resources.getString(R.string.dialer_default_class));
+    }
+
     public void observeDefaultDialerApplication(Executor executor, IntConsumer observer) {
         mRoleManagerAdapter.observeDefaultDialerApp(executor, observer);
     }
@@ -289,4 +295,8 @@
     public ContentObserver getContentObserver() {
         return mDefaultDialerObserver;
     }
+
+    public RoleManagerAdapter getRoleManagerAdapter() {
+        return mRoleManagerAdapter;
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/server/telecom/InCallController.java b/src/com/android/server/telecom/InCallController.java
index 228cb3d..d685a53 100644
--- a/src/com/android/server/telecom/InCallController.java
+++ b/src/com/android/server/telecom/InCallController.java
@@ -20,9 +20,11 @@
 import android.annotation.NonNull;
 import android.app.Notification;
 import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
@@ -43,6 +45,7 @@
 import android.telecom.TelecomManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 
 import com.android.internal.annotations.VisibleForTesting;
 // TODO: Needed for move to system service: import com.android.internal.R;
@@ -58,6 +61,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -322,7 +326,10 @@
                 String packageName = mInCallServiceInfo.getComponentName().getPackageName();
                 mContext.unbindService(mServiceConnection);
                 mIsConnected = false;
-                if (mIsNullBinding) {
+                if (mIsNullBinding && mInCallServiceInfo.getType() != IN_CALL_SERVICE_TYPE_NON_UI) {
+                    // Non-UI InCallServices are allowed to return null from onBind if they don't
+                    // want to handle calls at the moment, so don't report them to the user as
+                    // crashed.
                     sendCrashedInCallServiceNotification(packageName);
                 }
                 if (mCall != null) {
@@ -444,7 +451,7 @@
 
         @Override
         public void disconnect() {
-            Log.i(this, "Disconnect forced!");
+            Log.i(this, "Disconnecting from InCallService");
             if (mIsProxying) {
                 mSubConnection.disconnect();
             } else {
@@ -721,6 +728,20 @@
             }
             pw.decreaseIndent();
         }
+
+        public void addConnections(List<InCallServiceBindingConnection> newConnections) {
+            // connect() needs to be called with a Call object. Since we're in the middle of any
+            // possible number of calls right now, choose an arbitrary one from the ones that
+            // InCallController is tracking.
+            if (mCallIdMapper.getCalls().isEmpty()) {
+                Log.w(InCallController.this, "No calls tracked while adding new NonUi incall");
+                return;
+            }
+            Call callToConnectWith = mCallIdMapper.getCalls().iterator().next();
+            for (InCallServiceBindingConnection newConnection : newConnections) {
+                newConnection.connect(callToConnectWith);
+            }
+        }
     }
 
     private final Call.Listener mCallListener = new Call.ListenerBase() {
@@ -847,9 +868,50 @@
         }
     };
 
-    private final SystemStateListener mSystemStateListener =
-            (priority, packageName, isCarMode) -> InCallController.this.handleCarModeChange(
-                    priority, packageName, isCarMode);
+    private BroadcastReceiver mPackageChangedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.startSession("ICC.pCR");
+            try {
+                if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())) {
+                    synchronized (mLock) {
+                        String changedPackage = intent.getData().getSchemeSpecificPart();
+                        List<InCallServiceBindingConnection> componentsToBind =
+                                Arrays.stream(intent.getStringArrayExtra(
+                                        Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST))
+                                        .map((className) ->
+                                                ComponentName.createRelative(changedPackage,
+                                                        className))
+                                        .filter(mKnownNonUiInCallServices::contains)
+                                        .flatMap(componentName -> getInCallServiceComponents(
+                                                componentName,
+                                                IN_CALL_SERVICE_TYPE_NON_UI).stream())
+                                        .map(InCallServiceBindingConnection::new)
+                                        .collect(Collectors.toList());
+
+                        if (mNonUIInCallServiceConnections != null) {
+                            mNonUIInCallServiceConnections.addConnections(componentsToBind);
+                        }
+                    }
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
+    };
+
+    private final SystemStateListener mSystemStateListener = new SystemStateListener() {
+        @Override
+        public void onCarModeChanged(int priority, String packageName, boolean isCarMode) {
+            InCallController.this.handleCarModeChange(priority, packageName, isCarMode);
+        }
+
+        @Override
+        public void onPackageUninstalled(String packageName) {
+            mCarModeTracker.forceExitCarMode(packageName);
+            updateCarModeForSwitchingConnection();
+        }
+    };
 
     private static final int IN_CALL_SERVICE_TYPE_INVALID = 0;
     private static final int IN_CALL_SERVICE_TYPE_DIALER_UI = 1;
@@ -875,6 +937,11 @@
     private NonUIInCallServiceConnectionCollection mNonUIInCallServiceConnections;
     private final ClockProxy mClockProxy;
 
+    // A set of known non-UI in call services on the device, including those that are disabled.
+    // We track this so that we can efficiently bind to them when we're notified that a new
+    // component has been enabled.
+    private Set<ComponentName> mKnownNonUiInCallServices = new ArraySet<>();
+
     // Future that's in a completed state unless we're in the middle of binding to a service.
     // The future will complete with true if binding succeeds, false if it timed out.
     private CompletableFuture<Boolean> mBindingFuture = CompletableFuture.completedFuture(true);
@@ -940,7 +1007,8 @@
                 ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
                         true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
                         info.isExternalCallsSupported(), includeRttCall,
-                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI);
+                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI ||
+                        info.getType() == IN_CALL_SERVICE_TYPE_NON_UI);
                 try {
                     inCallService.addCall(sanitizeParcelableCallForService(info, parcelableCall));
                 } catch (RemoteException ignored) {
@@ -1004,7 +1072,8 @@
                 ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(call,
                         true /* includeVideoProvider */, mCallsManager.getPhoneAccountRegistrar(),
                         info.isExternalCallsSupported(), includeRttCall,
-                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI);
+                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI ||
+                        info.getType() == IN_CALL_SERVICE_TYPE_NON_UI);
                 try {
                     inCallService.addCall(sanitizeParcelableCallForService(info, parcelableCall));
                 } catch (RemoteException ignored) {
@@ -1034,7 +1103,8 @@
                         false /* supportsExternalCalls */,
                         android.telecom.Call.STATE_DISCONNECTED /* overrideState */,
                         false /* includeRttCall */,
-                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI
+                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI ||
+                        info.getType() == IN_CALL_SERVICE_TYPE_NON_UI
                         );
 
                 try {
@@ -1227,6 +1297,12 @@
      * Unbinds an existing bound connection to the in-call app.
      */
     private void unbindFromServices() {
+        try {
+            mContext.unregisterReceiver(mPackageChangedReceiver);
+        } catch (IllegalArgumentException e) {
+            // Ignore this -- we may or may not have registered it, but when we bind, we want to
+            // unregister no matter what.
+        }
         if (mInCallServiceConnection != null) {
             mInCallServiceConnection.disconnect();
             mInCallServiceConnection = null;
@@ -1312,6 +1388,10 @@
         }
         mNonUIInCallServiceConnections = new NonUIInCallServiceConnectionCollection(nonUIInCalls);
         mNonUIInCallServiceConnections.connect(call);
+
+        IntentFilter packageChangedFilter = new IntentFilter(Intent.ACTION_PACKAGE_CHANGED);
+        packageChangedFilter.addDataScheme("package");
+        mContext.registerReceiver(mPackageChangedReceiver, packageChangedFilter);
     }
 
     private InCallServiceInfo getDefaultDialerComponent() {
@@ -1387,7 +1467,7 @@
         PackageManager packageManager = mContext.getPackageManager();
         for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(
                 serviceIntent,
-                PackageManager.GET_META_DATA,
+                PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_COMPONENTS,
                 mCallsManager.getCurrentUserHandle().getIdentifier())) {
             ServiceInfo serviceInfo = entry.serviceInfo;
             if (serviceInfo != null) {
@@ -1400,14 +1480,13 @@
 
                 int currentType = getInCallServiceType(entry.serviceInfo, packageManager,
                         packageName);
-                if (requestedType == 0 || requestedType == currentType) {
-                    if (requestedType == IN_CALL_SERVICE_TYPE_NON_UI) {
-                        // We enforce the rule that self-managed calls are not supported by non-ui
-                        // InCallServices.
-                        isSelfManageCallsSupported = false;
-                    }
-                    retval.add(new InCallServiceInfo(
-                            new ComponentName(serviceInfo.packageName, serviceInfo.name),
+                ComponentName foundComponentName =
+                        new ComponentName(serviceInfo.packageName, serviceInfo.name);
+                if (requestedType == IN_CALL_SERVICE_TYPE_NON_UI) {
+                    mKnownNonUiInCallServices.add(foundComponentName);
+                }
+                if (serviceInfo.enabled && (requestedType == 0 || requestedType == currentType)) {
+                    retval.add(new InCallServiceInfo(foundComponentName,
                             isExternalCallsSupported, isSelfManageCallsSupported, requestedType));
                 }
             }
@@ -1546,7 +1625,8 @@
                         mCallsManager.getPhoneAccountRegistrar(),
                         info.isExternalCallsSupported(),
                         includeRttCall,
-                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI);
+                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI ||
+                        info.getType() == IN_CALL_SERVICE_TYPE_NON_UI);
                 inCallService.addCall(sanitizeParcelableCallForService(info, parcelableCall));
             } catch (RemoteException ignored) {
             }
@@ -1556,7 +1636,11 @@
             inCallService.onCanAddCallChanged(mCallsManager.canAddCall());
         } catch (RemoteException ignored) {
         }
-        mBindingFuture.complete(true);
+        // Don't complete the binding future for non-ui incalls
+        if (info.getType() != IN_CALL_SERVICE_TYPE_NON_UI) {
+            mBindingFuture.complete(true);
+        }
+
         Log.i(this, "%s calls sent to InCallService.", numCallsSent);
         return true;
     }
@@ -1610,7 +1694,8 @@
                         mCallsManager.getPhoneAccountRegistrar(),
                         info.isExternalCallsSupported(),
                         rttInfoChanged && info.equals(mInCallServiceConnection.getInfo()),
-                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI);
+                        info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI ||
+                        info.getType() == IN_CALL_SERVICE_TYPE_NON_UI);
                 ComponentName componentName = info.getComponentName();
                 IInCallService inCallService = entry.getValue();
                 componentsUpdated.add(componentName);
@@ -1701,7 +1786,7 @@
 
         if (TextUtils.isEmpty(ringingPackage)) {
             // The current in-call UI returned nothing, so lets use the default dialer.
-            ringingPackage = mDefaultDialerCache.getDefaultDialerApplication(
+            ringingPackage = mDefaultDialerCache.getRoleManagerAdapter().getDefaultDialerApp(
                     mCallsManager.getCurrentUserHandle().getIdentifier());
             if (ringingPackage != null) {
                 Log.d(this, "doesConnectedDialerSupportRinging: notCurentlyConnectedPackage=%s",
@@ -1784,7 +1869,8 @@
     public void handleCarModeChange(int priority, String packageName, boolean isCarMode) {
         Log.i(this, "handleCarModeChange: packageName=%s, priority=%d, isCarMode=%b",
                 packageName, priority, isCarMode);
-        if (!isCarModeInCallService(packageName)) {
+        // Don't ignore the signal if we are disabling car mode; package may be uninstalled.
+        if (isCarMode && !isCarModeInCallService(packageName)) {
             Log.i(this, "handleCarModeChange: not a valid InCallService; packageName=%s",
                     packageName);
             return;
@@ -1796,8 +1882,12 @@
             mCarModeTracker.handleExitCarMode(priority, packageName);
         }
 
+        updateCarModeForSwitchingConnection();
+    }
+
+    public void updateCarModeForSwitchingConnection() {
         if (mInCallServiceConnection != null) {
-            Log.i(this, "handleCarModeChange: car mode apps: %s",
+            Log.i(this, "updateCarModeForSwitchingConnection: car mode apps: %s",
                     mCarModeTracker.getCarModeApps().stream().collect(Collectors.joining(", ")));
             if (shouldUseCarModeUI()) {
                 mInCallServiceConnection.changeCarModeApp(
diff --git a/src/com/android/server/telecom/LogUtils.java b/src/com/android/server/telecom/LogUtils.java
index 5bb14e6..e4a414b 100644
--- a/src/com/android/server/telecom/LogUtils.java
+++ b/src/com/android/server/telecom/LogUtils.java
@@ -101,6 +101,8 @@
         public static final String SET_DISCONNECTED = "SET_DISCONNECTED";
         public static final String SET_DISCONNECTING = "SET_DISCONNECTING";
         public static final String SET_SELECT_PHONE_ACCOUNT = "SET_SELECT_PHONE_ACCOUNT";
+        public static final String SET_AUDIO_PROCESSING = "SET_AUDIO_PROCESSING";
+        public static final String SET_SIMULATED_RINGING = "SET_SIMULATED_RINGING";
         public static final String REQUEST_HOLD = "REQUEST_HOLD";
         public static final String REQUEST_UNHOLD = "REQUEST_UNHOLD";
         public static final String REQUEST_DISCONNECT = "REQUEST_DISCONNECT";
diff --git a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
index f0efe92..86fedd5 100644
--- a/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
+++ b/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java
@@ -21,7 +21,6 @@
 import android.app.Activity;
 import android.app.BroadcastOptions;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
@@ -495,9 +494,7 @@
 
     private void launchSystemDialer(Uri handle) {
         Intent systemDialerIntent = new Intent();
-        systemDialerIntent.setComponent(
-                new ComponentName(mDefaultDialerCache.getSystemDialerApplication(),
-                    mContext.getResources().getString(R.string.dialer_default_class)));
+        systemDialerIntent.setComponent(mDefaultDialerCache.getDialtactsSystemDialerComponent());
         systemDialerIntent.setAction(Intent.ACTION_DIAL);
         systemDialerIntent.setData(handle);
         systemDialerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/src/com/android/server/telecom/ParcelableCallUtils.java b/src/com/android/server/telecom/ParcelableCallUtils.java
index 5c821a4..a5291e7 100644
--- a/src/com/android/server/telecom/ParcelableCallUtils.java
+++ b/src/com/android/server/telecom/ParcelableCallUtils.java
@@ -42,9 +42,9 @@
 
     /**
      * A list of extra keys which should be removed from a {@link ParcelableCall} when it is being
-     * generated for the purpose of sending to a dialer other than the system dialer.
+     * generated for the purpose of sending to a incallservice other than the system incallservice.
      * By convention we only pass keys namespaced with android.*, however there are some keys which
-     * should not be passed to non-system dialer apps either.
+     * should not be passed to non-system incallservice apps either.
      */
     private static List<String> EXTRA_KEYS_TO_SANITIZE;
     static {
@@ -90,9 +90,9 @@
      *      {@link InCallService} which supports external calls or not.
      * @param includeRttCall {@code true} if the RTT call should be included, {@code false}
      *      otherwise.
-     * @param isForSystemDialer {@code true} if this call is being parcelled for the system dialer,
-     *      {@code false} otherwise.  When parceling for the system dialer, the entire call extras
-     *      is included.  When parceling for anything other than the system dialer, some extra key
+     * @param isForSystemInCallService {@code true} if this call is being parcelled for the system incallservice,
+     *      {@code false} otherwise.  When parceling for the system incallservice, the entire call extras
+     *      is included.  When parceling for anything other than the system incallservice, some extra key
      *      values will be stripped for privacy sake.
      */
     public static ParcelableCall toParcelableCall(
@@ -101,10 +101,10 @@
             PhoneAccountRegistrar phoneAccountRegistrar,
             boolean supportsExternalCalls,
             boolean includeRttCall,
-            boolean isForSystemDialer) {
+            boolean isForSystemInCallService) {
         return toParcelableCall(call, includeVideoProvider, phoneAccountRegistrar,
                 supportsExternalCalls, CALL_STATE_OVERRIDE_NONE /* overrideState */,
-                includeRttCall, isForSystemDialer);
+                includeRttCall, isForSystemInCallService);
     }
 
     /**
@@ -120,9 +120,9 @@
      *      {@link InCallService} which supports external calls or not.
      * @param overrideState When not {@link #CALL_STATE_OVERRIDE_NONE}, use the provided state as an
      *      override to whatever is defined in the call.
-     * @param isForSystemDialer {@code true} if this call is being parcelled for the system dialer,
-     *      {@code false} otherwise.  When parceling for the system dialer, the entire call extras
-     *      is included.  When parceling for anything other than the system dialer, some extra key
+     * @param isForSystemInCallService {@code true} if this call is being parcelled for the system incallservice,
+     *      {@code false} otherwise.  When parceling for the system incallservice, the entire call extras
+     *      is included.  When parceling for anything other than the system incallservice, some extra key
      *      values will be stripped for privacy sake.
      * @return The {@link ParcelableCall} containing all call information from the {@link Call}.
      */
@@ -133,7 +133,7 @@
             boolean supportsExternalCalls,
             int overrideState,
             boolean includeRttCall,
-            boolean isForSystemDialer) {
+            boolean isForSystemInCallService) {
         int state;
         if (overrideState == CALL_STATE_OVERRIDE_NONE) {
             state = getParcelableState(call, supportsExternalCalls);
@@ -216,7 +216,7 @@
         }
 
         Bundle extras;
-        if (isForSystemDialer) {
+        if (isForSystemInCallService) {
             extras = call.getExtras();
         } else {
             extras = sanitizeExtras(call.getExtras());
@@ -269,9 +269,9 @@
      *     <li>Caller number verification status (verstat)</li>
      * </ul>
      * All other fields are nulled or set to 0 values.
-     * Where the call screening service is part of the system dialer, the
+     * Where the call screening service is part of the system incallservice, the
      * {@link Connection#EXTRA_SIP_INVITE} header information is also sent to the call screening
-     * service (since the system dialer has access to this anyways).
+     * service (since the system incallservice has access to this anyways).
      * @param call The telecom call to send to a call screening service.
      * @param areRestrictedExtrasIncluded {@code true} if the set of restricted extras defined in
      *                                    {@link #RESTRICTED_CALL_SCREENING_EXTRA_KEYS} are to
@@ -333,7 +333,7 @@
 
     /**
      * Sanitize the extras bundle passed in, removing keys which should not be sent to non-system
-     * dialer apps.
+     * incallservice apps.
      * @param oldExtras Extras bundle to sanitize.
      * @return The sanitized extras bundle.
      */
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index ef2840a..e9ddfa0 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -18,6 +18,7 @@
 
 import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -485,6 +486,7 @@
      * target phone account.
      * @return phone account handle of sim call manager based on the ongoing call.
      */
+    @Nullable
     public PhoneAccountHandle getSimCallManagerFromCall(Call call) {
         if (call == null) {
             return null;
@@ -1597,10 +1599,16 @@
             return BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length);
         }
 
+        @Nullable
         protected Icon readIcon(XmlPullParser parser) throws IOException {
-            byte[] iconByteArray = Base64.decode(parser.getText(), 0);
-            ByteArrayInputStream stream = new ByteArrayInputStream(iconByteArray);
-            return Icon.createFromStream(stream);
+            try {
+                byte[] iconByteArray = Base64.decode(parser.getText(), 0);
+                ByteArrayInputStream stream = new ByteArrayInputStream(iconByteArray);
+                return Icon.createFromStream(stream);
+            } catch (IllegalArgumentException e) {
+                Log.e(this, e, "Bitmap must not be null.");
+                return null;
+            }
         }
     }
 
diff --git a/src/com/android/server/telecom/SystemStateHelper.java b/src/com/android/server/telecom/SystemStateHelper.java
index 073b081..3be3d5e 100644
--- a/src/com/android/server/telecom/SystemStateHelper.java
+++ b/src/com/android/server/telecom/SystemStateHelper.java
@@ -26,6 +26,7 @@
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
+import android.net.Uri;
 import android.telecom.Log;
 
 import java.util.Set;
@@ -38,7 +39,7 @@
  * Provides various system states to the rest of the telecom codebase.
  */
 public class SystemStateHelper {
-    public static interface SystemStateListener {
+    public interface SystemStateListener {
         /**
          * Listener method to inform interested parties when a package name requests to enter or
          * exit car mode.
@@ -48,6 +49,12 @@
          *                              otherwise.
          */
         void onCarModeChanged(int priority, String packageName, boolean isCarMode);
+
+        /**
+         * Notifies when a package has been uninstalled.
+         * @param packageName the package name of the uninstalled package
+         */
+        void onPackageUninstalled(String packageName);
     }
 
     private final Context mContext;
@@ -62,7 +69,7 @@
                             UiModeManager.DEFAULT_PRIORITY);
                     String callingPackage = intent.getStringExtra(
                             UiModeManager.EXTRA_CALLING_PACKAGE);
-                    Log.i(SystemStateHelper.this, "ENTER_CAR_MODE_PRIVILEGED; priority=%d, pkg=%s",
+                    Log.i(SystemStateHelper.this, "ENTER_CAR_MODE_PRIORITIZED; priority=%d, pkg=%s",
                             priority, callingPackage);
                     onEnterCarMode(priority, callingPackage);
                 } else if (UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED.equals(action)) {
@@ -70,11 +77,21 @@
                             UiModeManager.DEFAULT_PRIORITY);
                     String callingPackage = intent.getStringExtra(
                             UiModeManager.EXTRA_CALLING_PACKAGE);
-                    Log.i(SystemStateHelper.this, "EXIT_CAR_MODE_PRIVILEGED; priority=%d, pkg=%s",
+                    Log.i(SystemStateHelper.this, "EXIT_CAR_MODE_PRIORITIZED; priority=%d, pkg=%s",
                             priority, callingPackage);
                     onExitCarMode(priority, callingPackage);
+                } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+                    Uri data = intent.getData();
+                    if (data == null) {
+                        Log.w(SystemStateHelper.this,
+                                "Got null data for package removed, ignoring");
+                        return;
+                    }
+                    mListeners.forEach(
+                            l -> l.onPackageUninstalled(data.getEncodedSchemeSpecificPart()));
                 } else {
-                    Log.w(this, "Unexpected intent received: %s", intent.getAction());
+                    Log.w(SystemStateHelper.this,
+                            "Unexpected intent received: %s", intent.getAction());
                 }
             } finally {
                 Log.endSession();
@@ -88,11 +105,16 @@
     public SystemStateHelper(Context context) {
         mContext = context;
 
-        IntentFilter intentFilter = new IntentFilter(
+        IntentFilter intentFilter1 = new IntentFilter(
                 UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED);
-        intentFilter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED);
-        mContext.registerReceiver(mBroadcastReceiver, intentFilter);
-        Log.i(this, "Registering car mode receiver: %s", intentFilter);
+        intentFilter1.addAction(UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED);
+
+        IntentFilter intentFilter2 = new IntentFilter(Intent.ACTION_PACKAGE_REMOVED);
+        intentFilter2.addDataScheme("package");
+        mContext.registerReceiver(mBroadcastReceiver, intentFilter1);
+        mContext.registerReceiver(mBroadcastReceiver, intentFilter2);
+        Log.i(this, "Registering broadcast receiver: %s", intentFilter1);
+        Log.i(this, "Registering broadcast receiver: %s", intentFilter2);
 
         mIsCarMode = getSystemCarMode();
     }
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 62e0f3f..1cf25a3 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -710,7 +710,7 @@
         public ComponentName getDefaultPhoneApp() {
             try {
                 Log.startSession("TSI.gDPA");
-                return mDefaultDialerCache.getSystemDialerComponent();
+                return mDefaultDialerCache.getDialtactsSystemDialerComponent();
             } finally {
                 Log.endSession();
             }
@@ -1737,6 +1737,32 @@
             }
         }
 
+        /**
+         * A method intended for use in testing to clean up any calls that get stuck in the
+         * {@link CallState#DISCONNECTED} or {@link CallState#DISCONNECTING} states. Stuck calls
+         * during CTS cause cascading failures, so if the CTS test detects such a state, it should
+         * call this method via a shell command to clean up before moving on to the next test.
+         */
+        @Override
+        public void cleanupStuckCalls() {
+            Log.startSession("TCI.cSC");
+            try {
+                synchronized (mLock) {
+                    enforceShellOnly(Binder.getCallingUid(), "cleanupStuckCalls");
+                    Binder.withCleanCallingIdentity(() -> {
+                        for (Call call : mCallsManager.getCalls()) {
+                            if (call.getState() == CallState.DISCONNECTED
+                                    || call.getState() == CallState.DISCONNECTING) {
+                                mCallsManager.markCallAsRemoved(call);
+                            }
+                        }
+                    });
+                }
+            } finally {
+                Log.endSession();
+            }
+        }
+
         @Override
         public void setTestDefaultCallRedirectionApp(String packageName) {
             try {
diff --git a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
index 3549db5..1fe7c5f 100644
--- a/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
+++ b/src/com/android/server/telecom/settings/BlockedNumbersActivity.java
@@ -38,6 +38,7 @@
 import android.provider.ContactsContract;
 import android.telephony.PhoneNumberFormattingTextWatcher;
 import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
 import android.text.Editable;
 import android.text.InputType;
 import android.text.TextUtils;
@@ -285,7 +286,7 @@
      * Add blocked number if it does not exist.
      */
     private void addBlockedNumber(String number) {
-        if (PhoneNumberUtils.isEmergencyNumber(number)) {
+        if (isEmergencyNumber(this, number)) {
             Toast.makeText(
                     this,
                     getString(R.string.blocked_numbers_block_emergency_number_message),
@@ -298,6 +299,16 @@
         }
     }
 
+    private boolean isEmergencyNumber(Context context, String number) {
+        try {
+            TelephonyManager tm = (TelephonyManager) context.getSystemService(
+                    Context.TELEPHONY_SERVICE);
+            return tm.isEmergencyNumber(number);
+        } catch (IllegalStateException ise) {
+            return false;
+        }
+    }
+
     @Override
     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
         // no-op
diff --git a/src/com/android/server/telecom/ui/IncomingCallNotifier.java b/src/com/android/server/telecom/ui/IncomingCallNotifier.java
index 6e203aa..edea89b 100644
--- a/src/com/android/server/telecom/ui/IncomingCallNotifier.java
+++ b/src/com/android/server/telecom/ui/IncomingCallNotifier.java
@@ -41,6 +41,7 @@
 import com.android.server.telecom.TelecomBroadcastIntentProcessor;
 import com.android.server.telecom.components.TelecomBroadcastReceiver;
 
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 
@@ -68,7 +69,7 @@
     public static final int NOTIFICATION_INCOMING_CALL = 1;
     @VisibleForTesting
     public static final String NOTIFICATION_TAG = IncomingCallNotifier.class.getSimpleName();
-
+    private final Object mLock = new Object();
 
     public final Call.ListenerBase mCallListener = new Call.ListenerBase() {
         @Override
@@ -104,8 +105,10 @@
 
     @Override
     public void onCallAdded(Call call) {
-        if (!mCalls.contains(call)) {
-            mCalls.add(call);
+        synchronized (mLock) {
+            if (!mCalls.contains(call)) {
+                mCalls.add(call);
+            }
         }
 
         updateIncomingCall();
@@ -113,10 +116,11 @@
 
     @Override
     public void onCallRemoved(Call call) {
-        if (mCalls.contains(call)) {
-            mCalls.remove(call);
+        synchronized (mLock) {
+            if (mCalls.contains(call)) {
+                mCalls.remove(call);
+            }
         }
-
         updateIncomingCall();
     }
 
@@ -130,11 +134,16 @@
      * UI.
      */
     private void updateIncomingCall() {
-        Optional<Call> incomingCallOp = mCalls.stream()
-                .filter(call -> call.isSelfManaged() && call.isIncoming() &&
-                        call.getState() == CallState.RINGING &&
-                        call.getHandoverState() == HandoverState.HANDOVER_NONE)
-                .findFirst();
+        Optional<Call> incomingCallOp;
+        synchronized (mLock) {
+            incomingCallOp = mCalls.stream()
+                    .filter(Objects::nonNull)
+                    .filter(call -> call.isSelfManaged() && call.isIncoming() &&
+                            call.getState() == CallState.RINGING &&
+                            call.getHandoverState() == HandoverState.HANDOVER_NONE)
+                    .findFirst();
+        }
+
         Call incomingCall = incomingCallOp.orElse(null);
         if (incomingCall != null && mCallsManagerProxy != null &&
                 !mCallsManagerProxy.hasUnholdableCallsForOtherConnectionService(
diff --git a/testapps/AndroidManifest.xml b/testapps/AndroidManifest.xml
index 4238191..9c461ca 100644
--- a/testapps/AndroidManifest.xml
+++ b/testapps/AndroidManifest.xml
@@ -15,40 +15,41 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          coreApp="true"
-          package="com.android.server.telecom.testapps">
+     coreApp="true"
+     package="com.android.server.telecom.testapps">
 
-    <uses-sdk
-        android:minSdkVersion="28"
-        android:targetSdkVersion="30" />
+    <uses-sdk android:minSdkVersion="28"
+         android:targetSdkVersion="30"/>
 
-    <uses-permission android:name="android.permission.ACCEPT_HANDOVER" />
-    <uses-permission android:name="android.permission.BLUETOOTH" />
-    <uses-permission android:name="android.permission.CAMERA" />
-    <uses-permission android:name="android.permission.CALL_PHONE" />
-    <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE" />
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
-    <uses-permission android:name="android.permission.READ_CALL_LOG" />
-    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
-    <uses-permission android:name="android.permission.REGISTER_CALL_PROVIDER" />
-    <uses-permission android:name="android.permission.REGISTER_CONNECTION_MANAGER" />
-    <uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION" />
-    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+    <uses-permission android:name="android.permission.ACCEPT_HANDOVER"/>
+    <uses-permission android:name="android.permission.BLUETOOTH"/>
+    <uses-permission android:name="android.permission.CAMERA"/>
+    <uses-permission android:name="android.permission.CALL_PHONE"/>
+    <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.MANAGE_OWN_CALLS"/>
+    <uses-permission android:name="android.permission.READ_CALL_LOG"/>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.REGISTER_CALL_PROVIDER"/>
+    <uses-permission android:name="android.permission.REGISTER_CONNECTION_MANAGER"/>
+    <uses-permission android:name="android.permission.REGISTER_SIM_SUBSCRIPTION"/>
+    <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
 
     <application android:label="@string/app_name">
-        <uses-library android:name="android.test.runner" />
+        <uses-library android:name="android.test.runner"/>
 
         <!-- Miscellaneous telecom app-related test activities. -->
 
         <service android:name="com.android.server.telecom.testapps.TestConnectionService"
-                 android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" >
+             android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.telecom.ConnectionService" />
+                <action android:name="android.telecom.ConnectionService"/>
             </intent-filter>
         </service>
 
-        <receiver android:name=".TestConnectionServiceReceiver">
+        <receiver android:name=".TestConnectionServiceReceiver"
+             android:exported="true">
             <intent-filter>
                 <action android:name="android.server.telecom.testapps.ACTION_SWITCH_PHONE_ACCOUNT"/>
                 <action android:name="android.server.telecom.testapps.ACTION_SWITCH_PHONE_ACCOUNT_WRONG"/>
@@ -56,23 +57,27 @@
         </receiver>
 
         <service android:name="com.android.server.telecom.testapps.TestConnectionManager"
-                 android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE" >
+             android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.telecom.ConnectionService" />
+                <action android:name="android.telecom.ConnectionService"/>
             </intent-filter>
         </service>
 
         <service android:name="com.android.server.telecom.testapps.TestInCallServiceImpl"
-                 android:process="com.android.server.telecom.testapps.TestInCallService"
-                 android:permission="android.permission.BIND_INCALL_SERVICE" >
-            <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true"/>
+             android:process="com.android.server.telecom.testapps.TestInCallService"
+             android:permission="android.permission.BIND_INCALL_SERVICE"
+             android:exported="true">
+            <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI"
+                 android:value="true"/>
             <intent-filter>
                 <action android:name="android.telecom.InCallService"/>
             </intent-filter>
         </service>
 
         <receiver android:name="com.android.server.telecom.testapps.TestInCallServiceBroadcastReceiver"
-                 android:process="com.android.server.telecom.testapps.TestInCallService" >
+             android:process="com.android.server.telecom.testapps.TestInCallService"
+             android:exported="true">
             <intent-filter>
                 <action android:name="android.server.telecom.testapps.ACTION_SEND_UPDATE_REQUEST_FROM_TEST_INCALL_SERVICE"/>
                 <action android:name="android.server.telecom.testapps.ACTION_SEND_UPGRADE_RESPONSE"/>
@@ -84,201 +89,212 @@
 
 
         <activity android:name="com.android.server.telecom.testapps.TestInCallUI"
-                android:process="com.android.server.telecom.testapps.TestInCallService"
-                android:label="@string/inCallUiAppLabel"
-                android:launchMode="singleInstance">
+             android:process="com.android.server.telecom.testapps.TestInCallService"
+             android:label="@string/inCallUiAppLabel"
+             android:launchMode="singleInstance"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
 
         <activity android:name="com.android.server.telecom.testapps.TestRttActivity"
-                  android:process="com.android.server.telecom.testapps.TestInCallService"
-                  android:label="@string/rttUiLabel"
-                  android:launchMode="singleInstance">
+             android:process="com.android.server.telecom.testapps.TestInCallService"
+             android:label="@string/rttUiLabel"
+             android:launchMode="singleInstance"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
 
         <activity android:name="com.android.server.telecom.testapps.TestCallActivity"
-                  android:theme="@android:style/Theme.NoDisplay"
-                  android:label="@string/testCallActivityLabel">
+             android:theme="@android:style/Theme.NoDisplay"
+             android:label="@string/testCallActivityLabel"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.telecom.testapps.ACTION_START_INCOMING_CALL" />
-                <action android:name="android.telecom.testapps.ACTION_NEW_UNKNOWN_CALL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="tel" />
-                <data android:scheme="sip" />
+                <action android:name="android.telecom.testapps.ACTION_START_INCOMING_CALL"/>
+                <action android:name="android.telecom.testapps.ACTION_NEW_UNKNOWN_CALL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="tel"/>
+                <data android:scheme="sip"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.telecom.testapps.ACTION_HANGUP_CALLS" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.telecom.testapps.ACTION_HANGUP_CALLS"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.telecom.testapps.ACTION_SEND_UPGRADE_REQUEST" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="int" />
+                <action android:name="android.telecom.testapps.ACTION_SEND_UPGRADE_REQUEST"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="int"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.telecom.testapps.ACTION_RTT_CALL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <data android:scheme="tel" />
+                <action android:name="android.telecom.testapps.ACTION_RTT_CALL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <data android:scheme="tel"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.telecom.testapps.ACTION_REMOTE_RTT_UPGRADE" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.telecom.testapps.ACTION_REMOTE_RTT_UPGRADE"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
 
         <receiver android:name="com.android.server.telecom.testapps.CallNotificationReceiver"
-                  android:exported="false">
+             android:exported="false">
             <intent-filter>
-                <action android:name="com.android.server.telecom.testapps.ACTION_CALL_SERVICE_EXIT" />
+                <action android:name="com.android.server.telecom.testapps.ACTION_CALL_SERVICE_EXIT"/>
             </intent-filter>
         </receiver>
 
         <activity android:name="com.android.server.telecom.testapps.TestDialerActivity"
-                  android:label="@string/testDialerActivityLabel"
-                  android:process="com.android.server.telecom.testapps.TestInCallService">
+             android:label="@string/testDialerActivityLabel"
+             android:process="com.android.server.telecom.testapps.TestInCallService"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.DIAL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:mimeType="vnd.android.cursor.item/phone" />
-                <data android:mimeType="vnd.android.cursor.item/person" />
+                <action android:name="android.intent.action.DIAL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE"/>
+                <data android:mimeType="vnd.android.cursor.item/phone"/>
+                <data android:mimeType="vnd.android.cursor.item/person"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.DIAL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="voicemail" />
+                <action android:name="android.intent.action.DIAL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE"/>
+                <data android:scheme="voicemail"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.DIAL" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.intent.action.DIAL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <action android:name="android.intent.action.DIAL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="tel" />
+                <action android:name="android.intent.action.VIEW"/>
+                <action android:name="android.intent.action.DIAL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE"/>
+                <data android:scheme="tel"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
 
         <activity android:name="com.android.server.telecom.testapps.TestUssdActivity"
-                android:label="@string/UssdUiAppLabel"
-                android:launchMode="singleInstance">
+             android:label="@string/UssdUiAppLabel"
+             android:launchMode="singleInstance"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
           </activity>
 
         <activity android:name="com.android.server.telecom.testapps.TestCertActivity"
-                android:label="@string/KeyUiAppLabel"
-                android:launchMode="singleInstance">
+             android:label="@string/KeyUiAppLabel"
+             android:launchMode="singleInstance"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
           </activity>
 
         <activity android:name="com.android.server.telecom.testapps.SelfManagedCallingActivity"
-                  android:label="@string/selfManagedCallingActivityLabel"
-                  android:process="com.android.server.telecom.testapps.SelfMangingCallingApp"
-                  android:theme="@android:style/Theme.Material.Light">
+             android:label="@string/selfManagedCallingActivityLabel"
+             android:process="com.android.server.telecom.testapps.SelfMangingCallingApp"
+             android:theme="@android:style/Theme.Material.Light"
+             android:exported="true">
           <intent-filter>
-              <action android:name="android.intent.action.MAIN" />
-              <category android:name="android.intent.category.DEFAULT" />
-              <category android:name="android.intent.category.LAUNCHER" />
+              <action android:name="android.intent.action.MAIN"/>
+              <category android:name="android.intent.category.DEFAULT"/>
+              <category android:name="android.intent.category.LAUNCHER"/>
           </intent-filter>
         </activity>
 
         <activity android:name="com.android.server.telecom.testapps.IncomingSelfManagedCallActivity"
-                  android:label="@string/selfManagedCallingActivityLabel"
-                  android:process="com.android.server.telecom.testapps.SelfMangingCallingApp">
+             android:label="@string/selfManagedCallingActivityLabel"
+             android:process="com.android.server.telecom.testapps.SelfMangingCallingApp"
+             android:exported="true">
           <intent-filter>
-              <action android:name="android.intent.action.MAIN" />
+              <action android:name="android.intent.action.MAIN"/>
           </intent-filter>
         </activity>
 
         <activity android:name="com.android.server.telecom.testapps.HandoverActivity"
-                  android:label="@string/selfManagedCallingActivityLabel"
-                  android:process="com.android.server.telecom.testapps.SelfMangingCallingApp">
+             android:label="@string/selfManagedCallingActivityLabel"
+             android:process="com.android.server.telecom.testapps.SelfMangingCallingApp"
+             android:exported="true">
           <intent-filter>
-              <action android:name="android.intent.action.MAIN" />
+              <action android:name="android.intent.action.MAIN"/>
           </intent-filter>
         </activity>
 
         <service android:name="com.android.server.telecom.testapps.SelfManagedConnectionService"
-                 android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
-                 android:process="com.android.server.telecom.testapps.SelfMangingCallingApp">
+             android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
+             android:process="com.android.server.telecom.testapps.SelfMangingCallingApp"
+             android:exported="true">
           <intent-filter>
-              <action android:name="android.telecom.ConnectionService" />
+              <action android:name="android.telecom.ConnectionService"/>
           </intent-filter>
         </service>
 
         <receiver android:exported="false"
-            android:process="com.android.server.telecom.testapps.SelfMangingCallingApp"
-            android:name="com.android.server.telecom.testapps.SelfManagedCallNotificationReceiver" />
+             android:process="com.android.server.telecom.testapps.SelfMangingCallingApp"
+             android:name="com.android.server.telecom.testapps.SelfManagedCallNotificationReceiver"/>
 
         <receiver android:exported="true"
-                  android:name="com.android.server.telecom.testapps.NuisanceReportReceiver">
+             android:name="com.android.server.telecom.testapps.NuisanceReportReceiver">
             <intent-filter>
-                <action android:name="android.telecom.action.NUISANCE_CALL_STATUS_CHANGED" />
+                <action android:name="android.telecom.action.NUISANCE_CALL_STATUS_CHANGED"/>
             </intent-filter>
         </receiver>
 
-        <service
-            android:name=".TestCallScreeningService"
-            android:permission="android.permission.BIND_SCREENING_SERVICE">
+        <service android:name=".TestCallScreeningService"
+             android:permission="android.permission.BIND_SCREENING_SERVICE"
+             android:exported="true">
             <intent-filter>
                 <action android:name="android.telecom.CallScreeningService"/>
             </intent-filter>
         </service>
 
         <activity android:name=".CallScreeningActivity"
-                  android:configChanges="orientation|screenSize|keyboardHidden"
-                  android:excludeFromRecents="true"
-                  android:launchMode="singleInstance">
+             android:configChanges="orientation|screenSize|keyboardHidden"
+             android:excludeFromRecents="true"
+             android:launchMode="singleInstance">
         </activity>
 
-        <service
-                android:name=".TestCallRedirectionService"
-                android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE">
+        <service android:name=".TestCallRedirectionService"
+             android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE"
+             android:exported="true">
             <intent-filter>
                 <action android:name="android.telecom.CallRedirectionService"/>
             </intent-filter>
         </service>
 
         <activity android:name=".CallRedirectionActivity"
-                  android:configChanges="orientation|screenSize|keyboardHidden"
-                  android:excludeFromRecents="true"
-                  android:launchMode="singleInstance">
+             android:configChanges="orientation|screenSize|keyboardHidden"
+             android:excludeFromRecents="true"
+             android:launchMode="singleInstance">
         </activity>
 
         <activity android:name=".PostCallActivity"
-                  android:label="@string/postCallActivityLabel">
+             android:label="@string/postCallActivityLabel"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.telecom.action.POST_CALL" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.telecom.action.POST_CALL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
     </application>
diff --git a/testapps/carmodedialer/AndroidManifest.xml b/testapps/carmodedialer/AndroidManifest.xml
index 7f55f7e..f237211 100644
--- a/testapps/carmodedialer/AndroidManifest.xml
+++ b/testapps/carmodedialer/AndroidManifest.xml
@@ -15,75 +15,77 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          coreApp="true"
-          package="com.android.server.telecom.carmodedialer">
+     coreApp="true"
+     package="com.android.server.telecom.carmodedialer">
 
-    <uses-sdk
-        android:minSdkVersion="28"
-        android:targetSdkVersion="29" />
+    <uses-sdk android:minSdkVersion="28"
+         android:targetSdkVersion="29"/>
 
-    <uses-permission android:name="android.permission.ACCEPT_HANDOVER" />
-    <uses-permission android:name="android.permission.BLUETOOTH" />
-    <uses-permission android:name="android.permission.CALL_PHONE" />
-    <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE" />
-    <uses-permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED" />
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.READ_CALL_LOG" />
-    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
-    <uses-permission android:name="android.permission.WRITE_CALL_LOG" />
+    <uses-permission android:name="android.permission.ACCEPT_HANDOVER"/>
+    <uses-permission android:name="android.permission.BLUETOOTH"/>
+    <uses-permission android:name="android.permission.CALL_PHONE"/>
+    <uses-permission android:name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
+    <uses-permission android:name="android.permission.ENTER_CAR_MODE_PRIORITIZED"/>
+    <uses-permission android:name="android.permission.INTERNET"/>
+    <uses-permission android:name="android.permission.READ_CALL_LOG"/>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
+    <uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
 
     <application android:label="Telecom CarMode">
-        <uses-library android:name="android.test.runner" />
+        <uses-library android:name="android.test.runner"/>
 
         <service android:name="com.android.server.telecom.carmodedialer.CarModeInCallServiceImpl"
-                 android:permission="android.permission.BIND_INCALL_SERVICE" >
+             android:permission="android.permission.BIND_INCALL_SERVICE"
+             android:exported="true">
           <meta-data android:name="android.telecom.IN_CALL_SERVICE_CAR_MODE_UI"
-                     android:value="true"/>
+               android:value="true"/>
           <intent-filter>
               <action android:name="android.telecom.InCallService"/>
           </intent-filter>
         </service>
 
         <activity android:name="com.android.server.telecom.carmodedialer.CarModeInCallUI"
-                android:label="CarMode Dialer"
-                android:launchMode="singleInstance">
+             android:label="CarMode Dialer"
+             android:launchMode="singleInstance"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
 
         <activity android:name="com.android.server.telecom.carmodedialer.CarModeDialerActivity"
-                  android:label="CarMode Dialer">
+             android:label="CarMode Dialer"
+             android:exported="true">
             <intent-filter>
-                <action android:name="android.intent.action.DIAL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:mimeType="vnd.android.cursor.item/phone" />
-                <data android:mimeType="vnd.android.cursor.item/person" />
+                <action android:name="android.intent.action.DIAL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE"/>
+                <data android:mimeType="vnd.android.cursor.item/phone"/>
+                <data android:mimeType="vnd.android.cursor.item/person"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.DIAL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="voicemail" />
+                <action android:name="android.intent.action.DIAL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE"/>
+                <data android:scheme="voicemail"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.DIAL" />
-                <category android:name="android.intent.category.DEFAULT" />
+                <action android:name="android.intent.action.DIAL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <action android:name="android.intent.action.DIAL" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.BROWSABLE" />
-                <data android:scheme="tel" />
+                <action android:name="android.intent.action.VIEW"/>
+                <action android:name="android.intent.action.DIAL"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.BROWSABLE"/>
+                <data android:scheme="tel"/>
             </intent-filter>
             <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.DEFAULT"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
         </activity>
     </application>
diff --git a/testapps/src/com/android/server/telecom/testapps/TestConnectionManager.java b/testapps/src/com/android/server/telecom/testapps/TestConnectionManager.java
index abb9108..5c78d52 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestConnectionManager.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestConnectionManager.java
@@ -37,7 +37,6 @@
 
 /**
  * Service which acts as a fake ConnectionManager if so configured.
- * TODO(santoscordon): Rename all classes in the directory to Dummy* (e.g., DummyConnectionService).
  */
 public class TestConnectionManager extends ConnectionService {
     public final class TestManagedConnection extends Connection {
diff --git a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
index f6fa116..3d1bc70 100644
--- a/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
+++ b/testapps/src/com/android/server/telecom/testapps/TestConnectionService.java
@@ -53,7 +53,6 @@
 
 /**
  * Service which provides fake calls to test the ConnectionService interface.
- * TODO: Rename all classes in the directory to Dummy* (e.g., DummyConnectionService).
  */
 public class TestConnectionService extends ConnectionService {
     /**
@@ -430,9 +429,9 @@
             int videoState = extras.getInt(EXTRA_START_VIDEO_STATE, VideoProfile.STATE_AUDIO_ONLY);
             Uri providedHandle = extras.getParcelable(EXTRA_HANDLE);
 
-            // Use dummy number for testing incoming calls.
+            // Use test number for testing incoming calls.
             Uri address = providedHandle == null ?
-                    Uri.fromParts(PhoneAccount.SCHEME_TEL, getDummyNumber(
+                    Uri.fromParts(PhoneAccount.SCHEME_TEL, getRandomNumber(
                             VideoProfile.isVideo(videoState)), null)
                     : providedHandle;
             connection.setVideoState(videoState);
@@ -480,7 +479,7 @@
             final Uri providedHandle = extras.getParcelable(EXTRA_HANDLE);
 
             Uri handle = providedHandle == null ?
-                    Uri.fromParts(PhoneAccount.SCHEME_TEL, getDummyNumber(false), null)
+                    Uri.fromParts(PhoneAccount.SCHEME_TEL, getRandomNumber(false), null)
                     : providedHandle;
 
             connection.setAddress(handle,  TelecomManager.PRESENTATION_ALLOWED);
@@ -613,7 +612,7 @@
      * @param isVideo {@code True} if the call is a video call.
      * @return The phone number.
      */
-    private String getDummyNumber(boolean isVideo) {
+    private String getRandomNumber(boolean isVideo) {
         int videoDigit = isVideo ? 1 : 0;
         int number = mRandom.nextInt(999);
         return String.format("555%s%03d", videoDigit, number);
diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml
index 3fb2a84..02b35a4 100644
--- a/tests/AndroidTest.xml
+++ b/tests/AndroidTest.xml
@@ -27,4 +27,10 @@
         <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
         <option name="hidden-api-checks" value="false"/>
     </test>
+    <object type="module_controller"
+            class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
+        <option name="screenshot-on-failure" value="false" />
+        <option name="bugreportz-on-failure" value="false" />
+        <option name="logcat-on-failure" value="true" />
+  </object>
 </configuration>
diff --git a/tests/src/com/android/server/telecom/tests/BasicCallTests.java b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
index 6fd53eb..a8e1c00 100644
--- a/tests/src/com/android/server/telecom/tests/BasicCallTests.java
+++ b/tests/src/com/android/server/telecom/tests/BasicCallTests.java
@@ -163,6 +163,9 @@
                 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
         telecomManager.acceptRingingCall();
 
+        waitForHandlerAction(mTelecomSystem.getCallsManager()
+                .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
+
         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                 .answer(eq(ids.mConnectionId), any());
         mConnectionServiceFixtureA.sendSetActive(ids.mConnectionId);
@@ -219,6 +222,9 @@
                 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
         telecomManager.acceptRingingCall(VideoProfile.STATE_AUDIO_ONLY);
 
+        waitForHandlerAction(mTelecomSystem.getCallsManager()
+                .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
+
         // The generic answer method on the ConnectionService is used to answer audio-only calls.
         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                 .answer(eq(ids.mConnectionId), any());
@@ -248,6 +254,9 @@
                 .getApplicationContext().getSystemService(Context.TELECOM_SERVICE);
         telecomManager.acceptRingingCall(999 /* invalid videostate */);
 
+        waitForHandlerAction(mTelecomSystem.getCallsManager()
+                .getConnectionServiceFocusManager().getHandler(), TEST_TIMEOUT);
+
         // Answer video API should be called
         verify(mConnectionServiceFixtureA.getTestDouble(), timeout(TEST_TIMEOUT))
                 .answerVideo(eq(ids.mConnectionId), eq(VideoProfile.STATE_BIDIRECTIONAL), any());
@@ -626,6 +635,10 @@
         mConnectionServiceFixtureA.
                 sendSetDisconnected(outgoing.mConnectionId, DisconnectCause.REMOTE);
 
+        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
+                .getCallAudioModeStateMachine().getHandler(), TEST_TIMEOUT);
+        waitForHandlerAction(mTelecomSystem.getCallsManager().getCallAudioManager()
+                .getCallAudioRouteStateMachine().getHandler(), TEST_TIMEOUT);
         verify(audioManager, timeout(TEST_TIMEOUT))
                 .abandonAudioFocusForCall();
         verify(audioManager, timeout(TEST_TIMEOUT).atLeastOnce())
diff --git a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
index 58f1ee7..879ed0f 100644
--- a/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
+++ b/tests/src/com/android/server/telecom/tests/CallAudioRouteTransitionTests.java
@@ -384,8 +384,12 @@
         // rest of the system
         verifyNoSystemAudioChanges();
 
+        // Special case for SPEAKER_ON -- we don't expect any route transitions to happen when
+        // there are no calls, so set the expected state to the initial route.
+        int expectedRoute = (mParams.action == CallAudioRouteStateMachine.SPEAKER_ON)
+                ? mParams.initialRoute : mParams.expectedRoute;
         // Verify the end state
-        CallAudioState expectedState = new CallAudioState(false, mParams.expectedRoute,
+        CallAudioState expectedState = new CallAudioState(false, expectedRoute,
                 mParams.expectedAvailableRoutes | CallAudioState.ROUTE_SPEAKER,
                 mParams.expectedBluetoothDevice, mParams.availableBluetoothDevices);
         assertEquals(expectedState, stateMachine.getCurrentCallAudioState());
@@ -811,7 +815,7 @@
                 "Speakerphone turned off externally during speaker", // name
                 CallAudioState.ROUTE_SPEAKER, // initialRoute
                 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes
-                NONE, // speakerInteraction
+                OFF, // speakerInteraction
                 ON, // bluetoothInteraction
                 CallAudioRouteStateMachine.SPEAKER_OFF, // action
                 CallAudioState.ROUTE_BLUETOOTH, // expectedRoute
diff --git a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
index 4dffe59..0cc04d6 100644
--- a/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CallsManagerTest.java
@@ -1019,7 +1019,7 @@
     @SmallTest
     @Test
     public void testHangupActiveCallWhenHeadsetMediaButtonLongPressDuringTwoCalls() {
-        // GIVEN an  ongoing call
+        // GIVEN an ongoing call
         Call ongoingCall = addSpyCall();
         doReturn(CallState.ACTIVE).when(ongoingCall).getState();
 
diff --git a/tests/src/com/android/server/telecom/tests/CarModeTrackerTest.java b/tests/src/com/android/server/telecom/tests/CarModeTrackerTest.java
index 4ef4596..dbfcdb1 100644
--- a/tests/src/com/android/server/telecom/tests/CarModeTrackerTest.java
+++ b/tests/src/com/android/server/telecom/tests/CarModeTrackerTest.java
@@ -17,6 +17,7 @@
 package com.android.server.telecom.tests;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.TestCase.assertNull;
 
@@ -104,6 +105,17 @@
     }
 
     /**
+     * Ensure that we don't keep a package around after it's been removed from the device
+     */
+    @Test
+    public void testForceExitCarMode() {
+        testEnterCarModeBasic();
+        mCarModeTracker.forceExitCarMode(CAR_MODE_APP1_PACKAGE_NAME);
+        assertFalse(mCarModeTracker.isInCarMode());
+        assertNull(mCarModeTracker.getCurrentCarModePackage());
+    }
+
+    /**
      * Verifies only the first app at the default priority gets tracked.
      */
     @Test
diff --git a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
index 46b1522..26f24ef 100755
--- a/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
+++ b/tests/src/com/android/server/telecom/tests/ConnectionServiceFixture.java
@@ -249,6 +249,7 @@
 
         @Override
         public void createConnectionComplete(String id, Session.Info info) throws RemoteException {
+            Log.i(ConnectionServiceFixture.this, "createConnectionComplete: %s", id);
             mConnectionServiceDelegateAdapter.createConnectionComplete(id, null /*Session.Info*/);
         }
 
diff --git a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
index e16b598..0e5ac27 100644
--- a/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
+++ b/tests/src/com/android/server/telecom/tests/InCallControllerTests.java
@@ -23,6 +23,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.matches;
 import static org.mockito.ArgumentMatchers.nullable;
@@ -34,6 +35,7 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -65,6 +67,7 @@
 import android.telecom.TelecomManager;
 import android.test.mock.MockContext;
 import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.SmallTest;
 import android.text.TextUtils;
 
 import com.android.internal.telecom.IInCallAdapter;
@@ -98,6 +101,7 @@
 
 import java.util.Collections;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.concurrent.CompletableFuture;
 
 @RunWith(JUnit4.class)
@@ -133,6 +137,10 @@
     private static final String CAR2_CLASS = "carcls";
     private static final int CAR_UID = 4;
     private static final int CAR2_UID = 5;
+    private static final String NONUI_PKG = "nonui_pkg";
+    private static final String NONUI_CLASS = "nonui_cls";
+    private static final int NONUI_UID = 6;
+
     private static final PhoneAccountHandle PA_HANDLE =
             new PhoneAccountHandle(new ComponentName("pa_pkg", "pa_cls"), "pa_id");
 
@@ -140,6 +148,8 @@
     private InCallController mInCallController;
     private TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() {};
     private EmergencyCallHelper mEmergencyCallHelper;
+    private SystemStateHelper.SystemStateListener mSystemStateListener;
+    private CarModeTracker mCarModeTracker = spy(new CarModeTracker());
 
     @Override
     @Before
@@ -160,7 +170,13 @@
         when(mMockCallsManager.getRoleManagerAdapter()).thenReturn(mMockRoleManagerAdapter);
         mInCallController = new InCallController(mMockContext, mLock, mMockCallsManager,
                 mMockSystemStateHelper, mDefaultDialerCache, mTimeoutsAdapter,
-                mEmergencyCallHelper, new CarModeTracker(), mClockProxy);
+                mEmergencyCallHelper, mCarModeTracker, mClockProxy);
+
+        ArgumentCaptor<SystemStateHelper.SystemStateListener> systemStateListenerArgumentCaptor
+                = ArgumentCaptor.forClass(SystemStateHelper.SystemStateListener.class);
+        verify(mMockSystemStateHelper).addListener(systemStateListenerArgumentCaptor.capture());
+        mSystemStateListener = systemStateListenerArgumentCaptor.getValue();
+
         when(mMockContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
                 .thenReturn(mNotificationManager);
         // Companion Apps don't have CONTROL_INCALL_EXPERIENCE permission.
@@ -177,6 +193,8 @@
                     return new String[] { CAR_PKG };
                 case CAR2_UID:
                     return new String[] { CAR2_PKG };
+                case NONUI_UID:
+                    return new String[] { NONUI_PKG };
             }
             return null;
         }).when(mMockPackageManager).getPackagesForUid(anyInt());
@@ -189,6 +207,9 @@
         when(mMockPackageManager.checkPermission(
                 matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
                 matches(CAR2_PKG))).thenReturn(PackageManager.PERMISSION_GRANTED);
+        when(mMockPackageManager.checkPermission(
+                matches(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
+                matches(NONUI_PKG))).thenReturn(PackageManager.PERMISSION_GRANTED);
     }
 
     @Override
@@ -199,6 +220,24 @@
         super.tearDown();
     }
 
+    @SmallTest
+    @Test
+    public void testCarModeAppRemoval() {
+        setupMockPackageManager(true /* default */, true /* system */, true /* external calls */);
+        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
+        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
+
+        when(mMockSystemStateHelper.isCarMode()).thenReturn(true);
+
+        mSystemStateListener.onCarModeChanged(666, CAR_PKG, true);
+        verify(mCarModeTracker).handleEnterCarMode(666, CAR_PKG);
+        assertTrue(mCarModeTracker.isInCarMode());
+
+        mSystemStateListener.onPackageUninstalled(CAR_PKG);
+        verify(mCarModeTracker).forceExitCarMode(CAR_PKG);
+        assertFalse(mCarModeTracker.isInCarMode());
+    }
+
     @MediumTest
     @Test
     public void testBindToService_NoServicesFound_IncomingCall() throws Exception {
@@ -291,7 +330,8 @@
         ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
                 queryIntentCaptor.capture(),
-                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
+                eq(PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_COMPONENTS),
+                eq(CURRENT_USER_ID));
 
         // Verify call for default dialer InCallService
         assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
@@ -350,7 +390,8 @@
         ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
                 queryIntentCaptor.capture(),
-                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
+                eq(PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_COMPONENTS),
+                eq(CURRENT_USER_ID));
 
         // Verify call for default dialer InCallService
         assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
@@ -428,7 +469,8 @@
         ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
                 queryIntentCaptor.capture(),
-                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
+                eq(PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_COMPONENTS),
+                eq(CURRENT_USER_ID));
 
         // Verify call for default dialer InCallService
         assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
@@ -510,7 +552,8 @@
         ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
                 queryIntentCaptor.capture(),
-                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
+                eq(PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_COMPONENTS),
+                eq(CURRENT_USER_ID));
 
         // Verify call for default dialer InCallService
         assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
@@ -634,7 +677,8 @@
         ArgumentCaptor<Intent> queryIntentCaptor = ArgumentCaptor.forClass(Intent.class);
         verify(mMockPackageManager, times(4)).queryIntentServicesAsUser(
                 queryIntentCaptor.capture(),
-                eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
+                eq(PackageManager.GET_META_DATA | PackageManager.MATCH_DISABLED_COMPONENTS),
+                eq(CURRENT_USER_ID));
 
         // Verify call for default dialer InCallService
         assertEquals(DEF_PKG, queryIntentCaptor.getAllValues().get(0).getPackage());
@@ -884,13 +928,15 @@
                 nullable(ContentResolver.class))).thenReturn(500L);
 
         when(mMockCallsManager.getCalls()).thenReturn(Collections.singletonList(mMockCall));
-        setupMockPackageManager(true /* default */, true /* system */, false /* external calls */);
+        setupMockPackageManager(true /* default */, true /* nonui */, true /* system */,
+                false /* external calls */,
+                false /* self mgd in default*/, false /* self mgd in car*/);
         mInCallController.bindToServices(mMockCall);
 
         ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
         ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
                 ArgumentCaptor.forClass(ServiceConnection.class);
-        verify(mMockContext, times(1)).bindServiceAsUser(
+        verify(mMockContext, times(2)).bindServiceAsUser(
                 bindIntentCaptor.capture(),
                 serviceConnectionCaptor.capture(),
                 eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
@@ -903,13 +949,39 @@
 
         // Start the connection, make sure we don't unbind, and make sure that we don't send
         // anything to the in-call service yet.
-        ServiceConnection serviceConnection = serviceConnectionCaptor.getValue();
+        List<ServiceConnection> serviceConnections = serviceConnectionCaptor.getAllValues();
+        List<Intent> intents = bindIntentCaptor.getAllValues();
+
+        // Find the non-ui service and have it connect first.
+        int nonUiIdx = findFirstIndexMatching(intents,
+                i -> NONUI_PKG.equals(i.getComponent().getPackageName()));
+        if (nonUiIdx < 0) {
+            fail("Did not bind to non-ui incall");
+        }
+
+        {
+            ComponentName nonUiComponentName = new ComponentName(NONUI_PKG, NONUI_CLASS);
+            IBinder mockBinder = mock(IBinder.class);
+            IInCallService mockInCallService = mock(IInCallService.class);
+            when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockInCallService);
+            serviceConnections.get(nonUiIdx).onServiceConnected(nonUiComponentName, mockBinder);
+
+            // Make sure the non-ui binding didn't trigger the future.
+            assertFalse(bindTimeout.isDone());
+        }
+
+        int defDialerIdx = findFirstIndexMatching(intents,
+                i -> DEF_PKG.equals(i.getComponent().getPackageName()));
+        if (defDialerIdx < 0) {
+            fail("Did not bind to default dialer incall");
+        }
+
         ComponentName defDialerComponentName = new ComponentName(DEF_PKG, DEF_CLASS);
         IBinder mockBinder = mock(IBinder.class);
         IInCallService mockInCallService = mock(IInCallService.class);
         when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockInCallService);
 
-        serviceConnection.onServiceConnected(defDialerComponentName, mockBinder);
+        serviceConnections.get(defDialerIdx).onServiceConnected(defDialerComponentName, mockBinder);
         verify(mockInCallService).setInCallAdapter(nullable(IInCallAdapter.class));
 
         // Make sure that the future completed without timing out.
@@ -1038,6 +1110,7 @@
             serviceInfo.applicationInfo = new ApplicationInfo();
             serviceInfo.applicationInfo.uid = DEF_UID;
             serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
+            serviceInfo.enabled = true;
             serviceInfo.metaData = new Bundle();
             serviceInfo.metaData.putBoolean(
                     TelecomManager.METADATA_IN_CALL_SERVICE_UI, true);
@@ -1065,6 +1138,7 @@
                 serviceInfo.applicationInfo.uid = CAR2_UID;
             }
             serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
+            serviceInfo.enabled = true;
             serviceInfo.metaData = new Bundle();
             serviceInfo.metaData.putBoolean(
                     TelecomManager.METADATA_IN_CALL_SERVICE_CAR_MODE_UI, true);
@@ -1086,6 +1160,7 @@
             serviceInfo.name = SYS_CLASS;
             serviceInfo.applicationInfo = new ApplicationInfo();
             serviceInfo.applicationInfo.uid = SYS_UID;
+            serviceInfo.enabled = true;
             serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
         }};
     }
@@ -1097,13 +1172,26 @@
             serviceInfo.name = COMPANION_CLASS;
             serviceInfo.applicationInfo = new ApplicationInfo();
             serviceInfo.applicationInfo.uid = COMPANION_UID;
+            serviceInfo.enabled = true;
+            serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
+        }};
+    }
+
+    private ResolveInfo getNonUiResolveinfo() {
+        return new ResolveInfo() {{
+            serviceInfo = new ServiceInfo();
+            serviceInfo.packageName = NONUI_PKG;
+            serviceInfo.name = NONUI_CLASS;
+            serviceInfo.applicationInfo = new ApplicationInfo();
+            serviceInfo.applicationInfo.uid = NONUI_UID;
+            serviceInfo.enabled = true;
             serviceInfo.permission = Manifest.permission.BIND_INCALL_SERVICE;
         }};
     }
 
     private void setupMockPackageManager(final boolean useDefaultDialer,
             final boolean useSystemDialer, final boolean includeExternalCalls) {
-        setupMockPackageManager(useDefaultDialer, useSystemDialer, includeExternalCalls,
+        setupMockPackageManager(useDefaultDialer, false, useSystemDialer, includeExternalCalls,
                 false /* self mgd */, false /* self mgd */);
     }
 
@@ -1111,6 +1199,16 @@
             final boolean useSystemDialer, final boolean includeExternalCalls,
             final boolean includeSelfManagedCallsInDefaultDialer,
             final boolean includeSelfManagedCallsInCarModeDialer) {
+        setupMockPackageManager(useDefaultDialer, false /* nonui */, useSystemDialer,
+                includeExternalCalls, includeSelfManagedCallsInDefaultDialer,
+                includeSelfManagedCallsInCarModeDialer);
+    }
+
+    private void setupMockPackageManager(final boolean useDefaultDialer,
+            final boolean useNonUiInCalls,
+            final boolean useSystemDialer, final boolean includeExternalCalls,
+            final boolean includeSelfManagedCallsInDefaultDialer,
+            final boolean includeSelfManagedCallsInCarModeDialer) {
         doAnswer(new Answer() {
             @Override
             public Object answer(InvocationOnMock invocation) throws Throwable {
@@ -1145,11 +1243,17 @@
                         resolveInfo.add(getCarModeResolveinfo(CAR2_PKG, CAR2_CLASS,
                                 includeExternalCalls, includeSelfManagedCallsInCarModeDialer));
                     }
+                } else {
+                    // InCallController uses a blank package name when querying for non-ui incalls
+                    if (useNonUiInCalls) {
+                        resolveInfo.add(getNonUiResolveinfo());
+                    }
                 }
+
                 return resolveInfo;
             }
         }).when(mMockPackageManager).queryIntentServicesAsUser(
-                any(Intent.class), eq(PackageManager.GET_META_DATA), eq(CURRENT_USER_ID));
+                any(Intent.class), anyInt(), eq(CURRENT_USER_ID));
     }
 
     private void setupMockPackageManagerLocationPermission(final String pkg,
diff --git a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
index 9470008..a5b78b7 100644
--- a/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
+++ b/tests/src/com/android/server/telecom/tests/NewOutgoingCallIntentBroadcasterTest.java
@@ -229,7 +229,7 @@
         mComponentContextFixture.putResource(R.string.dialer_default_class,
                 dialer_default_class_string);
         when(mDefaultDialerCache.getSystemDialerApplication()).thenReturn(ui_package_string);
-        when(mDefaultDialerCache.getSystemDialerComponent()).thenReturn(
+        when(mDefaultDialerCache.getDialtactsSystemDialerComponent()).thenReturn(
                 new ComponentName(ui_package_string, dialer_default_class_string));
 
         int result = processIntent(intent, false).disconnectCause;
diff --git a/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java b/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java
index 2de3c83..893ae3d 100644
--- a/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java
+++ b/tests/src/com/android/server/telecom/tests/SystemStateHelperTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.telecom.tests;
 
+import static junit.framework.Assert.fail;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -23,9 +25,11 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -39,6 +43,7 @@
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
+import android.net.Uri;
 import android.test.suitebuilder.annotation.SmallTest;
 
 import com.android.server.telecom.SystemStateHelper;
@@ -53,11 +58,10 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.mockito.internal.util.reflection.FieldSetter;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 /**
  * Unit tests for SystemStateHelper
@@ -128,16 +132,53 @@
 
     @SmallTest
     @Test
-    public void testReceiverAndIntentFilter() {
-        ArgumentCaptor<IntentFilter> intentFilter = ArgumentCaptor.forClass(IntentFilter.class);
-        new SystemStateHelper(mContext);
-        verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
+    public void testPackageRemoved() {
+        ArgumentCaptor<BroadcastReceiver> receiver =
+                ArgumentCaptor.forClass(BroadcastReceiver.class);
+        new SystemStateHelper(mContext).addListener(mSystemStateListener);
+        verify(mContext, atLeastOnce())
+                .registerReceiver(receiver.capture(), any(IntentFilter.class));
+        Intent packageRemovedIntent = new Intent(Intent.ACTION_PACKAGE_REMOVED);
+        packageRemovedIntent.setData(Uri.fromParts("package", "com.android.test", null));
+        receiver.getValue().onReceive(mContext, packageRemovedIntent);
+        verify(mSystemStateListener).onPackageUninstalled("com.android.test");
+    }
 
-        assertEquals(2, intentFilter.getValue().countActions());
-        assertEquals(UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED,
-                intentFilter.getValue().getAction(0));
-        assertEquals(UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED,
-                intentFilter.getValue().getAction(1));
+    @SmallTest
+    @Test
+    public void testReceiverAndIntentFilter() {
+        ArgumentCaptor<IntentFilter> intentFilterCaptor =
+                ArgumentCaptor.forClass(IntentFilter.class);
+        new SystemStateHelper(mContext);
+        verify(mContext, times(2)).registerReceiver(
+                any(BroadcastReceiver.class), intentFilterCaptor.capture());
+
+        Predicate<IntentFilter> carModeFilterTest = (intentFilter) ->
+                2 == intentFilter.countActions()
+                        && intentFilter.hasAction(UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED)
+                        && intentFilter.hasAction(UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED);
+
+        Predicate<IntentFilter> packageRemovedFilterTest = (intentFilter) ->
+                1 == intentFilter.countActions()
+                        && intentFilter.hasAction(Intent.ACTION_PACKAGE_REMOVED)
+                        && intentFilter.hasDataScheme("package");
+
+        List<IntentFilter> capturedFilters = intentFilterCaptor.getAllValues();
+        assertEquals(2, capturedFilters.size());
+        for (IntentFilter filter : capturedFilters) {
+            if (carModeFilterTest.test(filter)) {
+                carModeFilterTest = (i) -> false;
+                continue;
+            }
+            if (packageRemovedFilterTest.test(filter)) {
+                packageRemovedFilterTest = (i) -> false;
+                continue;
+            }
+            String failString = String.format("Registered intent filters not correct. Got %s",
+                    capturedFilters.stream().map(IntentFilter::toString)
+                            .collect(Collectors.joining("\n")));
+            fail(failString);
+        }
     }
 
     @SmallTest
@@ -147,7 +188,8 @@
                 ArgumentCaptor.forClass(BroadcastReceiver.class);
         new SystemStateHelper(mContext).addListener(mSystemStateListener);
 
-        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
+        verify(mContext, atLeastOnce())
+                .registerReceiver(receiver.capture(), any(IntentFilter.class));
 
         when(mIntentEnter.getAction()).thenReturn(UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED);
         receiver.getValue().onReceive(mContext, mIntentEnter);
diff --git a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
index 442c310..152dfe5 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomSystemTest.java
@@ -925,7 +925,12 @@
         // Wait for the handler to start the CallerInfo lookup
         waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
 
+        // Wait a few more times to address flakiness due to timing issues.
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
+        waitForHandlerAction(new Handler(Looper.getMainLooper()), TEST_TIMEOUT);
+
         // Ensure callback to CS on successful creation happened.
+
         verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
                 .createConnectionComplete(anyString(), any());
 
diff --git a/tests/src/com/android/server/telecom/tests/TelecomTestCase.java b/tests/src/com/android/server/telecom/tests/TelecomTestCase.java
index b0b1ec0..264e087 100644
--- a/tests/src/com/android/server/telecom/tests/TelecomTestCase.java
+++ b/tests/src/com/android/server/telecom/tests/TelecomTestCase.java
@@ -25,8 +25,10 @@
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Predicate;
 
 public abstract class TelecomTestCase {
     protected static final String TESTING_TAG = "Telecom-TEST";
@@ -75,4 +77,13 @@
             }
         }
     }
+
+    protected static <T> int findFirstIndexMatching(List<T> items, Predicate<T> matcher) {
+        for (int i = 0; i < items.size(); i++) {
+            if (matcher.test(items.get(i))) {
+                return i;
+            }
+        }
+        return -1;
+    }
 }