Merge "Import translations. DO NOT MERGE" into nyc-dev
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index a9de23e..9cd563e 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -55,19 +55,22 @@
     final String mSubscriberId;
     final String mNetworkId;
     final boolean mRoaming;
+    final boolean mMetered;
 
     public NetworkIdentity(
-            int type, int subType, String subscriberId, String networkId, boolean roaming) {
+            int type, int subType, String subscriberId, String networkId, boolean roaming,
+            boolean metered) {
         mType = type;
         mSubType = COMBINE_SUBTYPE_ENABLED ? SUBTYPE_COMBINED : subType;
         mSubscriberId = subscriberId;
         mNetworkId = networkId;
         mRoaming = roaming;
+        mMetered = metered;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming);
+        return Objects.hash(mType, mSubType, mSubscriberId, mNetworkId, mRoaming, mMetered);
     }
 
     @Override
@@ -76,7 +79,8 @@
             final NetworkIdentity ident = (NetworkIdentity) obj;
             return mType == ident.mType && mSubType == ident.mSubType && mRoaming == ident.mRoaming
                     && Objects.equals(mSubscriberId, ident.mSubscriberId)
-                    && Objects.equals(mNetworkId, ident.mNetworkId);
+                    && Objects.equals(mNetworkId, ident.mNetworkId)
+                    && mMetered == ident.mMetered;
         }
         return false;
     }
@@ -102,6 +106,7 @@
         if (mRoaming) {
             builder.append(", ROAMING");
         }
+        builder.append(", metered=").append(mMetered);
         return builder.append("}").toString();
     }
 
@@ -125,6 +130,10 @@
         return mRoaming;
     }
 
+    public boolean getMetered() {
+        return mMetered;
+    }
+
     /**
      * Scrub given IMSI on production builds.
      */
@@ -162,6 +171,7 @@
         String subscriberId = null;
         String networkId = null;
         boolean roaming = false;
+        boolean metered = false;
 
         if (isNetworkTypeMobile(type)) {
             if (state.subscriberId == null) {
@@ -171,6 +181,9 @@
             subscriberId = state.subscriberId;
             roaming = state.networkInfo.isRoaming();
 
+            metered = !state.networkCapabilities.hasCapability(
+                    NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+
         } else if (type == TYPE_WIFI) {
             if (state.networkId != null) {
                 networkId = state.networkId;
@@ -182,7 +195,7 @@
             }
         }
 
-        return new NetworkIdentity(type, subType, subscriberId, networkId, roaming);
+        return new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered);
     }
 
     @Override
@@ -200,6 +213,9 @@
         if (res == 0) {
             res = Boolean.compare(mRoaming, another.mRoaming);
         }
+        if (res == 0) {
+            res = Boolean.compare(mMetered, another.mMetered);
+        }
         return res;
     }
 }
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index b32b2cc..caf7982 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -19,6 +19,7 @@
 import static android.net.ConnectivityManager.TYPE_BLUETOOTH;
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
 import static android.net.ConnectivityManager.TYPE_PROXY;
+import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
 import static android.net.ConnectivityManager.TYPE_WIMAX;
@@ -30,9 +31,6 @@
 import static android.telephony.TelephonyManager.NETWORK_CLASS_UNKNOWN;
 import static android.telephony.TelephonyManager.getNetworkClass;
 
-import static com.android.internal.util.ArrayUtils.contains;
-
-import android.content.res.Resources;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.BackupUtils;
@@ -71,16 +69,6 @@
     public static final int MATCH_BLUETOOTH = 8;
     public static final int MATCH_PROXY = 9;
 
-    /**
-     * Set of {@link NetworkInfo#getType()} that reflect data usage.
-     */
-    private static final int[] DATA_USAGE_NETWORK_TYPES;
-
-    static {
-        DATA_USAGE_NETWORK_TYPES = Resources.getSystem().getIntArray(
-                com.android.internal.R.array.config_data_usage_network_types);
-    }
-
     private static boolean sForceAllNetworkTypes = false;
 
     @VisibleForTesting
@@ -318,9 +306,8 @@
             // TODO: consider matching against WiMAX subscriber identity
             return true;
         } else {
-            final boolean matchesType = (sForceAllNetworkTypes
-                    || contains(DATA_USAGE_NETWORK_TYPES, ident.mType));
-            return matchesType && !ArrayUtils.isEmpty(mMatchSubscriberIds)
+            return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
+                    && !ArrayUtils.isEmpty(mMatchSubscriberIds)
                     && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId);
         }
     }
