Merge "Make sure manual selected network is shown in next search result."
diff --git a/Android.mk b/Android.mk
index be929f1..4846ea1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -46,6 +46,7 @@
     --extra-packages android.support.v14.preference
 
 LOCAL_PACKAGE_NAME := TeleService
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3665284..f86cdef 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -181,6 +181,7 @@
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
     <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
     <uses-permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE" />
+    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
 
     <application android:name="PhoneApp"
             android:persistent="true"
diff --git a/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml b/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml
new file mode 100644
index 0000000..905dc55
--- /dev/null
+++ b/res/drawable/progress_indeterminate_horizontal_material_trimmed.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Variant of progress_indeterminate_horizontal_material in frameworks/base/core/res, which
+     draws the whole height of the progress bar instead having blank space above and below the
+     bar. -->
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:drawable="@drawable/vector_drawable_progress_indeterminate_horizontal_trimmed" >
+    <target
+        android:name="rect2_grp"
+        android:animation="@*android:anim/progress_indeterminate_horizontal_rect2" />
+    <target
+        android:name="rect1_grp"
+        android:animation="@*android:anim/progress_indeterminate_horizontal_rect1" />
+</animated-vector>
\ No newline at end of file
diff --git a/res/drawable/signal_strength_1x.xml b/res/drawable/signal_strength_1x.xml
new file mode 100644
index 0000000..d1d2229
--- /dev/null
+++ b/res/drawable/signal_strength_1x.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2018 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="8.5dp"
+    android:height="17dp"
+    android:viewportWidth="12.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M8.600000,5.500000l1.200000,-3.000000l1.900000,0.000000L9.700000,6.700000l2.200000,4.300000L9.900000,11.000000L8.700000,7.900000L7.400000,11.000000L5.500000,11.000000l2.100000,-4.300000L5.600000,2.500000l1.900000,0.000000L8.600000,5.500000z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/signal_strength_3g.xml b/res/drawable/signal_strength_3g.xml
new file mode 100644
index 0000000..49f52a9
--- /dev/null
+++ b/res/drawable/signal_strength_3g.xml
@@ -0,0 +1,28 @@
+<!--
+Copyright (C) 2018 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="9.208dp"
+    android:height="17dp"
+    android:viewportWidth="13.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S6.700000,9.000000 6.700000,7.900000L6.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000l-1.600000,0.000000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000s-0.500000,-0.300000 -0.900000,-0.300000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S8.400000,5.000000 8.400000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L10.799999,7.800000L9.600000,7.800000L9.600000,6.600000l2.900000,0.000000L12.500000,9.900000z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/signal_strength_g.xml b/res/drawable/signal_strength_g.xml
new file mode 100644
index 0000000..7258c94
--- /dev/null
+++ b/res/drawable/signal_strength_g.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2018 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="4.958dp"
+    android:height="17dp"
+    android:viewportWidth="7.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/signal_strength_lte.xml b/res/drawable/signal_strength_lte.xml
new file mode 100644
index 0000000..e6edd24
--- /dev/null
+++ b/res/drawable/signal_strength_lte.xml
@@ -0,0 +1,31 @@
+<!--
+Copyright (C) 2018 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="9.208dp"
+    android:height="17dp"
+    android:viewportWidth="13.0"
+    android:viewportHeight="24.0"
+    android:tint="?android:attr/colorControlNormal">
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M8.300000,3.800000L7.000000,3.800000L7.000000,11.000000L5.300000,11.000000L5.300000,3.800000L4.000000,3.800000L4.000000,2.500000l4.300000,0.000000L8.300000,3.800000z"/>
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M12.400000,7.300000l-1.700000,0.000000l0.000000,2.400000l2.100000,0.000000L12.799999,11.000000L9.000000,11.000000L9.000000,2.500000l3.700000,0.000000l0.000000,1.300000l-2.100000,0.000000l0.000000,2.100000l1.700000,0.000000L12.300000,7.300000z"/>
+</vector>
\ No newline at end of file
diff --git a/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml b/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml
new file mode 100644
index 0000000..dc0352a
--- /dev/null
+++ b/res/drawable/vector_drawable_progress_indeterminate_horizontal_trimmed.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<!-- Variant of vector_drawable_progress_indeterminate_horizontal in frameworks/base/core/res, which
+     draws the whole height of the progress bar instead having blank space above and below the
+     bar. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:height="10dp"
+    android:width="360dp"
+    android:viewportHeight="10"
+    android:viewportWidth="360" >
+    <group
+        android:name="progress_group"
+        android:translateX="180"
+        android:translateY="5" >
+        <path
+            android:name="background_track"
+            android:pathData="M -180.0,-5.0 l 360.0,0 l 0,10.0 l -360.0,0 Z"
+            android:fillColor="?android:attr/colorControlActivated"
+            android:fillAlpha="?android:attr/disabledAlpha"/>
+        <group
+            android:name="rect2_grp"
+            android:translateX="-197.60001"
+            android:scaleX="0.1" >
+            <path
+                android:name="rect2"
+                android:pathData="M -144.0,-5.0 l 288.0,0 l 0,10.0 l -288.0,0 Z"
+                android:fillColor="?android:attr/colorControlActivated" />
+        </group>
+        <group
+            android:name="rect1_grp"
+            android:translateX="-522.59998"
+            android:scaleX="0.1" >
+            <path
+                android:name="rect1"
+                android:pathData="M -144.0,-5.0 l 288.0,0 l 0,10.0 l -288.0,0 Z"
+                android:fillColor="?android:attr/colorControlActivated" />
+        </group>
+    </group>
+</vector>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 5dc7279..f6d1b79 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -108,4 +108,6 @@
     <dimen name="floating_action_button_width">67dp</dimen>
     <dimen name="floating_action_button_height">67dp</dimen>
     <dimen name="floating_action_button_margin_bottom">32dp</dimen>
+
+    <dimen name="signal_strength_icon_size">24dp</dimen>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 72be3b2..f8afe6f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -283,10 +283,10 @@
     <string name="exception_error">Network or SIM card error.</string>
     <!-- Status message displayed in the "Call settings error" dialog when
          current SS request is modified to a different request by STK CC -->
-    <string name="stk_cc_ss_to_dial_error">SS request modified to DIAL request.</string>
-    <string name="stk_cc_ss_to_ussd_error">SS request modified to USSD request.</string>
-    <string name="stk_cc_ss_to_ss_error">SS request modified to new SS request.</string>
-    <string name="stk_cc_ss_to_dial_video_error">SS request modified to Video DIAL request.</string>
+    <string name="stk_cc_ss_to_dial_error">SS request changed to regular call</string>
+    <string name="stk_cc_ss_to_ussd_error">SS request changed to USSD request</string>
+    <string name="stk_cc_ss_to_ss_error">Changed to new SS request</string>
+    <string name="stk_cc_ss_to_dial_video_error">SS request changed to video call</string>
 
     <!-- Status message displayed in the "Call settings error" dialog when operation fails due to FDN
          [CHAR LIMIT=NONE] -->
@@ -369,7 +369,7 @@
     <!-- Available networks screen, text when no networks are found -->
     <string name="empty_networks_list">No networks found.</string>
     <!-- Available networks screen, toast when an error is encountered when searching for networks -->
-    <string name="network_query_error">Error while searching for networks.</string>
+    <string name="network_query_error">Couldn\'t find networks. Try again.</string>
     <!-- Available networks screen, toast when registering on a specific network -->
     <string name="register_on_network">Registering on <xliff:g id="network">%s</xliff:g>\u2026</string>
     <!-- Available networks screen, toast when SIM card isn't allowed on a network -->
@@ -387,6 +387,16 @@
     <string name="preferred_network_mode_summary">Change the network operating mode</string>
     <string name="preferred_network_mode_dialogtitle">Preferred network type</string>
     <string name="forbidden_network">(forbidden)</string>
+    <!-- Available networks screen, name of button when user wants to select network manually  -->
+    <string name="choose_network_title">Choose network</string>
+    <!-- Available networks screen, text when no networks connected -->
+    <string name="network_disconnected">Disconnected</string>
+    <!-- Available networks screen, text when network connected -->
+    <string name="network_connected">Connected</string>
+    <!-- Available networks screen, text when a network is connecting -->
+    <string name="network_connecting">Connecting...</string>
+    <!-- Available networks screen, text when a network cannot be connected -->
+    <string name="network_could_not_connect">Couldn’t connect</string>
 
     <!-- The preferred network modes in Mobile network settings -->
     <string-array name="preferred_network_mode_choices">
@@ -524,7 +534,9 @@
     <!-- Mobile network settings UI: notification message shown when you
          lose data connectivity because you're roaming and you have the
          "data roaming" feature turned off. -->
-    <string name="roaming_reenable_message">You\'ve lost data connectivity because you left your home network with data roaming turned off.</string>
+    <string name="roaming_reenable_message">Data roaming is turned off. Tap to turn on.</string>
+    <!-- Roaming notification tile, notifying lost of roaming data connection -->
+    <string name="roaming_notification_title">Lost mobile data connection</string>
     <!-- Mobile network settings screen, dialog message when user selects the Data roaming check box -->
     <string name="roaming_warning">You may incur significant charges.</string>
     <!-- Mobile network settings screen, dialog message title when user selects the Data roaming check box -->
@@ -1499,111 +1511,111 @@
     <!-- In-call screen: status label displayed briefly after a call ends -->
     <string name="clh_card_title_call_ended_txt">Call ended</string>
     <!-- In-call screen: call failure reason (radio is off) -->
-    <string name="clh_callFailed_powerOff_txt">Radio off</string>
+    <string name="clh_callFailed_powerOff_txt">Airplane mode is on</string>
     <!-- In-call screen: call failure reason (SIM error) -->
-    <string name="clh_callFailed_simError_txt">No SIM card or SIM card error</string>
+    <string name="clh_callFailed_simError_txt">Can\'t access SIM card</string>
     <!-- In-call screen: call failure message displayed in an error dialog -->
     <string name="clh_incall_error_out_of_service_txt">Mobile network not available</string>
 
     <!-- See CallFailCause for details on what causes each message -->
     <!-- In-call screen: call failure reason (Cause Number 1) -->
-    <string name="clh_callFailed_unassigned_number_txt">Unassigned (unallocated) number</string>
+    <string name="clh_callFailed_unassigned_number_txt">Issue with phone number you are trying to dial. Error code 1.</string>
     <!-- In-call screen: call failure reason (Cause Number 3) -->
-    <string name="clh_callFailed_no_route_to_destination_txt">No route to destination</string>
+    <string name="clh_callFailed_no_route_to_destination_txt">Couldn\'t complete call. Error code 3.</string>
     <!-- In-call screen: call failure reason (Cause Number 6) -->
-    <string name="clh_callFailed_channel_unacceptable_txt">Channel unacceptable</string>
+    <string name="clh_callFailed_channel_unacceptable_txt">Couldn\'t complete call. Error code 6.</string>
     <!-- In-call screen: call failure reason (Cause Number 8) -->
-    <string name="clh_callFailed_operator_determined_barring_txt">Operator determined barring</string>
+    <string name="clh_callFailed_operator_determined_barring_txt">Couldn\'t complete call. Error code 8.</string>
     <!-- In-call screen: call failure reason (Cause Number 16) -->
-    <string name="clh_callFailed_normal_call_clearing_txt">Normal call clearing</string>
+    <string name="clh_callFailed_normal_call_clearing_txt">Couldn\'t complete call. Error code 16.</string>
     <!-- In-call screen: call failure reason (Cause Number 17) -->
     <string name="clh_callFailed_user_busy_txt">User busy</string>
     <!-- In-call screen: call failure reason (Cause Number 18) -->
-    <string name="clh_callFailed_no_user_responding_txt">No user responding</string>
+    <string name="clh_callFailed_no_user_responding_txt">User not responding</string>
     <!-- In-call screen: call failure reason (Cause Number 19) -->
-    <string name="clh_callFailed_user_alerting_txt">User alerting, no answer</string>
+    <string name="clh_callFailed_user_alerting_txt">Couldn\'t complete call. Error code 19.</string>
     <!-- In-call screen: call failure reason (Cause Number 21) -->
     <string name="clh_callFailed_call_rejected_txt">Call rejected</string>
     <!-- In-call screen: call failure reason (Cause Number 22) -->
     <string name="clh_callFailed_number_changed_txt">Number changed</string>
     <!-- In-call screen: call failure reason (Cause Number 25) -->
-    <string name="clh_callFailed_pre_emption_txt">Pre-emption</string>
+    <string name="clh_callFailed_pre_emption_txt">Couldn\'t complete call. Error code 25.</string>
     <!-- In-call screen: call failure reason (Cause Number 26) -->
-    <string name="clh_callFailed_non_selected_user_clearing_txt">Non selected user clearing</string>
+    <string name="clh_callFailed_non_selected_user_clearing_txt">Couldn\'t complete call. Error code 26.</string>
     <!-- In-call screen: call failure reason (Cause Number 27) -->
-    <string name="clh_callFailed_destination_out_of_order_txt">Destination out of order</string>
+    <string name="clh_callFailed_destination_out_of_order_txt">Couldn\'t complete call. Error code 27.</string>
     <!-- In-call screen: call failure reason (Cause Number 28) -->
     <string name="clh_callFailed_invalid_number_format_txt">Invalid number format (incomplete number)</string>
     <!-- In-call screen: call failure reason (Cause Number 29) -->
