Merge "Move ACTION_NETWORK_SET_TIME to android.telephony intents"
diff --git a/Android.bp b/Android.bp
index a9e4cd2..76e910f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,6 +24,7 @@
         "ims-common",
         "org.apache.http.legacy",
         "libprotobuf-java-lite",
+        "unsupportedappusage",
     ],
 
     static_libs: [
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 60f7718..d4835f3 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -95,6 +95,9 @@
     <!-- For Vendor Debugging in Telephony -->
     <protected-broadcast android:name="android.telephony.action.ANOMALY_REPORTED" />
 
+    <!-- Allows granting runtime permissions to telephony related components. -->
+    <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS" />
+
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.CALL_PHONE" />
     <uses-permission android:name="android.permission.CALL_PRIVILEGED" />
@@ -158,6 +161,7 @@
     <uses-permission android:name="android.permission.MANAGE_USERS" />
     <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
     <uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES" />
+    <uses-permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS" />
     <uses-permission android:name="android.permission.NETWORK_FACTORY" />
     <uses-permission android:name="android.permission.OBSERVE_NETWORK_POLICY" />
     <uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS" />
@@ -170,7 +174,7 @@
     <!-- BIND_CARRIER_MESSAGING_SERVICE has been deprecated in favor of BIND_CARRIER_SERVICES. -->
     <uses-permission android:name="android.permission.BIND_CARRIER_MESSAGING_SERVICE" />
     <uses-permission android:name="android.permission.BIND_EUICC_SERVICE" />
-    <uses-permission android:name="com.android.permission.BIND_TELEPHONY_NETWORK_SERVICE" />
+    <uses-permission android:name="android.permission.BIND_TELEPHONY_NETWORK_SERVICE" />
     <uses-permission android:name="android.permission.BIND_CELL_BROADCAST_SERVICE" />
     <uses-permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" />
     <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
diff --git a/apex/Android.bp b/apex/Android.bp
index 86ebe3a..f9e4b67 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -1,19 +1,24 @@
-apex {
-    name: "com.android.telephony",
-
-    manifest: "apex_manifest.json",
+apex_defaults {
+    name: "com.android.telephony-defaults",
 
     // optional. if unspecified, a default one is auto-generated
     androidManifest: "AndroidManifest.xml",
 
     java_libs: ["telephony-common", "ims-common"],
     //apps: ["TeleService", "StkLib", "ONSLib"],
-    apps: ["StkLib"],
 
     key: "com.android.telephony.key",
     certificate: ":com.android.telephony.certificate",
 }
 
+apex {
+    name: "com.android.telephony",
+    manifest: "apex_manifest.json",
+    apps: ["StkLib"],
+
+    defaults:["com.android.telephony-defaults"],
+}
+
 apex_key {
     name: "com.android.telephony.key",
     public_key: "com.android.telephony.avbpubkey",
diff --git a/apex/testing/Android.bp b/apex/testing/Android.bp
new file mode 100644
index 0000000..10455a4
--- /dev/null
+++ b/apex/testing/Android.bp
@@ -0,0 +1,25 @@
+// Copyright (C) 2019 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.
+
+apex {
+    name: "test_com.android.telephony",
+    visibility: [
+        "//system/apex/tests",
+    ],
+    defaults: ["com.android.telephony-defaults"],
+    manifest: "test_manifest.json",
+    file_contexts: ":com.android.telephony-file_contexts",
+    // Test APEX, should never be installed
+    installable: false,
+}
\ No newline at end of file
diff --git a/apex/testing/AndroidManifest.xml b/apex/testing/AndroidManifest.xml
new file mode 100644
index 0000000..e2af9f5
--- /dev/null
+++ b/apex/testing/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2019 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.telephony">
+    <!-- APEX does not have classes.dex -->
+    <application android:hasCode="false" />
+    <uses-sdk
+        android:targetSdkVersion="30"
+    />
+</manifest>
\ No newline at end of file
diff --git a/apex/testing/test_manifest.json b/apex/testing/test_manifest.json
new file mode 100644
index 0000000..30bfda2
--- /dev/null
+++ b/apex/testing/test_manifest.json
@@ -0,0 +1,4 @@
+{
+  "name": "com.android.telephony",
+  "version": 2147483647
+}
\ No newline at end of file
diff --git a/src/com/android/phone/CLIRListPreference.java b/src/com/android/phone/CLIRListPreference.java
index 5c6132b..d8a9041 100755
--- a/src/com/android/phone/CLIRListPreference.java
+++ b/src/com/android/phone/CLIRListPreference.java
@@ -47,10 +47,15 @@
     protected void onDialogClosed(boolean positiveResult) {
         super.onDialogClosed(positiveResult);
 
-        mPhone.setOutgoingCallerIdDisplay(convertValueToCLIRMode(getValue()),
-                mHandler.obtainMessage(MyHandler.MESSAGE_SET_CLIR));
-        if (mTcpListener != null) {
-            mTcpListener.onStarted(this, false);
+        if (positiveResult && (getValue() != null)) {
+            mPhone.setOutgoingCallerIdDisplay(convertValueToCLIRMode(getValue()),
+                    mHandler.obtainMessage(MyHandler.MESSAGE_SET_CLIR));
+            if (mTcpListener != null) {
+                mTcpListener.onStarted(this, false);
+            }
+        } else {
+            Log.d(LOG_TAG, String.format("onDialogClosed: positiveResult=%b value=%s -- do nothing",
+                        positiveResult, getValue()));
         }
     }
 
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 288b9b0..d451ccf 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -110,7 +110,7 @@
     private final BroadcastReceiver mBootReceiver = new ConfigLoaderBroadcastReceiver();
     // Broadcast receiver for SIM and pkg intents, register intent filter in constructor.
     private final BroadcastReceiver mPackageReceiver = new ConfigLoaderBroadcastReceiver();
-    private final LocalLog mCarrierConfigLoadingLog = new LocalLog(50);
+    private final LocalLog mCarrierConfigLoadingLog = new LocalLog(100);
 
 
     // Message codes; see mHandler below.
@@ -200,6 +200,7 @@
                         // have sent it before unlock. This will avoid we try to load carrier config
                         // when SIM is still loading when unlock happens.
                         if (mHasSentConfigChange[i]) {
+                            logWithLocalLog("System unlocked");
                             updateConfigForPhoneId(i);
                         }
                     }
@@ -214,6 +215,8 @@
                     if (clearCachedConfigForPackage(carrierPackageName)) {
                         int numPhones = TelephonyManager.from(mContext).getActiveModemCount();
                         for (int i = 0; i < numPhones; ++i) {
+                            logWithLocalLog("Package changed: " + carrierPackageName
+                                    + ", phone=" + i);
                             updateConfigForPhoneId(i);
                         }
                     }
@@ -975,7 +978,10 @@
             PersistableBundle config = mConfigFromDefaultApp[phoneId];
             if (config != null) {
                 retConfig.putAll(config);
-                retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+                if (getCarrierPackageForPhoneId(phoneId) == null) {
+                    retConfig.putBoolean(
+                            CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+                }
             }
             config = mConfigFromCarrierApp[phoneId];
             if (config != null) {
@@ -990,7 +996,6 @@
             config = mOverrideConfigs[phoneId];
             if (config != null) {
                 retConfig.putAll(config);
-                retConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
             }
         }
         return retConfig;
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index d1ff56f..06d2367 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -18,13 +18,22 @@
 
 import android.content.Context;
 import android.net.Uri;
+import android.os.Binder;
+import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.telephony.ims.ImsException;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
 import android.telephony.ims.aidl.IImsRcsController;
 import android.telephony.ims.aidl.IRcsUceControllerCallback;
 import android.telephony.ims.feature.RcsFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.util.Log;
 
+import com.android.ims.RcsFeatureManager;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.imsphone.ImsPhone;
+
 import java.util.List;
 
 /**
@@ -60,28 +69,94 @@
         ServiceManager.addService(Context.TELEPHONY_IMS_SERVICE, this);
     }
 
+    /**
+     * Register a capability callback which will provide RCS availability updates for the
+     * subscription specified.
+     *
+     * @param subId the subscription ID
+     * @param callback The ImsCapabilityCallback to be registered.
+     */
     @Override
-    public void registerRcsAvailabilityCallback(IImsCapabilityCallback c) {
+    public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback)
+            throws RemoteException {
         enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            getRcsFeatureManager(subId).registerRcsAvailabilityCallback(callback);
+        } catch (com.android.ims.ImsException e) {
+            Log.e(TAG, "registerRcsAvailabilityCallback: sudId=" + subId + ", " + e.getMessage());
+            throw new ServiceSpecificException(e.getCode());
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
+    /**
+     * Remove the registered capability callback.
+     *
+     * @param subId the subscription ID
+     * @param callback The ImsCapabilityCallback to be removed.
+     */
     @Override
-    public void unregisterRcsAvailabilityCallback(IImsCapabilityCallback c) {
+    public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
         enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
+        final long token = Binder.clearCallingIdentity();
+        try {
+            getRcsFeatureManager(subId).unregisterRcsAvailabilityCallback(callback);
+        } catch (com.android.ims.ImsException e) {
+            Log.e(TAG, "unregisterRcsAvailabilityCallback: sudId=" + subId + "," + e.getMessage());
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
+    /**
+     * Query for the capability of an IMS RCS service
+     *
+     * @param subId the subscription ID
+     * @param capability the RCS capability to query.
+     * @param radioTech the radio tech that this capability failed for
+     * @return true if the RCS capability is capable for this subscription, false otherwise.
+     */
     @Override
     public boolean isCapable(int subId,
-            @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
+            @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+            @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
         enforceReadPrivilegedPermission("isCapable");
-        return false;
+        final long token = Binder.clearCallingIdentity();
+        try {
+            return getRcsFeatureManager(subId).isCapable(capability, radioTech);
+        } catch (com.android.ims.ImsException e) {
+            Log.e(TAG, "isCapable: sudId=" + subId
+                    + ", capability=" + capability + ", " + e.getMessage());
+            return false;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
+    /**
+     * Query the availability of an IMS RCS capability.
+     *
+     * @param subId the subscription ID
+     * @param capability the RCS capability to query.
+     * @return true if the RCS capability is currently available for the associated subscription,
+     * false otherwise.
+     */
     @Override
     public boolean isAvailable(int subId,
             @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
         enforceReadPrivilegedPermission("isAvailable");
-        return false;
+        final long token = Binder.clearCallingIdentity();
+        try {
+            return getRcsFeatureManager(subId).isAvailable(capability);
+        } catch (com.android.ims.ImsException e) {
+            Log.e(TAG, "isAvailable: sudId=" + subId
+                    + ", capability=" + capability + ", " + e.getMessage());
+            return false;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     @Override
@@ -125,4 +200,30 @@
     private void enforceModifyPermission() {
         mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
     }
+
+    /**
+     * Retrieve RcsFeatureManager instance.
+     *
+     * @param subId the subscription ID
+     * @return The RcsFeatureManager instance
+     * @throws SecurityException if getting Phone or RcsFeatureManager instance failed.
+     */
+    private RcsFeatureManager getRcsFeatureManager(int subId) {
+        Phone phone = PhoneGlobals.getPhone(subId);
+        if (phone == null) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_INVALID_SUBSCRIPTION,
+                    "Invalid subscription Id: " + subId);
+        }
+        ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
+        if (imsPhone == null) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+                    "Cannot find ImsPhone instance: " + subId);
+        }
+        RcsFeatureManager rcsFeatureManager = imsPhone.getRcsManager();
+        if (rcsFeatureManager == null) {
+            throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
+                    "Cannot find RcsFeatureManager instance: " + subId);
+        }
+        return rcsFeatureManager;
+    }
 }
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 05e1fb3..296525d 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -1778,6 +1778,7 @@
     }
 
     public boolean needMobileRadioShutdown() {
+        enforceReadPrivilegedPermission("needMobileRadioShutdown");
         /*
          * If any of the Radios are available, it will need to be
          * shutdown. So return true if any Radio is available.
@@ -2032,7 +2033,15 @@
     }
 
     @Override
-    public String getNetworkCountryIsoForPhone(int phoneId) {
+    public String getNetworkCountryIsoForPhone(int phoneId, String callingPackage) {
+        if (!TextUtils.isEmpty(callingPackage)) {
+            final int subId = mSubscriptionController.getSubIdUsingPhoneId(phoneId);
+            if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
+                    mApp, subId, callingPackage, "getNetworkCountryIsoForPhone")) {
+                return "";
+            }
+        }
+
         // Reporting the correct network country is ambiguous when IWLAN could conflict with
         // registered cell info, so return a NULL country instead.
         final long identity = Binder.clearCallingIdentity();
diff --git a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
index 96f04e1..c47e014 100644
--- a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
+++ b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
@@ -18,6 +18,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Activity;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -95,7 +96,7 @@
 
         grantDefaultPermissionsToActiveLuiApp(activityInfo);
 
-        euiccUiIntent.setComponent(activityInfo.getComponentName());
+        euiccUiIntent.setComponent(new ComponentName(activityInfo.packageName, activityInfo.name));
         return euiccUiIntent;
     }
 
diff --git a/src/com/android/phone/otasp/OtaspSimStateReceiver.java b/src/com/android/phone/otasp/OtaspSimStateReceiver.java
index 78f7baf..bb4022a 100644
--- a/src/com/android/phone/otasp/OtaspSimStateReceiver.java
+++ b/src/com/android/phone/otasp/OtaspSimStateReceiver.java
@@ -18,9 +18,11 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
@@ -32,15 +34,32 @@
     private static final boolean DBG = true;
     private Context mContext;
 
-    private PhoneStateListener mPhoneStateListener = new PhoneStateListener(){
+    private static final int EVENT_OTASP_CHANGED = 1;
+
+    private Handler mOtaspHandler = new Handler() {
         @Override
-        public void onOtaspChanged(int otaspMode) {
-            logd("onOtaspChanged: otaspMode=" + otaspMode);
-            if (otaspMode == TelephonyManager.OTASP_NEEDED) {
-                logd("otasp activation required, start otaspActivationService");
-                mContext.startService(new Intent(mContext, OtaspActivationService.class));
-            } else if (otaspMode == TelephonyManager.OTASP_NOT_NEEDED) {
-                OtaspActivationService.updateActivationState(mContext, true);
+        public void handleMessage(Message msg) {
+            AsyncResult ar;
+            switch (msg.what) {
+                case EVENT_OTASP_CHANGED:
+                    ar = (AsyncResult) msg.obj;
+                    if (ar.exception == null && ar.result != null) {
+                        int otaspMode = (Integer) ar.result;
+                        logd("EVENT_OTASP_CHANGED: otaspMode=" + otaspMode);
+                        if (otaspMode == TelephonyManager.OTASP_NEEDED) {
+                            logd("otasp activation required, start otaspActivationService");
+                            mContext.startService(
+                                    new Intent(mContext, OtaspActivationService.class));
+                        } else if (otaspMode == TelephonyManager.OTASP_NOT_NEEDED) {
+                            OtaspActivationService.updateActivationState(mContext, true);
+                        }
+                    } else {
+                        logd("EVENT_OTASP_CHANGED: exception=" + ar.exception);
+                    }
+                    break;
+                default:
+                    super.handleMessage(msg);
+                    break;
             }
         }
     };
@@ -74,13 +93,17 @@
         if(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
             if (DBG) logd("Received intent: " + intent.getAction());
             if (PhoneGlobals.getPhone().getIccRecordsLoaded() && isCarrierSupported()) {
-                final TelephonyManager telephonyManager = TelephonyManager.from(context);
-                telephonyManager.listen(mPhoneStateListener,
-                        PhoneStateListener.LISTEN_OTASP_CHANGED);
+                registerOtaspChangedHandler();
             }
         }
     }
 
+    // It's fine to call mutiple times, as the registrants are de-duped by Handler object.
+    private void registerOtaspChangedHandler() {
+        final Phone phone = PhoneGlobals.getPhone();
+        phone.registerForOtaspChange(mOtaspHandler, EVENT_OTASP_CHANGED, null);
+    }
+
     private static void logd(String s) {
         Log.d(TAG, s);
     }
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index 04045f1..ce5b839 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -192,6 +192,7 @@
     private static final int EVENT_SET_PREFERRED_TYPE_DONE = 1001;
     private static final int EVENT_QUERY_SMSC_DONE = 1005;
     private static final int EVENT_UPDATE_SMSC_DONE = 1006;
+    private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 1007;
 
     private static final int MENU_ITEM_SELECT_BAND         = 0;
     private static final int MENU_ITEM_VIEW_ADN            = 1;
@@ -345,12 +346,6 @@
             updateImsProvisionedState();
         }
 
-        @Override
-        public void onPhysicalChannelConfigurationChanged(
-                List<PhysicalChannelConfig> configs) {
-            updatePhysicalChannelConfiguration(configs);
-        }
-
     }
 
     private void updatePhysicalChannelConfiguration(List<PhysicalChannelConfig> configs) {
@@ -428,6 +423,13 @@
                         mSmsc.setText("update error");
                     }
                     break;
+                case EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED:
+                    ar = (AsyncResult) msg.obj;
+                    if (ar.exception != null) {
+                        mPhyChanConfig.setText(("update error"));
+                    }
+                    updatePhysicalChannelConfiguration((List<PhysicalChannelConfig>) ar.result);
+                    break;
                 default:
                     super.handleMessage(msg);
                     break;
@@ -644,6 +646,8 @@
 
         unregisterPhoneStateListener();
         registerPhoneStateListener();
+        mPhone.registerForPhysicalChannelConfig(mHandler,
+            EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED, null);
 
         mConnectivityManager.registerNetworkCallback(
                 mDefaultNetworkRequest, mNetworkCallback, mHandler);
@@ -759,6 +763,7 @@
 
     private void unregisterPhoneStateListener() {
         mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+        mPhone.unregisterForPhysicalChannelConfig(mHandler);
 
         // clear all fields so they are blank until the next listener event occurs
         mOperatorName.setText("");
@@ -794,8 +799,7 @@
                 | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
                 | PhoneStateListener.LISTEN_CELL_INFO
                 | PhoneStateListener.LISTEN_SERVICE_STATE
-                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
-                | PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION);
+                | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
     }
 
     private void updateDnsCheckState() {
diff --git a/src/com/android/phone/vvm/RemoteVvmTaskManager.java b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
index 14030a1..6b60303 100644
--- a/src/com/android/phone/vvm/RemoteVvmTaskManager.java
+++ b/src/com/android/phone/vvm/RemoteVvmTaskManager.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.pm.ComponentInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
@@ -38,6 +39,7 @@
 import android.telephony.VisualVoicemailSms;
 import android.text.TextUtils;
 
+import com.android.internal.telephony.util.TelephonyUtils;
 import com.android.phone.Assert;
 import com.android.phone.R;
 
@@ -167,7 +169,8 @@
             }
             if (info.serviceInfo == null) {
                 VvmLog.w(TAG,
-                        "Component " + info.getComponentInfo() + " is not a service, ignoring");
+                        "Component " + TelephonyUtils.getComponentInfo(info)
+                            + " is not a service, ignoring");
                 continue;
             }
             if (!android.Manifest.permission.BIND_VISUAL_VOICEMAIL_SERVICE
@@ -180,7 +183,8 @@
                 VvmLog.w(TAG, "target package " + targetPackage
                         + " is no longer the active VisualVoicemailService, ignoring");
             }
-            return info.getComponentInfo().getComponentName();
+            ComponentInfo componentInfo = TelephonyUtils.getComponentInfo(info);
+            return new ComponentName(componentInfo.packageName, componentInfo.name);
 
         }
         return null;
@@ -199,7 +203,8 @@
         if (info.isEmpty()) {
             return null;
         }
-        return info.get(0).getComponentInfo().getComponentName();
+        ComponentInfo componentInfo = TelephonyUtils.getComponentInfo(info.get(0));
+        return new ComponentName(componentInfo.packageName, componentInfo.name);
     }
 
     @Override
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 5a9fbcf..fb865b4 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -203,6 +203,7 @@
                     // whether the call should have the HD audio property set.
                     refreshConferenceSupported();
                     refreshDisableAddCall();
+                    refreshHoldSupported();
                     updateConnectionProperties();
                     break;
 
@@ -1345,6 +1346,18 @@
         }
     }
 
+    private void refreshHoldSupported() {
+       if (mOriginalConnection == null) {
+           Log.w(this, "refreshHoldSupported org conn is null");
+           return;
+       }
+
+       if (!mOriginalConnection.shouldAllowHoldingVideoCall() && canHoldImsCalls() !=
+               ((getConnectionCapabilities() & (CAPABILITY_HOLD | CAPABILITY_SUPPORT_HOLD)) != 0)) {
+           updateConnectionCapabilities();
+       }
+    }
+
     private void refreshDisableAddCall() {
         if (shouldSetDisableAddCallExtra()) {
             Bundle newExtras = getExtras();
@@ -1501,8 +1514,10 @@
     private boolean canHoldImsCalls() {
         PersistableBundle b = getCarrierConfig();
         // Return true if the CarrierConfig is unavailable
-        return !doesDeviceRespectHoldCarrierConfig() || b == null ||
-                b.getBoolean(CarrierConfigManager.KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL);
+        return (!doesDeviceRespectHoldCarrierConfig() || b == null ||
+                b.getBoolean(CarrierConfigManager.KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL)) &&
+                ((mOriginalConnection != null && mOriginalConnection.shouldAllowHoldingVideoCall())
+                || !VideoProfile.isVideo(getVideoState()));
     }
 
     @VisibleForTesting
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 10d2c2f..40b941e 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -1457,16 +1457,32 @@
                         phone.getEmergencyNumberTracker().getEmergencyNumber(number);
                 if (emergencyNumber != null) {
                     phone.notifyOutgoingEmergencyCall(emergencyNumber);
-                    // If we do not support holding ongoing calls for an outgoing emergency call,
-                    // disconnect the ongoing calls.
-                    if (!shouldHoldForEmergencyCall(phone) && !getAllConnections().isEmpty()) {
-                        for (Connection c : getAllConnections()) {
-                            if (!c.equals(connection)
-                                    && c.getState() != Connection.STATE_DISCONNECTED
-                                    && c instanceof TelephonyConnection) {
-                                ((TelephonyConnection) c).hangup(
-                                        android.telephony.DisconnectCause
-                                                .OUTGOING_EMERGENCY_CALL_PLACED);
+                    if (!getAllConnections().isEmpty()) {
+                        if (!shouldHoldForEmergencyCall(phone)) {
+                            // If we do not support holding ongoing calls for an outgoing
+                            // emergency call, disconnect the ongoing calls.
+                            for (Connection c : getAllConnections()) {
+                                if (!c.equals(connection)
+                                        && c.getState() != Connection.STATE_DISCONNECTED
+                                        && c instanceof TelephonyConnection) {
+                                    ((TelephonyConnection) c).hangup(
+                                            android.telephony.DisconnectCause
+                                                    .OUTGOING_EMERGENCY_CALL_PLACED);
+                                }
+                            }
+                        } else if (!isVideoCallHoldAllowed(phone)) {
+                            // If we do not support holding ongoing video call for an outgoing
+                            // emergency call, disconnect the ongoing video call.
+                            for (Connection c : getAllConnections()) {
+                                if (!c.equals(connection)
+                                        && c.getState() == Connection.STATE_ACTIVE
+                                        && VideoProfile.isVideo(c.getVideoState())
+                                        && c instanceof TelephonyConnection) {
+                                    ((TelephonyConnection) c).hangup(
+                                            android.telephony.DisconnectCause
+                                                    .OUTGOING_EMERGENCY_CALL_PLACED);
+                                    break;
+                                }
                             }
                         }
                     }
@@ -1536,6 +1552,18 @@
         }
     }
 
+    private boolean isVideoCallHoldAllowed(Phone phone) {
+         CarrierConfigManager cfgManager = (CarrierConfigManager)
+                phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
+        if (cfgManager == null) {
+            // For some reason CarrierConfigManager is unavailable, return default
+            Log.w(this, "isVideoCallHoldAllowed: couldn't get CarrierConfigManager");
+            return true;
+        }
+        return cfgManager.getConfigForSubId(phone.getSubId()).getBoolean(
+                CarrierConfigManager.KEY_ALLOW_HOLDING_VIDEO_CALL_BOOL, true);
+    }
+
     private boolean shouldHoldForEmergencyCall(Phone phone) {
         CarrierConfigManager cfgManager = (CarrierConfigManager)
                 phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
diff --git a/testapps/TelephonyRegistryTestApp/src/com/android/phone/testapps/telephonyregistry/TelephonyRegistryTestApp.java b/testapps/TelephonyRegistryTestApp/src/com/android/phone/testapps/telephonyregistry/TelephonyRegistryTestApp.java
index 96f8bf7..f8d4487 100644
--- a/testapps/TelephonyRegistryTestApp/src/com/android/phone/testapps/telephonyregistry/TelephonyRegistryTestApp.java
+++ b/testapps/TelephonyRegistryTestApp/src/com/android/phone/testapps/telephonyregistry/TelephonyRegistryTestApp.java
@@ -50,7 +50,6 @@
         put(PhoneStateListener.LISTEN_DATA_CONNECTION_STATE, "DATA_CONNECTION_STATE");
         put(PhoneStateListener.LISTEN_DATA_ACTIVITY, "DATA_ACTIVITY");
         put(PhoneStateListener.LISTEN_SIGNAL_STRENGTHS, "SIGNAL_STRENGTHS");
-        put(PhoneStateListener.LISTEN_OTASP_CHANGED, "OTASP_CHANGED");
         put(PhoneStateListener.LISTEN_CELL_INFO, "CELL_INFO");
         put(PhoneStateListener.LISTEN_PRECISE_CALL_STATE, "PRECISE_CALL_STATE");
         put(PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE,