Merge "Update language to comply with Android's inclusive language guidance"
diff --git a/res/layout/radio_info.xml b/res/layout/radio_info.xml
index 40c2e53..71cd32a 100644
--- a/res/layout/radio_info.xml
+++ b/res/layout/radio_info.xml
@@ -122,6 +122,37 @@
             <TextView android:id="@+id/ul_kbps" style="@style/info_value" />
         </LinearLayout>
 
+
+        <!-- EN-DC Available -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:id="@+id/endc_available_label" android:text="@string/radio_info_endc_available" style="@style/info_label" />
+            <TextView android:id="@+id/endc_available" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- DCNR Restricted -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:id="@+id/dcnr_restricted_label" android:text="@string/radio_info_dcnr_restricted" style="@style/info_label" />
+            <TextView android:id="@+id/dcnr_restricted" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- NR Available -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:id="@+id/nr_available_label" android:text="@string/radio_info_nr_available" style="@style/info_label" />
+            <TextView android:id="@+id/nr_available" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- NR State -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:id="@+id/nr_state_label" android:text="@string/radio_info_nr_state" style="@style/info_label" />
+            <TextView android:id="@+id/nr_state" style="@style/info_value" />
+        </LinearLayout>
+
+        <!-- NR Frequency -->
+        <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+            <TextView android:id="@+id/nr_frequency_label" android:text="@string/radio_info_nr_frequency" style="@style/info_label" />
+            <TextView android:id="@+id/nr_frequency" style="@style/info_value" />
+        </LinearLayout>
+
         <!-- Physical Channel Config -->
         <LinearLayout style="@style/RadioInfo_entry_layout">
             <TextView android:text="@string/radio_info_phy_chan_config" style="@style/info_label" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b74b2ff..54047c2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2140,6 +2140,16 @@
     <string name="radio_info_toggle_dns_check_label">Toggle DNS Check</string>
     <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
     <string name="oem_radio_info_label">OEM-specific Info/Settings</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_endc_available">EN-DC Available:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_dcnr_restricted">DCNR Restricted:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_nr_available">NR Available:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_nr_state">NR State:</string>
+    <!-- Radio Info screen. Label for a status item.  Used for diagnostic info screens, precise translation isn't needed -->
+    <string name="radio_info_nr_frequency">NR Frequency:</string>
 
     <!-- Band Mode Selection -->
     <!-- Band mode screen.  Title of activity. -->
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 4f6be79..8c6be60 100755
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -1929,20 +1929,52 @@
         }
     }
 
+    /**
+     * This method has been removed due to privacy and stability concerns.
+     */
+    @Override
     public void updateServiceLocation() {
-        updateServiceLocationForSubscriber(getDefaultSubscription());
-
+        Log.e(LOG_TAG, "Call to unsupported method updateServiceLocation()");
+        return;
     }
 
