Merge changes from topic "equalizer_1"

* changes:
  Fixing code formatting to comform to checkstyle
  Add sensor HAL process into dump list
diff --git a/compiled-classes-phone b/compiled-classes-phone
index cf4b28b..71fc5c1 100644
--- a/compiled-classes-phone
+++ b/compiled-classes-phone
@@ -3824,7 +3824,6 @@
 android.system.StructAddrinfo
 android.system.StructFlock
 android.system.StructGroupReq
-android.system.StructGroupSourceReq
 android.system.StructIcmpHdr
 android.system.StructIfaddrs
 android.system.StructLinger
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 1d879e9..970b362 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -9329,7 +9329,7 @@
                 for (int i=0; i<N; i++) {
                     char c = data.charAt(i);
                     if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
-                            || c == '.' || c == '-') {
+                            || (c >= '0' && c <= '9') || c == '.' || c == '-' || c == '+') {
                         continue;
                     }
                     if (c == ':' && i > 0) {
diff --git a/media/java/android/media/MediaDescription.java b/media/java/android/media/MediaDescription.java
index 14485d3..e6aea99 100644
--- a/media/java/android/media/MediaDescription.java
+++ b/media/java/android/media/MediaDescription.java
@@ -220,6 +220,33 @@
     }
 
     @Override
+    public boolean equals(Object o) {
+        if (o == null) {
+            return false;
+        }
+
+        if (!(o instanceof MediaDescription)){
+            return false;
+        }
+
+        final MediaDescription d = (MediaDescription) o;
+
+        if (!String.valueOf(mTitle).equals(String.valueOf(d.mTitle))) {
+            return false;
+        }
+
+        if (!String.valueOf(mSubtitle).equals(String.valueOf(d.mSubtitle))) {
+            return false;
+        }
+
+        if (!String.valueOf(mDescription).equals(String.valueOf(d.mDescription))) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
     public String toString() {
         return mTitle + ", " + mSubtitle + ", " + mDescription;
     }
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index dfd2bb3..9536d3d 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -48,6 +48,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * Allows interaction with media controllers, volume keys, media buttons, and
@@ -1256,6 +1257,28 @@
                     "Description=" + mDescription +
                     ", Id=" + mId + " }";
         }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o == null) {
+                return false;
+            }
+
+            if (!(o instanceof QueueItem)) {
+                return false;
+            }
+
+            final QueueItem item = (QueueItem) o;
+            if (mId != item.mId) {
+                return false;
+            }
+
+            if (!Objects.equals(mDescription, item.mDescription)) {
+                return false;
+            }
+
+            return true;
+        }
     }
 
     private static final class Command {
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index db3274a..d90665a 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -105,6 +105,7 @@
     <!-- Titles for Bluetooth AVRCP Versions -->
     <string-array name="bluetooth_avrcp_versions">
         <item>AVRCP 1.4 (Default)</item>
+        <item>AVRCP 1.3</item>
         <item>AVRCP 1.5</item>
         <item>AVRCP 1.6</item>
     </string-array>
@@ -112,6 +113,7 @@
     <!-- Values for Bluetooth AVRCP Versions -->
     <string-array name="bluetooth_avrcp_version_values">
         <item>avrcp14</item>
+        <item>avrcp13</item>
         <item>avrcp15</item>
         <item>avrcp16</item>
     </string-array>
diff --git a/preloaded-classes b/preloaded-classes
index 9612231..c1896aa 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -2103,7 +2103,6 @@
 android.system.StructAddrinfo
 android.system.StructFlock
 android.system.StructGroupReq
-android.system.StructGroupSourceReq
 android.system.StructIfaddrs
 android.system.StructLinger
 android.system.StructPasswd
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index aad4431..16a927c 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -2426,14 +2426,14 @@
             out.attribute(null, "p", Integer.toHexString(widget.provider.tag));
         }
         if (widget.options != null) {
-            out.attribute(null, "min_width", Integer.toHexString(widget.options.getInt(
-                    AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)));
-            out.attribute(null, "min_height", Integer.toHexString(widget.options.getInt(
-                    AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)));
-            out.attribute(null, "max_width", Integer.toHexString(widget.options.getInt(
-                    AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH)));
-            out.attribute(null, "max_height", Integer.toHexString(widget.options.getInt(
-                    AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT)));
+            int minWidth = widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
+            int minHeight = widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
+            int maxWidth = widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH);
+            int maxHeight = widget.options.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);
+            out.attribute(null, "min_width", Integer.toHexString((minWidth > 0) ? minWidth : 0));
+            out.attribute(null, "min_height", Integer.toHexString((minHeight > 0) ? minHeight : 0));
+            out.attribute(null, "max_width", Integer.toHexString((maxWidth > 0) ? maxWidth : 0));
+            out.attribute(null, "max_height", Integer.toHexString((maxHeight > 0) ? maxHeight : 0));
             out.attribute(null, "host_category", Integer.toHexString(widget.options.getInt(
                     AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)));
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f39bd7f..be236f9 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -130,7 +130,6 @@
 import com.android.server.connectivity.KeepaliveTracker;
 import com.android.server.connectivity.LingerMonitor;
 import com.android.server.connectivity.MockableSystemProperties;