@@ -389,7 +376,7 @@
         if (ident.mType == TYPE_WIMAX) {
             return true;
         } else {
-            return sForceAllNetworkTypes || contains(DATA_USAGE_NETWORK_TYPES, ident.mType);
+            return sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered);
         }
     }
 
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index ddad23a..584233c 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1240,6 +1240,13 @@
         public static final int PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME = 0x00010000;
 
         /**
+         * Flag to indicate that this window is always drawing the status bar background, no matter
+         * what the other flags are.
+         * @hide
+         */
+        public static final int PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND = 0x00020000;
+
+        /**
          * Control flags that are private to the platform.
          * @hide
          */
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 0c916c0..f9ac563 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -45,7 +45,6 @@
 import android.graphics.Rect;
 import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
 import android.util.Log;
@@ -81,6 +80,8 @@
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.os.Build.VERSION_CODES.M;
+import static android.os.Build.VERSION_CODES.N;
 import static android.view.View.MeasureSpec.AT_MOST;
 import static android.view.View.MeasureSpec.EXACTLY;
 import static android.view.View.MeasureSpec.getMode;
@@ -171,7 +172,7 @@
     private final Interpolator mShowInterpolator;
     private final Interpolator mHideInterpolator;
     private final int mBarEnterExitDuration;
-    private final boolean mForceWindowDrawsStatusBarBackground;
+    final boolean mForceWindowDrawsStatusBarBackground;
     private final int mSemiTransparentStatusBarColor;
 
     private final BackgroundFallback mBackgroundFallback = new BackgroundFallback();
@@ -236,7 +237,8 @@
         mBarEnterExitDuration = context.getResources().getInteger(
                 R.integer.dock_enter_exit_duration);
         mForceWindowDrawsStatusBarBackground = context.getResources().getBoolean(
-                R.bool.config_forceWindowDrawsStatusBarBackground);
+                R.bool.config_forceWindowDrawsStatusBarBackground)
+                && context.getApplicationInfo().targetSdkVersion >= N;
         mSemiTransparentStatusBarColor = context.getResources().getColor(
                 R.color.system_bar_background_semi_transparent, null /* theme */);
 
@@ -2210,7 +2212,7 @@
         public void onDestroyActionMode(ActionMode mode) {
             mWrapped.onDestroyActionMode(mode);
             final boolean isMncApp = mContext.getApplicationInfo().targetSdkVersion
-                    >= Build.VERSION_CODES.M;
+                    >= M;
             final boolean isPrimary;
             final boolean isFloating;
             if (isMncApp) {
diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
index 9907ea9..669e1ef 100644
--- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java
@@ -17,9 +17,13 @@
 package com.android.internal.policy;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
 import android.util.Log;
+import android.view.Display;
+import android.view.DisplayInfo;
 
 import java.util.ArrayList;
 
@@ -57,6 +61,7 @@
     private final ArrayList<SnapTarget> mTargets = new ArrayList<>();
     private final Rect mInsets = new Rect();
     private final int mSnapMode;
+    private final int mMinimalSizeResizableTask;
     private final float mFixedRatio;
     private boolean mIsHorizontalDivision;
 
@@ -70,6 +75,22 @@
     private final SnapTarget mDismissEndTarget;
     private final SnapTarget mMiddleTarget;
 
+    public static DividerSnapAlgorithm create(Context ctx, Rect insets) {
+        DisplayInfo displayInfo = new DisplayInfo();
+        ctx.getSystemService(DisplayManager.class).getDisplay(
+                Display.DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
+        int dividerWindowWidth = ctx.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.docked_stack_divider_thickness);
+        int dividerInsets = ctx.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.docked_stack_divider_insets);
+        return new DividerSnapAlgorithm(ctx.getResources(),
+                displayInfo.logicalWidth, displayInfo.logicalHeight,
+                dividerWindowWidth - 2 * dividerInsets,
+                ctx.getResources().getConfiguration().orientation
+                        == Configuration.ORIENTATION_PORTRAIT,
+                insets);
+    }
+
     public DividerSnapAlgorithm(Resources res, int displayWidth, int displayHeight, int dividerSize,
             boolean isHorizontalDivision, Rect insets) {
         mMinFlingVelocityPxPerSecond =
@@ -85,6 +106,8 @@
                 com.android.internal.R.integer.config_dockedStackDividerSnapMode);
         mFixedRatio = res.getFraction(
                 com.android.internal.R.fraction.docked_stack_divider_fixed_ratio, 1, 1);
+        mMinimalSizeResizableTask = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.default_minimal_size_resizable_task);
         calculateTargets(isHorizontalDivision);
         mFirstSplitTarget = mTargets.get(1);
         mLastSplitTarget = mTargets.get(mTargets.size() - 2);
@@ -93,6 +116,20 @@
         mMiddleTarget = mTargets.get(mTargets.size() / 2);
     }
 
+    /**
+     * @return whether it's feasible to enable split screen in the current configuration, i.e. when
+     *         snapping in the middle both tasks are larger than the minimal task size.
+     */
+    public boolean isSplitScreenFeasible() {
+        int statusBarSize = mInsets.top;
+        int navBarSize = mIsHorizontalDivision ? mInsets.bottom : mInsets.right;
+        int size = mIsHorizontalDivision
+                ? mDisplayHeight
+                : mDisplayWidth;
+        int availableSpace = size - navBarSize - statusBarSize - mDividerSize;
+        return availableSpace / 2 >= mMinimalSizeResizableTask;
+    }
+
     public SnapTarget calculateSnapTarget(int position, float velocity) {
         return calculateSnapTarget(position, velocity, true /* hardDismiss */);
     }