-    <string name="clh_callFailed_facility_rejected_txt">Facility rejected</string>
+    <string name="clh_callFailed_facility_rejected_txt">Couldn\'t complete call. Error code 29.</string>
     <!-- In-call screen: call failure reason (Cause Number 30) -->
-    <string name="clh_callFailed_response_to_STATUS_ENQUIRY_txt">Response to STATUS ENQUIRY</string>
+    <string name="clh_callFailed_response_to_STATUS_ENQUIRY_txt">Couldn\'t complete call. Error code 30.</string>
     <!-- In-call screen: call failure reason (Cause Number 31) -->
-    <string name="clh_callFailed_normal_unspecified_txt">Normal, unspecified</string>
+    <string name="clh_callFailed_normal_unspecified_txt">Couldn\'t complete call. Error code 31.</string>
     <!-- In-call screen: call failure reason (Cause Number 34) -->
-    <string name="clh_callFailed_no_circuit_available_txt">No circuit/channel available</string>
+    <string name="clh_callFailed_no_circuit_available_txt">Couldn\'t complete call. Error code 34.</string>
     <!-- In-call screen: call failure reason (Cause Number 38) -->
-    <string name="clh_callFailed_network_out_of_order_txt">Network out of order</string>
+    <string name="clh_callFailed_network_out_of_order_txt">Couldn\'t complete call. Error code 38.</string>
     <!-- In-call screen: call failure reason (Cause Number 41) -->
-    <string name="clh_callFailed_temporary_failure_txt">Temporary failure</string>
+    <string name="clh_callFailed_temporary_failure_txt">Couldn\'t complete call. Error code 41.</string>
     <!-- In-call screen: call failure reason (Cause Number 42) -->
-    <string name="clh_callFailed_switching_equipment_congestion_txt">Switching equipment congestion</string>
+    <string name="clh_callFailed_switching_equipment_congestion_txt">Couldn\'t complete call. Error code 42.</string>
     <!-- In-call screen: call failure reason (Cause Number 43) -->
-    <string name="clh_callFailed_access_information_discarded_txt">Access information discarded</string>
+    <string name="clh_callFailed_access_information_discarded_txt">Couldn\'t complete call. Error code 43.</string>
     <!-- In-call screen: call failure reason (Cause Number 44) -->
-    <string name="clh_callFailed_requested_circuit_txt">Requested circuit/channel not available</string>
+    <string name="clh_callFailed_requested_circuit_txt">Couldn\'t complete call. Error code 44.</string>
     <!-- In-call screen: call failure reason (Cause Number 47) -->
-    <string name="clh_callFailed_resources_unavailable_unspecified_txt">Resources unavailable, unspecified</string>
+    <string name="clh_callFailed_resources_unavailable_unspecified_txt">Couldn\'t complete call. Error code 47.</string>
     <!-- In-call screen: call failure reason (Cause Number 49) -->
-    <string name="clh_callFailed_quality_of_service_unavailable_txt">Quality of service unavailable</string>
+    <string name="clh_callFailed_quality_of_service_unavailable_txt">Couldn\'t complete call. Error code 49.</string>
     <!-- In-call screen: call failure reason (Cause Number 50) -->
-    <string name="clh_callFailed_requested_facility_not_subscribed_txt">Requested facility not subscribed</string>
+    <string name="clh_callFailed_requested_facility_not_subscribed_txt">Couldn\'t complete call. Error code 50.</string>
     <!-- In-call screen: call failure reason (Cause Number 55) -->
-    <string name="clh_callFailed_incoming_calls_barred_within_the_CUG_txt">Incoming calls barred within the CUG</string>
+    <string name="clh_callFailed_incoming_calls_barred_within_the_CUG_txt">Couldn\'t complete call. Error code 55.</string>
     <!-- In-call screen: call failure reason (Cause Number 57) -->
-    <string name="clh_callFailed_bearer_capability_not_authorized_txt">Bearer capability not authorized</string>
+    <string name="clh_callFailed_bearer_capability_not_authorized_txt">Couldn\'t complete call. Error code 57.</string>
     <!-- In-call screen: call failure reason (Cause Number 58) -->
-    <string name="clh_callFailed_bearer_capability_not_presently_available_txt">Bearer capability not presently available</string>
+    <string name="clh_callFailed_bearer_capability_not_presently_available_txt">Couldn\'t complete call. Error code 58.</string>
     <!-- In-call screen: call failure reason (Cause Number 63) -->
-    <string name="clh_callFailed_service_or_option_not_available_unspecified_txt">Service or option not available, unspecified</string>
+    <string name="clh_callFailed_service_or_option_not_available_unspecified_txt">Couldn\'t complete call. Error code 63.</string>
     <!-- In-call screen: call failure reason (Cause Number 65) -->
-    <string name="clh_callFailed_bearer_service_not_implemented_txt">Bearer service not implemented</string>
+    <string name="clh_callFailed_bearer_service_not_implemented_txt">Couldn\'t complete call. Error code 65.</string>
     <!-- In-call screen: call failure reason (Cause Number 68) -->
-    <string name="clh_callFailed_ACM_equal_to_or_greater_than_ACMmax_txt">ACM equal to or greater than ACMmax</string>
+    <string name="clh_callFailed_ACM_equal_to_or_greater_than_ACMmax_txt">Couldn\'t complete call. Error code 68.</string>
     <!-- In-call screen: call failure reason (Cause Number 69) -->
-    <string name="clh_callFailed_requested_facility_not_implemented_txt">Requested facility not implemented</string>
+    <string name="clh_callFailed_requested_facility_not_implemented_txt">Couldn\'t complete call. Error code 69.</string>
     <!-- In-call screen: call failure reason (Cause Number 70) -->
-    <string name="clh_callFailed_only_restricted_digital_information_bearer_capability_is_available_txt">Only restricted digital information bearer capability is available</string>
+    <string name="clh_callFailed_only_restricted_digital_information_bearer_capability_is_available_txt">Couldn\'t complete call. Error code 70.</string>
     <!-- In-call screen: call failure reason (Cause Number 79) -->
-    <string name="clh_callFailed_service_or_option_not_implemented_unspecified_txt">Service or option not implemented, unspecified</string>
+    <string name="clh_callFailed_service_or_option_not_implemented_unspecified_txt">Couldn\'t complete call. Error code 79.</string>
     <!-- In-call screen: call failure reason (Cause Number 81) -->
-    <string name="clh_callFailed_invalid_transaction_identifier_value_txt">Invalid transaction identifier value</string>
+    <string name="clh_callFailed_invalid_transaction_identifier_value_txt">Couldn\'t complete call. Error code 81.</string>
     <!-- In-call screen: call failure reason (Cause Number 87) -->
-    <string name="clh_callFailed_user_not_member_of_CUG_txt">User not member of CUG</string>
+    <string name="clh_callFailed_user_not_member_of_CUG_txt">Couldn\'t complete call. Error code 87.</string>
     <!-- In-call screen: call failure reason (Cause Number 88) -->
-    <string name="clh_callFailed_incompatible_destination_txt">Incompatible destination</string>
+    <string name="clh_callFailed_incompatible_destination_txt">Couldn\'t complete call. Error code 88.</string>
     <!-- In-call screen: call failure reason (Cause Number 91) -->
-    <string name="clh_callFailed_invalid_transit_network_selection_txt">Invalid transit network selection</string>
+    <string name="clh_callFailed_invalid_transit_network_selection_txt">Couldn\'t complete call. Error code 91.</string>
     <!-- In-call screen: call failure reason (Cause Number 95) -->
-    <string name="clh_callFailed_semantically_incorrect_message_txt">Semantically incorrect message</string>
+    <string name="clh_callFailed_semantically_incorrect_message_txt">Couldn\'t complete call. Error code 95.</string>
     <!-- In-call screen: call failure reason (Cause Number 96) -->
-    <string name="clh_callFailed_invalid_mandatory_information_txt">Invalid mandatory information</string>
+    <string name="clh_callFailed_invalid_mandatory_information_txt">Couldn\'t complete call. Error code 96.</string>
     <!-- In-call screen: call failure reason (Cause Number 97) -->
-    <string name="clh_callFailed_message_type_non_existent_or_not_implemented_txt">Message type non-existent or not implemented</string>
+    <string name="clh_callFailed_message_type_non_existent_or_not_implemented_txt">Couldn\'t complete call. Error code 97.</string>
     <!-- In-call screen: call failure reason (Cause Number 98) -->
-    <string name="clh_callFailed_message_type_not_compatible_with_protocol_state_txt">Message type not compatible with protocol state</string>
+    <string name="clh_callFailed_message_type_not_compatible_with_protocol_state_txt">Couldn\'t complete call. Error code 98.</string>
     <!-- In-call screen: call failure reason (Cause Number 99) -->
-    <string name="clh_callFailed_information_element_non_existent_or_not_implemented_txt">Information element non-existent or not implemented</string>
+    <string name="clh_callFailed_information_element_non_existent_or_not_implemented_txt">Couldn\'t complete call. Error code 99.</string>
     <!-- In-call screen: call failure reason (Cause Number 100) -->
-    <string name="clh_callFailed_conditional_IE_error_txt">Conditional IE error</string>
+    <string name="clh_callFailed_conditional_IE_error_txt">Couldn\'t complete call. Error code 100.</string>
     <!-- In-call screen: call failure reason (Cause Number 101) -->
-    <string name="clh_callFailed_message_not_compatible_with_protocol_state_txt">Message not compatible with protocol state</string>
+    <string name="clh_callFailed_message_not_compatible_with_protocol_state_txt">Couldn\'t complete call. Error code 101.</string>
     <!-- In-call screen: call failure reason (Cause Number 102) -->
-    <string name="clh_callFailed_recovery_on_timer_expiry_txt">Recovery on timer expiry</string>
+    <string name="clh_callFailed_recovery_on_timer_expiry_txt">Couldn\'t complete call. Error code 102.</string>
     <!-- In-call screen: call failure reason (Cause Number 111) -->
-    <string name="clh_callFailed_protocol_Error_unspecified_txt">Protocol error, unspecified</string>
+    <string name="clh_callFailed_protocol_Error_unspecified_txt">Couldn\'t complete call. Error code 111.</string>
     <!-- In-call screen: call failure reason (Cause Number 127) -->
-    <string name="clh_callFailed_interworking_unspecified_txt">Interworking, unspecified</string>
+    <string name="clh_callFailed_interworking_unspecified_txt">Couldn\'t complete call. Error code 127.</string>
     <!-- Call settings screen, setting option name -->
     <string name="labelCallBarring">Call barring</string>
     <!-- Call barring settings screen, setting summary text when a call barring option is activated -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 2b893e5..d003aec 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -187,6 +187,12 @@
         <item name="android:preferenceScreenStyle">@style/SettingsPreferenceScreen</item>
     </style>
 
+    <style name="TrimmedHorizontalProgressBar" parent="android:Widget.Material.ProgressBar.Horizontal">
+        <item name="android:indeterminateDrawable">@drawable/progress_indeterminate_horizontal_material_trimmed</item>
+        <item name="android:minHeight">3dip</item>
+        <item name="android:maxHeight">3dip</item>
+    </style>
+
     <style name="Empty" parent="@android:style/Theme.Material.Light">
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
diff --git a/res/xml/cdma_options.xml b/res/xml/cdma_options.xml
index 8a41f87..6ac5dae 100644
--- a/res/xml/cdma_options.xml
+++ b/res/xml/cdma_options.xml
@@ -38,7 +38,7 @@
     <PreferenceCategory
         android:key="category_cdma_apn_key">
         <!-- The launching Intent will be defined thru code as we need to pass some Extra -->
-        <Preference
+        <com.android.phone.RestrictedPreference
             android:key="button_cdma_apn_key"
             android:title="@string/apn_settings"
             android:persistent="false"/>
diff --git a/res/xml/gsm_umts_options.xml b/res/xml/gsm_umts_options.xml
index e6ddc37..e3e2617 100644
--- a/res/xml/gsm_umts_options.xml
+++ b/res/xml/gsm_umts_options.xml
@@ -37,7 +37,7 @@
     <!--we want user to change it with caution.-->
     <PreferenceCategory
         android:key="category_gsm_apn_key">
-        <Preference
+        <com.android.phone.RestrictedPreference
             android:key="button_gsm_apn_key"
             android:title="@string/apn_settings"
             android:persistent="false" />
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 1b1327f..86f0aa4 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -56,6 +56,7 @@
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyPermissions;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -174,7 +175,7 @@
                     mConfigFromDefaultApp[phoneId] = null;
                     mConfigFromCarrierApp[phoneId] = null;
                     mServiceConnection[phoneId] = null;
-                    broadcastConfigChangedIntent(phoneId);
+                    broadcastConfigChangedIntent(phoneId, false);
                     break;
                 }
 
@@ -512,10 +513,20 @@
     }
 
     private void broadcastConfigChangedIntent(int phoneId) {
+        broadcastConfigChangedIntent(phoneId, true);
+    }
+
+    private void broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra) {
         Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
                 Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
-        SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId);
+        // Include subId extra only if SIM records are loaded
+        TelephonyManager telephonyManager = TelephonyManager.from(mContext);
+        int simApplicationState = telephonyManager.getSimApplicationState();
+        if (addSubIdExtra && (simApplicationState != TelephonyManager.SIM_STATE_UNKNOWN
+                && simApplicationState != TelephonyManager.SIM_STATE_NOT_READY)) {
+            SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId);
+        }
         intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, phoneId);
         ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
         mHasSentConfigChange[phoneId] = true;