-import com.android.server.connectivity.Nat464Xlat;
 import com.android.server.connectivity.NetworkAgentInfo;
 import com.android.server.connectivity.NetworkDiagnostics;
 import com.android.server.connectivity.NetworkMonitor;
@@ -2223,7 +2222,7 @@
                 // A network factory has connected.  Send it all current NetworkRequests.
                 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
                     if (nri.request.isListen()) continue;
-                    NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
+                    NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId);
                     ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
                             (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
                 }
@@ -2300,9 +2299,9 @@
             // Remove all previously satisfied requests.
             for (int i = 0; i < nai.numNetworkRequests(); i++) {
                 NetworkRequest request = nai.requestAt(i);
-                NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);
+                NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId);
                 if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
-                    mNetworkForRequestId.remove(request.requestId);
+                    clearNetworkForRequest(request.requestId);
                     sendUpdatedScoreToFactories(request, 0);
                 }
             }
@@ -2378,7 +2377,7 @@
             }
         }
         rematchAllNetworksAndRequests(null, 0);
-        if (nri.request.isRequest() && mNetworkForRequestId.get(nri.request.requestId) == null) {
+        if (nri.request.isRequest() && getNetworkForRequest(nri.request.requestId) == null) {
             sendUpdatedScoreToFactories(nri.request, 0);
         }
     }
@@ -2433,7 +2432,7 @@
                     // 2. Unvalidated WiFi will not be reaped when validated cellular
                     //    is currently satisfying the request.  This is desirable when
                     //    WiFi ends up validating and out scoring cellular.
-                    mNetworkForRequestId.get(nri.request.requestId).getCurrentScore() <
+                    getNetworkForRequest(nri.request.requestId).getCurrentScore() <
                             nai.getCurrentScoreAsValidated())) {
                 return false;
             }
@@ -2460,7 +2459,7 @@
         if (mNetworkRequests.get(nri.request) == null) {
             return;
         }