@@ -212,10 +249,10 @@
         mTargets.add(new SnapTarget(-mDividerSize, SnapTarget.FLAG_DISMISS_START, 0.35f));
         switch (mSnapMode) {
             case SNAP_MODE_16_9:
-                addRatio16_9Targets(isHorizontalDivision);
+                addRatio16_9Targets(isHorizontalDivision, dividerMax);
                 break;
             case SNAP_FIXED_RATIO:
-                addFixedDivisionTargets(isHorizontalDivision);
+                addFixedDivisionTargets(isHorizontalDivision, dividerMax);
                 break;
             case SNAP_ONLY_1_1:
                 addMiddleTarget(isHorizontalDivision);
@@ -225,19 +262,24 @@
         mTargets.add(new SnapTarget(dividerMax - navBarSize, SnapTarget.FLAG_DISMISS_END, 0.35f));
     }
 
-    private void addFixedDivisionTargets(boolean isHorizontalDivision) {
+    private void addNonDismissingTargets(boolean isHorizontalDivision, int topPosition,
+            int bottomPosition, int dividerMax) {
+        maybeAddTarget(topPosition, topPosition - mInsets.top);
+        addMiddleTarget(isHorizontalDivision);
+        maybeAddTarget(bottomPosition, dividerMax - mInsets.bottom
+                - (bottomPosition + mDividerSize));
+    }
+    private void addFixedDivisionTargets(boolean isHorizontalDivision, int dividerMax) {
         int start = isHorizontalDivision ? mInsets.top : mInsets.left;
         int end = isHorizontalDivision
                 ? mDisplayHeight - mInsets.bottom
                 : mDisplayWidth - mInsets.right;
-        mTargets.add(new SnapTarget((int) (start + mFixedRatio * (end - start)) - mDividerSize / 2,
-                SnapTarget.FLAG_NONE));
-        addMiddleTarget(isHorizontalDivision);
-        mTargets.add(new SnapTarget((int) (start + (1 - mFixedRatio) * (end - start))
-                - mDividerSize / 2, SnapTarget.FLAG_NONE));
+        int topPosition = (int) (start + mFixedRatio * (end - start)) - mDividerSize / 2;
+        int bottomPosition = (int) (start + (1 - mFixedRatio) * (end - start)) - mDividerSize / 2;
+        addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax);
     }
 
-    private void addRatio16_9Targets(boolean isHorizontalDivision) {
+    private void addRatio16_9Targets(boolean isHorizontalDivision, int dividerMax) {
         int start = isHorizontalDivision ? mInsets.top : mInsets.left;
         int end = isHorizontalDivision
                 ? mDisplayHeight - mInsets.bottom
@@ -248,9 +290,19 @@
                 : mDisplayHeight - mInsets.bottom;
         float size = 9.0f / 16.0f * (endOther - startOther);
         int sizeInt = (int) Math.floor(size);
-        mTargets.add(new SnapTarget(start + sizeInt, SnapTarget.FLAG_NONE));
-        addMiddleTarget(isHorizontalDivision);
-        mTargets.add(new SnapTarget(end - sizeInt - mDividerSize, SnapTarget.FLAG_NONE));
+        int topPosition = start + sizeInt;
+        int bottomPosition = end - sizeInt - mDividerSize;
+        addNonDismissingTargets(isHorizontalDivision, topPosition, bottomPosition, dividerMax);
+    }
+
+    /**
+     * Adds a target at {@param position} but only if the area with size of {@param smallerSize}
+     * meets the minimal size requirement.
+     */
+    private void maybeAddTarget(int position, int smallerSize) {
+        if (smallerSize >= mMinimalSizeResizableTask) {
+            mTargets.add(new SnapTarget(position, SnapTarget.FLAG_NONE));
+        }
     }
 
     private void addMiddleTarget(boolean isHorizontalDivision) {
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index c64328b..d2ff9bc 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2435,6 +2435,8 @@
             mNavigationBarColor = a.getColor(R.styleable.Window_navigationBarColor, 0xFF000000);
         }
 
+        WindowManager.LayoutParams params = getAttributes();
+
         // Non-floating windows on high end devices must put up decor beneath the system bars and
         // therefore must know about visibility changes of those.
         if (!mIsFloating && ActivityManager.isHighEndGfx()) {
@@ -2444,6 +2446,9 @@
                 setFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS & ~getForcedWindowFlags());
             }
+            if (mDecor.mForceWindowDrawsStatusBarBackground) {
+                params.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+            }
         }
         if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
             decor.setSystemUiVisibility(
@@ -2459,8 +2464,6 @@
             }
         }
 