@@ -767,12 +778,23 @@
     @Override public
     @NonNull
     PersistableBundle getConfigForSubId(int subId) {
+        // TODO(b/73136824): Migrate to TelephonyPermissions#checkCallingOrSelfReadPhoneState.
         try {
             mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, null);
             // SKIP checking run-time READ_PHONE_STATE since using PRIVILEGED
         } catch (SecurityException e) {
-            mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, null);
+            try {
+                mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, null);
+            } catch (SecurityException securityException) {
+                // If we don't have the runtime permission, but do have carrier privileges, that
+                // suffices for reading phone state.
+                if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+                    throw securityException;
+                }
+                TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, null);
+            }
         }
+
         int phoneId = SubscriptionManager.getPhoneId(subId);
         PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig();
         if (SubscriptionManager.isValidPhoneId(phoneId)) {
diff --git a/src/com/android/phone/CdmaOptions.java b/src/com/android/phone/CdmaOptions.java
index 7c09265..ff37c70 100644
--- a/src/com/android/phone/CdmaOptions.java
+++ b/src/com/android/phone/CdmaOptions.java
@@ -29,6 +29,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.Phone;
+import com.android.settingslib.RestrictedLockUtils;
 
 /**
  * List of Phone-specific settings screens.
@@ -38,7 +39,7 @@
 
     private CdmaSystemSelectListPreference mButtonCdmaSystemSelect;
     private CdmaSubscriptionListPreference mButtonCdmaSubscription;
-    private Preference mButtonAPNExpand;
+    private RestrictedPreference mButtonAPNExpand;
     private Preference mCategoryAPNExpand;
     private Preference mButtonCarrierSettings;
 
@@ -63,7 +64,7 @@
         mButtonCdmaSubscription = (CdmaSubscriptionListPreference) mPrefScreen
                 .findPreference(BUTTON_CDMA_SUBSCRIPTION_KEY);
         mButtonCarrierSettings = mPrefScreen.findPreference(BUTTON_CARRIER_SETTINGS_KEY);
-        mButtonAPNExpand = mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
+        mButtonAPNExpand = (RestrictedPreference) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
         mCategoryAPNExpand = mPrefScreen.findPreference(CATEGORY_APN_EXPAND_KEY);
 
         update(phone);
@@ -93,6 +94,10 @@
         // Calling add or remove explicitly to make sure they are updated.
 
         if (addAPNExpand) {
+            mButtonAPNExpand.setDisabledByAdmin(
+                    MobileNetworkSettings.isDpcApnEnforced(mButtonAPNExpand.getContext())
+                            ? RestrictedLockUtils.getDeviceOwner(mButtonAPNExpand.getContext())
+                            : null);
             mButtonAPNExpand.setOnPreferenceClickListener(
                     new Preference.OnPreferenceClickListener() {
                         @Override
diff --git a/src/com/android/phone/GsmUmtsOptions.java b/src/com/android/phone/GsmUmtsOptions.java
index 5cf19ad..220cf34 100644
--- a/src/com/android/phone/GsmUmtsOptions.java
+++ b/src/com/android/phone/GsmUmtsOptions.java
@@ -28,6 +28,7 @@
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneFactory;
+import com.android.settingslib.RestrictedLockUtils;
 
 /**
  * List of Network-specific settings screens.
@@ -35,7 +36,7 @@
 public class GsmUmtsOptions {
     private static final String LOG_TAG = "GsmUmtsOptions";
 
-    private Preference mButtonAPNExpand;
+    private RestrictedPreference mButtonAPNExpand;
     private Preference mCategoryAPNExpand;
     Preference mCarrierSettingPref;
 
@@ -54,7 +55,7 @@
         mPrefFragment = prefFragment;
         mPrefScreen = prefScreen;
         mPrefFragment.addPreferencesFromResource(R.xml.gsm_umts_options);
-        mButtonAPNExpand = mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
+        mButtonAPNExpand = (RestrictedPreference) mPrefScreen.findPreference(BUTTON_APN_EXPAND_KEY);
         mCategoryAPNExpand = mPrefScreen.findPreference(CATEGORY_APN_EXPAND_KEY);
         mNetworkOperator = (NetworkOperators) mPrefScreen
                 .findPreference(NetworkOperators.CATEGORY_NETWORK_OPERATORS_KEY);
@@ -113,6 +114,10 @@
         // Calling add or remove explicitly to make sure they are updated.
 
         if (addAPNExpand) {
+            mButtonAPNExpand.setDisabledByAdmin(
+                    MobileNetworkSettings.isDpcApnEnforced(mButtonAPNExpand.getContext())
+                            ? RestrictedLockUtils.getDeviceOwner(mButtonAPNExpand.getContext())
+                            : null);
             mButtonAPNExpand.setOnPreferenceClickListener(
                     new Preference.OnPreferenceClickListener() {
                         @Override
diff --git a/src/com/android/phone/IccNetworkDepersonalizationPanel.java b/src/com/android/phone/IccNetworkDepersonalizationPanel.java
index 9dff461..8bd10a2 100644
--- a/src/com/android/phone/IccNetworkDepersonalizationPanel.java
+++ b/src/com/android/phone/IccNetworkDepersonalizationPanel.java
@@ -74,7 +74,7 @@
     /**
      * Shows the network depersonalization dialog, but only if it is not already visible.
      */
-    public static void showDialog() {
+    public static void showDialog(Phone phone) {
         if (sShowingDialog) {
             Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; skipped already shown.");
             return;
@@ -82,7 +82,7 @@
         Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; showing dialog.");
         sShowingDialog = true;
         IccNetworkDepersonalizationPanel ndpPanel =
-                new IccNetworkDepersonalizationPanel(PhoneGlobals.getInstance());
+                new IccNetworkDepersonalizationPanel(PhoneGlobals.getInstance(), phone);
         ndpPanel.show();
     }
 
@@ -133,6 +133,13 @@
     //constructor
     public IccNetworkDepersonalizationPanel(Context context) {
         super(context);
+        mPhone = PhoneGlobals.getPhone();
+    }
+
+    //constructor
+    public IccNetworkDepersonalizationPanel(Context context, Phone phone) {
+        super(context);
+        mPhone = phone == null ? PhoneGlobals.getPhone() : phone;
     }
 
     @Override
@@ -172,8 +179,6 @@
         //status panel is used since we're having problems with the alert dialog.
         mStatusPanel = (LinearLayout) findViewById(R.id.status_panel);
         mStatusText = (TextView) findViewById(R.id.status_text);
-
-        mPhone = PhoneGlobals.getPhone();
     }
 
     @Override
diff --git a/src/com/android/phone/LocationAccessPolicy.java b/src/com/android/phone/LocationAccessPolicy.java
deleted file mode 100644
index 6f2a5ec..0000000
--- a/src/com/android/phone/LocationAccessPolicy.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.phone;
-
-import android.Manifest;
-import android.annotation.NonNull;
-import android.annotation.UserIdInt;
-import android.app.ActivityManager;
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
-import android.os.Build;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-
-import java.util.List;
-
-/**
- * Helper for performing location access checks.
- */
-final class LocationAccessPolicy {
-
-    private LocationAccessPolicy() {
-        /* do nothing - hide ctor */
-    }
-
-    /**
-     * API to determine if the caller has permissions to get cell location.
-     *
-     * @param pkgName Package name of the application requesting access
-     * @param uid The uid of the package
-     * @param message Message to add to the exception if no location permission
-     * @return boolean true or false if permissions is granted
-     */
-    static boolean canAccessCellLocation(@NonNull Context context, @NonNull String pkgName,
-            int uid, String message) throws SecurityException {
-        context.getSystemService(AppOpsManager.class).checkPackage(uid, pkgName);
-        // We always require the location permission and also require the
-        // location mode to be on for non-legacy apps. Legacy apps are
-        // required to be in the foreground to at least mitigate the case
-        // where a legacy app the user is not using tracks their location.
-
-        // Grating ACCESS_FINE_LOCATION to an app automatically grants it ACCESS_COARSE_LOCATION.
-        context.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION, message);
-        final int opCode = AppOpsManager.permissionToOpCode(
-                Manifest.permission.ACCESS_COARSE_LOCATION);
-        if (opCode != AppOpsManager.OP_NONE && context.getSystemService(AppOpsManager.class)
-                .noteOp(opCode, uid, pkgName) != AppOpsManager.MODE_ALLOWED) {
-            return false;
-        }
-        if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))
-                && !isLegacyForeground(context, pkgName)) {
-            return false;
-        }
-        // If the user or profile is current, permission is granted.
-        // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission.
-        return isCurrentProfile(context, uid) || checkInteractAcrossUsersFull(context);
-    }
-
-    private static boolean isLocationModeEnabled(@NonNull Context context, @UserIdInt int userId) {
-        return Settings.Secure.getIntForUser(context.getContentResolver(),
-                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF, userId)
-                != Settings.Secure.LOCATION_MODE_OFF;
-    }
-
-    private static boolean isLegacyForeground(@NonNull Context context, @NonNull String pkgName) {
-        return isLegacyVersion(context, pkgName) && isForegroundApp(context, pkgName);
-    }
-
-    private static boolean isLegacyVersion(@NonNull Context context, @NonNull String pkgName) {
-        try {
-            if (context.getPackageManager().getApplicationInfo(pkgName, 0)
-                    .targetSdkVersion <= Build.VERSION_CODES.O) {
-                return true;
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            // In case of exception, assume known app (more strict checking)
-            // Note: This case will never happen since checkPackage is
-            // called to verify validity before checking app's version.
-        }
-        return false;
-    }
-
-    private static boolean isForegroundApp(@NonNull Context context, @NonNull String pkgName) {
-        final ActivityManager am = context.getSystemService(ActivityManager.class);
-        final List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
-        if (!tasks.isEmpty()) {
-            return pkgName.equals(tasks.get(0).topActivity.getPackageName());
-        }
-        return false;
-    }
-
-    private static boolean checkInteractAcrossUsersFull(@NonNull Context context) {
-        return context.checkCallingOrSelfPermission(
-                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
-                == PackageManager.PERMISSION_GRANTED;
-    }
-
-    private static boolean isCurrentProfile(@NonNull Context context, int uid) {
-        final int currentUser = ActivityManager.getCurrentUser();
-        final int callingUserId = UserHandle.getUserId(uid);
-        if (callingUserId == currentUser) {
-            return true;
-        } else {
-            List<UserInfo> userProfiles = context.getSystemService(
-                    UserManager.class).getProfiles(currentUser);
-            for (UserInfo user: userProfiles) {
-                if (user.id == callingUserId) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-}
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 5dc57dd..99950a8 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -16,6 +16,8 @@
 
 package com.android.phone;
 
+import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
+
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.DialogFragment;
@@ -30,6 +32,8 @@
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.database.ContentObserver;
+import android.database.Cursor;
 import android.net.Uri;
 import android.os.AsyncResult;
 import android.os.Bundle;
@@ -172,6 +176,20 @@
         return true;
     }
 
+    /**
+     * Returns if DPC APNs are enforced.
+     */
+    public static boolean isDpcApnEnforced(Context context) {
+        try (Cursor enforceCursor = context.getContentResolver().query(ENFORCE_MANAGED_URI,
+                null, null, null, null)) {
+            if (enforceCursor == null || enforceCursor.getCount() != 1) {
+                return false;
+            }
+            enforceCursor.moveToFirst();
+            return enforceCursor.getInt(0) > 0;
+        }
+    }
+
     public static class MobileNetworkFragment extends PreferenceFragment implements
             Preference.OnPreferenceChangeListener, RoamingDialogFragment.RoamingDialogListener {
 
@@ -213,6 +231,7 @@
         private static final String BUTTON_CDMA_APN_EXPAND_KEY = "button_cdma_apn_key";
 
         private final BroadcastReceiver mPhoneChangeReceiver = new PhoneChangeReceiver();
+        private final ContentObserver mDpcEnforcedContentObserver = new DpcApnEnforcedObserver();
 
         static final int preferredNetworkMode = Phone.PREFERRED_NT_MODE;
 
@@ -223,6 +242,8 @@
 
         //Information that needs to save into Bundle.
         private static final String EXPAND_ADVANCED_FIELDS = "expand_advanced_fields";
+        //Intent extra to indicate expand all fields.
+        private static final String EXPAND_EXTRA = "expandable";
 
         private SubscriptionManager mSubscriptionManager;
         private TelephonyManager mTelephonyManager;
@@ -650,6 +671,8 @@
 
             if (icicle != null) {
                 mExpandAdvancedFields = icicle.getBoolean(EXPAND_ADVANCED_FIELDS, false);
+            } else if (getActivity().getIntent().getBooleanExtra(EXPAND_EXTRA, false)) {
+                mExpandAdvancedFields = true;
             }
 
             bindNetworkQueryService();
@@ -701,6 +724,9 @@
                     TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
             activity.registerReceiver(mPhoneChangeReceiver, intentFilter);
 
+            activity.getContentResolver().registerContentObserver(ENFORCE_MANAGED_URI, false,
+                    mDpcEnforcedContentObserver);
+
             Log.i(LOG_TAG, "onCreate:-");
         }
 
@@ -732,12 +758,26 @@
             }
         }
 
+        private class DpcApnEnforcedObserver extends ContentObserver {
+            DpcApnEnforcedObserver() {
+                super(null);
+            }
+
+            @Override
+            public void onChange(boolean selfChange) {
+                Log.i(LOG_TAG, "DPC enforced onChange:");
+                updateBody();
+            }
+        }
+
         @Override
         public void onDestroy() {
             unbindNetworkQueryService();
             super.onDestroy();
             if (getActivity() != null) {
                 getActivity().unregisterReceiver(mPhoneChangeReceiver);
+                getActivity().getContentResolver().unregisterContentObserver(
+                        mDpcEnforcedContentObserver);
             }
         }
 
diff --git a/src/com/android/phone/NetworkQueryService.java b/src/com/android/phone/NetworkQueryService.java
index 86f4b11..22b5509 100644
--- a/src/com/android/phone/NetworkQueryService.java
+++ b/src/com/android/phone/NetworkQueryService.java
@@ -79,7 +79,7 @@
     private static final boolean INCREMENTAL_RESULTS = true;
     // The parameters below are in seconds
     private static final int SEARCH_PERIODICITY_SEC = 5;
-    private static final int MAX_SEARCH_TIME_SEC = 60;
+    private static final int MAX_SEARCH_TIME_SEC = 300;
     private static final int INCREMENTAL_RESULTS_PERIODICITY_SEC = 3;
 
     /**
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index d36c761..f790c07 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -539,7 +539,7 @@
 
         final Notification.Builder builder = new Notification.Builder(mContext)
                 .setSmallIcon(android.R.drawable.stat_sys_warning)
-                .setContentTitle(mContext.getText(R.string.roaming))
+                .setContentTitle(mContext.getText(R.string.roaming_notification_title))
                 .setColor(mContext.getResources().getColor(R.color.dialer_theme_color))
                 .setContentText(contentText)
                 .setChannel(NotificationChannelController.CHANNEL_ID_MOBILE_DATA_STATUS)
@@ -613,24 +613,37 @@
                 PhoneFactory.getPhone(phoneId) : PhoneFactory.getDefaultPhone();
         if (TelephonyCapabilities.supportsNetworkSelection(phone)) {
             if (SubscriptionManager.isValidSubscriptionId(subId)) {
-                // get the shared preference of network_selection.
-                // empty is auto mode, otherwise it is the operator alpha name
-                // in case there is no operator name, check the operator numeric
-                SharedPreferences sp =
-                        PreferenceManager.getDefaultSharedPreferences(mContext);
-                String networkSelection =
-                        sp.getString(Phone.NETWORK_SELECTION_NAME_KEY + subId, "");
-                if (TextUtils.isEmpty(networkSelection)) {
-                    networkSelection =
-                            sp.getString(Phone.NETWORK_SELECTION_KEY + subId, "");
+                // if restoring manual selection is controlled by framework, then get network
+                // selection from shared preference, otherwise get from real network indicators.
+                boolean restoreSelection = !mContext.getResources().getBoolean(
+                        com.android.internal.R.bool.skip_restoring_network_selection);
+                String selectedNetworkOperatorName;
+                boolean isManualSelection;
+                if (restoreSelection) {
+                    SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
+                    selectedNetworkOperatorName =
+                            sp.getString(Phone.NETWORK_SELECTION_NAME_KEY + subId, "");
+                    // get the shared preference of network_selection.
+                    // empty is auto mode, otherwise it is the operator alpha name
+                    // in case there is no operator name, check the operator numeric
+                    if (TextUtils.isEmpty(selectedNetworkOperatorName)) {
+                        selectedNetworkOperatorName =
+                                sp.getString(Phone.NETWORK_SELECTION_KEY + subId, "");
+                    }
+                    isManualSelection = !TextUtils.isEmpty(selectedNetworkOperatorName);
+                } else {
+                    selectedNetworkOperatorName = phone.getServiceStateTracker().mSS
+                            .getOperatorAlpha();
+                    isManualSelection = phone.getServiceStateTracker().mSS.getIsManualSelection();
                 }
 
-                if (DBG) log("updateNetworkSelection()..." + "state = " +
-                        serviceState + " new network " + networkSelection);
+                if (DBG) {
+                    log("updateNetworkSelection()..." + "state = " + serviceState + " new network "
+                            + (isManualSelection ? selectedNetworkOperatorName : ""));
+                }
 
-                if (serviceState == ServiceState.STATE_OUT_OF_SERVICE
-                        && !TextUtils.isEmpty(networkSelection)) {
-                    showNetworkSelection(networkSelection, subId);
+                if (serviceState == ServiceState.STATE_OUT_OF_SERVICE && isManualSelection) {
+                    showNetworkSelection(selectedNetworkOperatorName, subId);
                     mSelectedUnavailableNotify = true;
                 } else {
                     if (mSelectedUnavailableNotify) {
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 2d0b99d..3b65f40 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -199,7 +199,8 @@
                         // The user won't be able to do anything else until
                         // they enter a valid SIM network PIN.
                         Log.i(LOG_TAG, "show sim depersonal panel");
-                        IccNetworkDepersonalizationPanel.showDialog();
+                        Phone phone = (Phone) ((AsyncResult) msg.obj).userObj;
+                        IccNetworkDepersonalizationPanel.showDialog(phone);
                     }
                     break;
 
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
old mode 100644
new mode 100755
index 8ed8a7c..de41481
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -55,6 +55,7 @@
 import android.telephony.CellInfo;
 import android.telephony.ClientRequestStats;
 import android.telephony.IccOpenLogicalChannelResponse;
+import android.telephony.LocationAccessPolicy;
 import android.telephony.ModemActivityInfo;
 import android.telephony.NeighboringCellInfo;
 import android.telephony.NetworkScanRequest;
@@ -101,6 +102,7 @@
 import com.android.internal.telephony.RIL;
 import com.android.internal.telephony.RILConstants;
 import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.TelephonyPermissions;
 import com.android.internal.telephony.TelephonyProperties;
 import com.android.internal.telephony.euicc.EuiccConnector;
 import com.android.internal.telephony.uicc.IccIoResult;
@@ -109,6 +111,7 @@
 import com.android.internal.telephony.uicc.UiccCard;
 import com.android.internal.telephony.uicc.UiccCardApplication;
 import com.android.internal.telephony.uicc.UiccController;
+import com.android.internal.telephony.uicc.UiccProfile;
 import com.android.internal.telephony.uicc.UiccSlot;
 import com.android.internal.telephony.util.VoicemailNotificationSettingsUtil;
 import com.android.internal.util.HexDump;
@@ -624,7 +627,7 @@
                     uiccCard = getUiccCardFromRequest(request);
                     if (uiccCard == null) {
                         loge("iccCloseLogicalChannel: No UICC");
-                        request.result = new IccIoResult(0x6F, 0, (byte[])null);
+                        request.result = false;
                         synchronized (request) {
                             request.notifyAll();
                         }
@@ -1253,7 +1256,8 @@
 
     @Override
     public boolean isOffhookForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "isOffhookForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "isOffhookForSubscriber")) {
             return false;
         }
 
@@ -1272,7 +1276,8 @@
 
     @Override
     public boolean isRingingForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "isRingingForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "isRingingForSubscriber")) {
             return false;
         }
 
@@ -1291,7 +1296,8 @@
 
     @Override
     public boolean isIdleForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "isIdleForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "isIdleForSubscriber")) {
             return false;
         }
 
@@ -1466,7 +1472,8 @@
 
     @Override
     public boolean isRadioOnForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "isRadioOnForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "isRadioOnForSubscriber")) {
             return false;
         }
         return isRadioOnForSubscriber(subId);
@@ -1653,8 +1660,10 @@
 
     @Override
     public Bundle getCellLocation(String callingPackage) {
+        mPhone.getContext().getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
         if (!LocationAccessPolicy.canAccessCellLocation(mPhone.getContext(),
-                callingPackage, Binder.getCallingUid(), "getCellLocation")) {
+                callingPackage, Binder.getCallingUid(),Binder.getCallingPid())) {
             return null;
         }
 
@@ -1721,8 +1730,10 @@
     @Override
     @SuppressWarnings("unchecked")
     public List<NeighboringCellInfo> getNeighboringCellInfo(String callingPackage) {
+        mPhone.getContext().getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
         if (!LocationAccessPolicy.canAccessCellLocation(mPhone.getContext(),
-                callingPackage, Binder.getCallingUid(), "getNeighboringCellInfo")) {
+                callingPackage, Binder.getCallingUid(), Binder.getCallingPid())) {
             return null;
         }
 
@@ -1749,8 +1760,10 @@
 
     @Override
     public List<CellInfo> getAllCellInfo(String callingPackage) {
+        mPhone.getContext().getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
         if (!LocationAccessPolicy.canAccessCellLocation(mPhone.getContext(),
-                callingPackage, Binder.getCallingUid(), "getAllCellInfo")) {
+                callingPackage, Binder.getCallingUid(), Binder.getCallingPid())) {
             return null;
         }
 
@@ -1773,29 +1786,44 @@
 
     @Override
     public String getImeiForSlot(int slotIndex, String callingPackage) {
-      if (!canReadPhoneState(callingPackage, "getImeiForSlot")) {
-          return null;
-      }
-      Phone phone = PhoneFactory.getPhone(slotIndex);
-      return phone == null ? null : phone.getImei();
+        Phone phone = PhoneFactory.getPhone(slotIndex);
+        if (phone == null) {
+            return null;
+        }
+        int subId = phone.getSubId();
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getImeiForSlot")) {
+            return null;
+        }
+        return phone.getImei();
     }
 
     @Override
     public String getMeidForSlot(int slotIndex, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getMeidForSlot")) {
+        Phone phone = PhoneFactory.getPhone(slotIndex);
+        if (phone == null) {
             return null;
         }
-        Phone phone = PhoneFactory.getPhone(slotIndex);
-        return phone == null ? null : phone.getMeid();
+        int subId = phone.getSubId();
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getMeidForSlot")) {
+            return null;
+        }
+        return phone.getMeid();
     }
 
     @Override
     public String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage) {
-      if (!canReadPhoneState(callingPackage, "getDeviceSoftwareVersionForSlot")) {
-          return null;
-      }
-      Phone phone = PhoneFactory.getPhone(slotIndex);
-      return phone == null ? null : phone.getDeviceSvn();
+        Phone phone = PhoneFactory.getPhone(slotIndex);
+        if (phone == null) {
+            return null;
+        }
+        int subId = phone.getSubId();
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getDeviceSoftwareVersionForSlot")) {
+            return null;
+        }
+        return phone.getDeviceSvn();
     }
 
     @Override
@@ -1824,35 +1852,6 @@
     }
 
     /**
-     * Make sure either system app or the caller has carrier privilege.
-     *
-     * @throws SecurityException if the caller does not have the required permission/privilege
-     */
-    private void enforceModifyPermissionOrCarrierPrivilege(int subId) {
-        int permission = mApp.checkCallingOrSelfPermission(
-                android.Manifest.permission.MODIFY_PHONE_STATE);
-        if (permission == PackageManager.PERMISSION_GRANTED) {
-            return;
-        }
-
-        log("No modify permission, check carrier privilege next.");
-        enforceCarrierPrivilege(subId);
-    }
-
-    /**
-     * Make sure the caller has carrier privilege.
-     *
-     * @throws SecurityException if the caller does not have the required permission
-     */
-    private void enforceCarrierPrivilege(int subId) {
-        if (getCarrierPrivilegeStatus(subId) !=
-                    TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
-            loge("No Carrier Privilege.");
-            throw new SecurityException("No Carrier Privilege.");
-        }
-    }
-
-    /**
      * Make sure the caller has the CALL_PHONE permission.
      *
      * @throws SecurityException if the caller does not have the required permission
@@ -1912,7 +1911,8 @@
 
     @Override
     public int getCdmaEriIconIndexForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getCdmaEriIconIndexForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getCdmaEriIconIndexForSubscriber")) {
             return -1;
         }
         final Phone phone = getPhone(subId);
@@ -1935,7 +1935,8 @@
 
     @Override
     public int getCdmaEriIconModeForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getCdmaEriIconModeForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getCdmaEriIconModeForSubscriber")) {
             return -1;
         }
         final Phone phone = getPhone(subId);
@@ -1956,7 +1957,8 @@
 
     @Override
     public String getCdmaEriTextForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getCdmaEriIconTextForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getCdmaEriIconTextForSubscriber")) {
             return null;
         }
         final Phone phone = getPhone(subId);
@@ -1972,7 +1974,8 @@
      */
     @Override
     public String getCdmaMdn(int subId) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "getCdmaMdn");
         final Phone phone = getPhone(subId);
         if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA && phone != null) {
             return phone.getLine1Number();
@@ -1986,7 +1989,8 @@
      */
     @Override
     public String getCdmaMin(int subId) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "getCdmaMin");
         final Phone phone = getPhone(subId);
         if (phone != null && phone.getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
             return phone.getCdmaMin();
@@ -2007,7 +2011,7 @@
      */
     @Override
     public boolean setVoiceMailNumber(int subId, String alphaTag, String number) {
-        enforceCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, "setVoiceMailNumber");
         Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
                 new Pair<String, String>(alphaTag, number), new Integer(subId));
         return success;