-        if (mNetworkForRequestId.get(nri.request.requestId) != null) {
+        if (getNetworkForRequest(nri.request.requestId) != null) {
             return;
         }
         if (VDBG || (DBG && nri.request.isRequest())) {
@@ -2500,7 +2499,7 @@
         mNetworkRequestInfoLogs.log("RELEASE " + nri);
         if (nri.request.isRequest()) {
             boolean wasKept = false;
-            NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
+            NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId);
             if (nai != null) {
                 boolean wasBackgroundNetwork = nai.isBackgroundNetwork();
                 nai.removeRequest(nri.request.requestId);
@@ -2517,7 +2516,7 @@
                 } else {
                     wasKept = true;
                 }
-                mNetworkForRequestId.remove(nri.request.requestId);
+                clearNetworkForRequest(nri.request.requestId);
                 if (!wasBackgroundNetwork && nai.isBackgroundNetwork()) {
                     // Went from foreground to background.
                     updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
@@ -4309,7 +4308,8 @@
      * and the are the highest scored network available.
      * the are keyed off the Requests requestId.
      */
-    // TODO: Yikes, this is accessed on multiple threads: add synchronization.
+    // NOTE: Accessed on multiple threads, must be synchronized on itself.
+    @GuardedBy("mNetworkForRequestId")
     private final SparseArray<NetworkAgentInfo> mNetworkForRequestId =
             new SparseArray<NetworkAgentInfo>();
 
@@ -4339,8 +4339,26 @@
     // priority networks like Wi-Fi are active.
     private final NetworkRequest mDefaultMobileDataRequest;
 
+    private NetworkAgentInfo getNetworkForRequest(int requestId) {
+        synchronized (mNetworkForRequestId) {
+            return mNetworkForRequestId.get(requestId);
+        }
+    }
+
+    private void clearNetworkForRequest(int requestId) {
+        synchronized (mNetworkForRequestId) {
+            mNetworkForRequestId.remove(requestId);
+        }
+    }
+
+    private void setNetworkForRequest(int requestId, NetworkAgentInfo nai) {
+        synchronized (mNetworkForRequestId) {
+            mNetworkForRequestId.put(requestId, nai);
+        }
+    }
+
     private NetworkAgentInfo getDefaultNetwork() {
-        return mNetworkForRequestId.get(mDefaultRequest.requestId);
+        return getNetworkForRequest(mDefaultRequest.requestId);
     }
 
     private boolean isDefaultNetwork(NetworkAgentInfo nai) {
@@ -4894,7 +4912,7 @@
             // requests or not, and doesn't affect the network's score.
             if (nri.request.isListen()) continue;
 
-            final NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(nri.request.requestId);
+            final NetworkAgentInfo currentNetwork = getNetworkForRequest(nri.request.requestId);
             final boolean satisfies = newNetwork.satisfies(nri.request);
             if (newNetwork == currentNetwork && satisfies) {
                 if (VDBG) {
@@ -4926,7 +4944,7 @@
                         if (VDBG) log("   accepting network in place of null");
                     }
                     newNetwork.unlingerRequest(nri.request);
-                    mNetworkForRequestId.put(nri.request.requestId, newNetwork);
+                    setNetworkForRequest(nri.request.requestId, newNetwork);
                     if (!newNetwork.addRequest(nri.request)) {
                         Slog.wtf(TAG, "BUG: " + newNetwork.name() + " already has " + nri.request);
                     }
@@ -4960,7 +4978,7 @@
                 }
                 newNetwork.removeRequest(nri.request.requestId);
                 if (currentNetwork == newNetwork) {
-                    mNetworkForRequestId.remove(nri.request.requestId);
+                    clearNetworkForRequest(nri.request.requestId);
                     sendUpdatedScoreToFactories(nri.request, 0);
                 } else {
                     Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " +
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index e6585ad..fbbdf00 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -20,6 +20,7 @@
 import android.net.ConnectivityManager;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
+import android.net.NetworkInfo;
 import android.net.RouteInfo;
 import android.os.INetworkManagementService;
 import android.os.RemoteException;
@@ -44,12 +45,18 @@
     // This must match the interface prefix in clatd.c.
     private static final String CLAT_PREFIX = "v4-";
 
-    // The network types we will start clatd on,
+    // The network types on which we will start clatd,
     // allowing clat only on networks for which we can support IPv6-only.
     private static final int[] NETWORK_TYPES = {
-            ConnectivityManager.TYPE_MOBILE,
-            ConnectivityManager.TYPE_WIFI,
-            ConnectivityManager.TYPE_ETHERNET,
+        ConnectivityManager.TYPE_MOBILE,
+        ConnectivityManager.TYPE_WIFI,
+        ConnectivityManager.TYPE_ETHERNET,
+    };
+
+    // The network states in which running clatd is supported.
+    private static final NetworkInfo.State[] NETWORK_STATES = {
+        NetworkInfo.State.CONNECTED,
+        NetworkInfo.State.SUSPENDED,
     };
 
     private final INetworkManagementService mNMService;
@@ -81,11 +88,8 @@
      */
     public static boolean requiresClat(NetworkAgentInfo nai) {
         // TODO: migrate to NetworkCapabilities.TRANSPORT_*.
-        final int netType = nai.networkInfo.getType();
         final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType());
-        // TODO: this should also consider if the network is in SUSPENDED state to avoid stopping
-        // clatd in SUSPENDED state.
-        final boolean connected = nai.networkInfo.isConnected();
+        final boolean connected = ArrayUtils.contains(NETWORK_STATES, nai.networkInfo.getState());
         // We only run clat on networks that don't have a native IPv4 address.
         final boolean hasIPv4Address =
                 (nai.linkProperties != null) && nai.linkProperties.hasIPv4Address();
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
index 5eafe5f..057704a 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
@@ -52,6 +52,7 @@
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -73,6 +74,8 @@
     private static final String ANYIP = "0.0.0.0";
     private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
 
+    private static enum UpdateType { IF_NEEDED, FORCE };
+
     private final Handler mHandler;
     private final OffloadHardwareInterface mHwInterface;
     private final ContentResolver mContentResolver;
@@ -185,8 +188,8 @@
                         updateStatsForAllUpstreams();
                         forceTetherStatsPoll();
                         // [2] (Re)Push all state.
-                        // TODO: computeAndPushLocalPrefixes()
-                        // TODO: push all downstream state.
+                        computeAndPushLocalPrefixes(UpdateType.FORCE);
+                        pushAllDownstreamState();
                         pushUpstreamParameters(null);
                     }
 
@@ -319,7 +322,7 @@
     }
 
     private boolean maybeUpdateDataLimit(String iface) {
-        // setDataLimit may only be called while offload is occuring on this upstream.
+        // setDataLimit may only be called while offload is occurring on this upstream.
         if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) {
             return true;
         }
@@ -368,15 +371,15 @@
         // upstream parameters fails (probably just wait for a subsequent
         // onOffloadEvent() callback to tell us offload is available again and
         // then reapply all state).
-        computeAndPushLocalPrefixes();
+        computeAndPushLocalPrefixes(UpdateType.IF_NEEDED);
         pushUpstreamParameters(prevUpstream);
     }
 
     public void setLocalPrefixes(Set<IpPrefix> localPrefixes) {
-        if (!started()) return;
-
         mExemptPrefixes = localPrefixes;
-        computeAndPushLocalPrefixes();
+
+        if (!started()) return;
+        computeAndPushLocalPrefixes(UpdateType.IF_NEEDED);
     }
 
     public void notifyDownstreamLinkProperties(LinkProperties lp) {
@@ -385,27 +388,38 @@
         if (Objects.equals(oldLp, lp)) return;
 
         if (!started()) return;
+        pushDownstreamState(oldLp, lp);
+    }
 
-        final List<RouteInfo> oldRoutes = (oldLp != null) ? oldLp.getRoutes() : new ArrayList<>();
-        final List<RouteInfo> newRoutes = lp.getRoutes();
+    private void pushDownstreamState(LinkProperties oldLp, LinkProperties newLp) {
+        final String ifname = newLp.getInterfaceName();
+        final List<RouteInfo> oldRoutes =
+                (oldLp != null) ? oldLp.getRoutes() : Collections.EMPTY_LIST;
+        final List<RouteInfo> newRoutes = newLp.getRoutes();
 
         // For each old route, if not in new routes: remove.
-        for (RouteInfo oldRoute : oldRoutes) {
-            if (shouldIgnoreDownstreamRoute(oldRoute)) continue;
-            if (!newRoutes.contains(oldRoute)) {
-                mHwInterface.removeDownstreamPrefix(ifname, oldRoute.getDestination().toString());
+        for (RouteInfo ri : oldRoutes) {
+            if (shouldIgnoreDownstreamRoute(ri)) continue;
+            if (!newRoutes.contains(ri)) {
+                mHwInterface.removeDownstreamPrefix(ifname, ri.getDestination().toString());
             }
         }
 
         // For each new route, if not in old routes: add.
-        for (RouteInfo newRoute : newRoutes) {
-            if (shouldIgnoreDownstreamRoute(newRoute)) continue;
-            if (!oldRoutes.contains(newRoute)) {
-                mHwInterface.addDownstreamPrefix(ifname, newRoute.getDestination().toString());
+        for (RouteInfo ri : newRoutes) {
+            if (shouldIgnoreDownstreamRoute(ri)) continue;
+            if (!oldRoutes.contains(ri)) {
+                mHwInterface.addDownstreamPrefix(ifname, ri.getDestination().toString());
             }
         }
     }
 
+    private void pushAllDownstreamState() {
+        for (LinkProperties lp : mDownstreams.values()) {
+            pushDownstreamState(null, lp);
+        }
+    }
+
     public void removeDownstreamInterface(String ifname) {
         final LinkProperties lp = mDownstreams.remove(ifname);
         if (lp == null) return;
@@ -484,10 +498,11 @@
         return success;
     }
 
-    private boolean computeAndPushLocalPrefixes() {
+    private boolean computeAndPushLocalPrefixes(UpdateType how) {
+        final boolean force = (how == UpdateType.FORCE);
         final Set<String> localPrefixStrs = computeLocalPrefixStrings(
                 mExemptPrefixes, mUpstreamLinkProperties);
-        if (mLastLocalPrefixStrs.equals(localPrefixStrs)) return true;
+        if (!force && mLastLocalPrefixStrs.equals(localPrefixStrs)) return true;
 
         mLastLocalPrefixStrs = localPrefixStrs;
         return mHwInterface.setLocalPrefixes(new ArrayList<>(localPrefixStrs));
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3c841a4..386a3a3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -332,14 +332,29 @@
     public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
 
     /**
-     * Flag indicating whether we should downgrade/terminate VT calls and disable VT when
-     * data enabled changed (e.g. reach data limit or turn off data).
+     * When {@code true}, changes to the mobile data enabled switch will not cause the VT
+     * registration state to change.  That is, turning on or off mobile data will not cause VT to be
+     * enabled or disabled.
+     * When {@code false}, disabling mobile data will cause VT to be de-registered.
+     * <p>
+     * See also {@link #KEY_VILTE_DATA_IS_METERED_BOOL}.
      * @hide
      */
     public static final String KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS =
             "ignore_data_enabled_changed_for_video_calls";
 
     /**
+     * Flag indicating whether data used for a video call over LTE is metered or not.
+     * <p>
+     * When {@code true}, if the device hits the data limit or data is disabled during a ViLTE call,
+     * the call will be downgraded to audio-only (or paused if
+     * {@link #KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL} is {@code true}).
+     *
+     * @hide
+     */
+    public static final String KEY_VILTE_DATA_IS_METERED_BOOL = "vilte_data_is_metered_bool";
+
+    /**
      * Flag specifying whether WFC over IMS should be available for carrier: independent of
      * carrier provisioning. If false: hard disabled. If true: then depends on carrier
      * provisioning, availability etc.
@@ -1525,7 +1540,8 @@
         sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true);
         sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, "");
-        sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, false);
+        sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, true);
+        sDefaults.putBoolean(KEY_VILTE_DATA_IS_METERED_BOOL, true);
         sDefaults.putBoolean(KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL, false);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b7a7d8e..4d6e1e4 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -869,6 +869,20 @@
     public static final String EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC =
             "android.telephony.event.EVENT_NOTIFY_INTERNATIONAL_CALL_ON_WFC";
 
+    /**
+     * {@link android.telecom.Connection} event used to indicate that an outgoing call has been
+     * forwarded to another number.
+     * <p>
+     * Sent in response to an IMS supplementary service notification indicating the call has been
+     * forwarded.
+     * <p>
+     * Sent via {@link android.telecom.Connection#sendConnectionEvent(String, Bundle)}.
+     * The {@link Bundle} parameter is expected to be null when this connection event is used.
+     * @hide
+     */
+    public static final String EVENT_CALL_FORWARDED =
+            "android.telephony.event.EVENT_CALL_FORWARDED";
+
     /* Visual voicemail protocols */
 
     /**
diff --git a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
index e3f46a4..de28de6 100644
--- a/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
+++ b/tests/net/java/com/android/server/connectivity/Nat464XlatTest.java
@@ -85,6 +85,32 @@
     }
 
     @Test
+    public void testRequiresClat() throws Exception {
+        final int[] supportedTypes = {
+            ConnectivityManager.TYPE_MOBILE,
+            ConnectivityManager.TYPE_WIFI,
+            ConnectivityManager.TYPE_ETHERNET,
+        };
+
+        // NetworkInfo doesn't allow setting the State directly, but rather
+        // requires setting DetailedState in order set State as a side-effect.
+        final NetworkInfo.DetailedState[] supportedDetailedStates = {
+            NetworkInfo.DetailedState.CONNECTED,
+            NetworkInfo.DetailedState.SUSPENDED,
+        };
+
+        for (int type : supportedTypes) {
+            mNai.networkInfo.setType(type);
+            for (NetworkInfo.DetailedState state : supportedDetailedStates) {
+                mNai.networkInfo.setDetailedState(state, "reason", "extraInfo");
+                assertTrue(
+                        String.format("requiresClat expected for type=%d state=%s", type, state),
+                        Nat464Xlat.requiresClat(mNai));
+            }
+        }
+    }
+
+    @Test
     public void testNormalStartAndStop() throws Exception {
         Nat464Xlat nat = makeNat464Xlat();
         ArgumentCaptor<LinkProperties> c = ArgumentCaptor.forClass(LinkProperties.class);
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 2199a13..2a8efc0 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -676,6 +676,35 @@
             offload.setUpstreamLinkProperties(upstreamLp);
         }
 
+        // Pretend that some local prefixes and downstreams have been added
+        // (and removed, for good measure).
+        final Set<IpPrefix> minimumLocalPrefixes = new HashSet<>();
+        for (String s : new String[]{
+                "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"}) {
+            minimumLocalPrefixes.add(new IpPrefix(s));
+        }
+        offload.setLocalPrefixes(minimumLocalPrefixes);
+
+        final LinkProperties usbLinkProperties = new LinkProperties();
+        usbLinkProperties.setInterfaceName(RNDIS0);
+        usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24"));
+        usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX)));
+        offload.notifyDownstreamLinkProperties(usbLinkProperties);
+
+        final LinkProperties wifiLinkProperties = new LinkProperties();
+        wifiLinkProperties.setInterfaceName(WLAN0);
+        wifiLinkProperties.addLinkAddress(new LinkAddress("192.168.43.1/24"));
+        wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(WIFI_PREFIX)));
+        wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL)));
+        // Use a benchmark prefix (RFC 5180 + erratum), since the documentation
+        // prefix is included in the excluded prefix list.
+        wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::1/64"));
+        wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::2/64"));
+        wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix("2001:2::/64")));
+        offload.notifyDownstreamLinkProperties(wifiLinkProperties);
+
+        offload.removeDownstreamInterface(RNDIS0);
+
         // Clear invocation history, especially the getForwardedStats() calls
         // that happen with setUpstreamParameters().
         clearInvocations(mHardware);
@@ -690,6 +719,17 @@
         verifyNoMoreInteractions(mNMService);
 
         // TODO: verify local prefixes and downstreams are also pushed to the HAL.
+        verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture());
+        ArrayList<String> localPrefixes = mStringArrayCaptor.getValue();
+        assertEquals(4, localPrefixes.size());
+        assertArrayListContains(localPrefixes,
+                // TODO: The logic to find and exclude downstream IP prefixes
+                // is currently in Tethering's OffloadWrapper but must be moved
+                // into OffloadController proper. After this, also check for:
+                //     "192.168.43.1/32", "2001:2::1/128", "2001:2::2/128"
+                "127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64");
+        verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "192.168.43.0/24");
+        verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "2001:2::/64");
         verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any());
         verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong());
         verifyNoMoreInteractions(mHardware);
@@ -697,7 +737,7 @@
 
     private static void assertArrayListContains(ArrayList<String> list, String... elems) {
         for (String element : elems) {
-            assertTrue(list.contains(element));
+            assertTrue(element + " not in list", list.contains(element));
         }
     }
 }