-        WindowManager.LayoutParams params = getAttributes();
-
         if (!hasSoftInputMode()) {
             params.softInputMode = a.getInt(
                     R.styleable.Window_windowSoftInputMode,
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b4371c1..dfa5143b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -265,19 +265,6 @@
         <item>"0,1"</item>
     </string-array>
 
-    <!-- Set of NetworkInfo.getType() that reflect data usage. -->
-    <integer-array translatable="false" name="config_data_usage_network_types">
-        <item>0</item> <!-- TYPE_MOBILE -->
-        <item>2</item> <!-- TYPE_MOBILE_MMS -->
-        <item>3</item> <!-- TYPE_MOBILE_SUPL -->
-        <item>4</item> <!-- TYPE_MOBILE_DUN -->
-        <item>5</item> <!-- TYPE_MOBILE_HIPRI -->
-        <item>10</item> <!-- TYPE_MOBILE_FOTA -->
-        <item>11</item> <!-- TYPE_MOBILE_IMS -->
-        <item>12</item> <!-- TYPE_MOBILE_CBS -->
-        <item>14</item> <!-- TYPE_MOBILE_IA -->
-    </integer-array>
-
     <!-- The maximum duration (in milliseconds) we expect a network transition to take -->
     <integer name="config_networkTransitionTimeout">60000</integer>
 
@@ -2434,10 +2421,6 @@
          disables NetworkPolicyManagerService's presentation of data-usage notifications. -->
     <string translatable="false" name="config_networkPolicyNotificationComponent"></string>
 
-    <!-- The fraction of display size (lower of height and width) that will be used to determine
-         the default minimal size for resizeable tasks. -->
-    <fraction name="config_displayFractionForDefaultMinimalSizeOfResizeableTask">25%</fraction>
-
     <!-- The BT name of the keyboard packaged with the device. If this is defined, SystemUI will
          automatically try to pair with it when the device exits tablet mode. -->
     <string translatable="false" name="config_packagedKeyboardName"></string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 9aec1bb..dd54d57 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -455,4 +455,7 @@
     <item type="fraction" name="docked_stack_divider_fixed_ratio">34.15%</item>
 
     <dimen name="resize_shadow_size">5dp</dimen>
+
+    <!-- The default minimal size of a resizable task, in both dimensions. -->
+    <dimen name="default_minimal_size_resizable_task">220dp</dimen>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9342eb1..41dce01 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1128,7 +1128,6 @@
   <java-symbol type="plurals" name="pinpuk_attempts" />
 
   <java-symbol type="array" name="carrier_properties" />
-  <java-symbol type="array" name="config_data_usage_network_types" />
   <java-symbol type="array" name="config_sms_enabled_locking_shift_tables" />
   <java-symbol type="array" name="config_sms_enabled_single_shift_tables" />
   <java-symbol type="array" name="config_twoDigitNumberPattern" />
@@ -1727,7 +1726,7 @@
   <java-symbol type="id" name="replace_app_icon" />
   <java-symbol type="id" name="replace_message" />
   <java-symbol type="fraction" name="config_dimBehindFadeDuration" />
-  <java-symbol type="fraction" name="config_displayFractionForDefaultMinimalSizeOfResizeableTask" />
+  <java-symbol type="dimen" name="default_minimal_size_resizable_task" />
   <java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
   <java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" />
   <java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 3d7e744..72f5742 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -697,7 +697,8 @@
 
     /**
      * Reads Exif tags from the specified image file descriptor. Attribute mutation is supported
-     * for writable and seekable file descriptors only.
+     * for writable and seekable file descriptors only. This constructor will not rewind the offset
+     * of the given file descriptor. Developers should close the file descriptor after use.
      */
     public ExifInterface(FileDescriptor fileDescriptor) throws IOException {
         if (fileDescriptor == null) {
@@ -730,7 +731,8 @@
 
     /**
      * Reads Exif tags from the specified image input stream. Attribute mutation is not supported
-     * for input streams.
+     * for input streams. The given input stream will proceed its current position. Developers
+     * should close the input stream after use.
      */
     public ExifInterface(InputStream inputStream) throws IOException {
         if (inputStream == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
index 33d5bb7..a867bde 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
@@ -19,15 +19,20 @@
 import android.app.ActivityManager;
 import android.content.res.Configuration;
 import android.graphics.Point;
+import android.graphics.Rect;
+import android.provider.Settings;
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.widget.Toast;
 
+import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.RecentsImpl;
 import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
@@ -81,12 +86,20 @@
     private float mDragSlop;
 
     private DropTarget mLastDropTarget;
+    private DividerSnapAlgorithm mDividerSnapAlgorithm;
     private ArrayList<DropTarget> mDropTargets = new ArrayList<>();
     private ArrayList<TaskStack.DockState> mVisibleDockStates = new ArrayList<>();
 
     public RecentsViewTouchHandler(RecentsView rv) {
         mRv = rv;
         mDragSlop = ViewConfiguration.get(rv.getContext()).getScaledTouchSlop();
+        updateSnapAlgorithm();
+    }
+
+    private void updateSnapAlgorithm() {
+        Rect insets = new Rect();
+        SystemServicesProxy.getInstance(mRv.getContext()).getStableInsets(insets);
+        mDividerSnapAlgorithm = DividerSnapAlgorithm.create(mRv.getContext(), insets);
     }
 
     /**
@@ -150,7 +163,8 @@
         mTaskView.setTranslationY(y);
 
         mVisibleDockStates.clear();
-        if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()) {
+        if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()
+                && mDividerSnapAlgorithm.isSplitScreenFeasible()) {
             if (!event.task.isDockable) {
                 Toast.makeText(mRv.getContext(), R.string.recents_drag_non_dockable_task_message,
                         Toast.LENGTH_SHORT).show();
@@ -176,6 +190,10 @@
         mLastDropTarget = null;
     }
 
+    public final void onBusEvent(ConfigurationChangedEvent event) {
+        updateSnapAlgorithm();
+    }
+
     /**
      * Handles dragging touch events
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index d036fe4..933d5bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1167,7 +1167,9 @@
 
         @Override
         public boolean onLongClick(View v) {
-            if (mRecents == null || !ActivityManager.supportsMultiWindow()) {
+            if (mRecents == null || !ActivityManager.supportsMultiWindow()
+                    || !getComponent(Divider.class).getView().getSnapAlgorithm()
+                            .isSplitScreenFeasible()) {
                 return false;
             }
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 8395083..d34e8fc 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3249,13 +3249,9 @@
     }
 
     private void calculateDefaultMinimalSizeOfResizeableTasks(ActivityDisplay display) {
-        if (display.mDisplayId != Display.DEFAULT_DISPLAY) {
-            return;
-        }
-        final float fraction = mService.mContext.getResources().getFraction(com.android.internal.R.
-                fraction.config_displayFractionForDefaultMinimalSizeOfResizeableTask, 1, 1);
-        mDefaultMinimalSizeOfResizeableTask = (int) (fraction * Math.min(
-                display.mDisplayInfo.logicalWidth, display.mDisplayInfo.logicalHeight));
+        mDefaultMinimalSizeOfResizeableTask =
+                mService.mContext.getResources().getDimensionPixelSize(
+                        com.android.internal.R.dimen.default_minimal_size_resizable_task);
     }
 
     private void handleDisplayRemoved(int displayId) {
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 771d5b2..6fba8c8 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -986,8 +986,12 @@
             }
             top.deliverNewIntentLocked(
                     mCallingUid, mStartActivity.intent, mStartActivity.launchedFromPackage);
-            mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.task,
-                    preferredLaunchStackId, topStack.mStackId);
+
+            // Don't use mStartActivity.task to show the toast. We're not starting a new activity
+            // but reusing 'top'. Fields in mStartActivity may not be fully initialized.
+            mSupervisor.handleNonResizableTaskIfNeeded(
+                    top.task, preferredLaunchStackId, topStack.mStackId);
+
             return START_DELIVERED_TO_TOP;
         }
 
diff --git a/services/core/java/com/android/server/net/NetworkIdentitySet.java b/services/core/java/com/android/server/net/NetworkIdentitySet.java
index 68dc715..959a823 100644
--- a/services/core/java/com/android/server/net/NetworkIdentitySet.java
+++ b/services/core/java/com/android/server/net/NetworkIdentitySet.java
@@ -23,6 +23,8 @@
 import java.io.IOException;
 import java.util.HashSet;
 
+import static android.net.ConnectivityManager.TYPE_MOBILE;
+
 /**
  * Identity of a {@code iface}, defined by the set of {@link NetworkIdentity}
  * active on that interface.
@@ -34,6 +36,7 @@
     private static final int VERSION_INIT = 1;
     private static final int VERSION_ADD_ROAMING = 2;
     private static final int VERSION_ADD_NETWORK_ID = 3;
+    private static final int VERSION_ADD_METERED = 4;
 
     public NetworkIdentitySet() {
     }
@@ -61,12 +64,22 @@
                 roaming = false;
             }
 
-            add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming));
+            final boolean metered;
+            if (version >= VERSION_ADD_METERED) {
+                metered = in.readBoolean();
+            } else {
+                // If this is the old data and the type is mobile, treat it as metered. (Note that
+                // if this is a mobile network, TYPE_MOBILE is the only possible type that could be
+                // used.)
+                metered = (type == TYPE_MOBILE);
+            }
+
+            add(new NetworkIdentity(type, subType, subscriberId, networkId, roaming, metered));
         }
     }
 
     public void writeToStream(DataOutputStream out) throws IOException {
-        out.writeInt(VERSION_ADD_NETWORK_ID);
+        out.writeInt(VERSION_ADD_METERED);
         out.writeInt(size());
         for (NetworkIdentity ident : this) {
             out.writeInt(ident.getType());
@@ -74,6 +87,7 @@
             writeOptionalString(out, ident.getSubscriberId());
             writeOptionalString(out, ident.getNetworkId());
             out.writeBoolean(ident.getRoaming());
+            out.writeBoolean(ident.getMetered());
         }
     }
 
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 612bae2..c248608 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -940,7 +940,7 @@
             for (int subId : subIds) {
                 final String subscriberId = tele.getSubscriberId(subId);
                 final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                        TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
+                        TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
                 if (template.matches(probeIdent)) {
                     return true;
                 }
@@ -1333,7 +1333,7 @@
     private void ensureActiveMobilePolicyLocked(String subscriberId) {
         // Poke around to see if we already have a policy
         final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
-                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
+                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false, true);
         for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
             final NetworkTemplate template = mNetworkPolicy.keyAt(i);
             if (template.matches(probeIdent)) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index fb56a0c..5ce451f 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -692,9 +692,7 @@
     private final LogDecelerateInterpolator mLogDecelerateInterpolator
             = new LogDecelerateInterpolator(100, 0);
 
-    private boolean mForceWindowDrawsStatusBarBackground;
     private final MutableBoolean mTmpBoolean = new MutableBoolean(false);
-
     private static final int MSG_ENABLE_POINTER_LOCATION = 1;
     private static final int MSG_DISABLE_POINTER_LOCATION = 2;
     private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
@@ -1745,8 +1743,6 @@
 
         mScreenshotChordEnabled = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_enableScreenshotChord);
-        mForceWindowDrawsStatusBarBackground = mContext.getResources().getBoolean(
-                R.bool.config_forceWindowDrawsStatusBarBackground);
 
         mGlobalKeyManager = new GlobalKeyManager(mContext);
 
@@ -2217,9 +2213,12 @@
             if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
                 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
             }
+            final boolean forceWindowDrawsStatusBarBackground =
+                    (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND)
+                            != 0;
             if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
-                    || (mForceWindowDrawsStatusBarBackground
-                            && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT)) {
+                    || forceWindowDrawsStatusBarBackground
+                            && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
                 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
             }
         }
@@ -4274,6 +4273,7 @@
         }
 
         final int fl = PolicyControl.getWindowFlags(win, attrs);
+        final int pfl = attrs.privateFlags;
         final int sim = attrs.softInputMode;
         final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null);
 
@@ -4369,7 +4369,7 @@
                         && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0
                         && (fl & WindowManager.LayoutParams.
                                 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
-                        && !mForceWindowDrawsStatusBarBackground) {
+                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
                     // Ensure policy decor includes status bar
                     dcf.top = mStableTop;
                 }
@@ -7243,6 +7243,15 @@
         return vis;
     }
 
+    private boolean drawsSystemBarBackground(WindowState win) {
+        return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+    }
+
+    private boolean forcesDrawStatusBarBackground(WindowState win) {
+        return win == null || (win.getAttrs().privateFlags
+                & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+    }
+
     private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
         final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
         final boolean freeformStackVisible =
@@ -7256,11 +7265,22 @@
         final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
 
         // apply translucent bar vis flags
-        WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
+        WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen
                 ? mStatusBar
                 : mTopFullscreenOpaqueWindowState;
-        vis = mStatusBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
-        vis = mNavigationBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
+        vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
+        vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
+        final int dockedVis = mStatusBarController.applyTranslucentFlagLw(
+                mTopDockedOpaqueWindowState, 0, 0);
+
+        final boolean fullscreenDrawsStatusBarBackground =
+                (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState)
+                        && (vis & View.STATUS_BAR_TRANSLUCENT) == 0)
+                || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState);
+        final boolean dockedDrawsStatusBarBackground =
+                (drawsSystemBarBackground(mTopDockedOpaqueWindowState)
+                        && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0)
+                || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState);
 
         // prevent status bar interaction from clearing certain flags
         int type = win.getAttrs().type;
@@ -7277,18 +7297,16 @@
             vis = (vis & ~flags) | (oldVis & flags);
         }
 
-        if ((!areTranslucentBarsAllowed() && transWin != mStatusBar)
+        if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
+            vis |= View.STATUS_BAR_TRANSPARENT;
+            vis &= ~View.STATUS_BAR_TRANSLUCENT;
+        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
                 || forceOpaqueStatusBar) {
             vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
         }
 
         vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
 
-        if (mForceWindowDrawsStatusBarBackground) {
-            vis |= View.STATUS_BAR_TRANSPARENT;
-            vis &= ~View.STATUS_BAR_TRANSLUCENT;
-        }
-
         // update status bar
         boolean immersiveSticky =
                 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index f430a30..6722332 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -252,15 +252,22 @@
         long mLastSeen;
 
         // For debugging only. Offsets into the packet where PIOs are.
-        private final ArrayList<Integer> mPrefixOptionOffsets;
+        private final ArrayList<Integer> mPrefixOptionOffsets = new ArrayList<>();
+
+        // For debugging only. Offsets into the packet where RDNSS options are.
+        private final ArrayList<Integer> mRdnssOptionOffsets = new ArrayList<>();
+
         // For debugging only. How many times this RA was seen.
         int seenCount = 0;
 
         // For debugging only. Returns the hex representation of the last matching packet.
         String getLastMatchingPacket() {
-            return HexDump.toHexString(mPacket.array(), 0, mPacket.capacity(), false /* lowercase */);
+            return HexDump.toHexString(mPacket.array(), 0, mPacket.capacity(),
+                    false /* lowercase */);
         }
 
+        // For debugging only. Returns the string representation of the IPv6 address starting at
+        // position pos in the packet.
         private String IPv6AddresstoString(int pos) {
             try {
                 byte[] array = mPacket.array();
@@ -295,19 +302,37 @@
             return s & 0xffffffff;
         }
 
+        private void prefixOptionToString(StringBuffer sb, int offset) {
+            String prefix = IPv6AddresstoString(offset + 16);
+            int length = uint8(mPacket.get(offset + 2));
+            long valid = mPacket.getInt(offset + 4);
+            long preferred = mPacket.getInt(offset + 8);
+            sb.append(String.format("%s/%d %ds/%ds ", prefix, length, valid, preferred));
+        }
+
+        private void rdnssOptionToString(StringBuffer sb, int offset) {
+            int optLen = uint8(mPacket.get(offset + 1)) * 8;
+            if (optLen < 24) return;  // Malformed or empty.
+            long lifetime = uint32(mPacket.getInt(offset + 4));
+            int numServers = (optLen - 8) / 16;
+            sb.append("DNS ").append(lifetime).append("s");
+            for (int server = 0; server < numServers; server++) {
+                sb.append(" ").append(IPv6AddresstoString(offset + 8 + 16 * server));
+            }
+        }
+
         public String toString() {
             try {
                 StringBuffer sb = new StringBuffer();
-                sb.append(String.format("RA %s -> %s %d ",
+                sb.append(String.format("RA %s -> %s %ds ",
                         IPv6AddresstoString(IPV6_SRC_ADDR_OFFSET),
                         IPv6AddresstoString(IPV6_DEST_ADDR_OFFSET),
                         uint16(mPacket.getShort(ICMP6_RA_ROUTER_LIFETIME_OFFSET))));
                 for (int i: mPrefixOptionOffsets) {
-                    String prefix = IPv6AddresstoString(i + 16);
-                    int length = uint8(mPacket.get(i + 2));
-                    long valid = mPacket.getInt(i + 4);
-                    long preferred = mPacket.getInt(i + 8);
-                    sb.append(String.format("%s/%d %d/%d ", prefix, length, valid, preferred));
+                    prefixOptionToString(sb, i);
+                }
+                for (int i: mRdnssOptionOffsets) {
+                    rdnssOptionToString(sb, i);
                 }
                 return sb.toString();
             } catch (BufferUnderflowException | IndexOutOfBoundsException e) {
@@ -352,8 +377,7 @@
                     ICMP6_RA_ROUTER_LIFETIME_OFFSET,
                     ICMP6_RA_ROUTER_LIFETIME_LEN);
 
-            // Parse ICMPv6 options
-            mPrefixOptionOffsets = new ArrayList<>();
+            // Ensures that the RA is not truncated.
             mPacket.position(ICMP6_RA_OPTION_OFFSET);
             while (mPacket.hasRemaining()) {
                 int optionType = ((int)mPacket.get(mPacket.position())) & 0xff;
@@ -372,8 +396,10 @@
                         break;
                     // These three options have the same lifetime offset and size, so process
                     // together:
-                    case ICMP6_ROUTE_INFO_OPTION_TYPE:
                     case ICMP6_RDNSS_OPTION_TYPE:
+                        mRdnssOptionOffsets.add(mPacket.position());
+                        // Fall through.
+                    case ICMP6_ROUTE_INFO_OPTION_TYPE:
                     case ICMP6_DNSSL_OPTION_TYPE:
                         // Parse lifetime
                         lastNonLifetimeStart = addNonLifetime(lastNonLifetimeStart,
@@ -520,6 +546,10 @@
     @GuardedBy("this")
     private byte[] mLastInstalledProgram;
 
+    // For debugging only. How many times the program was updated since we started.
+    @GuardedBy("this")
+    private int mNumProgramUpdates;
+
     /**
      * Generate filter code to process ARP packets. Execution of this code ends in either the
      * DROP_LABEL or PASS_LABEL and does not fall off the end.
@@ -724,6 +754,8 @@
         mLastTimeInstalledProgram = curTime();
         mLastInstalledProgramMinLifetime = programMinLifetime;
         mLastInstalledProgram = program;
+        mNumProgramUpdates++;
+
         if (VDBG) {
             hexDump("Installing filter: ", program, program.length);
         }
@@ -865,19 +897,20 @@
     }
 
     public synchronized void dump(IndentingPrintWriter pw) {
-        pw.println("APF caps: " + mApfCapabilities);
+        pw.println("Capabilities: " + mApfCapabilities);
         pw.println("Receive thread: " + (mReceiveThread != null ? "RUNNING" : "STOPPED"));
-        pw.println("Multicast filtering: " + mMulticastFilter);
+        pw.println("Multicast: " + (mMulticastFilter ? "DROP" : "ALLOW"));
         try {
-            pw.println("IPv4 address: " + InetAddress.getByAddress(mIPv4Address));
+            pw.println("IPv4 address: " + InetAddress.getByAddress(mIPv4Address).getHostAddress());
         } catch (UnknownHostException|NullPointerException e) {}
+
         if (mLastTimeInstalledProgram == 0) {
             pw.println("No program installed.");
             return;
         }
-
+        pw.println("Program updates: " + mNumProgramUpdates);
         pw.println(String.format(
-                "Last program length %d, installed %ds ago, lifetime %d",
+                "Last program length %d, installed %ds ago, lifetime %ds",
                 mLastInstalledProgram.length, curTime() - mLastTimeInstalledProgram,
                 mLastInstalledProgramMinLifetime));
 
@@ -896,6 +929,7 @@
             }
             pw.decreaseIndent();
         }
+        pw.decreaseIndent();
 
         if (DBG) {
             pw.println("Last program:");
@@ -903,7 +937,5 @@
             pw.println(HexDump.toHexString(mLastInstalledProgram, false /* lowercase */));
             pw.decreaseIndent();
         }
-
-        pw.decreaseIndent();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java
index 6026644..9f53c87 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsCollectionTest.java
@@ -162,7 +162,7 @@
         final NetworkStats.Entry entry = new NetworkStats.Entry();
         final NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                TEST_IMSI, null, false));
+                TEST_IMSI, null, false, true));
 
         int myUid = Process.myUid();
         int otherUidInSameUser = Process.myUid() + 1;
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
index 82c6b6d..cff5876 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkStatsObserversTest.java
@@ -283,7 +283,7 @@
         NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */));
+                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
         mActiveIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
@@ -315,7 +315,7 @@
         NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */));