@@ -2030,10 +2034,17 @@
     @Override
     public String getVisualVoicemailPackageName(String callingPackage, int subId) {
         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
-        if (!canReadPhoneState(callingPackage, "getVisualVoicemailPackageName")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getVisualVoicemailPackageName")) {
             return null;
         }
-        return RemoteVvmTaskManager.getRemotePackage(mPhone.getContext(), subId).getPackageName();
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return RemoteVvmTaskManager
+                    .getRemotePackage(mPhone.getContext(), subId).getPackageName();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 
     @Override
@@ -2094,7 +2105,8 @@
      */
     @Override
     public void setVoiceActivationState(int subId, int activationState) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setVoiceActivationState");
         final Phone phone = getPhone(subId);
         if (phone != null) {
             phone.setVoiceActivationState(activationState);
@@ -2108,7 +2120,8 @@
      */
     @Override
     public void setDataActivationState(int subId, int activationState) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setDataActivationState");
         final Phone phone = getPhone(subId);
         if (phone != null) {
             phone.setDataActivationState(activationState);
@@ -2122,7 +2135,8 @@
      */
     @Override
     public int getVoiceActivationState(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getVoiceActivationStateForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getVoiceActivationStateForSubscriber")) {
             return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
         }
         final Phone phone = getPhone(subId);
@@ -2138,7 +2152,8 @@
      */
     @Override
     public int getDataActivationState(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getDataActivationStateForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getDataActivationStateForSubscriber")) {
             return TelephonyManager.SIM_ACTIVATION_STATE_UNKNOWN;
         }
         final Phone phone = getPhone(subId);
@@ -2189,7 +2204,8 @@
         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
         String defaultDialer = TelecomManager.from(mPhone.getContext()).getDefaultDialerPackage();
         if (!TextUtils.equals(callingPackage, defaultDialer)) {
-            enforceCarrierPrivilege(getDefaultSubscription());
+            TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
+                    getDefaultSubscription(), "sendDialerSpecialCode");
         }
         mPhone.sendDialerSpecialCode(inputCode);
     }
@@ -2215,7 +2231,8 @@
      */
     @Override
     public int getNetworkTypeForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getNetworkTypeForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getNetworkTypeForSubscriber")) {
             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
         }
 
