Merge "[Telephony Mainline] Move TelephonyUtils to telephony/common"
diff --git a/api/current.txt b/api/current.txt
index bd8cc2e..6dc6c7d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28659,6 +28659,37 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortal> CREATOR;
   }
 
+  public class ConnectivityDiagnosticsManager {
+    method public void registerConnectivityDiagnosticsCallback(@NonNull android.net.NetworkRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
+    method public void unregisterConnectivityDiagnosticsCallback(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback);
+    field public static final int DETECTION_METHOD_DNS_EVENTS = 1; // 0x1
+    field public static final int DETECTION_METHOD_TCP_METRICS = 2; // 0x2
+  }
+
+  public abstract static class ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback {
+    ctor public ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback();
+    method public void onConnectivityReport(@NonNull android.net.ConnectivityDiagnosticsManager.ConnectivityReport);
+    method public void onDataStallSuspected(@NonNull android.net.ConnectivityDiagnosticsManager.DataStallReport);
+    method public void onNetworkConnectivityReported(@NonNull android.net.Network, boolean);
+  }
+
+  public static class ConnectivityDiagnosticsManager.ConnectivityReport {
+    ctor public ConnectivityDiagnosticsManager.ConnectivityReport(@NonNull android.net.Network, long, @NonNull android.net.LinkProperties, @NonNull android.net.NetworkCapabilities, @NonNull android.os.PersistableBundle);
+    field @NonNull public final android.os.PersistableBundle additionalInfo;
+    field @NonNull public final android.net.LinkProperties linkProperties;
+    field @NonNull public final android.net.Network network;
+    field @NonNull public final android.net.NetworkCapabilities networkCapabilities;
+    field public final long reportTimestamp;
+  }
+
+  public static class ConnectivityDiagnosticsManager.DataStallReport {
+    ctor public ConnectivityDiagnosticsManager.DataStallReport(@NonNull android.net.Network, long, int, @NonNull android.os.PersistableBundle);
+    field public final int detectionMethod;
+    field @NonNull public final android.net.Network network;
+    field public final long reportTimestamp;
+    field @NonNull public final android.os.PersistableBundle stallDetails;
+  }
+
   public class ConnectivityManager {
     method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
     method public boolean bindProcessToNetwork(@Nullable android.net.Network);
@@ -35224,7 +35255,9 @@
     method public int describeContents();
     method @Nullable public android.os.PersistableBundle getPersistableBundle(@Nullable String);
     method public void putPersistableBundle(@Nullable String, @Nullable android.os.PersistableBundle);
+    method @NonNull public static android.os.PersistableBundle readFromStream(@NonNull java.io.InputStream) throws java.io.IOException;
     method public void writeToParcel(android.os.Parcel, int);
+    method public void writeToStream(@NonNull java.io.OutputStream) throws java.io.IOException;
     field @NonNull public static final android.os.Parcelable.Creator<android.os.PersistableBundle> CREATOR;
     field public static final android.os.PersistableBundle EMPTY;
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index d3b0067..75bdf0c 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8761,6 +8761,7 @@
   }
 
   public class ServiceState implements android.os.Parcelable {
+    method @NonNull public android.telephony.ServiceState createLocationInfoSanitizedCopy(boolean);
     method public int getDataRegistrationState();
     method @Nullable public android.telephony.NetworkRegistrationInfo getNetworkRegistrationInfo(int, int);
     method @NonNull public java.util.List<android.telephony.NetworkRegistrationInfo> getNetworkRegistrationInfoList();
@@ -8914,6 +8915,7 @@
 
   public class SubscriptionManager {
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean canDisablePhysicalSubscription();
+    method public boolean canManageSubscription(@Nullable android.telephony.SubscriptionInfo, @Nullable String);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String);
     method public java.util.List<android.telephony.SubscriptionInfo> getAvailableSubscriptionInfoList();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int);
@@ -8926,6 +8928,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultVoiceSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUiccApplicationsEnabled(boolean, int);
     field @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED";
     field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
     field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
new file mode 100644
index 0000000..6afdb5e
--- /dev/null
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ */
+
+package android.net;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.PersistableBundle;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
+
+/**
+ * Class that provides utilities for collecting network connectivity diagnostics information.
+ * Connectivity information is made available through triggerable diagnostics tools and by listening
+ * to System validations. Some diagnostics information may be permissions-restricted.
+ *
+ * <p>ConnectivityDiagnosticsManager is intended for use by applications offering network
+ * connectivity on a user device. These tools will provide several mechanisms for these applications
+ * to be alerted to network conditions as well as diagnose potential network issues themselves.
+ *
+ * <p>The primary responsibilities of this class are to:
+ *
+ * <ul>
+ *   <li>Allow permissioned applications to register and unregister callbacks for network event
+ *       notifications
+ *   <li>Invoke callbacks for network event notifications, including:
+ *       <ul>
+ *         <li>Network validations
+ *         <li>Data stalls
+ *         <li>Connectivity reports from applications
+ *       </ul>
+ * </ul>
+ */
+public class ConnectivityDiagnosticsManager {
+    public static final int DETECTION_METHOD_DNS_EVENTS = 1;
+    public static final int DETECTION_METHOD_TCP_METRICS = 2;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(
+            prefix = {"DETECTION_METHOD_"},
+            value = {DETECTION_METHOD_DNS_EVENTS, DETECTION_METHOD_TCP_METRICS})
+    public @interface DetectionMethod {}
+
+    /** @hide */
+    public ConnectivityDiagnosticsManager() {}
+
+    /** Class that includes connectivity information for a specific Network at a specific time. */
+    public static class ConnectivityReport {
+        /** The Network for which this ConnectivityReport applied */
+        @NonNull public final Network network;
+
+        /**
+         * The timestamp for the report. The timestamp is taken from {@link
+         * System#currentTimeMillis}.
+         */
+        public final long reportTimestamp;
+
+        /** LinkProperties available on the Network at the reported timestamp */
+        @NonNull public final LinkProperties linkProperties;
+
+        /** NetworkCapabilities available on the Network at the reported timestamp */
+        @NonNull public final NetworkCapabilities networkCapabilities;
+
+        /** PersistableBundle that may contain additional info about the report */
+        @NonNull public final PersistableBundle additionalInfo;
+
+        /**
+         * Constructor for ConnectivityReport.
+         *
+         * <p>Apps should obtain instances through {@link
+         * ConnectivityDiagnosticsCallback#onConnectivityReport} instead of instantiating their own
+         * instances (unless for testing purposes).
+         *
+         * @param network The Network for which this ConnectivityReport applies
+         * @param reportTimestamp The timestamp for the report
+         * @param linkProperties The LinkProperties available on network at reportTimestamp
+         * @param networkCapabilities The NetworkCapabilities available on network at
+         *     reportTimestamp
+         * @param additionalInfo A PersistableBundle that may contain additional info about the
+         *     report
+         */
+        public ConnectivityReport(
+                @NonNull Network network,
+                long reportTimestamp,
+                @NonNull LinkProperties linkProperties,
+                @NonNull NetworkCapabilities networkCapabilities,
+                @NonNull PersistableBundle additionalInfo) {
+            this.network = network;
+            this.reportTimestamp = reportTimestamp;
+            this.linkProperties = linkProperties;
+            this.networkCapabilities = networkCapabilities;
+            this.additionalInfo = additionalInfo;
+        }
+    }
+
+    /** Class that includes information for a suspected data stall on a specific Network */
+    public static class DataStallReport {
+        /** The Network for which this DataStallReport applied */
+        @NonNull public final Network network;
+
+        /**
+         * The timestamp for the report. The timestamp is taken from {@link
+         * System#currentTimeMillis}.
+         */
+        public final long reportTimestamp;
+
+        /** The detection method used to identify the suspected data stall */
+        @DetectionMethod public final int detectionMethod;
+
+        /** PersistableBundle that may contain additional information on the suspected data stall */
+        @NonNull public final PersistableBundle stallDetails;
+
+        /**
+         * Constructor for DataStallReport.
+         *
+         * <p>Apps should obtain instances through {@link
+         * ConnectivityDiagnosticsCallback#onDataStallSuspected} instead of instantiating their own
+         * instances (unless for testing purposes).
+         *
+         * @param network The Network for which this DataStallReport applies
+         * @param reportTimestamp The timestamp for the report
+         * @param detectionMethod The detection method used to identify this data stall
+         * @param stallDetails A PersistableBundle that may contain additional info about the report
+         */
+        public DataStallReport(
+                @NonNull Network network,
+                long reportTimestamp,
+                @DetectionMethod int detectionMethod,
+                @NonNull PersistableBundle stallDetails) {
+            this.network = network;
+            this.reportTimestamp = reportTimestamp;
+            this.detectionMethod = detectionMethod;
+            this.stallDetails = stallDetails;
+        }
+    }
+
+    /**
+     * Abstract base class for Connectivity Diagnostics callbacks. Used for notifications about
+     * network connectivity events. Must be extended by applications wanting notifications.
+     */
+    public abstract static class ConnectivityDiagnosticsCallback {
+        /**
+         * Called when the platform completes a data connectivity check. This will also be invoked
+         * upon registration with the latest report.
+         *
+         * <p>The Network specified in the ConnectivityReport may not be active any more when this
+         * method is invoked.
+         *
+         * @param report The ConnectivityReport containing information about a connectivity check
+         */
+        public void onConnectivityReport(@NonNull ConnectivityReport report) {}
+
+        /**
+         * Called when the platform suspects a data stall on some Network.
+         *
+         * <p>The Network specified in the DataStallReport may not be active any more when this
+         * method is invoked.
+         *
+         * @param report The DataStallReport containing information about the suspected data stall
+         */
+        public void onDataStallSuspected(@NonNull DataStallReport report) {}
+
+        /**
+         * Called when any app reports connectivity to the System.
+         *
+         * @param network The Network for which connectivity has been reported
+         * @param hasConnectivity The connectivity reported to the System
+         */
+        public void onNetworkConnectivityReported(
+                @NonNull Network network, boolean hasConnectivity) {}
+    }
+
+    /**
+     * Registers a ConnectivityDiagnosticsCallback with the System.
+     *
+     * <p>Only apps that offer network connectivity to the user are allowed to register callbacks.
+     * This includes:
+     *
+     * <ul>
+     *   <li>Carrier apps with active subscriptions
+     *   <li>Active VPNs
+     *   <li>WiFi Suggesters
+     * </ul>
+     *
+     * <p>Callbacks will be limited to receiving notifications for networks over which apps provide
+     * connectivity.
+     *
+     * <p>If a registering app loses its relevant permissions, any callbacks it registered will
+     * silently stop receiving callbacks.
+     *
+     * <p>Each register() call <b>MUST</b> use a unique ConnectivityDiagnosticsCallback instance. If
+     * a single instance is registered with multiple NetworkRequests, an IllegalArgumentException
+     * will be thrown.
+     *
+     * @param request The NetworkRequest that will be used to match with Networks for which
+     *     callbacks will be fired
+     * @param e The Executor to be used for running the callback method invocations
+     * @param callback The ConnectivityDiagnosticsCallback that the caller wants registered with the
+     *     System
+     * @throws IllegalArgumentException if the same callback instance is registered with multiple
+     *     NetworkRequests
+     * @throws SecurityException if the caller does not have appropriate permissions to register a
+     *     callback
+     */
+    public void registerConnectivityDiagnosticsCallback(
+            @NonNull NetworkRequest request,
+            @NonNull Executor e,
+            @NonNull ConnectivityDiagnosticsCallback callback) {
+        // TODO(b/143187964): implement ConnectivityDiagnostics functionality
+        throw new UnsupportedOperationException("registerCallback() not supported yet");
+    }
+
+    /**
+     * Unregisters a ConnectivityDiagnosticsCallback with the System.
+     *
+     * <p>If the given callback is not currently registered with the System, this operation will be
+     * a no-op.
+     *
+     * @param callback The ConnectivityDiagnosticsCallback to be unregistered from the System.
+     */
+    public void unregisterConnectivityDiagnosticsCallback(
+            @NonNull ConnectivityDiagnosticsCallback callback) {
+        // TODO(b/143187964): implement ConnectivityDiagnostics functionality
+        throw new UnsupportedOperationException("registerCallback() not supported yet");
+    }
+}
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
index 6f1bf71..29aaf534 100644
--- a/core/java/android/os/PersistableBundle.java
+++ b/core/java/android/os/PersistableBundle.java
@@ -16,17 +16,24 @@
 
 package android.os;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.util.ArrayMap;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
 import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.ArrayList;
 
 /**
@@ -339,4 +346,44 @@
 
         proto.end(token);
     }
+
+    /**
+     * Writes the content of the {@link PersistableBundle} to a {@link OutputStream}.
+     *
+     * <p>The content can be read by a {@link #readFromStream}.
+     *
+     * @see #readFromStream
+     */
+    public void writeToStream(@NonNull OutputStream outputStream) throws IOException {
+        FastXmlSerializer serializer = new FastXmlSerializer();
+        serializer.setOutput(outputStream, UTF_8.name());
+        serializer.startTag(null, "bundle");
+        try {
+            saveToXml(serializer);
+        } catch (XmlPullParserException e) {
+            throw new IOException(e);
+        }
+        serializer.endTag(null, "bundle");
+        serializer.flush();
+    }
+
+    /**
+     * Reads a {@link PersistableBundle} from an {@link InputStream}.
+     *
+     * <p>The stream must be generated by {@link #writeToStream}.
+     *
+     * @see #writeToStream
+     */
+    @NonNull
+    public static PersistableBundle readFromStream(@NonNull InputStream inputStream)
+            throws IOException {
+        try {
+            XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+            parser.setInput(inputStream, UTF_8.name());
+            parser.next();
+            return PersistableBundle.restoreFromXml(parser);
+        } catch (XmlPullParserException e) {
+            throw new IOException(e);
+        }
+    }
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 6d71c50..a42ba17 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -451,7 +451,6 @@
     <protected-broadcast android:name="android.intent.action.internal_sim_state_changed" />
     <protected-broadcast android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
     <protected-broadcast android:name="android.intent.action.PRECISE_CALL_STATE" />
-    <protected-broadcast android:name="android.intent.action.PRECISE_DATA_CONNECTION_STATE_CHANGED" />
     <protected-broadcast android:name="android.intent.action.SUBSCRIPTION_PHONE_STATE" />
     <protected-broadcast android:name="android.intent.action.USER_INFO_CHANGED" />
     <protected-broadcast android:name="android.intent.action.USER_UNLOCKED" />
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index fe154ed..9b1326b 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -16,6 +16,8 @@
 
 package com.android.server;
 
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+
 import android.Manifest;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
@@ -37,6 +39,7 @@
 import android.os.UserHandle;
 import android.service.carrier.CarrierMessagingService;
 import android.telephony.SmsManager;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.util.Slog;
@@ -512,11 +515,11 @@
 
                 // Grant permission for the carrier app.
                 Intent intent = new Intent(action);
-                TelephonyManager telephonyManager =
-                        (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
-                List<String> carrierPackages =
-                        telephonyManager.getCarrierPackageNamesForIntentAndPhone(
-                                intent, SubscriptionManager.getPhoneId(subId));
+                TelephonyManager telephonyManager = (TelephonyManager)
+                        mContext.getSystemService(Context.TELEPHONY_SERVICE);
+                List<String> carrierPackages = telephonyManager
+                        .getCarrierPackageNamesForIntentAndPhone(
+                                intent, getPhoneIdFromSubId(subId));
                 if (carrierPackages != null && carrierPackages.size() == 1) {
                     LocalServices.getService(UriGrantsManagerInternal.class)
                             .grantUriPermissionFromIntent(callingUid, carrierPackages.get(0),
@@ -528,4 +531,13 @@
             return contentUri;
         }
     }
+
+    private int getPhoneIdFromSubId(int subId) {
+        SubscriptionManager subManager = (SubscriptionManager)
+                mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        if (subManager == null) return INVALID_SIM_SLOT_INDEX;
+        SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
+        if (info == null) return INVALID_SIM_SLOT_INDEX;
+        return info.getSimSlotIndex();
+    }
 }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 078ef78..6a4ef4c 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
 import static android.telephony.TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED;
 import static android.telephony.TelephonyRegistryManager.SIM_ACTIVATION_TYPE_DATA;
 import static android.telephony.TelephonyRegistryManager.SIM_ACTIVATION_TYPE_VOICE;
@@ -57,6 +58,7 @@
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.data.ApnSetting;
@@ -95,7 +97,7 @@
  * and 15973975 by saving the phoneId of the registrant and then using the
  * phoneId when deciding to to make a callback. This is necessary because
  * a subId changes from to a dummy value when a SIM is removed and thus won't
- * compare properly. Because SubscriptionManager.getPhoneId(int subId) handles
+ * compare properly. Because getPhoneIdFromSubId(int subId) handles
  * the dummy value conversion we properly do the callbacks.
  *
  * Eventually we may want to remove the notion of dummy value but for now this
@@ -128,7 +130,7 @@
 
         int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
-        int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+        int phoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
 
         boolean matchPhoneStateListenerEvent(int events) {
             return (callback != null) && ((events & this.events) != 0);
@@ -226,7 +228,7 @@
 
     private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
-    private int mDefaultPhoneId = SubscriptionManager.INVALID_PHONE_INDEX;
+    private int mDefaultPhoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
 
     private int[] mRingingCallState;
 
@@ -355,7 +357,7 @@
                         SubscriptionManager.getDefaultSubscriptionId());
                 int newDefaultPhoneId = intent.getIntExtra(
                         SubscriptionManager.EXTRA_SLOT_INDEX,
-                        SubscriptionManager.getPhoneId(newDefaultSubId));
+                        getPhoneIdFromSubId(newDefaultSubId));
                 if (DBG) {
                     log("onReceive:current mDefaultSubId=" + mDefaultSubId
                             + " current mDefaultPhoneId=" + mDefaultPhoneId
@@ -751,7 +753,7 @@
                 return;
             }
 
-            int phoneId = SubscriptionManager.getPhoneId(subId);
+            int phoneId = getPhoneIdFromSubId(subId);
             synchronized (mRecords) {
                 // register
                 IBinder b = callback.asBinder();
@@ -786,9 +788,11 @@
                             if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
                                 r.callback.onServiceStateChanged(rawSs);
                             } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
-                                r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(false));
+                                r.callback.onServiceStateChanged(
+                                        rawSs.createLocationInfoSanitizedCopy(false));
                             } else {
-                                r.callback.onServiceStateChanged(rawSs.sanitizeLocationInfo(true));
+                                r.callback.onServiceStateChanged(
+                                        rawSs.createLocationInfoSanitizedCopy(true));
                             }
                         } catch (RemoteException ex) {
                             remove(r.binder);
@@ -1077,7 +1081,7 @@
         // Called only by Telecomm to communicate call state across different phone accounts. So
         // there is no need to add a valid subId or slotId.
         broadcastCallStateChanged(state, phoneNumber,
-                SubscriptionManager.INVALID_PHONE_INDEX,
+                SubscriptionManager.INVALID_SIM_SLOT_INDEX,
                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
     }
 
@@ -1144,9 +1148,9 @@
                             if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
                                 stateToSend = new ServiceState(state);
                             } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