+                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
         mActiveIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
@@ -354,7 +354,7 @@
         NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */));
+                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
         mActiveIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
@@ -393,13 +393,13 @@
         NetworkIdentitySet identSet1 = new NetworkIdentitySet();
         identSet1.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */));
+                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
         mActiveIfaces.put(TEST_IFACE, identSet1);
 
         NetworkIdentitySet identSet2 = new NetworkIdentitySet();
         identSet2.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_2, null /* networkId */, false /* roaming */));
+                IMSI_2, null /* networkId */, false /* roaming */, true /* metered */));
         mActiveIfaces.put(TEST_IFACE2, identSet2);
 
         // Baseline
@@ -441,7 +441,7 @@
         NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */));
+                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
         mActiveUidIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
@@ -481,7 +481,7 @@
         NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */));
+                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
         mActiveUidIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
@@ -521,7 +521,7 @@
         NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */));
+                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
         mActiveUidIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
@@ -561,7 +561,7 @@
         NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */));
+                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
         mActiveUidIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
@@ -601,7 +601,7 @@
         NetworkIdentitySet identSet = new NetworkIdentitySet();
         identSet.add(new NetworkIdentity(
                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN,
-                IMSI_1, null /* networkId */, false /* roaming */));
+                IMSI_1, null /* networkId */, false /* roaming */, true /* metered */));
         mActiveUidIfaces.put(TEST_IFACE, identSet);
 
         // Baseline
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 461611d..adc7c21 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -419,6 +419,13 @@
     public static final String KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG =
             "carrier_data_call_apn_delay_faster_long";
 
+    /**
+     * Default APN types that are metered by the carrier
+     * @hide
+     */
+    public static final String KEY_CARRIER_METERED_APN_TYPES_STRINGS =
+            "carrier_metered_apn_types_strings";
+
     /* The following 3 fields are related to carrier visual voicemail. */
 
     /**
@@ -699,6 +706,8 @@
         sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG, 20000);
         sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG, 3000);
         sDefaults.putInt(KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT, 7200);
+        sDefaults.putStringArray(KEY_CARRIER_METERED_APN_TYPES_STRINGS,
+                new String[]{"default", "mms", "dun", "supl"});
 
         sDefaults.putStringArray(KEY_GSM_ROAMING_NETWORKS_STRING_ARRAY, null);
         sDefaults.putStringArray(KEY_GSM_NONROAMING_NETWORKS_STRING_ARRAY, null);