@@ -2240,7 +2257,8 @@
      */
     @Override
     public int getDataNetworkTypeForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getDataNetworkTypeForSubscriber")) {
             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
         }
 
@@ -2257,7 +2275,8 @@
      */
     @Override
     public int getVoiceNetworkTypeForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getDataNetworkTypeForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getDataNetworkTypeForSubscriber")) {
             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
         }
 
@@ -2307,7 +2326,8 @@
 
     @Override
     public int getLteOnCdmaModeForSubscriber(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getLteOnCdmaModeForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getLteOnCdmaModeForSubscriber")) {
             return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
         }
 
@@ -2364,7 +2384,8 @@
     @Override
     public IccOpenLogicalChannelResponse iccOpenLogicalChannel(
             int subId, String callingPackage, String aid, int p2) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "iccOpenLogicalChannel");
 
         if (TextUtils.equals(ISDR_AID, aid)) {
             // Only allows LPA to open logical channel to ISD-R.
@@ -2387,7 +2408,8 @@
 
     @Override
     public boolean iccCloseLogicalChannel(int subId, int channel) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "iccCloseLogicalChannel");
 
         if (DBG) log("iccCloseLogicalChannel: subId=" + subId + " chnl=" + channel);
         if (channel < 0) {
@@ -2401,7 +2423,8 @@
     @Override
     public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
             int command, int p1, int p2, int p3, String data) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "iccTransmitApduLogicalChannel");
 
         if (DBG) {
             log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel +
@@ -2429,7 +2452,8 @@
     @Override
     public String iccTransmitApduBasicChannel(int subId, String callingPackage, int cla,
             int command, int p1, int p2, int p3, String data) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "iccTransmitApduBasicChannel");
 
         if (command == SELECT_COMMAND && p1 == SELECT_P1 && p2 == SELECT_P2 && p3 == SELECT_P3
                 && TextUtils.equals(ISDR_AID, data)) {
@@ -2465,7 +2489,8 @@
     @Override
     public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2, int p3,
             String filePath) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "iccExchangeSimIO");
 
         if (DBG) {
             log("Exchange SIM_IO " + subId + ":" + fileID + ":" + command + " " +
@@ -2501,6 +2526,7 @@
      * on a particular subscription
      */
     public String[] getForbiddenPlmns(int subId, int appType) {
+        // TODO(b/73884967): Migrate to TelephonyPermissions check.
         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
                 "Requires READ_PHONE_STATE");
         if (appType != TelephonyManager.APPTYPE_USIM && appType != TelephonyManager.APPTYPE_SIM) {
@@ -2518,7 +2544,8 @@
 
     @Override
     public String sendEnvelopeWithStatus(int subId, String content) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "sendEnvelopeWithStatus");
 
         IccIoResult response = (IccIoResult)sendRequest(CMD_SEND_ENVELOPE, content, subId);
         if (response.payload == null) {
@@ -2541,7 +2568,8 @@
      */
     @Override
     public String nvReadItem(int itemID) {
-        enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, getDefaultSubscription(), "nvReadItem");
         if (DBG) log("nvReadItem: item " + itemID);
         String value = (String) sendRequest(CMD_NV_READ_ITEM, itemID);
         if (DBG) log("nvReadItem: item " + itemID + " is \"" + value + '"');
@@ -2558,7 +2586,8 @@
      */
     @Override
     public boolean nvWriteItem(int itemID, String itemValue) {
-        enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, getDefaultSubscription(), "nvWriteItem");
         if (DBG) log("nvWriteItem: item " + itemID + " value \"" + itemValue + '"');
         Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_ITEM,
                 new Pair<Integer, String>(itemID, itemValue));
@@ -2575,7 +2604,8 @@
      */
     @Override
     public boolean nvWriteCdmaPrl(byte[] preferredRoamingList) {
-        enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, getDefaultSubscription(), "nvWriteCdmaPrl");
         if (DBG) log("nvWriteCdmaPrl: value: " + HexDump.toHexString(preferredRoamingList));
         Boolean success = (Boolean) sendRequest(CMD_NV_WRITE_CDMA_PRL, preferredRoamingList);
         if (DBG) log("nvWriteCdmaPrl: " + (success ? "ok" : "fail"));
@@ -2591,24 +2621,17 @@
      */
     @Override
     public boolean nvResetConfig(int resetType) {
-        enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, getDefaultSubscription(), "nvResetConfig");
         if (DBG) log("nvResetConfig: type " + resetType);
         Boolean success = (Boolean) sendRequest(CMD_NV_RESET_CONFIG, resetType);
         if (DBG) log("nvResetConfig: type " + resetType + ' ' + (success ? "ok" : "fail"));
         return success;
     }
 
-    /**
-     * {@hide}
-     * Returns Default sim, 0 in the case of single standby.
-     */
-    public int getDefaultSim() {
-        //TODO Need to get it from Telephony Devcontroller
-        return 0;
-    }
-
     public String[] getPcscfAddress(String apnType, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getPcscfAddress")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, mPhone.getSubId(), callingPackage, "getPcscfAddress")) {
             return new String[0];
         }
 
@@ -2674,6 +2697,15 @@
         return PhoneFactory.getImsResolver().getImsConfig(slotId, feature);
     }
 
+    /**
+     * @return true if the IMS resolver is busy resolving a binding and should not be considered
+     * available, false if the IMS resolver is idle.
+     */
+    public boolean isResolvingImsBinding() {
+        enforceModifyPermission();
+        return PhoneFactory.getImsResolver().isResolvingBinding();
+    }
+
     public void setImsRegistrationState(boolean registered) {
         enforceModifyPermission();
         mPhone.setImsRegistrationState(registered);
@@ -2685,7 +2717,8 @@
      */
     @Override
     public void setNetworkSelectionModeAutomatic(int subId) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setNetworkSelectionModeAutomatic");
         if (DBG) log("setNetworkSelectionModeAutomatic: subId " + subId);
         sendRequest(CMD_SET_NETWORK_SELECTION_MODE_AUTOMATIC, null, subId);
     }
@@ -2696,7 +2729,8 @@
     @Override
     public boolean setNetworkSelectionModeManual(int subId, String operatorNumeric,
             boolean persistSelection) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setNetworkSelectionModeManual");
         OperatorInfo operator = new OperatorInfo(
                 /* operatorAlphaLong */ "",
                 /* operatorAlphaShort */ "",
@@ -2712,7 +2746,8 @@
      */
     @Override
     public CellNetworkScanResult getCellNetworkScanResults(int subId) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "getCellNetworkScanResults");
         if (DBG) log("getCellNetworkScanResults: subId " + subId);
         CellNetworkScanResult result = (CellNetworkScanResult) sendRequest(
                 CMD_PERFORM_NETWORK_SCAN, null, subId);
@@ -2731,7 +2766,8 @@
     @Override
     public int requestNetworkScan(int subId, NetworkScanRequest request, Messenger messenger,
             IBinder binder) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "requestNetworkScan");
         return mNetworkScanRequestTracker.startNetworkScan(
                 request, messenger, binder, getPhone(subId));
     }
@@ -2744,7 +2780,8 @@
      */
     @Override
     public void stopNetworkScan(int subId, int scanId) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "stopNetworkScan");
         mNetworkScanRequestTracker.stopNetworkScan(scanId);
     }
 
@@ -2756,7 +2793,8 @@
      */
     @Override
     public int getCalculatedPreferredNetworkType(String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getCalculatedPreferredNetworkType")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, mPhone.getSubId(), callingPackage, "getCalculatedPreferredNetworkType")) {
             return RILConstants.PREFERRED_NETWORK_MODE;
         }
 
@@ -2771,7 +2809,8 @@
      */
     @Override
     public int getPreferredNetworkType(int subId) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "getPreferredNetworkType");
         if (DBG) log("getPreferredNetworkType");
         int[] result = (int[]) sendRequest(CMD_GET_PREFERRED_NETWORK_TYPE, null, subId);
         int networkType = (result != null ? result[0] : -1);
@@ -2788,7 +2827,8 @@
      */
     @Override
     public boolean setPreferredNetworkType(int subId, int networkType) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setPreferredNetworkType");
         if (DBG) log("setPreferredNetworkType: subId " + subId + " type " + networkType);
         Boolean success = (Boolean) sendRequest(CMD_SET_PREFERRED_NETWORK_TYPE, networkType, subId);
         if (DBG) log("setPreferredNetworkType: " + (success ? "ok" : "fail"));
@@ -2828,7 +2868,8 @@
      */
     @Override
     public void setUserDataEnabled(int subId, boolean enable) {
-        enforceModifyPermissionOrCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setUserDataEnabled");
         int phoneId = mSubscriptionController.getPhoneId(subId);
         if (DBG) log("setUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
         Phone phone = PhoneFactory.getPhone(phoneId);
@@ -2871,7 +2912,8 @@
             mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
                     null);
         } catch (Exception e) {
-            enforceModifyPermissionOrCarrierPrivilege(subId);
+            TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                    mApp, subId, "isUserDataEnabled");
         }
         int phoneId = mSubscriptionController.getPhoneId(subId);
         if (DBG) log("isUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
@@ -2902,7 +2944,8 @@
             mApp.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_NETWORK_STATE,
                     null);
         } catch (Exception e) {
-            enforceModifyPermissionOrCarrierPrivilege(subId);
+            TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                    mApp, subId, "isDataEnabled");
         }
         int phoneId = mSubscriptionController.getPhoneId(subId);
         if (DBG) log("isDataEnabled: subId=" + subId + " phoneId=" + phoneId);
@@ -2934,6 +2977,22 @@
     }
 
     @Override
+    public int getCarrierPrivilegeStatusForUid(int subId, int uid) {
+        final Phone phone = getPhone(subId);
+        if (phone == null) {
+            loge("getCarrierPrivilegeStatus: Invalid subId");
+            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
+        }
+        UiccProfile profile =
+                UiccController.getInstance().getUiccProfileForPhone(phone.getPhoneId());
+        if (profile == null) {
+            loge("getCarrierPrivilegeStatus: No UICC");
+            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
+        }
+        return profile.getCarrierPrivilegeStatusForUid(phone.getContext().getPackageManager(), uid);
+    }
+
+    @Override
     public int checkCarrierPrivilegesForPackage(String pkgName) {
         if (TextUtils.isEmpty(pkgName))
             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
@@ -3032,7 +3091,8 @@
     @Override
     public boolean setLine1NumberForDisplayForSubscriber(int subId, String alphaTag,
             String number) {
-        enforceCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
+                subId, "setLine1NumberForDisplayForSubscriber");
 
         final String iccId = getIccId(subId);
         final Phone phone = getPhone(subId);
@@ -3078,7 +3138,8 @@
     @Override
     public String getLine1NumberForDisplay(int subId, String callingPackage) {
         // This is open to apps with WRITE_SMS.
-        if (!canReadPhoneNumber(callingPackage, "getLine1NumberForDisplay")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(
+                mApp, subId, callingPackage, "getLine1NumberForDisplay")) {
             if (DBG_MERGE) log("getLine1NumberForDisplay returning null due to permission");
             return null;
         }
@@ -3098,7 +3159,8 @@
 
     @Override
     public String getLine1AlphaTagForDisplay(int subId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getLine1AlphaTagForDisplay")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getLine1AlphaTagForDisplay")) {
             return null;
         }
 
@@ -3112,7 +3174,11 @@
 
     @Override
     public String[] getMergedSubscriberIds(String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getMergedSubscriberIds")) {
+        // This API isn't public, so no need to provide a valid subscription ID - we're not worried
+        // about carrier-privileged callers not having access.
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID, callingPackage,
+                "getMergedSubscriberIds")) {
             return null;
         }
         final Context context = mPhone.getContext();