-                                stateToSend = state.sanitizeLocationInfo(false);
+                                stateToSend = state.createLocationInfoSanitizedCopy(false);
                             } else {
-                                stateToSend = state.sanitizeLocationInfo(true);
+                                stateToSend = state.createLocationInfoSanitizedCopy(true);
                             }
                             if (DBG) {
                                 log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
@@ -1301,7 +1305,7 @@
         synchronized (mRecords) {
             mCarrierNetworkChangeState = active;
             for (int subId : subIds) {
-                int phoneId = SubscriptionManager.getPhoneId(subId);
+                int phoneId = getPhoneIdFromSubId(subId);
 
                 if (VDBG) {
                     log("notifyCarrierNetworkChange: active=" + active + "subId: " + subId);
@@ -1334,7 +1338,7 @@
             log("notifyCellInfoForSubscriber: subId=" + subId
                 + " cellInfo=" + cellInfo);
         }
-        int phoneId = SubscriptionManager.getPhoneId(subId);
+        int phoneId = getPhoneIdFromSubId(subId);
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
                 mCellInfo.set(phoneId, cellInfo);
@@ -1425,7 +1429,7 @@
             log("notifyCallForwardingChangedForSubscriber: subId=" + subId
                 + " cfi=" + cfi);
         }
-        int phoneId = SubscriptionManager.getPhoneId(subId);
+        int phoneId = getPhoneIdFromSubId(subId);
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
                 mCallForwarding[phoneId] = cfi;
@@ -1453,7 +1457,7 @@
         if (!checkNotifyPermission("notifyDataActivity()" )) {
             return;
         }
-        int phoneId = SubscriptionManager.getPhoneId(subId);
+        int phoneId = getPhoneIdFromSubId(subId);
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
                 mDataActivity[phoneId] = state;
@@ -1626,7 +1630,7 @@
             log("notifyCellLocationForSubscriber: subId=" + subId
                 + " cellLocation=" + cellLocation);
         }
-        int phoneId = SubscriptionManager.getPhoneId(subId);
+        int phoneId = getPhoneIdFromSubId(subId);
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
                 mCellLocation[phoneId] = cellLocation;
@@ -1735,7 +1739,7 @@
         if (!checkNotifyPermission("notifyImsCallDisconnectCause()")) {
             return;
         }
-        int phoneId = SubscriptionManager.getPhoneId(subId);
+        int phoneId = getPhoneIdFromSubId(subId);
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
                 mImsReasonInfo.set(phoneId, imsReasonInfo);
@@ -1802,7 +1806,7 @@
         if (VDBG) {
             log("notifySrvccStateChanged: subId=" + subId + " srvccState=" + state);
         }
-        int phoneId = SubscriptionManager.getPhoneId(subId);
+        int phoneId = getPhoneIdFromSubId(subId);
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
                 mSrvccState[phoneId] = state;
@@ -2208,7 +2212,7 @@
             intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId);
         }
         // If the phoneId is invalid, the broadcast is for overall call state.