-    public void updateServiceLocationForSubscriber(int subId) {
-        // No permission check needed here: this call is harmless, and it's
-        // needed for the ServiceState.requestStateUpdate() call (which is
-        // already intentionally exposed to 3rd parties.)
+    @Override
+    public void updateServiceLocationWithPackageName(String callingPackage) {
+        mApp.getSystemService(AppOpsManager.class)
+                .checkPackage(Binder.getCallingUid(), callingPackage);
+
+        final int targetSdk = getTargetSdk(callingPackage);
+        if (targetSdk > android.os.Build.VERSION_CODES.R) {
+            // Callers targeting S have no business invoking this method.
+            return;
+        }
+
+        LocationAccessPolicy.LocationPermissionResult locationResult =
+                LocationAccessPolicy.checkLocationPermission(mApp,
+                        new LocationAccessPolicy.LocationPermissionQuery.Builder()
+                                .setCallingPackage(callingPackage)
+                                .setCallingFeatureId(null)
+                                .setCallingPid(Binder.getCallingPid())
+                                .setCallingUid(Binder.getCallingUid())
+                                .setMethod("updateServiceLocation")
+                                .setMinSdkVersionForCoarse(Build.VERSION_CODES.BASE)
+                                .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
+                                .build());
+        // Apps that lack location permission have no business calling this method;
+        // however, because no permission was declared in the public API, denials must
+        // all be "soft".
+        switch (locationResult) {
+            case DENIED_HARD: /* fall through */
+            case DENIED_SOFT:
+                return;
+        }
+
+        WorkSource workSource = getWorkSource(Binder.getCallingUid());
         final long identity = Binder.clearCallingIdentity();
         try {
-            final Phone phone = getPhone(subId);
+            final Phone phone = getPhone(getDefaultSubscription());
             if (phone != null) {
-                phone.updateServiceLocation();
+                phone.updateServiceLocation(workSource);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -2317,46 +2349,30 @@
         }
     }
 
+    /**
+     * This method was removed due to potential issues caused by performing partial
+     * updates of service state, and lack of a credible use case.
+     *
+     * This has the ability to break the telephony implementation by disabling notification of
+     * changes in device connectivity. DO NOT USE THIS!
+     */
     @Override
     public void enableLocationUpdates() {
-        enableLocationUpdatesForSubscriber(getDefaultSubscription());
-    }
-
-    @Override
-    public void enableLocationUpdatesForSubscriber(int subId) {
         mApp.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            final Phone phone = getPhone(subId);
-            if (phone != null) {
-                phone.enableLocationUpdates();
-            }
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
     }
 
+    /**
+     * This method was removed due to potential issues caused by performing partial
+     * updates of service state, and lack of a credible use case.
+     *
+     * This has the ability to break the telephony implementation by disabling notification of
+     * changes in device connectivity. DO NOT USE THIS!
+     */
     @Override
     public void disableLocationUpdates() {
-        disableLocationUpdatesForSubscriber(getDefaultSubscription());
-    }
-
-    @Override
-    public void disableLocationUpdatesForSubscriber(int subId) {
         mApp.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CONTROL_LOCATION_UPDATES, null);
-
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            final Phone phone = getPhone(subId);
-            if (phone != null) {
-                phone.disableLocationUpdates();
-            }
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
     }
 
     /**
@@ -4355,7 +4371,8 @@
             if (phone == null) {
                 return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
             } else {
-                return phone.getLteOnCdmaMode();
+                return TelephonyProperties.lte_on_cdma_device()
+                        .orElse(PhoneConstants.LTE_ON_CDMA_FALSE);
             }
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -5537,6 +5554,74 @@
     }
 
     /**
+     * Get the allowed network types for certain reason.
+     *
+     * @param subId the id of the subscription.
+     * @param reason the reason the allowed network type change is taking place
+     * @return the allowed network types.
+     */
+    @Override
+    public long getAllowedNetworkTypesForReason(int subId,
+            @TelephonyManager.AllowedNetworkTypesReason int reason) {
+        TelephonyPermissions
+                .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+                        mApp, subId, "getAllowedNetworkTypesForReason");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getPhoneFromSubId(subId).getAllowedNetworkTypes(reason);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Get the effective allowed network types on the device.
+     * This API will return an intersection of allowed network types for all reasons,
+     * including the configuration done through setAllowedNetworkTypes
+     *
+     * @param subId the id of the subscription.
+     * @return the allowed network types
+     */
+    @Override
+    public long getEffectiveAllowedNetworkTypes(int subId) {
+        TelephonyPermissions
+                .enforeceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+                        mApp, subId, "getEffectiveAllowedNetworkTypes");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            return getPhoneFromSubId(subId).getEffectiveAllowedNetworkTypes();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
+     * Set the allowed network types of the device and
+     * provide the reason triggering the allowed network change.
+     *
+     * @param subId the id of the subscription.
+     * @param reason the reason the allowed network type change is taking place
+     * @param allowedNetworkTypes the allowed network types.
+     * @return true on success; false on any failure.
+     */
+    @Override
+    public boolean setAllowedNetworkTypesForReason(int subId,
+            @TelephonyManager.AllowedNetworkTypesReason int reason, long allowedNetworkTypes) {
+        TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
+                mApp, subId, "setAllowedNetworkTypesForReason");
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            getPhoneFromSubId(subId).setAllowedNetworkTypes(reason, allowedNetworkTypes);
+            int preferredNetworkMode = Settings.Global.getInt(mApp.getContentResolver(),
+                    Settings.Global.PREFERRED_NETWORK_MODE + subId,
+                    RILConstants.PREFERRED_NETWORK_MODE);
+            return setPreferredNetworkType(subId, preferredNetworkMode);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    /**
      * Check whether DUN APN is required for tethering with subId.
      *
      * @param subId the id of the subscription to require tethering.
@@ -5698,6 +5783,11 @@
 
     private int getCarrierPrivilegeStatusFromCarrierConfigRules(int privilegeFromSim, int uid,
             Phone phone) {
+        if (uid == Process.SYSTEM_UID || uid == Process.PHONE_UID) {
+            // Skip the check if it's one of these special uids
+            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+        }
+
         //load access rules from carrier configs, and check those as well: b/139133814
         SubscriptionController subController = SubscriptionController.getInstance();
         if (privilegeFromSim == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
@@ -6429,6 +6519,8 @@
 
     @Override
     public @Nullable PhoneAccountHandle getPhoneAccountHandleForSubscriptionId(int subscriptionId) {
+        enforceReadPrivilegedPermission("getPhoneAccountHandleForSubscriptionId, "
+                + "subscriptionId: " + subscriptionId);
         final long identity = Binder.clearCallingIdentity();
         try {
             Phone phone = getPhone(subscriptionId);
@@ -7578,7 +7670,7 @@
     private boolean getDefaultDataRoamingEnabled(int subId) {
         final CarrierConfigManager configMgr = (CarrierConfigManager)
                 mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        boolean isDataRoamingEnabled = TelephonyProperties.data_roaming().orElse(true);
+        boolean isDataRoamingEnabled = TelephonyProperties.data_roaming().orElse(false);
         isDataRoamingEnabled |= configMgr.getConfigForSubId(subId).getBoolean(
                 CarrierConfigManager.KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL);
         return isDataRoamingEnabled;
@@ -8223,6 +8315,11 @@
         //TODO investigate if this API should require proper permission check in R b/133791609
         final long identity = Binder.clearCallingIdentity();
         try {
+            String carrierUAProfUrl = mApp.getCarrierConfigForSubId(subId).getString(
+                    CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING);
+            if (!TextUtils.isEmpty(carrierUAProfUrl)) {
+                return carrierUAProfUrl;
+            }
             return SubscriptionManager.getResourcesForSubId(getDefaultPhone().getContext(), subId)
                     .getString(com.android.internal.R.string.config_mms_user_agent_profile_url);
         } finally {
@@ -8235,6 +8332,11 @@
         //TODO investigate if this API should require proper permission check in R b/133791609
         final long identity = Binder.clearCallingIdentity();
         try {
+            String carrierUserAgent = mApp.getCarrierConfigForSubId(subId).getString(
+                    CarrierConfigManager.KEY_MMS_USER_AGENT_STRING);
+            if (!TextUtils.isEmpty(carrierUserAgent)) {
+                return carrierUserAgent;
+            }
             return SubscriptionManager.getResourcesForSubId(getDefaultPhone().getContext(), subId)
                     .getString(com.android.internal.R.string.config_mms_user_agent);
         } finally {
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 53b3356..e0c9110 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -22,6 +22,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ShellCommand;
+import android.provider.BlockedNumberContract;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -56,6 +57,7 @@
     private static final String IMS_SUBCOMMAND = "ims";
     private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
     private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
+    private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
     private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
     private static final String DATA_TEST_MODE = "data";
     private static final String DATA_ENABLE = "enable";
@@ -82,6 +84,7 @@
 
     private SubscriptionManager mSubscriptionManager;
     private CarrierConfigManager mCarrierConfigManager;
+    private Context mContext;
 
     private enum CcType {
         BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
@@ -132,6 +135,7 @@
                 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
         mSubscriptionManager = (SubscriptionManager)
                 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        mContext = context;
     }
 
     @Override
@@ -153,6 +157,8 @@
             }
             case DATA_TEST_MODE:
                 return handleDataTestModeCommand();
+            case END_BLOCK_SUPPRESSION:
+                return handleEndBlockSuppressionCommand();
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -169,12 +175,15 @@
         pw.println("    IMS Commands.");
         pw.println("  emergency-number-test-mode");
         pw.println("    Emergency Number Test Mode Commands.");
+        pw.println("  end-block-suppression");
+        pw.println("    End Block Suppression command.");
         pw.println("  data");
         pw.println("    Data Test Mode Commands.");
         pw.println("  cc");
         pw.println("    Carrier Config Commands.");
         onHelpIms();
         onHelpEmergencyNumber();
+        onHelpEndBlockSupperssion();
         onHelpDataTestMode();
         onHelpCc();
     }
@@ -242,6 +251,13 @@
         pw.println("      -p: get the full emergency number list in the test mode.");
     }
 
+    private void onHelpEndBlockSupperssion() {
+        PrintWriter pw = getOutPrintWriter();
+        pw.println("End Block Suppression command:");
+        pw.println("  end-block-suppression: disable suppressing blocking by contact");
+        pw.println("                         with emergency services.");
+    }
+
     private void onHelpCc() {
         PrintWriter pw = getOutPrintWriter();
         pw.println("Carrier Config Commands:");
@@ -1169,4 +1185,15 @@
         }
         return bundle;
     }
+
+    private int handleEndBlockSuppressionCommand() {
+        if (!checkShellUid()) {
+            return -1;
+        }
+
+        if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
+            BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
+        }
+        return 0;
+    }
 }
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index d0951e4..f20da59 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -41,6 +41,7 @@
 import android.os.PersistableBundle;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.telephony.AccessNetworkConstants;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CellIdentityCdma;
 import android.telephony.CellIdentityGsm;
@@ -56,6 +57,8 @@
 import android.telephony.CellSignalStrengthGsm;
 import android.telephony.CellSignalStrengthLte;
 import android.telephony.CellSignalStrengthWcdma;
+import android.telephony.DataSpecificRegistrationInfo;
+import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhoneStateListener;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
@@ -240,6 +243,11 @@
     private TextView mDnsCheckState;
     private TextView mDownlinkKbps;
     private TextView mUplinkKbps;
+    private TextView mEndcAvailable;
+    private TextView mDcnrRestricted;
+    private TextView mNrAvailable;
+    private TextView mNrState;
+    private TextView mNrFrequency;
     private EditText mSmsc;
     private Switch mRadioPowerOnSwitch;
     private Button mCellInfoRefreshRateButton;
@@ -357,6 +365,7 @@
             updateRadioPowerState();
             updateNetworkType();
             updateImsProvisionedState();
+            updateNrStats(serviceState);
         }
 
     }
@@ -501,9 +510,28 @@
         mPingHostnameV4 = (TextView) findViewById(R.id.pingHostnameV4);
         mPingHostnameV6 = (TextView) findViewById(R.id.pingHostnameV6);
         mHttpClientTest = (TextView) findViewById(R.id.httpClientTest);
-
+        mEndcAvailable = (TextView) findViewById(R.id.endc_available);
+        mDcnrRestricted = (TextView) findViewById(R.id.dcnr_restricted);
+        mNrAvailable = (TextView) findViewById(R.id.nr_available);
+        mNrState = (TextView) findViewById(R.id.nr_state);
+        mNrFrequency = (TextView) findViewById(R.id.nr_frequency);
         mPhyChanConfig = (TextView) findViewById(R.id.phy_chan_config);
 
+        // hide 5G stats on devices that don't support 5G
+        if ((mTelephonyManager.getSupportedRadioAccessFamily()
+                & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
+            ((TextView) findViewById(R.id.endc_available_label)).setVisibility(View.GONE);
+            mEndcAvailable.setVisibility(View.GONE);
+            ((TextView) findViewById(R.id.dcnr_restricted_label)).setVisibility(View.GONE);
+            mDcnrRestricted.setVisibility(View.GONE);
+            ((TextView) findViewById(R.id.nr_available_label)).setVisibility(View.GONE);
+            mNrAvailable.setVisibility(View.GONE);
+            ((TextView) findViewById(R.id.nr_state_label)).setVisibility(View.GONE);
+            mNrState.setVisibility(View.GONE);
+            ((TextView) findViewById(R.id.nr_frequency_label)).setVisibility(View.GONE);
+            mNrFrequency.setVisibility(View.GONE);
+        }
+
         mPreferredNetworkType = (Spinner) findViewById(R.id.preferredNetworkType);
         ArrayAdapter<String> mPreferredNetworkTypeAdapter = new ArrayAdapter<String>(this,
                 android.R.layout.simple_spinner_item, PREFERRED_NETWORK_LABELS);
@@ -625,6 +653,7 @@
         updateProperties();
         updateDnsCheckState();
         updateNetworkType();
+        updateNrStats(null);
 
         updateLocation(mCellLocationResult);
         updateCellInfo(mCellInfoResult);
@@ -1132,6 +1161,32 @@
         }
     }
 
+    private void updateNrStats(ServiceState serviceState) {
+        if ((mTelephonyManager.getSupportedRadioAccessFamily()
+                & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
+            return;
+        }
+
+        ServiceState ss = serviceState;
+        if (ss == null && mPhone != null) {
+            ss = mPhone.getServiceState();
+        }
+        if (ss != null) {
+            NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
+                    NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+            if (nri != null) {
+                DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
+                if (dsri != null) {
+                    mEndcAvailable.setText(dsri.isEnDcAvailable ? "True" : "False");
+                    mDcnrRestricted.setText(dsri.isDcNrRestricted ? "True" : "False");
+                    mNrAvailable.setText(dsri.isNrAvailable ? "True" : "False");
+                }
+            }
+            mNrState.setText(NetworkRegistrationInfo.nrStateToString(ss.getNrState()));
+            mNrFrequency.setText(ServiceState.frequencyRangeToString(ss.getNrFrequencyRange()));
+        }
+    }
+
     private void updateProperties() {
         String s;
         Resources r = getResources();