@@ -3185,7 +3251,8 @@
 
     @Override
     public boolean setOperatorBrandOverride(int subId, String brand) {
-        enforceCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
+                subId, "setOperatorBrandOverride");
         final Phone phone = getPhone(subId);
         return phone == null ? false : phone.setOperatorBrandOverride(brand);
     }
@@ -3194,7 +3261,7 @@
     public boolean setRoamingOverride(int subId, List<String> gsmRoamingList,
             List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
             List<String> cdmaNonRoamingList) {
-        enforceCarrierPrivilege(subId);
+        TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(subId, "setRoamingOverride");
         final Phone phone = getPhone(subId);
         if (phone == null) {
             return false;
@@ -3214,7 +3281,13 @@
 
     @Override
     public int getRadioAccessFamily(int phoneId, String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getRadioAccessFamily")) {
+        Phone phone = PhoneFactory.getPhone(phoneId);
+        if (phone == null) {
+            return RadioAccessFamily.RAF_UNKNOWN;
+        }
+        int subId = phone.getSubId();
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getRadioAccessFamily")) {
             return RadioAccessFamily.RAF_UNKNOWN;
         }
 
@@ -3229,7 +3302,8 @@
 
     @Override
     public boolean isVideoCallingEnabled(String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "isVideoCallingEnabled")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, mPhone.getSubId(), callingPackage, "isVideoCallingEnabled")) {
             return false;
         }
 
@@ -3283,16 +3357,16 @@
      */
     @Override
     public String getDeviceId(String callingPackage) {
-        if (!canReadPhoneState(callingPackage, "getDeviceId")) {
-            return null;
-        }
-
         final Phone phone = PhoneFactory.getPhone(0);
-        if (phone != null) {
-            return phone.getDeviceId();
-        } else {
+        if (phone == null) {
             return null;
         }
+        int subId = phone.getSubId();
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getDeviceId")) {
+            return null;
+        }
+        return phone.getDeviceId();
     }
 
     /**
@@ -3364,72 +3438,6 @@
         }
     }
 
-    private boolean canReadPhoneState(String callingPackage, String message) {
-        try {
-            mApp.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, message);
-
-            // SKIP checking for run-time permission since caller or self has PRIVILEDGED permission
-            return true;
-        } catch (SecurityException e) {
-            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
-                    message);
-        }
-
-        if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
-                callingPackage) != AppOpsManager.MODE_ALLOWED) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Besides READ_PHONE_STATE, WRITE_SMS and READ_SMS also allow apps to get phone numbers.
-     */
-    private boolean canReadPhoneNumber(String callingPackage, String message) {
-        // Default SMS app can always read it.
-        if (mAppOps.noteOp(AppOpsManager.OP_WRITE_SMS,
-                Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED) {
-            return true;
-        }
-
-        try {
-            return canReadPhoneState(callingPackage, message);
-        } catch (SecurityException readPhoneStateSecurityException) {
-        }
-        // Can be read with READ_SMS too.
-        try {
-            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_SMS, message);
-            int opCode = mAppOps.permissionToOpCode(android.Manifest.permission.READ_SMS);
-            if (opCode != AppOpsManager.OP_NONE) {
-                return mAppOps.noteOp(opCode, Binder.getCallingUid(), callingPackage)
-                        == AppOpsManager.MODE_ALLOWED;
-            } else {
-                return true;
-            }
-        } catch (SecurityException readSmsSecurityException) {
-        }
-        // Can be read with READ_PHONE_NUMBERS too.
-        try {
-            mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_NUMBERS,
-                    message);
-            int opCode = mAppOps.permissionToOpCode(android.Manifest.permission.READ_PHONE_NUMBERS);
-            if (opCode != AppOpsManager.OP_NONE) {
-                return mAppOps.noteOp(opCode, Binder.getCallingUid(), callingPackage)
-                        == AppOpsManager.MODE_ALLOWED;
-            } else {
-                return true;
-            }
-        } catch (SecurityException readPhoneNumberSecurityException) {
-        }
-
-        throw new SecurityException(message + ": Neither user " + Binder.getCallingUid() +
-                " nor current process has" + android.Manifest.permission.READ_PHONE_STATE +
-                ", " + android.Manifest.permission.READ_SMS + ", or " +
-                android.Manifest.permission.READ_PHONE_NUMBERS);
-    }
-
     @Override
     public void factoryReset(int subId) {
         enforceConnectivityInternalPermission();
@@ -3446,7 +3454,13 @@
                 // Set network selection mode to automatic
                 setNetworkSelectionModeAutomatic(subId);
                 // Set preferred mobile network type to the best available
-                setPreferredNetworkType(subId, Phone.PREFERRED_NT_MODE);
+                String defaultNetwork = TelephonyManager.getTelephonyProperty(
+                        mSubscriptionController.getPhoneId(subId),
+                        "ro.telephony.default_network",
+                        null);
+                int networkType = !TextUtils.isEmpty(defaultNetwork)
+                        ? Integer.parseInt(defaultNetwork) : Phone.PREFERRED_NT_MODE;
+                setPreferredNetworkType(subId, networkType);
                 // Turn off roaming
                 mPhone.setDataRoamingEnabled(false);
             }
@@ -3560,7 +3574,8 @@
     @Override
     public ServiceState getServiceStateForSubscriber(int subId, String callingPackage) {
 
-        if (!canReadPhoneState(callingPackage, "getServiceStateForSubscriber")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getServiceStateForSubscriber")) {
             return null;
         }
 
@@ -3607,8 +3622,9 @@
         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
         if (!TextUtils.equals(callingPackage,
                 TelecomManager.from(mPhone.getContext()).getDefaultDialerPackage())) {
-            enforceModifyPermissionOrCarrierPrivilege(
-                    PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle));
+            TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                    mApp, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle),
+                    "setVoicemailRingtoneUri");
         }
         Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
         if (phone == null){
@@ -3651,8 +3667,9 @@
         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
         if (!TextUtils.equals(callingPackage,
                 TelecomManager.from(mPhone.getContext()).getDefaultDialerPackage())) {
-            enforceModifyPermissionOrCarrierPrivilege(
-                    PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle));
+            TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                    mApp, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle),
+                    "setVoicemailVibrationEnabled");
         }
 
         Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
@@ -3775,7 +3792,8 @@
      */
     @Override
     public List<TelephonyHistogram> getTelephonyHistograms() {
-        enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, getDefaultSubscription(), "getTelephonyHistograms");
         return RIL.getTelephonyRILTimingHistograms();
     }
 
@@ -3942,7 +3960,8 @@
      */
     @Override
     public List<ClientRequestStats> getClientRequestStats(String callingPackage, int subId) {
-        if (!canReadPhoneState(callingPackage, "getClientRequestStats")) {
+        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                mApp, subId, callingPackage, "getClientRequestStats")) {
             return null;
         }
 
@@ -4062,7 +4081,12 @@
             }
 
             infos[i] = new UiccSlotInfo(
-                    slot.isActive(), slot.isEuicc(), cardId, cardState, slot.getPhoneId());
+                    slot.isActive(),
+                    slot.isEuicc(),
+                    cardId,
+                    cardState,
+                    slot.getPhoneId(),
+                    slot.isExtendedApduSupported());
         }
         return infos;
     }
@@ -4072,4 +4096,16 @@
         enforceModifyPermission();
         return (Boolean) sendRequest(CMD_SWITCH_SLOTS, physicalSlots);
     }
+
+    @Override
+    public void setRadioIndicationUpdateMode(int subId, int filters, int mode) {
+        enforceModifyPermission();
+        final Phone phone = getPhone(subId);
+        if (phone == null) {
+            loge("setRadioIndicationUpdateMode fails with invalid subId: " + subId);
+            return;
+        }
+
+        phone.setRadioIndicationUpdateMode(filters, mode);
+    }
 }
diff --git a/src/com/android/phone/PhoneSearchIndexablesProvider.java b/src/com/android/phone/PhoneSearchIndexablesProvider.java
index 9c5f354..75e6bab 100644
--- a/src/com/android/phone/PhoneSearchIndexablesProvider.java
+++ b/src/com/android/phone/PhoneSearchIndexablesProvider.java
@@ -99,8 +99,8 @@
         MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS);
 
         if (!mUserManager.isAdminUser()) {
-            final String[] values = new String[]{"preferred_network_mode_key", "button_roaming_key",
-                    "cdma_lte_data_service_key", "enabled_networks_key", "enhanced_4g_lte",
+            final String[] values = new String[]{"preferred_network_mode_key",
+                    "button_roaming_key", "cdma_lte_data_service_key", "enhanced_4g_lte",
                     "button_apn_key", "button_network_select_key", "carrier_settings_key",
                     "cdma_system_select_key", "esim_list_profile", "mobile_data_enable",
                     "data_usage_summary", "wifi_calling_key", "video_calling_key"};
@@ -115,6 +115,11 @@
                 cursor.addRow(createNonIndexableRow("enhanced_4g_lte" /* key */));
             }
         }
+        // enabled_networks button and preferred_network_mode button share the same title
+        // "Preferred network type"and are mutual exclusive. Thus we remove one from search
+        // result to avoid duplicate search result.
+        // TODO: b/63381516 all hidden buttons should dynamically be removed from search result.
+        cursor.addRow(createNonIndexableRow("enabled_networks_key" /* key */));
         cursor.addRow(createNonIndexableRow("carrier_settings_euicc_key" /* key */));
         cursor.addRow(createNonIndexableRow("advanced_options" /* key */));
         return cursor;