-        if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
+        if (phoneId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
             intent.putExtra(PHONE_CONSTANTS_SLOT_KEY, phoneId);
             intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, phoneId);
         }
@@ -2673,4 +2677,18 @@
     private static CallQuality createCallQuality() {
         return new CallQuality(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
     }
+
+    private int getPhoneIdFromSubId(int subId) {
+        SubscriptionManager subManager = (SubscriptionManager)
+                mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        if (subManager == null) return INVALID_SIM_SLOT_INDEX;
+
+        if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+            subId = SubscriptionManager.getDefaultSubscriptionId();
+        }
+
+        SubscriptionInfo info = subManager.getActiveSubscriptionInfo(subId);
+        if (info == null) return INVALID_SIM_SLOT_INDEX;
+        return info.getSimSlotIndex();
+    }
 }
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index a55f758..a3044edd 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1950,9 +1950,18 @@
      * Returns a copy of self with location-identifying information removed.
      * Always clears the NetworkRegistrationInfo's CellIdentity fields, but if removeCoarseLocation
      * is true, clears other info as well.
+     *
+     * @param removeCoarseLocation Whether to also remove coarse location information.
+     *                             if false, it only clears fine location information such as
+     *                             NetworkRegistrationInfo's CellIdentity fields; If true, it will
+     *                             also remove other location information such as operator's MCC
+     *                             and MNC.
+     * @return the copied ServiceState with location info sanitized.
      * @hide
      */
-    public ServiceState sanitizeLocationInfo(boolean removeCoarseLocation) {
+    @SystemApi
+    @NonNull
+    public ServiceState createLocationInfoSanitizedCopy(boolean removeCoarseLocation) {
         ServiceState state = new ServiceState(this);
         synchronized (state.mNetworkRegistrationInfos) {
             List<NetworkRegistrationInfo> networkRegistrationInfos =
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index c6142d9d..15c1807 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2650,8 +2650,7 @@
 
     /**
      * Checks whether the app with the given context is authorized to manage the given subscription
-     * according to its metadata. Only supported for embedded subscriptions (if
-     * {@code SubscriptionInfo#isEmbedded} returns true).
+     * according to its metadata.
      *
      * @param info The subscription to check.
      * @return whether the app is authorized to manage this subscription per its metadata.
@@ -2664,16 +2663,16 @@
      * Checks whether the given app is authorized to manage the given subscription. An app can only
      * be authorized if it is included in the {@link android.telephony.UiccAccessRule} of the
      * {@link android.telephony.SubscriptionInfo} with the access status.
-     * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded}
-     * returns true).
      *
      * @param info The subscription to check.
      * @param packageName Package name of the app to check.
      * @return whether the app is authorized to manage this subscription per its access rules.
      * @hide
      */
-    public boolean canManageSubscription(SubscriptionInfo info, String packageName) {
-        if (info == null || info.getAllAccessRules() == null) {
+    @SystemApi
+    public boolean canManageSubscription(@Nullable SubscriptionInfo info,
+            @Nullable String packageName) {
+        if (info == null || info.getAllAccessRules() == null || packageName == null) {
             return false;
         }
         PackageManager packageManager = mContext.getPackageManager();
@@ -3168,6 +3167,34 @@
     }
 
     /**
+     * Set uicc applications being enabled or disabled.
+     * The value will be remembered on the subscription and will be applied whenever it's present.
+     * If the subscription in currently present, it will also apply the setting to modem
+     * immediately.
+     *
+     * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+     *
+     * @param enabled whether uicc applications are enabled or disabled.
+     * @param subscriptionId which subscription to operate on.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+    public void setUiccApplicationsEnabled(boolean enabled, int subscriptionId) {
+        if (VDBG) {
+            logd("setUiccApplicationsEnabled subId= " + subscriptionId + " enable " + enabled);
+        }
+        try {
+            ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
+            if (iSub != null) {
+                iSub.setUiccApplicationsEnabled(enabled, subscriptionId);
+            }
+        } catch (RemoteException ex) {
+            // ignore it
+        }
+    }
+
+    /**
      * Whether it's supported to disable / re-enable a subscription on a physical (non-euicc) SIM.
      *
      * Physical SIM refers non-euicc, or aka non-programmable SIM.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 87bdaa9..b8ce32f 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -769,30 +769,6 @@
     public static final String EXTRA_PRECISE_DISCONNECT_CAUSE = "precise_disconnect_cause";
 
     /**
-     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
-     * for an String containing the data APN type.
-     *
-     * <p class="note">
-     * Retrieve with
-     * {@link android.content.Intent#getStringExtra(String name)}.
-     *
-     * @hide
-     */
-    public static final String EXTRA_DATA_APN_TYPE = PhoneConstants.DATA_APN_TYPE_KEY;
-
-    /**
-     * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast
-     * for an String containing the data APN.
-     *
-     * <p class="note">
-     * Retrieve with
-     * {@link android.content.Intent#getStringExtra(String name)}.
-     *
-     * @hide
-     */
-    public static final String EXTRA_DATA_APN = PhoneConstants.DATA_APN_KEY;
-
-    /**
      * Broadcast intent action for letting the default dialer to know to show voicemail
      * notification.
      *
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 92aab4b..5a26232 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -285,4 +285,6 @@
     int getActiveDataSubscriptionId();
 
     boolean canDisablePhysicalSubscription();
+
+    int setUiccApplicationsEnabled(boolean enabled, int subscriptionId);
 }