diff --git a/src/com/android/phone/RestrictedPreference.java b/src/com/android/phone/RestrictedPreference.java
new file mode 100644
index 0000000..b8b6fe7
--- /dev/null
+++ b/src/com/android/phone/RestrictedPreference.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import android.content.Context;
+import android.preference.Preference;
+import android.preference.PreferenceScreen;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.settingslib.RestrictedLockUtils;
+
+/**
+ * Preference class that supports being disabled by a device admin.
+ *
+ * <p>This class is a mimic of ../../../frameworks/base/packages/SettingsLib/src/com/android
+ * /settingslib/RestrictedPreference.java,
+ * but support framework {@link Preference}.
+ */
+public class RestrictedPreference extends Preference {
+    private final Context mContext;
+
+    private boolean mDisabledByAdmin;
+    private EnforcedAdmin mEnforcedAdmin;
+
+    public RestrictedPreference(Context context, AttributeSet attrs,
+            int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        mContext = context;
+
+        setLayoutResource(com.android.settingslib.R.layout.preference_two_target);
+        setWidgetLayoutResource(R.layout.restricted_icon);
+    }
+
+    public RestrictedPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public RestrictedPreference(Context context, AttributeSet attrs) {
+        this(context, attrs, android.R.attr.preferenceStyle);
+    }
+
+    public RestrictedPreference(Context context) {
+        this(context, null);
+    }
+
+    @Override
+    public void performClick(PreferenceScreen preferenceScreen) {
+        if (mDisabledByAdmin) {
+            RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, mEnforcedAdmin);
+        } else {
+            super.performClick(preferenceScreen);
+        }
+    }
+
+    @Override
+    protected void onBindView(View view) {
+        super.onBindView(view);
+
+        final View divider = view.findViewById(com.android.settingslib.R.id.two_target_divider);
+        final View widgetFrame = view.findViewById(android.R.id.widget_frame);
+        final View restrictedIcon = view.findViewById(R.id.restricted_icon);
+        final TextView summaryView = view.findViewById(android.R.id.summary);
+        if (divider != null) {
+            divider.setVisibility(mDisabledByAdmin ? View.VISIBLE : View.GONE);
+        }
+        if (widgetFrame != null) {
+            widgetFrame.setVisibility(mDisabledByAdmin ? View.VISIBLE : View.GONE);
+        }
+        if (restrictedIcon != null) {
+            restrictedIcon.setVisibility(mDisabledByAdmin ? View.VISIBLE : View.GONE);
+        }
+        if (summaryView != null && mDisabledByAdmin) {
+            summaryView.setText(com.android.settingslib.R.string.disabled_by_admin_summary_text);
+            summaryView.setVisibility(View.VISIBLE);
+        }
+
+        if (mDisabledByAdmin) {
+            view.setEnabled(true);
+        }
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        if (enabled && mDisabledByAdmin) {
+            setDisabledByAdmin(null);
+            return;
+        }
+        super.setEnabled(enabled);
+    }
+
+    /**
+     * Disable this preference based on the enforce admin.
+     *
+     * @param admin Details of the admin who enforced the restriction. If it is {@code null}, then
+     * this preference will be enabled. Otherwise, it will be disabled.
+     */
+    public void setDisabledByAdmin(EnforcedAdmin admin) {
+        final boolean disabled = admin != null;
+        mEnforcedAdmin = admin;
+        boolean changed = false;
+        if (mDisabledByAdmin != disabled) {
+            mDisabledByAdmin = disabled;
+            changed = true;
+        }
+        setEnabled(!disabled);
+        if (changed) {
+            notifyChanged();
+        }
+    }
+}
diff --git a/src/com/android/phone/settings/AccessibilitySettingsFragment.java b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
index 7ede23a..8ec747c 100644
--- a/src/com/android/phone/settings/AccessibilitySettingsFragment.java
+++ b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
@@ -106,9 +106,7 @@
             // TODO: this is going to be a on/off switch for now. Ask UX about how to integrate
             // this settings with TTY
             boolean rttOn = Settings.System.getInt(
-                    mContext.getContentResolver(), Settings.System.RTT_CALLING_MODE,
-                    TelecomManager.TTY_MODE_OFF)
-                    != TelecomManager.TTY_MODE_OFF;
+                    mContext.getContentResolver(), Settings.System.RTT_CALLING_MODE, 0) != 0;
             mButtonRtt.setChecked(rttOn);
         } else {
             getPreferenceScreen().removePreference(mButtonRtt);
@@ -149,8 +147,7 @@
             return true;
         } else if (preference == mButtonRtt) {
             Log.i(LOG_TAG, "RTT setting changed -- now " + mButtonRtt.isChecked());
-            int rttMode = mButtonRtt.isChecked()
-                    ? TelecomManager.TTY_MODE_FULL : TelecomManager.TTY_MODE_OFF;
+            int rttMode = mButtonRtt.isChecked() ? 1 : 0;
             Settings.System.putInt(mContext.getContentResolver(), Settings.System.RTT_CALLING_MODE,
                     rttMode);
             // Update RTT config with IMS Manager
diff --git a/src/com/android/phone/vvm/RemoteVvmTaskManager.java b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
index 4fc8c57..cf5011e 100644
--- a/src/com/android/phone/vvm/RemoteVvmTaskManager.java
+++ b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
@@ -119,6 +119,8 @@
         TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
         List<String> packages = new ArrayList<>();
         packages.add(telecomManager.getDefaultDialerPackage());
+        // TODO(b/73136824): Check permissions in the calling function and avoid relying on the
+        // binder caller's permissions to access the carrier config.
         PersistableBundle carrierConfig = context
                 .getSystemService(CarrierConfigManager.class).getConfigForSubId(subId);
         packages.add(
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 3cf420a..dd74d28 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -758,7 +758,8 @@
 
         participant.removeConnectionListener(mParticipantListener);
         synchronized(mUpdateSyncRoot) {
-            mConferenceParticipantConnections.remove(participant.getUserEntity());
+            mConferenceParticipantConnections.remove(new Pair<>(participant.getUserEntity(),
+                    participant.getEndpoint()));
         }
         mTelephonyConnectionService.removeConnection(participant);
     }
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index e007bb4..4dfaf44 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -36,6 +36,7 @@
 import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
 import com.android.internal.telephony.imsphone.ImsExternalCallTracker;
 import com.android.internal.telephony.imsphone.ImsExternalConnection;
+import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 import com.android.phone.PhoneUtils;
 
 import com.google.common.base.Preconditions;
@@ -243,6 +244,11 @@
         extras.putLong(TelecomManager.EXTRA_CALL_CREATED_TIME_MILLIS,
                 SystemClock.elapsedRealtime());
 
+        if (connection.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
+            if (((ImsPhoneConnection) connection).isRttEnabledForCall()) {
+                extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, true);
+            }
+        }
         PhoneAccountHandle handle = findCorrectPhoneAccountHandle();
         if (handle == null) {
             try {
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index b27baed..af9e9d5 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -546,6 +546,7 @@
 
         @Override
         public void onRttModifyResponseReceived(int status) {
+            updateConnectionProperties();
             if (status == RttModifyStatus.SESSION_MODIFY_REQUEST_SUCCESS) {
                 sendRttInitiationSuccess();
             } else {
@@ -562,11 +563,13 @@
 
         @Override
         public void onRttInitiated() {
+            updateConnectionProperties();
             sendRttInitiationSuccess();
         }
 
         @Override
         public void onRttTerminated() {
+            updateConnectionProperties();
             sendRttSessionRemotelyTerminated();
         }
     };
@@ -845,7 +848,7 @@
 
     @Override
     public void onStopRtt() {
-        // This is not supported by carriers/vendor yet. No-op for now.
+        Log.i(this, "Stopping RTT currently not supported. Doing nothing.");
     }
 
     @Override
@@ -1003,8 +1006,7 @@
                 mIsCdmaVoicePrivacyEnabled);
         newProperties = changeBitmask(newProperties, PROPERTY_ASSISTED_DIALING_USED,
                 mIsUsingAssistedDialing);
-        newProperties = changeBitmask(newProperties, PROPERTY_IS_RTT,
-                (getConnectionProperties() & PROPERTY_IS_RTT) != 0);
+        newProperties = changeBitmask(newProperties, PROPERTY_IS_RTT, isRtt());
 
         if (getConnectionProperties() != newProperties) {
             setConnectionProperties(newProperties);
@@ -1691,6 +1693,16 @@
     }
 
     /**
+     * Determines if the current connection has RTT enabled.
+     */
+    private boolean isRtt() {
+        return mOriginalConnection != null
+                && mOriginalConnection.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS
+                && mOriginalConnection instanceof ImsPhoneConnection
+                && ((ImsPhoneConnection) mOriginalConnection).isRttEnabledForCall();
+    }
+
+    /**
      * Determines if the current connection is pullable.
      *
      * A connection is deemed to be pullable if the original connection capabilities state that it
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 2022733..b3369b5 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -52,6 +52,7 @@
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.imsphone.ImsExternalCallTracker;
 import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 import com.android.phone.MMIDialogActivity;
 import com.android.phone.PhoneUtils;
 import com.android.phone.R;
@@ -700,10 +701,11 @@
         int videoState = originalConnection != null ? originalConnection.getVideoState() :
                 VideoProfile.STATE_AUDIO_ONLY;
 
-        Connection connection =
+        TelephonyConnection connection =
                 createConnectionFor(phone, originalConnection, false /* isOutgoing */,
                         request.getAccountHandle(), request.getTelecomCallId(),
                         request.getAddress(), videoState);
+        handleIncomingRtt(request, originalConnection);
         if (connection == null) {
             return Connection.createCanceledConnection();
         } else {
@@ -711,6 +713,36 @@
         }
     }
 
+    private void handleIncomingRtt(ConnectionRequest request,
+            com.android.internal.telephony.Connection originalConnection) {
+        if (originalConnection == null
+                || originalConnection.getPhoneType() != PhoneConstants.PHONE_TYPE_IMS) {
+            if (request.isRequestingRtt()) {
+                Log.w(this, "Requesting RTT on non-IMS call, ignoring");
+            }
+            return;
+        }
+
+        ImsPhoneConnection imsOriginalConnection = (ImsPhoneConnection) originalConnection;
+        if (!request.isRequestingRtt()) {
+            if (imsOriginalConnection.isRttEnabledForCall()) {
+                Log.w(this, "Incoming call requested RTT but we did not get a RttTextStream");
+            }
+            return;
+        }
+
+        if (!imsOriginalConnection.isRttEnabledForCall()) {
+            if (request.isRequestingRtt()) {
+                Log.w(this, "Incoming call processed as RTT but did not come in as one. Ignoring");
+            }
+            return;
+        }
+
+        Log.i(this, "Setting RTT stream on ImsPhoneConnection");
+        imsOriginalConnection.setCurrentRttTextStream(request.getRttTextStream());
+        imsOriginalConnection.getImsCall().setAnswerWithRtt();
+    }
+
     /**
      * Called by the {@link ConnectionService} when a newly created {@link Connection} has been
      * added to the {@link ConnectionService} and sent to Telecom.  Here it is safe to send
diff --git a/testapps/EmbmsServiceTestApp/Android.mk b/testapps/EmbmsServiceTestApp/Android.mk
index d8c4493..29b8112 100644
--- a/testapps/EmbmsServiceTestApp/Android.mk
+++ b/testapps/EmbmsServiceTestApp/Android.mk
@@ -10,6 +10,7 @@
 LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs))
 
 LOCAL_PACKAGE_NAME := EmbmsTestService
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
index 128793f..7bd0f70 100644
--- a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
@@ -371,11 +371,8 @@
             c.onProgressUpdated(request, fileToDownload, 10, 10, 10, 10);
         }
         // Take a round-trip through the download request serialization to exercise it
-        DownloadRequest request1 = new DownloadRequest.Builder(request.getSourceUri())
-                .setSubscriptionId(request.getSubscriptionId())
-                .setServiceId(request.getFileServiceId())
-                .setOpaqueData(request.getOpaqueData())
-                .build();
+        DownloadRequest request1 = DownloadRequest.Builder.fromSerializedRequest(
+                request.toByteArray()).build();
 
         Intent downloadResultIntent =
                 new Intent(VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL);
diff --git a/testapps/EmbmsTestDownloadApp/Android.mk b/testapps/EmbmsTestDownloadApp/Android.mk
index 080e5b0..445357c 100644
--- a/testapps/EmbmsTestDownloadApp/Android.mk
+++ b/testapps/EmbmsTestDownloadApp/Android.mk
@@ -14,6 +14,7 @@
 LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs))
 
 LOCAL_PACKAGE_NAME := EmbmsTestDownloadApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 LOCAL_MODULE_TAGS := tests
diff --git a/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/DownloadCompletionReceiver.java b/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/DownloadCompletionReceiver.java
index 3c94b76..736b912 100644
--- a/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/DownloadCompletionReceiver.java
+++ b/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/DownloadCompletionReceiver.java
@@ -21,14 +21,12 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.telephony.MbmsDownloadSession;
-import android.telephony.mbms.DownloadRequest;
 import android.telephony.mbms.FileInfo;
 
 import java.io.IOException;
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
 
 public class DownloadCompletionReceiver extends BroadcastReceiver {
     @Override
@@ -41,22 +39,8 @@
             }
             Uri completedFile = intent.getParcelableExtra(
                     MbmsDownloadSession.EXTRA_MBMS_COMPLETED_FILE_URI);
-            FileInfo completedFileInfo = intent.getParcelableExtra(
-                    MbmsDownloadSession.EXTRA_MBMS_FILE_INFO);
-            DownloadRequest request = intent.getParcelableExtra(
-                    MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST);
 
-            Path destinationFile = getDestinationFile(context,
-                    request.getFileServiceId(), completedFileInfo);
-            Path sourceFile = FileSystems.getDefault().getPath(completedFile.getPath());
-            try {
-                Files.move(sourceFile, destinationFile, StandardCopyOption.REPLACE_EXISTING);
-            } catch (IOException e) {
-                return;
-            }
-
-            EmbmsTestDownloadApp.getInstance().onDownloadDone(
-                    Uri.fromFile(destinationFile.toFile()));
+            EmbmsTestDownloadApp.getInstance().onDownloadDone(completedFile);
         }
     }
 
diff --git a/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java b/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java
index 4083f67..76baf05 100644
--- a/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java
+++ b/testapps/EmbmsTestDownloadApp/src/com/android/phone/testapps/embmsdownload/EmbmsTestDownloadApp.java
@@ -44,6 +44,7 @@
 import android.widget.Toast;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -203,7 +204,7 @@
 
         Button bindButton = (Button) findViewById(R.id.bind_button);
         bindButton.setOnClickListener((view) -> {
-            mDownloadManager = MbmsDownloadSession.create(this, mCallback, mHandler);
+            mDownloadManager = MbmsDownloadSession.create(this, mHandler::post, mCallback);
         });
 
         Button setTempFileRootButton = (Button) findViewById(R.id.set_temp_root_button);
@@ -291,26 +292,28 @@
                         "No DownloadRequest Pending for progress...", Toast.LENGTH_SHORT).show();
                 return;
             }
-            mDownloadManager.registerStateCallback(req, new DownloadStateCallback(
-                    DownloadStateCallback.PROGRESS_UPDATES) {
-                @Override
-                public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
-                        int currentDownloadSize, int fullDownloadSize, int currentDecodedSize,
-                        int fullDecodedSize) {
-                    Toast.makeText(EmbmsTestDownloadApp.this,
-                            "Progress Updated (" + fileInfo + ") cd: " + currentDecodedSize
-                                    + " fd: " + fullDownloadSize, Toast.LENGTH_SHORT).show();
-                }
+            mDownloadManager.registerStateCallback(req, sInstance.getMainThreadHandler()::post,
+                    new DownloadStateCallback(DownloadStateCallback.PROGRESS_UPDATES) {
+                        @Override
+                        public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
+                                int currentDownloadSize, int fullDownloadSize,
+                                int currentDecodedSize, int fullDecodedSize) {
+                            Toast.makeText(EmbmsTestDownloadApp.this,
+                                    "Progress Updated (" + fileInfo + ") cd: " + currentDecodedSize
+                                            + " fd: " + fullDownloadSize, Toast.LENGTH_SHORT)
+                                    .show();
+                        }
 
-                @Override
-                public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
-                        @MbmsDownloadSession.DownloadStatus int state) {
-                    // only registered for state callback, this shouldn't happen!
-                    Toast.makeText(EmbmsTestDownloadApp.this,
-                            "State ERROR: received state update for callback that didn't filter it",
-                            Toast.LENGTH_SHORT).show();
-                }
-            }, sInstance.getMainThreadHandler());
+                        @Override
+                        public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
+                                @MbmsDownloadSession.DownloadStatus int state) {
+                            // only registered for state callback, this shouldn't happen!
+                            Toast.makeText(EmbmsTestDownloadApp.this,
+                                    "State ERROR: received state update for callback that didn't"
+                                            + " filter it",
+                                    Toast.LENGTH_SHORT).show();
+                        }
+                    });
         });
 
         Button registerStateCallback =
@@ -327,26 +330,27 @@
                         "No DownloadRequest Pending for state...", Toast.LENGTH_SHORT).show();
                 return;
             }
-            mDownloadManager.registerStateCallback(req, new DownloadStateCallback(
-                    DownloadStateCallback.STATE_UPDATES) {
-                @Override
-                public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
-                        int currentDownloadSize, int fullDownloadSize, int currentDecodedSize,
-                        int fullDecodedSize) {
-                    // only registered for state callback, this shouldn't happen!
-                    Toast.makeText(EmbmsTestDownloadApp.this,
-                            "Progress ERROR: received progress update for callback that didn't "
-                                    + "filter it", Toast.LENGTH_SHORT).show();
-                }
+            mDownloadManager.registerStateCallback(req, sInstance.getMainThreadHandler()::post,
+                    new DownloadStateCallback(DownloadStateCallback.STATE_UPDATES) {
+                        @Override
+                        public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
+                                int currentDownloadSize, int fullDownloadSize,
+                                int currentDecodedSize, int fullDecodedSize) {
+                            // only registered for state callback, this shouldn't happen!
+                            Toast.makeText(EmbmsTestDownloadApp.this,
+                                    "Progress ERROR: received progress update for"
+                                            + " callback that didn't "
+                                            + "filter it", Toast.LENGTH_SHORT).show();
+                        }
 
-                @Override
-                public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
-                        @MbmsDownloadSession.DownloadStatus int state) {
-                    Toast.makeText(EmbmsTestDownloadApp.this,
-                            "State Updated (" + fileInfo + ") state: " + state,
-                            Toast.LENGTH_SHORT).show();
-                }
-            }, sInstance.getMainThreadHandler());
+                        @Override
+                        public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
+                                @MbmsDownloadSession.DownloadStatus int state) {
+                            Toast.makeText(EmbmsTestDownloadApp.this,
+                                    "State Updated (" + fileInfo + ") state: " + state,
+                                    Toast.LENGTH_SHORT).show();
+                        }
+                    });
         });
 
         Button registerAllCallbacks =
@@ -363,24 +367,26 @@
                         "No DownloadRequest Pending for state...", Toast.LENGTH_SHORT).show();
                 return;
             }
-            mDownloadManager.registerStateCallback(req, new DownloadStateCallback() {
-                @Override
-                public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
-                        int currentDownloadSize, int fullDownloadSize, int currentDecodedSize,
-                        int fullDecodedSize) {
-                    Toast.makeText(EmbmsTestDownloadApp.this,
-                            "Progress Updated (" + fileInfo + ") cd: " + currentDecodedSize
-                                    + " fd: " + fullDownloadSize, Toast.LENGTH_SHORT).show();
-                }
+            mDownloadManager.registerStateCallback(req, sInstance.getMainThreadHandler()::post,
+                    new DownloadStateCallback() {
+                        @Override
+                        public void onProgressUpdated(DownloadRequest request, FileInfo fileInfo,
+                                int currentDownloadSize, int fullDownloadSize,
+                                int currentDecodedSize, int fullDecodedSize) {
+                            Toast.makeText(EmbmsTestDownloadApp.this,
+                                    "Progress Updated (" + fileInfo + ") cd: " + currentDecodedSize
+                                            + " fd: " + fullDownloadSize, Toast.LENGTH_SHORT)
+                                    .show();
+                        }
 
-                @Override
-                public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
-                        @MbmsDownloadSession.DownloadStatus int state) {
-                    Toast.makeText(EmbmsTestDownloadApp.this,
-                            "State Updated (" + fileInfo + ") state: " + state,
-                            Toast.LENGTH_SHORT).show();
-                }
-            }, sInstance.getMainThreadHandler());
+                        @Override
+                        public void onStateUpdated(DownloadRequest request, FileInfo fileInfo,
+                                @MbmsDownloadSession.DownloadStatus int state) {
+                            Toast.makeText(EmbmsTestDownloadApp.this,
+                                    "State Updated (" + fileInfo + ") state: " + state,
+                                    Toast.LENGTH_SHORT).show();
+                        }
+                    });
         });
     }
 
@@ -429,7 +435,8 @@
         Intent completionIntent = new Intent(DOWNLOAD_DONE_ACTION);
         completionIntent.setClass(this, DownloadCompletionReceiver.class);
 
-        DownloadRequest request = new DownloadRequest.Builder(sourceUriBuilder.build())
+        DownloadRequest request = new DownloadRequest.Builder(sourceUriBuilder.build(),
+                getDestination(info.getServiceId()))
                 .setServiceInfo(info)
                 .setAppIntent(completionIntent)
                 .setSubscriptionId(SubscriptionManager.getDefaultSubscriptionId())
@@ -438,4 +445,24 @@
         mDownloadManager.download(request);
         mDownloadRequestAdapter.add(request);
     }
+
+    private Uri getDestination(String serviceId) {
+        File dest;
+        try {
+            if (serviceId.contains("2")) {
+                dest = new File(getFilesDir().getCanonicalFile(), "images/animals/");
+                if (!dest.exists()) {
+                    dest.mkdirs();
+                }
+            } else {
+                dest = new File(getFilesDir().getCanonicalFile(), "images/");
+                if (!dest.exists()) {
+                    dest.mkdirs();
+                }
+            }
+            return Uri.fromFile(dest);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
 }
diff --git a/testapps/EmbmsTestStreamingApp/Android.mk b/testapps/EmbmsTestStreamingApp/Android.mk
index 45826b9..f574990 100644
--- a/testapps/EmbmsTestStreamingApp/Android.mk
+++ b/testapps/EmbmsTestStreamingApp/Android.mk
@@ -10,6 +10,7 @@
 LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs))
 
 LOCAL_PACKAGE_NAME := EmbmsTestStreamingApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 LOCAL_MODULE_TAGS := tests
diff --git a/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/EmbmsTestStreamingApp.java b/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/EmbmsTestStreamingApp.java
index 0546c9d..75febda 100644
--- a/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/EmbmsTestStreamingApp.java
+++ b/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/EmbmsTestStreamingApp.java
@@ -154,7 +154,7 @@
         Button bindButton = (Button) findViewById(R.id.bind_button);
         bindButton.setOnClickListener((view) -> {
             mStreamingManager = MbmsStreamingSession.create(
-                    EmbmsTestStreamingApp.this, mStreamingListener, mHandler);
+                    EmbmsTestStreamingApp.this, mHandler::post, mStreamingListener);
         });
 
         Button getStreamingServicesButton = (Button)
diff --git a/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/StreamingServiceTracker.java b/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/StreamingServiceTracker.java
index 5244d30..d45b5fd 100644
--- a/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/StreamingServiceTracker.java
+++ b/testapps/EmbmsTestStreamingApp/src/com/android/phone/testapps/embmsfrontend/StreamingServiceTracker.java
@@ -60,13 +60,13 @@
      * Start streaming using the provided streaming session
      */
     public boolean startStreaming(MbmsStreamingSession streamingManager) {
-        mStreamingService =
-                streamingManager.startStreaming(mStreamingServiceInfo, new Callback(), null);
+        mStreamingService = streamingManager.startStreaming(mStreamingServiceInfo,
+                mActivity.getMainThreadHandler()::post, new Callback());
         return true;
     }
 
     public void stopStreaming() {
-        mStreamingService.stopStreaming();
+        mStreamingService.close();
     }
 
     public String getServiceId() {
diff --git a/testapps/ImsTestService/Android.mk b/testapps/ImsTestService/Android.mk
index 6afb3d5..29df224 100644
--- a/testapps/ImsTestService/Android.mk
+++ b/testapps/ImsTestService/Android.mk
@@ -19,6 +19,7 @@
 LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs))
 
 LOCAL_PACKAGE_NAME := ImsTestApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
diff --git a/testapps/ImsTestService/AndroidManifest.xml b/testapps/ImsTestService/AndroidManifest.xml
index 4d81ffd..f47210e 100644
--- a/testapps/ImsTestService/AndroidManifest.xml
+++ b/testapps/ImsTestService/AndroidManifest.xml
@@ -40,9 +40,8 @@
                  android:enabled="true"
                  android:persistent="true"
                  android:permission="android.permission.BIND_IMS_SERVICE">
-            <meta-data android:name="android.telephony.ims.MMTEL_FEATURE" android:value="true"/>
-            <!--meta-data android:name="android.telephony.ims.EMERGENCY_MMTEL_FEATURE"
-                       android:value="true" /-->
+            <!--meta-data android:name="android.telephony.ims.MMTEL_FEATURE" android:value="true"/-->
+            <!-- No features means we will get queried for dynamic config. -->
             <intent-filter>
                 <action android:name="android.telephony.ims.ImsService" />
             </intent-filter>
diff --git a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsConfigImpl.java b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsConfigImpl.java
index 4b8842a..3269a5a 100644
--- a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsConfigImpl.java
+++ b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsConfigImpl.java
@@ -55,6 +55,10 @@
         return sTestImsConfigImpl;
     }
 
+    private TestImsConfigImpl() {
+        super();
+    }
+
     public void setConfigListener(ImsConfigListener listener) {
         mListener = listener;
     }
diff --git a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java
index 434cdb5..71323d8 100644
--- a/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java
+++ b/testapps/ImsTestService/src/com/android/phone/testapps/imstestapp/TestImsService.java
@@ -17,9 +17,11 @@
 package com.android.phone.testapps.imstestapp;
 
 import android.telephony.ims.ImsService;
+import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.feature.MmTelFeature;
 import android.telephony.ims.feature.RcsFeature;
 import android.telephony.ims.stub.ImsConfigImplBase;
+import android.telephony.ims.stub.ImsFeatureConfiguration;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.util.Log;
 
@@ -54,8 +56,16 @@
     }
 
     @Override
+    public ImsFeatureConfiguration querySupportedImsFeatures() {
+        return new ImsFeatureConfiguration.Builder()
+                .addFeature(0, ImsFeature.FEATURE_EMERGENCY_MMTEL)
+                .addFeature(0, ImsFeature.FEATURE_MMTEL)
+                .build();
+    }
+
+    @Override
     public MmTelFeature createMmTelFeature(int slotId) {
-        Log.i(LOG_TAG, "TestImsService: onCreateEmergencyMMTelImsFeature");
+        Log.i(LOG_TAG, "TestImsService: onCreateMmTelImsFeature");
         return mTestMmTelFeature;
     }
 
diff --git a/testapps/TelephonyRegistryTestApp/Android.mk b/testapps/TelephonyRegistryTestApp/Android.mk
index ed1f2a3..8c0d286 100644
--- a/testapps/TelephonyRegistryTestApp/Android.mk
+++ b/testapps/TelephonyRegistryTestApp/Android.mk
@@ -9,6 +9,7 @@
 LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs))
 
 LOCAL_PACKAGE_NAME := TelephonyRegistryTestApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_CERTIFICATE := platform
 LOCAL_MODULE_TAGS := tests
diff --git a/tests/Android.mk b/tests/Android.mk
index b43533f..a6a79fe 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -21,6 +21,7 @@
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 LOCAL_PACKAGE_NAME := TeleServiceTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 LOCAL_MODULE_TAGS := tests
diff --git a/tests/src/com/android/phone/PhoneSearchIndexablesProviderTest.java b/tests/src/com/android/phone/PhoneSearchIndexablesProviderTest.java
index 2176d6b..6b7f825 100644
--- a/tests/src/com/android/phone/PhoneSearchIndexablesProviderTest.java
+++ b/tests/src/com/android/phone/PhoneSearchIndexablesProviderTest.java
@@ -124,16 +124,16 @@
         when(mUserManager.isAdminUser()).thenReturn(true);
         Cursor cursor2 = mProvider
                 .queryNonIndexableKeys(SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
-        assertThat(cursor2.getCount()).isEqualTo(2);
+        assertThat(cursor2.getCount()).isEqualTo(3);
 
         mProvider.setIsEuiccSettingsHidden(true /* isEuiccSettingsHidden */);
         Cursor cursor3 = mProvider
                 .queryNonIndexableKeys(SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
-        assertThat(cursor3.getCount()).isEqualTo(3);
+        assertThat(cursor3.getCount()).isEqualTo(4);
 
         mProvider.setIsEnhanced4gLteHidden(true /* isEnhanced4gLteHidden */);
         Cursor cursor4 = mProvider
                 .queryNonIndexableKeys(SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS);
-        assertThat(cursor4.getCount()).isEqualTo(4);
+        assertThat(cursor4.getCount()).isEqualTo(5);
     }
 }