Merge "Address review comments on ag/962875." into nyc-dev
diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java
index ecfc527..c475575 100644
--- a/core/java/android/app/job/JobInfo.java
+++ b/core/java/android/app/job/JobInfo.java
@@ -16,6 +16,8 @@
 
 package android.app.job;
 
+import static android.util.TimeUtils.formatDuration;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
@@ -24,7 +26,6 @@
 import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.util.Log;
-import static android.util.TimeUtils.formatDuration;
 
 import java.util.ArrayList;
 
@@ -154,6 +155,20 @@
      */
     public static final int PRIORITY_ADJ_ALWAYS_RUNNING = -80;
 
+    /**
+     * Indicates that the implementation of this job will be using
+     * {@link JobService#startForeground(int, android.app.Notification)} to run
+     * in the foreground.
+     * <p>
+     * When set, the internal scheduling of this job will ignore any background
+     * network restrictions for the requesting app. Note that this flag alone
+     * doesn't actually place your {@link JobService} in the foreground; you
+     * still need to post the notification yourself.
+     *
+     * @hide
+     */
+    public static final int FLAG_WILL_BE_FOREGROUND = 1 << 0;
+
     private final int jobId;
     private final PersistableBundle extras;
     private final ComponentName service;
@@ -174,6 +189,7 @@
     private final long initialBackoffMillis;
     private final int backoffPolicy;
     private final int priority;
+    private final int flags;
 
     /**
      * Unique job id associated with this class. This is assigned to your job by the scheduler.
@@ -201,6 +217,11 @@
         return priority;
     }
 
+    /** @hide */
+    public int getFlags() {
+        return flags;
+    }
+
     /**
      * Whether this job needs the device to be plugged in.
      */
@@ -356,6 +377,7 @@
         hasEarlyConstraint = in.readInt() == 1;
         hasLateConstraint = in.readInt() == 1;
         priority = in.readInt();
+        flags = in.readInt();
     }
 
     private JobInfo(JobInfo.Builder b) {
@@ -381,6 +403,7 @@
         hasEarlyConstraint = b.mHasEarlyConstraint;
         hasLateConstraint = b.mHasLateConstraint;
         priority = b.mPriority;
+        flags = b.mFlags;
     }
 
     @Override
@@ -410,6 +433,7 @@
         out.writeInt(hasEarlyConstraint ? 1 : 0);
         out.writeInt(hasLateConstraint ? 1 : 0);
         out.writeInt(priority);
+        out.writeInt(this.flags);
     }
 
     public static final Creator<JobInfo> CREATOR = new Creator<JobInfo>() {
@@ -504,6 +528,7 @@
         private PersistableBundle mExtras = PersistableBundle.EMPTY;
         private ComponentName mJobService;
         private int mPriority = PRIORITY_DEFAULT;
+        private int mFlags;
         // Requirements.
         private boolean mRequiresCharging;
         private boolean mRequiresDeviceIdle;
@@ -539,14 +564,18 @@
             mJobId = jobId;
         }
 
-        /**
-         * @hide
-         */
+        /** @hide */
         public Builder setPriority(int priority) {
             mPriority = priority;
             return this;
         }
 
+        /** @hide */
+        public Builder setFlags(int flags) {
+            mFlags = flags;
+            return this;
+        }
+
         /**
          * Set optional extras. This is persisted, so we only allow primitive types.
          * @param extras Bundle containing extras you want the scheduler to hold on to for you.
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 167befc..bdea1e0 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -188,7 +188,7 @@
      * See {@link android.R.attr#resizeableActivity}.
      * @hide
      */
-    public int resizeMode;
+    public int resizeMode = RESIZE_MODE_RESIZEABLE;
 
     /**
      * Name of the VrListenerService component to run for this activity.
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
index 194b9ee..aaf6c57 100644
--- a/core/java/android/hardware/location/ContextHubInfo.java
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -357,6 +357,7 @@
       retVal += "\n\tPeakMips : " + mPeakMips;
       retVal += ", StoppedPowerDraw : " + mStoppedPowerDrawMw + " mW";
       retVal += ", PeakPowerDraw : " + mPeakPowerDrawMw + " mW";
+      retVal += ", MaxPacketLength : " + mMaxPacketLengthBytes + " Bytes";
       retVal += "\n\tSupported sensors : " + Arrays.toString(mSupportedSensors);
       retVal += "\n\tMemory Regions : " + Arrays.toString(mMemoryRegions);
 
@@ -375,6 +376,7 @@
         mStoppedPowerDrawMw = in.readFloat();
         mSleepPowerDrawMw = in.readFloat();
         mPeakPowerDrawMw = in.readFloat();
+        mMaxPacketLengthBytes = in.readInt();
 
         int numSupportedSensors = in.readInt();
         mSupportedSensors = new int[numSupportedSensors];
@@ -398,6 +400,7 @@
         out.writeFloat(mStoppedPowerDrawMw);
         out.writeFloat(mSleepPowerDrawMw);
         out.writeFloat(mPeakPowerDrawMw);
+        out.writeInt(mMaxPacketLengthBytes);
 
         out.writeInt(mSupportedSensors.length);
         out.writeIntArray(mSupportedSensors);
@@ -414,4 +417,4 @@
             return new ContextHubInfo[size];
         }
     };
-}
\ No newline at end of file
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index faf5c64..933dddf 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -774,8 +774,13 @@
      * @hide
      */
     public Network getActiveNetworkForUid(int uid) {
+        return getActiveNetworkForUid(uid, false);
+    }
+
+    /** {@hide} */
+    public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
         try {
-            return mService.getActiveNetworkForUid(uid);
+            return mService.getActiveNetworkForUid(uid, ignoreBlocked);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -836,8 +841,13 @@
      * {@hide}
      */
     public NetworkInfo getActiveNetworkInfoForUid(int uid) {
+        return getActiveNetworkInfoForUid(uid, false);
+    }
+
+    /** {@hide} */
+    public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
         try {
-            return mService.getActiveNetworkInfoForUid(uid);
+            return mService.getActiveNetworkInfoForUid(uid, ignoreBlocked);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -880,8 +890,13 @@
      *        is not valid.
      */
     public NetworkInfo getNetworkInfo(Network network) {
+        return getNetworkInfoForUid(network, Process.myUid(), false);
+    }
+
+    /** {@hide} */
+    public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) {
         try {
-            return mService.getNetworkInfoForNetwork(network);
+            return mService.getNetworkInfoForUid(network, uid, ignoreBlocked);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index c897c45..aec6b3e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -44,11 +44,11 @@
 interface IConnectivityManager
 {
     Network getActiveNetwork();
-    Network getActiveNetworkForUid(int uid);
+    Network getActiveNetworkForUid(int uid, boolean ignoreBlocked);
     NetworkInfo getActiveNetworkInfo();
-    NetworkInfo getActiveNetworkInfoForUid(int uid);
+    NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked);
     NetworkInfo getNetworkInfo(int networkType);
-    NetworkInfo getNetworkInfoForNetwork(in Network network);
+    NetworkInfo getNetworkInfoForUid(in Network network, int uid, boolean ignoreBlocked);
     NetworkInfo[] getAllNetworkInfo();
     Network getNetworkForType(int networkType);
     Network[] getAllNetworks();
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 2b8b28d..224ff5b 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -38,6 +38,9 @@
 
     boolean isUidForeground(int uid);
 
+    /** Higher priority listener before general event dispatch */
+    void setConnectivityListener(INetworkPolicyListener listener);
+
     void registerListener(INetworkPolicyListener listener);
     void unregisterListener(INetworkPolicyListener listener);
 
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 2c63be2..959b309 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1157,6 +1157,8 @@
         
         public short batteryTemperature;
         public char batteryVoltage;
+
+        public int batteryChargeCoulombs;
         
         // Constants from SCREEN_BRIGHTNESS_*
         public static final int STATE_BRIGHTNESS_SHIFT = 0;
@@ -1181,6 +1183,8 @@
         public static final int STATE_WIFI_SCAN_FLAG = 1<<27;
         public static final int STATE_WIFI_RADIO_ACTIVE_FLAG = 1<<26;
         public static final int STATE_MOBILE_RADIO_ACTIVE_FLAG = 1<<25;
+        // Do not use, this is used for coulomb delta count.
+        private static final int STATE_RESERVED_0 = 1<<24;
         // These are on the lower bits used for the command; if they change
         // we need to write another int of data.
         public static final int STATE_SENSOR_ON_FLAG = 1<<23;
@@ -1352,6 +1356,7 @@
             bat = (((int)batteryTemperature)&0xffff)
                     | ((((int)batteryVoltage)<<16)&0xffff0000);
             dest.writeInt(bat);
+            dest.writeInt(batteryChargeCoulombs);
             dest.writeInt(states);
             dest.writeInt(states2);
             if (wakelockTag != null) {
@@ -1380,6 +1385,7 @@
             int bat2 = src.readInt();
             batteryTemperature = (short)(bat2&0xffff);
             batteryVoltage = (char)((bat2>>16)&0xffff);
+            batteryChargeCoulombs = src.readInt();
             states = src.readInt();
             states2 = src.readInt();
             if ((bat&0x10000000) != 0) {
@@ -1419,6 +1425,7 @@
             batteryPlugType = 0;
             batteryTemperature = 0;
             batteryVoltage = 0;
+            batteryChargeCoulombs = 0;
             states = 0;
             states2 = 0;
             wakelockTag = null;
@@ -1446,6 +1453,7 @@
             batteryPlugType = o.batteryPlugType;
             batteryTemperature = o.batteryTemperature;
             batteryVoltage = o.batteryVoltage;
+            batteryChargeCoulombs = o.batteryChargeCoulombs;
             states = o.states;
             states2 = o.states2;
             if (o.wakelockTag != null) {
@@ -1477,6 +1485,7 @@
                     && batteryPlugType == o.batteryPlugType
                     && batteryTemperature == o.batteryTemperature
                     && batteryVoltage == o.batteryVoltage
+                    && batteryChargeCoulombs == o.batteryChargeCoulombs
                     && states == o.states
                     && states2 == o.states2
                     && currentTime == o.currentTime;
@@ -4527,6 +4536,7 @@
         int oldPlug = -1;
         int oldTemp = -1;
         int oldVolt = -1;
+        int oldCharge = -1;
         long lastTime = -1;
 
         void reset() {
@@ -4537,6 +4547,7 @@
             oldPlug = -1;
             oldTemp = -1;
             oldVolt = -1;
+            oldCharge = -1;
         }
 
         public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
@@ -4698,6 +4709,11 @@
                     pw.print(checkin ? ",Bv=" : " volt=");
                     pw.print(oldVolt);
                 }
+                if (oldCharge != rec.batteryChargeCoulombs) {
+                    oldCharge = rec.batteryChargeCoulombs;
+                    pw.print(checkin ? ",Bcc=" : " charge=");
+                    pw.print(oldCharge);
+                }
                 printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag,
                         HISTORY_STATE_DESCRIPTIONS, !checkin);
                 printBitDescriptions(pw, oldState2, rec.states2, null,
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b1bf355..d98e217 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6869,14 +6869,6 @@
                "hdmi_control_auto_device_off_enabled";
 
        /**
-        * Whether to use the DHCP client from Lollipop and earlier instead of the newer Android DHCP
-        * client.
-        * (0 = false, 1 = true)
-        * @hide
-        */
-       public static final String LEGACY_DHCP_CLIENT = "legacy_dhcp_client";
-
-       /**
         * Whether TV will switch to MHL port when a mobile device is plugged in.
         * (0 = false, 1 = true)
         * @hide
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index e708b0a..cf783d2 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -764,9 +764,9 @@
         }
         mSystemContext = context;
         INotificationManager noMan = getNotificationInterface();
-        noMan.registerListener(mWrapper, componentName, currentUser);
-        mCurrentUser = currentUser;
         mHandler = new MyHandler(context.getMainLooper());
+        mCurrentUser = currentUser;
+        noMan.registerListener(mWrapper, componentName, currentUser);
     }
 
     /**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a0384f2..edf05ba 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -389,6 +389,8 @@
     /** Set to true once doDie() has been called. */
     private boolean mRemoved;
 
+    private boolean mNeedsHwRendererSetup;
+
     /**
      * Consistency verifier for debugging purposes.
      */
@@ -915,6 +917,11 @@
                 mWindowAttributes.surfaceInsets.set(
                         oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom);
                 mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets;
+            } else if (mWindowAttributes.surfaceInsets.left != oldInsetLeft
+                    || mWindowAttributes.surfaceInsets.top != oldInsetTop
+                    || mWindowAttributes.surfaceInsets.right != oldInsetRight
+                    || mWindowAttributes.surfaceInsets.bottom != oldInsetBottom) {
+                mNeedsHwRendererSetup = true;
             }
 
             applyKeepScreenOnFlag(mWindowAttributes);
@@ -1959,9 +1966,11 @@
             if (hardwareRenderer != null && hardwareRenderer.isEnabled()) {
                 if (hwInitialized
                         || mWidth != hardwareRenderer.getWidth()
-                        || mHeight != hardwareRenderer.getHeight()) {
+                        || mHeight != hardwareRenderer.getHeight()
+                        || mNeedsHwRendererSetup) {
                     hardwareRenderer.setup(mWidth, mHeight, mAttachInfo,
                             mWindowAttributes.surfaceInsets);
+                    mNeedsHwRendererSetup = false;
                 }
             }
 
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index 4737e9b..2d3b6ab 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -284,6 +284,13 @@
      * currently set for that origin. The host application should invoke the
      * specified callback with the desired permission state. See
      * {@link GeolocationPermissions} for details.
+     *
+     * <p>Note that for applications targeting Android N and later SDKs
+     * (API level > {@link android.os.Build.VERSION_CODES#M})
+     * this method is only called for requests originating from secure
+     * origins such as https. On non-secure origins geolocation requests
+     * are automatically denied.</p>
+     *
      * @param origin The origin of the web content attempting to use the
      *               Geolocation API.
      * @param callback The callback to use to set the permission state for the
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index ada7731..f54edf1 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -255,6 +255,16 @@
  * is loading.
  * </p>
  *
+ * <h3>HTML5 Geolocation API support</h3>
+ *
+ * <p>For applications targeting Android N and later releases
+ * (API level > {@link android.os.Build.VERSION_CODES#M}) the geolocation api is only supported on
+ * secure origins such as https. For such applications requests to geolocation api on non-secure
+ * origins are automatically denied without invoking the corresponding
+ * {@link WebChromeClient#onGeolocationPermissionsShowPrompt(String, GeolocationPermissions.Callback)}
+ * method.
+ * </p>
+ *
  * <h3>Layout size</h3>
  * <p>
  * It is recommended to set the WebView layout height to a fixed value or to
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index b6200a1..c21f1df 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -38,6 +38,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.widget.RadialTimePickerView.OnValueSelectedListener;
 
 import com.android.internal.R;
 import com.android.internal.widget.NumericTextView;
@@ -48,8 +49,7 @@
 /**
  * A delegate implementing the radial clock-based TimePicker.
  */
-class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate implements
-        RadialTimePickerView.OnValueSelectedListener {
+class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
     /**
      * Delay in milliseconds before valid but potentially incomplete, for
      * example "1" but not "12", keyboard edits are propagated from the
@@ -88,8 +88,8 @@
 
     private boolean mIsEnabled = true;
     private boolean mAllowAutoAdvance;
-    private int mInitialHourOfDay;
-    private int mInitialMinute;
+    private int mCurrentHour;
+    private int mCurrentMinute;
     private boolean mIs24Hour;
     private boolean mIsAmPmAtStart;
 
@@ -189,8 +189,7 @@
 
         mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById(R.id.radial_picker);
         mRadialTimePickerView.applyAttributes(attrs, defStyleAttr, defStyleRes);
-
-        setupListeners();
+        mRadialTimePickerView.setOnValueSelectedListener(mOnValueSelectedListener);
 
         mAllowAutoAdvance = true;
 
@@ -324,28 +323,24 @@
     }
 
     private void initialize(int hourOfDay, int minute, boolean is24HourView, int index) {
-        mInitialHourOfDay = hourOfDay;
-        mInitialMinute = minute;
+        mCurrentHour = hourOfDay;
+        mCurrentMinute = minute;
         mIs24Hour = is24HourView;
         updateUI(index);
     }
 
-    private void setupListeners() {
-        mRadialTimePickerView.setOnValueSelectedListener(this);
-    }
-
     private void updateUI(int index) {
         updateHeaderAmPm();
-        updateHeaderHour(mInitialHourOfDay, false);
+        updateHeaderHour(mCurrentHour, false);
         updateHeaderSeparator();
-        updateHeaderMinute(mInitialMinute, false);
+        updateHeaderMinute(mCurrentMinute, false);
         updateRadialPicker(index);
 
         mDelegator.invalidate();
     }
 
     private void updateRadialPicker(int index) {
-        mRadialTimePickerView.initialize(mInitialHourOfDay, mInitialMinute, mIs24Hour);
+        mRadialTimePickerView.initialize(mCurrentHour, mCurrentMinute, mIs24Hour);
         setCurrentItemShowing(index, false, true);
     }
 
@@ -358,7 +353,7 @@
             final boolean isAmPmAtStart = dateTimePattern.startsWith("a");
             setAmPmAtStart(isAmPmAtStart);
 
-            updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM);
+            updateAmPmLabelStates(mCurrentHour < 12 ? AM : PM);
         }
     }
 
@@ -388,15 +383,25 @@
      */
     @Override
     public void setHour(int hour) {
-        if (mInitialHourOfDay != hour) {
-            mInitialHourOfDay = hour;
-            updateHeaderHour(hour, true);
-            updateHeaderAmPm();
-            mRadialTimePickerView.setCurrentHour(hour);
-            mRadialTimePickerView.setAmOrPm(mInitialHourOfDay < 12 ? AM : PM);
-            mDelegator.invalidate();
-            onTimeChanged();
+        setHourInternal(hour, false, true);
+    }
+
+    private void setHourInternal(int hour, boolean isFromPicker, boolean announce) {
+        if (mCurrentHour == hour) {
+            return;
         }
+
+        mCurrentHour = hour;
+        updateHeaderHour(hour, announce);
+        updateHeaderAmPm();
+
+        if (!isFromPicker) {
+            mRadialTimePickerView.setCurrentHour(hour);
+            mRadialTimePickerView.setAmOrPm(hour < 12 ? AM : PM);
+        }
+
+        mDelegator.invalidate();
+        onTimeChanged();
     }
 
     /**
@@ -421,13 +426,23 @@
      */
     @Override
     public void setMinute(int minute) {
-        if (mInitialMinute != minute) {
-            mInitialMinute = minute;
-            updateHeaderMinute(minute, true);
-            mRadialTimePickerView.setCurrentMinute(minute);
-            mDelegator.invalidate();
-            onTimeChanged();
+        setMinuteInternal(minute, false);
+    }
+
+    private void setMinuteInternal(int minute, boolean isFromPicker) {
+        if (mCurrentMinute == minute) {
+            return;
         }
+
+        mCurrentMinute = minute;
+        updateHeaderMinute(minute, true);
+
+        if (!isFromPicker) {
+            mRadialTimePickerView.setCurrentMinute(minute);
+        }
+
+        mDelegator.invalidate();
+        onTimeChanged();
     }
 
     /**
@@ -448,7 +463,7 @@
     public void setIs24Hour(boolean is24Hour) {
         if (mIs24Hour != is24Hour) {
             mIs24Hour = is24Hour;
-            mInitialHourOfDay = getHour();
+            mCurrentHour = getHour();
 
             updateHourFormat();
             updateUI(mRadialTimePickerView.getCurrentItemShowing());
@@ -563,34 +578,6 @@
     }
 
     /**
-     * Called by the picker for updating the header display.
-     */
-    @Override
-    public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) {
-        switch (pickerIndex) {
-            case HOUR_INDEX:
-                if (mAllowAutoAdvance && autoAdvance) {
-                    updateHeaderHour(newValue, false);
-                    setCurrentItemShowing(MINUTE_INDEX, true, false);
-                    mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes);
-                } else {
-                    updateHeaderHour(newValue, true);
-                }
-                break;
-            case MINUTE_INDEX:
-                updateHeaderMinute(newValue, true);
-                break;
-            case AMPM_INDEX:
-                updateAmPmLabelStates(newValue);
-                break;
-        }
-
-        if (mOnTimeChangedListener != null) {
-            mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute());
-        }
-    }
-
-    /**
      * Converts hour-of-day (0-23) time into a localized hour number.
      * <p>
      * The localized value may be in the range (0-23), (1-24), (0-11), or
@@ -702,11 +689,43 @@
     private void setAmOrPm(int amOrPm) {
         updateAmPmLabelStates(amOrPm);
 
-        if (mRadialTimePickerView.setAmOrPm(amOrPm) && mOnTimeChangedListener != null) {
-            mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute());
+        if (mRadialTimePickerView.setAmOrPm(amOrPm)) {
+            mCurrentHour = getHour();
+
+            if (mOnTimeChangedListener != null) {
+                mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute());
+            }
         }
     }
 
+    /** Listener for RadialTimePickerView interaction. */
+    private final OnValueSelectedListener mOnValueSelectedListener = new OnValueSelectedListener() {
+        @Override
+        public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) {
+            switch (pickerIndex) {
+                case HOUR_INDEX:
+                    final boolean isTransition = mAllowAutoAdvance && autoAdvance;
+                    setHourInternal(newValue, true, !isTransition);
+                    if (isTransition) {
+                        setCurrentItemShowing(MINUTE_INDEX, true, false);
+                        mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes);
+                    }
+                    break;
+                case MINUTE_INDEX:
+                    setMinuteInternal(newValue, true);
+                    break;
+                case AMPM_INDEX:
+                    updateAmPmLabelStates(newValue);
+                    break;
+            }
+
+            if (mOnTimeChangedListener != null) {
+                mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute());
+            }
+        }
+    };
+
+    /** Listener for keyboard interaction. */
     private final OnValueChangedListener mDigitEnteredListener = new OnValueChangedListener() {
         @Override
         public void onValueChanged(NumericTextView view, int value,
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index a2a135b..42b89d5 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -122,7 +122,8 @@
     void noteNetworkInterfaceType(String iface, int type);
     void noteNetworkStatsEnabled();
     void noteDeviceIdleMode(int mode, String activeReason, int activeUid);
-    void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
+    void setBatteryState(int status, int health, int plugType, int level, int temp, int volt,
+            int chargeCount);
     long getAwakeTimeBattery();
     long getAwakeTimePlugged();
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5358d78..654a4f1 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -108,7 +108,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 143 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 144 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -2089,27 +2089,111 @@
         tag.poolIdx = index;
     }
 
+    /*
+        The history delta format uses flags to denote further data in subsequent ints in the parcel.
+
+        There is always the first token, which may contain the delta time, or an indicator of
+        the length of the time (int or long) following this token.
+
+        First token: always present,
+        31              23              15               7             0
+        █M|L|K|J|I|H|G|F█E|D|C|B|A|T|T|T█T|T|T|T|T|T|T|T█T|T|T|T|T|T|T|T█
+
+        T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately
+           follows containing the time, and 0x7ffff indicates a long immediately follows with the
+           delta time.
+        A: battery level changed and an int follows with battery data.
+        B: state changed and an int follows with state change data.
+        C: state2 has changed and an int follows with state2 change data.
+        D: wakelock/wakereason has changed and an wakelock/wakereason struct follows.
+        E: event data has changed and an event struct follows.
+        F: battery charge in coulombs has changed and an int with the charge follows.
+        G: state flag denoting that the mobile radio was active.
+        H: state flag denoting that the wifi radio was active.
+        I: state flag denoting that a wifi scan occurred.
+        J: state flag denoting that a wifi full lock was held.
+        K: state flag denoting that the gps was on.
+        L: state flag denoting that a wakelock was held.
+        M: state flag denoting that the cpu was running.
+
+        Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows
+        with the time delta.
+
+        Battery level int: if A in the first token is set,
+        31              23              15               7             0
+        █L|L|L|L|L|L|L|T█T|T|T|T|T|T|T|T█T|V|V|V|V|V|V|V█V|V|V|V|V|V|V|D█
+
+        D: indicates that extra history details follow.
+        V: the battery voltage.
+        T: the battery temperature.
+        L: the battery level (out of 100).
+
+        State change int: if B in the first token is set,
+        31              23              15               7             0
+        █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █
+
+        A: wifi multicast was on.
+        B: battery was plugged in.
+        C: screen was on.
+        D: phone was scanning for signal.
+        E: audio was on.
+        F: a sensor was active.
+
+        State2 change int: if C in the first token is set,
+        31              23              15               7             0
+        █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█
+
+        A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}.
+        B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4.
+        C: a bluetooth scan was active.
+        D: the camera was active.
+        E: bluetooth was on.
+        F: a phone call was active.
+        G: the device was charging.
+        H: 2 bits indicating the device-idle (doze) state: off, light, full
+        I: the flashlight was on.
+        J: wifi was on.
+        K: wifi was running.
+        L: video was playing.
+        M: power save mode was on.
+
+        Wakelock/wakereason struct: if D in the first token is set,
+        TODO(adamlesinski): describe wakelock/wakereason struct.
+
+        Event struct: if E in the first token is set,
+        TODO(adamlesinski): describe the event struct.
+
+        History step details struct: if D in the battery level int is set,
+        TODO(adamlesinski): describe the history step details struct.
+
+        Battery charge int: if F in the first token is set, an int representing the battery charge
+        in coulombs follows.
+     */
+
     // Part of initial delta int that specifies the time delta.
     static final int DELTA_TIME_MASK = 0x7ffff;
     static final int DELTA_TIME_LONG = 0x7ffff;   // The delta is a following long
     static final int DELTA_TIME_INT = 0x7fffe;    // The delta is a following int
     static final int DELTA_TIME_ABS = 0x7fffd;    // Following is an entire abs update.
     // Flag in delta int: a new battery level int follows.
-    static final int DELTA_BATTERY_LEVEL_FLAG   = 0x00080000;
+    static final int DELTA_BATTERY_LEVEL_FLAG               = 0x00080000;
     // Flag in delta int: a new full state and battery status int follows.
-    static final int DELTA_STATE_FLAG           = 0x00100000;
+    static final int DELTA_STATE_FLAG                       = 0x00100000;
     // Flag in delta int: a new full state2 int follows.
-    static final int DELTA_STATE2_FLAG          = 0x00200000;
+    static final int DELTA_STATE2_FLAG                      = 0x00200000;
     // Flag in delta int: contains a wakelock or wakeReason tag.
-    static final int DELTA_WAKELOCK_FLAG        = 0x00400000;
+    static final int DELTA_WAKELOCK_FLAG                    = 0x00400000;
     // Flag in delta int: contains an event description.
-    static final int DELTA_EVENT_FLAG           = 0x00800000;
+    static final int DELTA_EVENT_FLAG                       = 0x00800000;
+    // Flag in delta int: contains a coulomb charge count.
+    static final int DELTA_BATTERY_CHARGE_COULOMBS_FLAG     = 0x01000000;
     // These upper bits are the frequently changing state bits.
-    static final int DELTA_STATE_MASK           = 0xff000000;
+    static final int DELTA_STATE_MASK                       = 0xfe000000;
 
     // These are the pieces of battery state that are packed in to the upper bits of
     // the state int that have been packed in to the first delta int.  They must fit
-    // in DELTA_STATE_MASK.
+    // in STATE_BATTERY_MASK.
+    static final int STATE_BATTERY_MASK         = 0xff000000;
     static final int STATE_BATTERY_STATUS_MASK  = 0x00000007;
     static final int STATE_BATTERY_STATUS_SHIFT = 29;
     static final int STATE_BATTERY_HEALTH_MASK  = 0x00000007;
@@ -2165,6 +2249,12 @@
         if (cur.eventCode != HistoryItem.EVENT_NONE) {
             firstToken |= DELTA_EVENT_FLAG;
         }
+
+        final boolean batteryChargeCoulombsChanged = cur.batteryChargeCoulombs
+                != last.batteryChargeCoulombs;
+        if (batteryChargeCoulombsChanged) {
+            firstToken |= DELTA_BATTERY_CHARGE_COULOMBS_FLAG;
+        }
         dest.writeInt(firstToken);
         if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken)
                 + " deltaTime=" + deltaTime);
@@ -2247,6 +2337,12 @@
             mLastHistoryStepDetails = null;
         }
         mLastHistoryStepLevel = cur.batteryLevel;
+
+        if (batteryChargeCoulombsChanged) {
+            if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeCoulombs="
+                    + cur.batteryChargeCoulombs);
+            dest.writeInt(cur.batteryChargeCoulombs);
+        }
     }
 
     private int buildBatteryLevelInt(HistoryItem h) {
@@ -2273,7 +2369,7 @@
         return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT)
                 | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT)
                 | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT)
-                | (h.states&(~DELTA_STATE_MASK));
+                | (h.states&(~STATE_BATTERY_MASK));
     }
 
     private void computeHistoryStepDetails(final HistoryStepDetails out,
@@ -2412,7 +2508,7 @@
 
         if ((firstToken&DELTA_STATE_FLAG) != 0) {
             int stateInt = src.readInt();
-            cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~DELTA_STATE_MASK));
+            cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK));
             cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT)
                     & STATE_BATTERY_STATUS_MASK);
             cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT)
@@ -2438,7 +2534,7 @@
                     + " batteryPlugType=" + cur.batteryPlugType
                     + " states=0x" + Integer.toHexString(cur.states));
         } else {
-            cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~DELTA_STATE_MASK));
+            cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK));
         }
 
         if ((firstToken&DELTA_STATE2_FLAG) != 0) {
@@ -2493,6 +2589,10 @@
         } else {
             cur.stepDetails = null;
         }
+
+        if ((firstToken&DELTA_BATTERY_CHARGE_COULOMBS_FLAG) != 0) {
+            cur.batteryChargeCoulombs = src.readInt();
+        }
     }
 
     @Override
@@ -5611,12 +5711,12 @@
                 mWifiControllerActivity.reset(false);
             }
 
-            if (mBsi.mBluetoothActivity != null) {
-                mBsi.mBluetoothActivity.reset(false);
+            if (mBluetoothControllerActivity != null) {
+                mBluetoothControllerActivity.reset(false);
             }
 
-            if (mBsi.mModemActivity != null) {
-                mBsi.mModemActivity.reset(false);
+            if (mModemControllerActivity != null) {
+                mModemControllerActivity.reset(false);
             }
 
             mUserCpuTime.reset(false);
@@ -9210,7 +9310,7 @@
     public static final int BATTERY_PLUGGED_NONE = 0;
 
     public void setBatteryStateLocked(int status, int health, int plugType, int level,
-            int temp, int volt) {
+            int temp, int volt, int chargeCount) {
         final boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
         final long uptime = mClocks.uptimeMillis();
         final long elapsedRealtime = mClocks.elapsedRealtime();
@@ -9254,6 +9354,7 @@
         if (mDischargePlugLevel < 0) {
             mDischargePlugLevel = level;
         }
+
         if (onBattery != mOnBattery) {
             mHistoryCur.batteryLevel = (byte)level;
             mHistoryCur.batteryStatus = (byte)status;
@@ -9261,6 +9362,7 @@
             mHistoryCur.batteryPlugType = (byte)plugType;
             mHistoryCur.batteryTemperature = (short)temp;
             mHistoryCur.batteryVoltage = (char)volt;
+            mHistoryCur.batteryChargeCoulombs = chargeCount;
             setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
         } else {
             boolean changed = false;
@@ -9294,6 +9396,11 @@
                 mHistoryCur.batteryVoltage = (char)volt;
                 changed = true;
             }
+            if (chargeCount >= (mHistoryCur.batteryChargeCoulombs+10)
+                    || chargeCount <= (mHistoryCur.batteryChargeCoulombs-10)) {
+                mHistoryCur.batteryChargeCoulombs = chargeCount;
+                changed = true;
+            }
             long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT)
                     | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT)
                     | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT);
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 1848fe8..bc12391 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -592,9 +592,11 @@
         private void refreshCoordinatesAndOverflowDirection(Rect contentRectOnScreen) {
             refreshViewPort();
 
-            int x = contentRectOnScreen.centerX() - mPopupWindow.getWidth() / 2;
-            // Update x so that the toolbar isn't rendered behind the nav bar in landscape.
-            x = Math.max(0, Math.min(x, mViewPortOnScreen.right - mPopupWindow.getWidth()));
+            // Initialize x ensuring that the toolbar isn't rendered behind the nav bar in
+            // landscape.
+            final int x = Math.min(
+                    contentRectOnScreen.centerX() - mPopupWindow.getWidth() / 2,
+                    mViewPortOnScreen.right - mPopupWindow.getWidth());
 
             final int y;
 
@@ -684,7 +686,8 @@
             int rootViewTopOnWindow = mTmpCoords[1];
             int windowLeftOnScreen = rootViewLeftOnScreen - rootViewLeftOnWindow;
             int windowTopOnScreen = rootViewTopOnScreen - rootViewTopOnWindow;
-            mCoordsOnWindow.set(x - windowLeftOnScreen, y - windowTopOnScreen);
+            mCoordsOnWindow.set(
+                    Math.max(0, x - windowLeftOnScreen), Math.max(0, y - windowTopOnScreen));
         }
 
         /**
diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp
index 5c961d9..98d6b24 100644
--- a/core/jni/android_hardware_location_ContextHubService.cpp
+++ b/core/jni/android_hardware_location_ContextHubService.cpp
@@ -44,7 +44,6 @@
 static constexpr int HEADER_FIELD_HUB_HANDLE=2;
 static constexpr int HEADER_FIELD_APP_INSTANCE=3;
 
-
 namespace android {
 
 namespace {
@@ -164,9 +163,20 @@
     return db.hubInfo.hubs[hubHandle].hub_id;
 }
 
+static int get_app_instance_for_app_id(uint64_t app_id) {
+    auto end = db.appInstances.end();
+    for (auto current = db.appInstances.begin(); current != end; ++current) {
+        if (current->second.appInfo.app_name.id == app_id) {
+            return current->first;
+        }
+    }
+    ALOGD("Cannot find app for app instance %" PRIu64 ".", app_id);
+    return -1;
+}
+
 static int set_dest_app(hub_message_t *msg, int id) {
     if (!db.appInstances.count(id)) {
-        ALOGD("%s: Cannod find app for app instance %d", __FUNCTION__, id);
+        ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id);
         return -1;
     }
 
@@ -301,7 +311,7 @@
     }
 }
 
-static int onMessageReceipt(int *header, int headerLen, char *msg, int msgLen) {
+static int onMessageReceipt(uint32_t *header, size_t headerLen, char *msg, size_t msgLen) {
     JNIEnv *env;
 
     if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) {
@@ -396,14 +406,9 @@
 int context_hub_callback(uint32_t hubId,
                          const struct hub_message_t *msg,
                          void *cookie) {
-    int msgHeader[MSG_HEADER_SIZE];
-
     if (!msg) {
         return -1;
     }
-
-    msgHeader[HEADER_FIELD_MSG_TYPE] = msg->message_type;
-
     if (!sanity_check_cookie(cookie, hubId)) {
         ALOGW("Incorrect cookie %" PRId32 " for cookie %p! Bailing",
               hubId, cookie);
@@ -411,17 +416,22 @@
         return -1;
     }
 
-    msgHeader[HEADER_FIELD_HUB_HANDLE] = *(uint32_t*)cookie;
+    uint32_t messageType = msg->message_type;
+    uint32_t hubHandle = *(uint32_t*) cookie;
 
-    if (msgHeader[HEADER_FIELD_MSG_TYPE] < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE &&
-        msgHeader[HEADER_FIELD_MSG_TYPE] != 0 ) {
-        handle_os_message(msgHeader[HEADER_FIELD_MSG_TYPE],
-                          msgHeader[HEADER_FIELD_HUB_HANDLE],
-                          (char *)msg->message,
-                          msg->message_len);
+    if (messageType < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) {
+        handle_os_message(messageType, hubHandle, (char*) msg->message, msg->message_len);
     } else {
-        onMessageReceipt(msgHeader, sizeof(msgHeader),
-                         (char *)msg->message, msg->message_len);
+        int appHandle = get_app_instance_for_app_id(msg->app_name.id);
+        if (appHandle < 0) {
+            ALOGE("Filtering out message due to invalid App Instance.");
+        } else {
+            uint32_t msgHeader[MSG_HEADER_SIZE] = {};
+            msgHeader[HEADER_FIELD_MSG_TYPE] = messageType;
+            msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle;
+            msgHeader[HEADER_FIELD_APP_INSTANCE] = appHandle;
+            onMessageReceipt(msgHeader, MSG_HEADER_SIZE, (char*) msg->message, msg->message_len);
+        }
     }
 
     return 0;
diff --git a/core/res/res/layout-sw600dp/date_picker_dialog.xml b/core/res/res/layout-sw600dp/date_picker_dialog.xml
index f18485f..5e3ca14 100644
--- a/core/res/res/layout-sw600dp/date_picker_dialog.xml
+++ b/core/res/res/layout-sw600dp/date_picker_dialog.xml
@@ -21,4 +21,5 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:spinnersShown="true"
-    android:calendarViewShown="true" />
+    android:calendarViewShown="true"
+    android:datePickerMode="@integer/date_picker_mode" />
diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml
index 64ac1b9..8f36e95 100644
--- a/core/res/res/layout/date_picker_dialog.xml
+++ b/core/res/res/layout/date_picker_dialog.xml
@@ -21,4 +21,5 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:spinnersShown="true"
-    android:calendarViewShown="false" />
+    android:calendarViewShown="false"
+    android:datePickerMode="@integer/date_picker_mode" />
diff --git a/core/res/res/layout/time_picker_dialog.xml b/core/res/res/layout/time_picker_dialog.xml
index 30fe910..d1f3902 100644
--- a/core/res/res/layout/time_picker_dialog.xml
+++ b/core/res/res/layout/time_picker_dialog.xml
@@ -21,4 +21,5 @@
     android:id="@+id/timePicker"
     android:layout_gravity="center_horizontal"
     android:layout_width="wrap_content"
-    android:layout_height="wrap_content" />
+    android:layout_height="wrap_content"
+    android:timePickerMode="@integer/time_picker_mode" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fb7a19f9..dffab2c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -626,7 +626,7 @@
     <!-- Title for the capability of an accessibility service to request touch exploration. -->
     <string name="capability_title_canRequestTouchExploration">Turn on Explore by Touch</string>
     <!-- Description for the capability of an accessibility service to request touch exploration. -->
-    <string name="capability_desc_canRequestTouchExploration">Touched items will be spoken aloud
+    <string name="capability_desc_canRequestTouchExploration">Tapped items will be spoken aloud
         and the screen can be explored using gestures.</string>
 
     <!-- Title for the capability of an accessibility service to request enhanced web accessibility. -->
@@ -1708,7 +1708,7 @@
     <string name="keyguard_password_enter_pin_prompt">New PIN code</string>
 
     <!-- Displayed as hint in passwordEntry EditText on PasswordUnlockScreen [CHAR LIMIT=30]-->
-    <string name="keyguard_password_entry_touch_hint"><font size="17">Touch to type password</font></string>
+    <string name="keyguard_password_entry_touch_hint"><font size="17">Tap to type password</font></string>
 
     <!-- Instructions telling the user to enter their text password to unlock the keyguard.
          Displayed in one line in a large font.  -->
@@ -2577,7 +2577,7 @@
         is running</string>
     <!-- [CHAR LIMIT=NONE] Stub notification text for an app running a service that has provided
          a bad bad notification for itself. -->
-    <string name="app_running_notification_text">Touch for more information
+    <string name="app_running_notification_text">Tap for more information
         or to stop the app.</string>
 
     <!-- Preference framework strings. -->
@@ -2761,7 +2761,7 @@
     <string name="heavy_weight_notification"><xliff:g id="app">%1$s</xliff:g> running</string>
 
     <!-- Notification details to tell the user that a heavy-weight application is running. -->
-    <string name="heavy_weight_notification_detail">Touch to switch to app</string>
+    <string name="heavy_weight_notification_detail">Tap to switch to app</string>
 
     <!-- Title of dialog prompting whether user wants to switch between heavy-weight apps. -->
     <string name="heavy_weight_switcher_title">Switch apps?</string>
@@ -2782,7 +2782,7 @@
 
     <!-- Notification details to tell the user that a process has exceeded its memory limit. -->
     <string name="dump_heap_notification_detail">Heap dump has been collected;
-        touch to share</string>
+        tap to share</string>
 
     <!-- Title of dialog prompting the user to share a heap dump. -->
     <string name="dump_heap_title">Share heap dump?</string>
@@ -2865,7 +2865,7 @@
     <string name="wifi_no_internet">Wi-Fi has no Internet access</string>
 
     <!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's message. -->
-    <string name="wifi_no_internet_detailed">Touch for options</string>
+    <string name="wifi_no_internet_detailed">Tap for options</string>
 
      <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems.  This is the notification's title / ticker. -->
      <string name="wifi_watchdog_network_disabled">Couldn\'t connect to Wi-Fi</string>
@@ -2887,7 +2887,7 @@
     <string name="wifi_p2p_turnon_message">Start Wi-Fi Direct. This will turn off Wi-Fi client/hotspot.</string>
     <string name="wifi_p2p_failed_message">Couldn\'t start Wi-Fi Direct.</string>
     <string name="wifi_p2p_enabled_notification_title">Wi-Fi Direct is on</string>
-    <string name="wifi_p2p_enabled_notification_message">Touch for settings</string>
+    <string name="wifi_p2p_enabled_notification_message">Tap for settings</string>
 
     <string name="accept">Accept</string>
     <string name="decline">Decline</string>
@@ -2995,12 +2995,12 @@
     <!-- USB_PREFERENCES: Notification for when a USB accessory is attached.  This is the title -->
     <string name="usb_accessory_notification_title">Connected to a USB accessory</string>
     <!-- See USB_PREFERENCES. This is the message. -->
-    <string name="usb_notification_message">Touch for more options.</string>
+    <string name="usb_notification_message">Tap for more options.</string>
 
     <!-- Title of notification shown when ADB is actively connected to the phone. -->
     <string name="adb_active_notification_title">USB debugging connected</string>
     <!-- Message of notification shown when ADB is actively connected to the phone. -->
-    <string name="adb_active_notification_message">Touch to disable USB debugging.</string>
+    <string name="adb_active_notification_message">Tap to disable USB debugging.</string>
 
     <!-- Title of notification shown to indicate that bug report is being collected. -->
     <string name="taking_remote_bugreport_notification_title">Taking bug report\u2026</string>
@@ -3057,12 +3057,12 @@
     <!-- Notification title when external media is unmountable (corrupt) [CHAR LIMIT=30] -->
     <string name="ext_media_unmountable_notification_title">Corrupted <xliff:g id="name" example="SD card">%s</xliff:g></string>
     <!-- Notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] -->
-    <string name="ext_media_unmountable_notification_message"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Touch to fix.</string>
+    <string name="ext_media_unmountable_notification_message"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Tap to fix.</string>
 
     <!-- Notification title when external media is unsupported [CHAR LIMIT=30] -->
     <string name="ext_media_unsupported_notification_title">Unsupported <xliff:g id="name" example="SD card">%s</xliff:g></string>
     <!-- Notification body when external media is unsupported [CHAR LIMIT=NONE] -->
-    <string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Touch to set up in a supported format.</string>
+    <string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Tap to set up in a supported format.</string>
 
     <!-- Notification title when external media is unsafely removed [CHAR LIMIT=30] -->
     <string name="ext_media_badremoval_notification_title"><xliff:g id="name" example="SD card">%s</xliff:g> unexpectedly removed</string>
@@ -3148,7 +3148,7 @@
     <string name="permdesc_requestInstallPackages">Allows an application to request installation of packages.</string>
 
     <!-- Shown in the tutorial for tap twice for zoom control. -->
-    <string name="tutorial_double_tap_to_zoom_message_short">Touch twice for zoom control</string>
+    <string name="tutorial_double_tap_to_zoom_message_short">Tap twice for zoom control</string>
 
 
     <!-- Shown in gadget hosts (e.g. the home screen) when there was an error inflating
@@ -3235,9 +3235,9 @@
     <!-- The title of the notification when VPN is active with an application name. -->
     <string name="vpn_title_long">VPN is activated by <xliff:g id="app" example="FooVPN client">%s</xliff:g></string>
     <!-- The text of the notification when VPN is active. -->
-    <string name="vpn_text">Touch to manage the network.</string>
+    <string name="vpn_text">Tap to manage the network.</string>
     <!-- The text of the notification when VPN is active with a session name. -->
-    <string name="vpn_text_long">Connected to <xliff:g id="session" example="office">%s</xliff:g>. Touch to manage the network.</string>
+    <string name="vpn_text_long">Connected to <xliff:g id="session" example="office">%s</xliff:g>. Tap to manage the network.</string>
 
     <!-- Notification title when connecting to lockdown VPN. -->
     <string name="vpn_lockdown_connecting">Always-on VPN connecting\u2026</string>
@@ -3246,7 +3246,7 @@
     <!-- Notification title when error connecting to lockdown VPN. -->
     <string name="vpn_lockdown_error">Always-on VPN error</string>
     <!-- Notification body that indicates user can touch to configure lockdown VPN connection. -->
-    <string name="vpn_lockdown_config">Touch to configure</string>
+    <string name="vpn_lockdown_config">Tap to configure</string>
 
     <!-- Localized strings for WebView -->
     <!-- Label for button in a WebView that will open a chooser to choose a file to upload -->
@@ -3261,12 +3261,12 @@
     <!-- Strings for car mode notification -->
     <!-- Shown when car mode is enabled -->
     <string name="car_mode_disable_notification_title">Car mode enabled</string>
-    <string name="car_mode_disable_notification_message">Touch to exit car mode.</string>
+    <string name="car_mode_disable_notification_message">Tap to exit car mode.</string>
 
     <!-- Strings for tethered notification -->
     <!-- Shown when the device is tethered -->
     <string name="tethered_notification_title">Tethering or hotspot active</string>
-    <string name="tethered_notification_message">Touch to set up.</string>
+    <string name="tethered_notification_message">Tap to set up.</string>
 
     <!--  Strings for possible PreferenceActivity Back/Next buttons -->
     <string name="back_button_label">Back</string>
@@ -3352,7 +3352,7 @@
     <!-- Description of the button to decrease the NumberPicker value. [CHAR LIMIT=NONE] -->
     <string name="number_picker_decrement_button">Decrease</string>
     <!-- Description of the tap and hold action to get into scroll mode in NumberPicker. [CHAR LIMIT=NONE] -->
-    <string name="number_picker_increment_scroll_mode"><xliff:g id="value" example="3">%s</xliff:g> touch and hold.</string>
+    <string name="number_picker_increment_scroll_mode"><xliff:g id="value" example="3">%s</xliff:g> touch &amp; hold.</string>
     <!-- Description of the scrolling action in NumberPicker. [CHAR LIMIT=NONE] -->
     <string name="number_picker_increment_scroll_action">Slide up to increase and down to decrease.</string>
 
@@ -3470,7 +3470,7 @@
     <!-- Notification title when data usage has exceeded warning threshold. [CHAR LIMIT=32] -->
     <string name="data_usage_warning_title">Data usage warning</string>
     <!-- Notification body when data usage has exceeded warning threshold. [CHAR LIMIT=32] -->
-    <string name="data_usage_warning_body">Touch to view usage and settings.</string>
+    <string name="data_usage_warning_body">Tap to view usage and settings.</string>
 
     <!-- Notification title when 2G-3G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
     <string name="data_usage_3g_limit_title">2G-3G data limit reached</string>
@@ -3497,7 +3497,7 @@
     <!-- Notification title when background data usage is limited. [CHAR LIMIT=32] -->
     <string name="data_usage_restricted_title">Background data restricted</string>
     <!-- Notification body when background data usage is limited. [CHAR LIMIT=32] -->
-    <string name="data_usage_restricted_body">Touch to remove restriction.</string>
+    <string name="data_usage_restricted_body">Tap to remove restriction.</string>
 
     <!-- SSL Certificate dialogs -->
     <!-- Title for an SSL Certificate dialog -->
@@ -4080,9 +4080,9 @@
     <string name="date_picker_day_typeface">sans-serif-medium</string>
 
     <!-- Notify use that they are in Lock-to-app -->
-    <string name="lock_to_app_toast">To unpin this screen, touch and hold Back.</string>
+    <string name="lock_to_app_toast">To unpin this screen, touch &amp; hold Back.</string>
     <!-- Notify use that they are in Lock-to-app in accessibility mode -->
-    <string name="lock_to_app_toast_accessible">To unpin this screen, touch and hold Overview.</string>
+    <string name="lock_to_app_toast_accessible">To unpin this screen, touch &amp; hold Overview.</string>
     <!-- Notify user that they are locked in lock-to-app mode -->
     <string name="lock_to_app_toast_locked">App is pinned: Unpinning isn\'t allowed on this device.</string>
     <!-- Starting lock-to-app indication. -->
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 8a33406..6752e3c 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -660,7 +660,7 @@
     </style>
 
     <style name="Widget.Material.TimePicker">
-        <item name="timePickerMode">@integer/time_picker_mode</item>
+        <item name="timePickerMode">clock</item>
         <item name="legacyLayout">@layout/time_picker_legacy_material</item>
         <!-- Attributes for new-style TimePicker. -->
         <item name="internalLayout">@layout/time_picker_material</item>
@@ -674,7 +674,7 @@
     </style>
 
     <style name="Widget.Material.DatePicker">
-        <item name="datePickerMode">@integer/date_picker_mode</item>
+        <item name="datePickerMode">calendar</item>
         <item name="legacyLayout">@layout/date_picker_legacy_holo</item>
         <item name="calendarViewShown">true</item>
         <!-- Attributes for new-style DatePicker. -->
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 94b7e55..1e7761b 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -55,7 +55,7 @@
 
 
 <!-- start studio download modal -->
-<div data-modal="studio_tos" class="dac-modal" id="langform">
+<div data-modal="studio_tos" class="dac-modal" id="studio_tos">
   <div class="dac-modal-container">
     <div class="dac-modal-window">
       <header class="dac-modal-header">
@@ -534,4 +534,3 @@
 </div>
 
 </section>
-
diff --git a/graphics/java/android/view/PixelCopy.java b/graphics/java/android/view/PixelCopy.java
index 95c930c..29bf963 100644
--- a/graphics/java/android/view/PixelCopy.java
+++ b/graphics/java/android/view/PixelCopy.java
@@ -123,6 +123,9 @@
     public static void request(@NonNull Surface source, @NonNull Bitmap dest,
             @NonNull OnPixelCopyFinishedListener listener, @NonNull Handler listenerThread) {
         validateBitmapDest(dest);
+        if (!source.isValid()) {
+            throw new IllegalArgumentException("Surface isn't valid, source.isValid() == false");
+        }
         // TODO: Make this actually async and fast and cool and stuff
         int result = ThreadedRenderer.copySurfaceInto(source, dest);
         listenerThread.post(new Runnable() {
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index fdbe76a..0a8e3f3 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -471,18 +471,19 @@
     return *this;
 }
 
-GlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture) {
+GlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture, Matrix4& textureTransform) {
     TRIGGER_STAGE(kFillStage);
     REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     mOutGlop->fill.texture = { &texture,
             GL_TEXTURE_EXTERNAL_OES, GL_LINEAR, GL_CLAMP_TO_EDGE,
-            nullptr };
+            &textureTransform };
 
     setFill(SK_ColorWHITE, 1.0f, SkXfermode::kSrc_Mode, Blend::ModeOrderSwap::NoSwap,
             nullptr, nullptr);
 
     mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
+    mDescription.hasTextureTransform = true;
     return *this;
 }
 
diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h
index b6c186d..a9dd56f 100644
--- a/libs/hwui/GlopBuilder.h
+++ b/libs/hwui/GlopBuilder.h
@@ -73,7 +73,7 @@
     // TODO: Texture should probably know and own its target.
     // setFillLayer() forces it to GL_TEXTURE which isn't always correct.
     // Similarly setFillLayer normally forces its own wrap & filter mode
-    GlopBuilder& setFillExternalTexture(Texture& texture);
+    GlopBuilder& setFillExternalTexture(Texture& texture, Matrix4& textureTransform);
 
     GlopBuilder& setTransform(const Snapshot& snapshot, const int transformFlags) {
         return setTransform(*snapshot.transform, transformFlags);
diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h
index 36007cd..9cde5d6 100644
--- a/libs/hwui/Matrix.h
+++ b/libs/hwui/Matrix.h
@@ -236,6 +236,8 @@
 
     static const Matrix4& identity();
 
+    void invalidateType() { mType = kTypeUnknown; }
+
 private:
     mutable uint8_t mType;
 
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index 49596e1..55f823d 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -101,7 +101,10 @@
     // Setup the source
     sp<GraphicBuffer> sourceBuffer;
     sp<Fence> sourceFence;
-    status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence);
+    Matrix4 texTransform;
+    status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence,
+            texTransform.data);
+    texTransform.invalidateType();
     if (err != NO_ERROR) {
         ALOGW("Failed to get last queued buffer, error = %d", err);
         return CopyResult::UnknownError;
@@ -163,8 +166,8 @@
         Glop glop;
         GlopBuilder(renderState, caches, &glop)
                 .setRoundRectClipState(nullptr)
-                .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
-                .setFillExternalTexture(sourceTexture)
+                .setMeshTexturedUnitQuad(nullptr)
+                .setFillExternalTexture(sourceTexture, texTransform)
                 .setTransform(Matrix4::identity(), TransformFlags::None)
                 .setModelViewMapUnitToRect(destRect)
                 .build();
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index a8c2652..6257238 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -1247,7 +1247,8 @@
         private Range<Double> estimateFrameRatesFor(int width, int height) {
             Size size = findClosestSize(width, height);
             Range<Long> range = mMeasuredFrameRates.get(size);
-            Double ratio = (double)(size.getWidth() * size.getHeight()) / (width * height);
+            Double ratio = getBlockCount(size.getWidth(), size.getHeight())
+                    / (double)Math.max(getBlockCount(width, height), 1);
             return Range.create(range.getLower() * ratio, range.getUpper() * ratio);
         }
 
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 346f083..93c595f 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -46,7 +46,8 @@
  * <tr><td>{@link #KEY_HEIGHT}</td><td>Integer</td><td></td></tr>
  * <tr><td>{@link #KEY_COLOR_FORMAT}</td><td>Integer</td><td>set by the user
  *         for encoders, readable in the output format of decoders</b></td></tr>
- * <tr><td>{@link #KEY_FRAME_RATE}</td><td>Integer or Float</td><td><b>encoder-only</b></td></tr>
+ * <tr><td>{@link #KEY_FRAME_RATE}</td><td>Integer or Float</td><td>required for <b>encoders</b>,
+ *         optional for <b>decoders</b></td></tr>
  * <tr><td>{@link #KEY_CAPTURE_RATE}</td><td>Integer</td><td></td></tr>
  * <tr><td>{@link #KEY_I_FRAME_INTERVAL}</td><td>Integer</td><td><b>encoder-only</b></td></tr>
  * <tr><td>{@link #KEY_INTRA_REFRESH_PERIOD}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr>
@@ -197,7 +198,19 @@
 
     /**
      * A key describing the frame rate of a video format in frames/sec.
-     * The associated value is an integer or a float.
+     * The associated value is normally an integer when the value is used by the platform,
+     * but video codecs also accept float configuration values.
+     * Specifically, {@link MediaExtractor#getTrackFormat MediaExtractor} provides an integer
+     * value corresponding to the frame rate information of the track if specified and non-zero.
+     * Otherwise, this key is not present. {@link MediaCodec#configure MediaCodec} accepts both
+     * float and integer values. This represents the desired operating frame rate if the
+     * {@link #KEY_OPERATING_RATE} is not present and {@link #KEY_PRIORITY} is {@code 0}
+     * (realtime). For video encoders this value corresponds to the intended frame rate,
+     * although encoders are expected
+     * to support variable frame rate based on {@link MediaCodec.BufferInfo#presentationTimeUs
+     * buffer timestamp}. This key is not used in the {@code MediaCodec}
+     * {@link MediaCodec#getInputFormat input}/{@link MediaCodec#getOutputFormat output} formats,
+     * nor by {@link MediaMuxer#addTrack MediaMuxer}.
      */
     public static final String KEY_FRAME_RATE = "frame-rate";
 
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 74c98e4..efa34ff 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -421,8 +421,6 @@
     <string name="wifi_aggressive_handover">Aggressive Wi\u2011Fi to Cellular handover</string>
     <!-- Setting Checkbox title whether to enable WiFi Scanning in the presence of traffic. [CHAR LIMIT=80] -->
     <string name="wifi_allow_scan_with_traffic">Always allow Wi\u2011Fi Roam Scans</string>
-    <!-- Setting Checkbox title whether to enable WiFi Scanning in the presence of traffic. [CHAR LIMIT=80] -->
-    <string name="legacy_dhcp_client">Use legacy DHCP client</string>
     <!-- Setting Checkbox title whether to always keep cellular data active. [CHAR LIMIT=80] -->
     <string name="mobile_data_always_on">Cellular data always active</string>
     <!-- Setting Checkbox title for disabling Bluetooth absolute volume -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index bcbc6ac..bf75046 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -52,7 +52,7 @@
     protected static final boolean DEBUG_TIMING = false;
     private static final String TAG = "SettingsDrawerActivity";
 
-    static final String EXTRA_SHOW_MENU = "show_drawer_menu";
+    public static final String EXTRA_SHOW_MENU = "show_drawer_menu";
 
     private static List<DashboardCategory> sDashboardCategories;
     private static HashMap<Pair<String, String>, Tile> sTileCache;
diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml
index f0ae1c9..be05a3a 100644
--- a/packages/SystemUI/res/layout/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout/volume_dialog_row.xml
@@ -18,6 +18,7 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:clipChildren="false"
+    android:clipToPadding="false"
     android:id="@+id/volume_dialog_row"
     android:paddingEnd="@dimen/volume_button_size" >
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 716185f..b2aa966 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -106,6 +106,7 @@
     public void setHost(QSTileHost host) {
         mHost = host;
         mPhoneStatusBar = host.getPhoneStatusBar();
+        mTileAdapter.setHost(host);
     }
 
     public void setContainer(NotificationsQuickSettingsContainer notificationsQsContainer) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index 41b49d8..ec0eefb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -81,6 +81,7 @@
     private Holder mCurrentDrag;
     private boolean mAccessibilityMoving;
     private int mAccessibilityFromIndex;
+    private QSTileHost mHost;
 
     public TileAdapter(Context context) {
         mContext = context;
@@ -88,6 +89,10 @@
         mItemTouchHelper = new ItemTouchHelper(mCallbacks);
     }
 
+    public void setHost(QSTileHost host) {
+        mHost = host;
+    }
+
     @Override
     public long getItemId(int position) {
         return mTiles.get(position) != null ? mAllTiles.indexOf(mTiles.get(position))
@@ -108,7 +113,7 @@
             newSpecs.add(mTiles.get(i).spec);
         }
         host.changeTiles(mCurrentSpecs, newSpecs);
-        setTileSpecs(newSpecs);
+        mCurrentSpecs = newSpecs;
     }
 
     public void setTileSpecs(List<String> currentSpecs) {
@@ -285,6 +290,7 @@
         move(mAccessibilityFromIndex, position, v);
         notifyItemChanged(mAccessibilityFromIndex);
         notifyItemMoved(mAccessibilityFromIndex, position);
+        saveSpecs(mHost);
     }
 
     private void showAccessibilityDialog(final int position, final View v) {
@@ -373,6 +379,7 @@
                     fromLabel, (to + 1));
         }
         v.announceForAccessibility(announcement);
+        saveSpecs(mHost);
         return true;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 6d76763e..ce0163e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -327,7 +327,14 @@
     public static String contentDescForNotification(Context c, Notification n) {
         Notification.Builder builder = Notification.Builder.recoverBuilder(c, n);
         String appName = builder.loadHeaderAppName();
+
+        CharSequence title = n.extras.getString(Notification.EXTRA_TITLE);
         CharSequence ticker = n.tickerText;
-        return c.getString(R.string.accessibility_desc_notification_icon, appName, ticker);
+
+        CharSequence desc = !TextUtils.isEmpty(ticker) ? ticker
+                : !TextUtils.isEmpty(title) ? title : "";
+
+        return c.getString(R.string.accessibility_desc_notification_icon, appName, desc);
     }
+
 }
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 f7ecd61..6fc32de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -409,6 +409,9 @@
                 if (mKeyguardBottomArea != null) {
                     mKeyguardBottomArea.setUserSetupComplete(mUserSetup);
                 }
+                if (mNetworkController != null) {
+                    mNetworkController.setUserSetupComplete(mUserSetup);
+                }
             }
             if (mIconPolicy != null) {
                 mIconPolicy.setCurrentUserSetup(mUserSetup);
@@ -838,6 +841,7 @@
             }
         });
         mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper());
+        mNetworkController.setUserSetupComplete(mUserSetup);
         mHotspotController = new HotspotControllerImpl(mContext);
         mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper());
         mSecurityController = new SecurityControllerImpl(mContext);
@@ -1437,7 +1441,11 @@
     public void removeNotification(String key, RankingMap ranking) {
         boolean deferRemoval = false;
         if (mHeadsUpManager.isHeadsUp(key)) {
-            deferRemoval = !mHeadsUpManager.removeNotification(key);
+            // A cancel() in repsonse to a remote input shouldn't be delayed, as it makes the
+            // sending look longer than it takes.
+            boolean ignoreEarliestRemovalTime = mRemoteInputController.isSpinning(key)
+                    && !FORCE_REMOTE_INPUT_HISTORY;
+            deferRemoval = !mHeadsUpManager.removeNotification(key,  ignoreEarliestRemovalTime);
         }
         if (key.equals(mMediaNotificationKey)) {
             clearCurrentMediaNotification();
@@ -2364,7 +2372,7 @@
         if (wasHeadsUp) {
             if (!shouldPeek) {
                 // We don't want this to be interrupting anymore, lets remove it
-                mHeadsUpManager.removeNotification(key);
+                mHeadsUpManager.removeNotification(key, false /* ignoreEarliestRemovalTime */);
             } else {
                 mHeadsUpManager.updateNotification(entry, alertAgain);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 52fb470..d3ae549 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -264,9 +264,9 @@
      * @return true if the notification was removed and false if it still needs to be kept around
      * for a bit since it wasn't shown long enough
      */
-    public boolean removeNotification(String key) {
+    public boolean removeNotification(String key, boolean ignoreEarliestRemovalTime) {
         if (DEBUG) Log.v(TAG, "remove");
-        if (wasShownLongEnough(key)) {
+        if (wasShownLongEnough(key) || ignoreEarliestRemovalTime) {
             releaseImmediately(key);
             return true;
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 80dcfb6..83e25eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -114,6 +114,11 @@
         notifyListenersIfNecessary();
     }
 
+    public void setUserSetupComplete(boolean userSetup) {
+        mCurrentState.userSetup = userSetup;
+        notifyListenersIfNecessary();
+    }
+
     @Override
     public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) {
         boolean isValidated = validatedTransports.get(mTransportType);
@@ -204,11 +209,13 @@
 
         String contentDescription = getStringIfExists(getContentDescription());
         String dataContentDescription = getStringIfExists(icons.mDataContentDescription);
+        final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED
+                && mCurrentState.userSetup;
 
-        // Show icon in QS when we are connected or need to show roaming.
+        // Show icon in QS when we are connected or need to show roaming or data is disabled.
         boolean showDataIcon = mCurrentState.dataConnected
                 || mCurrentState.iconGroup == TelephonyIcons.ROAMING
-                || mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
+                || dataDisabled;
         IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode,
                 getCurrentIconId(), contentDescription);
 
@@ -230,7 +237,7 @@
                         && mCurrentState.activityOut;
         showDataIcon &= mCurrentState.isDefault
                 || mCurrentState.iconGroup == TelephonyIcons.ROAMING
-                || mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED;
+                || dataDisabled;
         int typeIcon = showDataIcon ? icons.mDataType : 0;
         callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon,
                 activityIn, activityOut, dataContentDescription, description, icons.mIsWide,
@@ -511,6 +518,7 @@
         boolean airplaneMode;
         boolean carrierNetworkChangeMode;
         boolean isDefault;
+        boolean userSetup;
 
         @Override
         public void copyFrom(State s) {
@@ -524,6 +532,7 @@
             isEmergency = state.isEmergency;
             airplaneMode = state.airplaneMode;
             carrierNetworkChangeMode = state.carrierNetworkChangeMode;
+            userSetup = state.userSetup;
         }
 
         @Override
@@ -537,7 +546,9 @@
             builder.append("isDefault=").append(isDefault).append(',');
             builder.append("isEmergency=").append(isEmergency).append(',');
             builder.append("airplaneMode=").append(airplaneMode).append(',');
-            builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode);
+            builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode)
+                    .append(',');
+            builder.append("userSetup=").append(userSetup);
         }
 
         @Override
@@ -550,6 +561,7 @@
                     && ((MobileState) o).isEmergency == isEmergency
                     && ((MobileState) o).airplaneMode == airplaneMode
                     && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode
+                    && ((MobileState) o).userSetup == userSetup
                     && ((MobileState) o).isDefault == isDefault;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 40dacd3..a633241 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -130,6 +130,7 @@
 
     @VisibleForTesting
     ServiceState mLastServiceState;
+    private boolean mUserSetup;
 
     /**
      * Construct this controller object and register for updates.
@@ -490,6 +491,7 @@
                 MobileSignalController controller = new MobileSignalController(mContext, mConfig,
                         mHasMobileDataFeature, mPhone, mCallbackHandler,
                         this, subscriptions.get(i), mSubDefaults, mReceiverHandler.getLooper());
+                controller.setUserSetupComplete(mUserSetup);
                 mMobileSignalControllers.put(subId, controller);
                 if (subscriptions.get(i).getSimSlotIndex() == 0) {
                     mDefaultSignalController = controller;
@@ -516,6 +518,23 @@
         updateAirplaneMode(true /* force */);
     }
 
+    public void setUserSetupComplete(final boolean userSetup) {
+        mReceiverHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                handleSetUserSetupComplete(userSetup);
+            }
+        });
+    }
+
+    @VisibleForTesting
+    void handleSetUserSetupComplete(boolean userSetup) {
+        mUserSetup = userSetup;
+        for (MobileSignalController controller : mMobileSignalControllers.values()) {
+            controller.setUserSetupComplete(mUserSetup);
+        }
+    }
+
     @VisibleForTesting
     boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) {
         if (allSubscriptions.size() != mMobileSignalControllers.size()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index f3033cd..a855aed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -91,8 +91,6 @@
         mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
             @Override
             public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
-
-                // Check if this was the result of hitting the enter key
                 final boolean isSoftImeEvent = event == null
                         && (actionId == EditorInfo.IME_ACTION_DONE
                         || actionId == EditorInfo.IME_ACTION_NEXT
@@ -102,7 +100,10 @@
                         && event.getAction() == KeyEvent.ACTION_DOWN;
 
                 if (isSoftImeEvent || isKeyboardEnterKey) {
-                    sendRemoteInput();
+                    if (mEditText.length() > 0) {
+                        sendRemoteInput();
+                    }
+                    // Consume action to prevent IME from closing.
                     return true;
                 }
                 return false;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
index 2c53e29..36dd727 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java
@@ -654,8 +654,9 @@
         intent.putExtra(PackageManager.EXTRA_MOVE_ID, move.moveId);
 
         final VolumeInfo vol = mStorageManager.findVolumeByQualifiedUuid(move.volumeUuid);
-        intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
-
+        if (vol != null) {
+            intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId());
+        }
         return PendingIntent.getActivityAsUser(mContext, move.moveId, intent,
                 PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 60d33fa..38cac1e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -111,6 +111,7 @@
         when(mMockTm.getDataEnabled(mSubId)).thenReturn(true);
         setDefaultSubId(mSubId);
         setSubscriptions(mSubId);
+        mNetworkController.handleSetUserSetupComplete(true);
         mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId);
         mPhoneStateListener = mMobileSignalController.mPhoneStateListener;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index d5eca95..542c390 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -1,9 +1,9 @@
 package com.android.systemui.statusbar.policy;
 
+import android.net.NetworkCapabilities;
 import android.os.Looper;
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
-
 import com.android.settingslib.net.DataUsageController;
 import org.mockito.Mockito;
 
@@ -99,6 +99,29 @@
                 TelephonyIcons.QS_DATA_4G);
     }
 
+    public void testDataDisabledIcon() {
+        setupNetworkController();
+        Mockito.when(mMockTm.getDataEnabled(mSubId)).thenReturn(false);
+        setupDefaultSignal();
+        updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
+        setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
+
+        verifyDataIndicators(TelephonyIcons.ICON_DATA_DISABLED,
+                TelephonyIcons.QS_ICON_DATA_DISABLED);
+    }
+
+    public void testDataDisabledIcon_UserNotSetup() {
+        setupNetworkController();
+        Mockito.when(mMockTm.getDataEnabled(mSubId)).thenReturn(false);
+        setupDefaultSignal();
+        updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
+        setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
+        mNetworkController.handleSetUserSetupComplete(false);
+
+        // Don't show the X until the device is setup.
+        verifyDataIndicators(0, 0);
+    }
+
     public void test4gDataIconConfigChange() {
         setupDefaultSignal();
         updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
@@ -145,7 +168,6 @@
         verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, DEFAULT_ICON);
         verifyLastQsMobileDataIndicators(true, DEFAULT_QS_SIGNAL_STRENGTH,
                 DEFAULT_QS_ICON, in, out);
-
     }
 
     private void verifyDataIndicators(int dataIcon, int qsDataIcon) {
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index f49235c..c417fe8 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2187,6 +2187,10 @@
     // reinflation.
     ACTION_REMOTE_INPUT_CLOSE = 400;
 
+    // OPEN: Settings > Accounts > Work profile settings
+    // CATEGORY: SETTINGS
+    ACCOUNTS_WORK_PROFILE_SETTINGS = 401;
+
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
   }
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 95f9e2d..1b63cd4 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -3706,7 +3706,7 @@
                         result = BackupTransport.TRANSPORT_OK;
                     }
                 } catch (IOException e) {
-                    Slog.e(TAG, "Error backing up " + mPkg.packageName, e);
+                    Slog.e(TAG, "Error backing up " + mPkg.packageName + ": " + e.getMessage());
                     result = BackupTransport.AGENT_ERROR;
                 } finally {
                     try {
@@ -4466,7 +4466,6 @@
                             }
                         }
 
-
                         // If we've lost our running criteria, tell the transport to cancel
                         // and roll back this (partial) backup payload; otherwise tell it
                         // that we've reached the clean finish state.
@@ -4484,14 +4483,16 @@
                             }
                         }
 
-                        // TRANSPORT_ERROR here means that we've hit an error that the runner
-                        // doesn't know about, so it's still moving data but we're pulling the
+                        // A transport-originated error here means that we've hit an error that the
+                        // runner doesn't know about, so it's still moving data but we're pulling the
                         // rug out from under it.  Don't ask for its result:  we already know better
                         // and we'll hang if we block waiting for it, since it relies on us to
                         // read back the data it's writing into the engine.  Just proceed with
                         // a graceful failure.  The runner/engine mechanism will tear itself
-                        // down cleanly when we close the pipes from this end.
-                        if (backupPackageStatus != BackupTransport.TRANSPORT_ERROR) {
+                        // down cleanly when we close the pipes from this end.  Transport-level
+                        // errors take precedence over agent/app-specific errors for purposes of
+                        // determining our course of action.
+                        if (backupPackageStatus == BackupTransport.TRANSPORT_OK) {
                             // We still could fail in backup runner thread, getting result from there.
                             int backupRunnerResult = backupRunner.getBackupResultBlocking();
                             if (backupRunnerResult != BackupTransport.TRANSPORT_OK) {
@@ -4499,10 +4500,14 @@
                                 // not TRANSPORT_ERROR here, overwrite it.
                                 backupPackageStatus = backupRunnerResult;
                             }
+                        } else {
+                            if (MORE_DEBUG) {
+                                Slog.i(TAG, "Transport-level failure; cancelling agent work");
+                            }
                         }
 
                         if (MORE_DEBUG) {
-                            Slog.i(TAG, "Done trying to send backup data: result="
+                            Slog.i(TAG, "Done delivering backup data: result="
                                     + backupPackageStatus);
                         }
 
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 8753992..6b51721 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -358,7 +358,7 @@
         try {
             mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth,
                     mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature,
-                    mBatteryProps.batteryVoltage);
+                    mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter);
         } catch (RemoteException e) {
             // Should never happen.
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d85827e..f5e9d19 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -29,8 +29,12 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
+import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
 import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
+import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
+import static android.net.NetworkPolicyManager.RULE_UNKNOWN;
+
 import android.annotation.Nullable;
 import android.app.BroadcastOptions;
 import android.app.Notification;
@@ -96,8 +100,10 @@
 import android.security.KeyStore;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.LocalLog;
 import android.util.LocalLog.ReadOnlyLocalLog;
+import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -121,9 +127,9 @@
 import com.android.server.am.BatteryStatsService;
 import com.android.server.connectivity.DataConnectionStats;
 import com.android.server.connectivity.KeepaliveTracker;
-import com.android.server.connectivity.NetworkDiagnostics;
 import com.android.server.connectivity.Nat464Xlat;
 import com.android.server.connectivity.NetworkAgentInfo;
+import com.android.server.connectivity.NetworkDiagnostics;
 import com.android.server.connectivity.NetworkMonitor;
 import com.android.server.connectivity.PacManager;
 import com.android.server.connectivity.PermissionMonitor;
@@ -131,8 +137,8 @@
 import com.android.server.connectivity.Vpn;
 import com.android.server.net.BaseNetworkObserver;
 import com.android.server.net.LockdownVpnTracker;
+
 import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -152,11 +158,11 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.SortedSet;
-import java.util.TreeSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 /**
  * @hide
@@ -202,9 +208,14 @@
     /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */
     private Object mRulesLock = new Object();
     /** Currently active network rules by UID. */
+    @GuardedBy("mRulesLock")
     private SparseIntArray mUidRules = new SparseIntArray();
     /** Set of ifaces that are costly. */
-    private HashSet<String> mMeteredIfaces = Sets.newHashSet();
+    @GuardedBy("mRulesLock")
+    private ArraySet<String> mMeteredIfaces = new ArraySet<>();
+    /** Flag indicating if background data is restricted. */
+    @GuardedBy("mRulesLock")
+    private boolean mRestrictBackground;
 
     final private Context mContext;
     private int mNetworkPreference;
@@ -651,7 +662,8 @@
         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
 
         try {
-            mPolicyManager.registerListener(mPolicyListener);
+            mPolicyManager.setConnectivityListener(mPolicyListener);
+            mRestrictBackground = mPolicyManager.getRestrictBackground();
         } catch (RemoteException e) {
             // ouch, no rules updates means some processes may never get network
             loge("unable to register INetworkPolicyListener" + e.toString());
@@ -819,7 +831,7 @@
         throw new IllegalStateException("No free netIds");
     }
 
-    private NetworkState getFilteredNetworkState(int networkType, int uid) {
+    private NetworkState getFilteredNetworkState(int networkType, int uid, boolean ignoreBlocked) {
         if (mLegacyTypeTracker.isTypeSupported(networkType)) {
             final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
             final NetworkState state;
@@ -834,7 +846,7 @@
                 state = new NetworkState(info, new LinkProperties(), new NetworkCapabilities(),
                         null, null, null);
             }
-            filterNetworkStateForUid(state, uid);
+            filterNetworkStateForUid(state, uid, ignoreBlocked);
             return state;
         } else {
             return NetworkState.EMPTY;
@@ -890,22 +902,36 @@
     /**
      * Check if UID should be blocked from using the network with the given LinkProperties.
      */
-    private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid) {
-        final boolean networkCostly;
+    private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
+            boolean ignoreBlocked) {
+        // Networks aren't blocked when ignoring blocked status
+        if (ignoreBlocked) return false;
+        // Networks are never blocked for system services
+        if (uid < Process.FIRST_APPLICATION_UID) return false;
+
+        final boolean networkMetered;
         final int uidRules;
 
         final String iface = (lp == null ? "" : lp.getInterfaceName());
         synchronized (mRulesLock) {
-            networkCostly = mMeteredIfaces.contains(iface);
-            uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
+            networkMetered = mMeteredIfaces.contains(iface);
+            uidRules = mUidRules.get(uid, RULE_UNKNOWN);
         }
 
-        if (uidRules == RULE_REJECT_ALL) {
-            return true;
-        } else if ((uidRules == RULE_REJECT_METERED) && networkCostly) {
-            return true;
-        } else {
-            return false;
+        switch (uidRules) {
+            case RULE_ALLOW_ALL:
+            case RULE_ALLOW_METERED:
+            case RULE_TEMPORARY_ALLOW_METERED:
+                return false;
+            case RULE_REJECT_METERED:
+                return networkMetered;
+            case RULE_REJECT_ALL:
+                return true;
+            case RULE_UNKNOWN:
+            default:
+                // When background data is restricted device-wide, the default
+                // behavior for apps should be like RULE_REJECT_METERED
+                return mRestrictBackground ? networkMetered : false;
         }
     }
 
@@ -930,10 +956,10 @@
      * on {@link #isNetworkWithLinkPropertiesBlocked}, or
      * {@link NetworkInfo#isMetered()} based on network policies.
      */
-    private void filterNetworkStateForUid(NetworkState state, int uid) {
+    private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) {
         if (state == null || state.networkInfo == null || state.linkProperties == null) return;
 
-        if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid)) {
+        if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) {
             state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null);
         }
         if (mLockdownTracker != null) {
@@ -962,7 +988,7 @@
         enforceAccessPermission();
         final int uid = Binder.getCallingUid();
         final NetworkState state = getUnfilteredActiveNetworkState(uid);
-        filterNetworkStateForUid(state, uid);
+        filterNetworkStateForUid(state, uid, false);
         maybeLogBlockedNetworkInfo(state.networkInfo, uid);
         return state.networkInfo;
     }
@@ -970,16 +996,16 @@
     @Override
     public Network getActiveNetwork() {
         enforceAccessPermission();
-        return getActiveNetworkForUidInternal(Binder.getCallingUid());
+        return getActiveNetworkForUidInternal(Binder.getCallingUid(), false);
     }
 
     @Override
-    public Network getActiveNetworkForUid(int uid) {
+    public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) {
         enforceConnectivityInternalPermission();
-        return getActiveNetworkForUidInternal(uid);
+        return getActiveNetworkForUidInternal(uid, ignoreBlocked);
     }
 
-    private Network getActiveNetworkForUidInternal(final int uid) {
+    private Network getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked) {
         final int user = UserHandle.getUserId(uid);
         int vpnNetId = NETID_UNSET;
         synchronized (mVpns) {
@@ -994,7 +1020,10 @@
             if (nai != null) return nai.network;
         }
         nai = getDefaultNetwork();
-        if (nai != null && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid)) nai = null;
+        if (nai != null
+                && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, ignoreBlocked)) {
+            nai = null;
+        }
         return nai != null ? nai.network : null;
     }
 
@@ -1006,10 +1035,10 @@
     }
 
     @Override
-    public NetworkInfo getActiveNetworkInfoForUid(int uid) {
+    public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) {
         enforceConnectivityInternalPermission();
         final NetworkState state = getUnfilteredActiveNetworkState(uid);
-        filterNetworkStateForUid(state, uid);
+        filterNetworkStateForUid(state, uid, ignoreBlocked);
         return state.networkInfo;
     }
 
@@ -1023,22 +1052,21 @@
             // getUnfilteredActiveNetworkState.
             final NetworkState state = getUnfilteredActiveNetworkState(uid);
             if (state.networkInfo != null && state.networkInfo.getType() == networkType) {
-                filterNetworkStateForUid(state, uid);
+                filterNetworkStateForUid(state, uid, false);
                 return state.networkInfo;
             }
         }
-        final NetworkState state = getFilteredNetworkState(networkType, uid);
+        final NetworkState state = getFilteredNetworkState(networkType, uid, false);
         return state.networkInfo;
     }
 
     @Override
-    public NetworkInfo getNetworkInfoForNetwork(Network network) {
+    public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) {
         enforceAccessPermission();
-        final int uid = Binder.getCallingUid();
         final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
         if (nai != null) {
             final NetworkState state = nai.getNetworkState();
-            filterNetworkStateForUid(state, uid);
+            filterNetworkStateForUid(state, uid, ignoreBlocked);
             return state.networkInfo;
         } else {
             return null;
@@ -1063,8 +1091,8 @@
     public Network getNetworkForType(int networkType) {
         enforceAccessPermission();
         final int uid = Binder.getCallingUid();
-        NetworkState state = getFilteredNetworkState(networkType, uid);
-        if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid)) {
+        NetworkState state = getFilteredNetworkState(networkType, uid, false);
+        if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) {
             return state.network;
         }
         return null;
@@ -1381,6 +1409,11 @@
             if (LOGD_RULES) {
                 log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")");
             }
+
+            synchronized (mRulesLock) {
+                mRestrictBackground = restrictBackground;
+            }
+
             if (restrictBackground) {
                 log("onRestrictBackgroundChanged(true): disabling tethering");
                 mTethering.untetherAll();
@@ -1824,6 +1857,10 @@
         pw.decreaseIndent();
         pw.println();
 
+        pw.print("Restrict background: ");
+        pw.println(mRestrictBackground);
+        pw.println();
+
         pw.println("Network Requests:");
         pw.increaseIndent();
         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
@@ -2765,7 +2802,7 @@
             // which isn't meant to work on uncreated networks.
             if (!nai.created) return;
 
-            if (isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid)) return;
+            if (isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, false)) return;
 
             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid);
         }
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index c912b11..cbf7e80 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -1281,8 +1281,14 @@
         // service can't connect to vold, it restarts, and then the new instance
         // does successfully connect.
         final IMountService service = getMountService();
-        String password = service.getPassword();
-        service.clearPassword();
+        String password;
+        long identity = Binder.clearCallingIdentity();
+        try {
+            password = service.getPassword();
+            service.clearPassword();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
         if (password == null) {
             return false;
         }
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index b0581aa..7253870 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -2648,6 +2648,8 @@
      */
     @Override
     public int getPasswordType() {
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+            "no permission to access the crypt keeper");
 
         waitForReady();
 
@@ -2672,6 +2674,8 @@
      */
     @Override
     public void setField(String field, String contents) throws RemoteException {
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+            "no permission to access the crypt keeper");
 
         waitForReady();
 
@@ -2690,6 +2694,8 @@
      */
     @Override
     public String getField(String field) throws RemoteException {
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+            "no permission to access the crypt keeper");
 
         waitForReady();
 
@@ -2714,6 +2720,8 @@
      */
     @Override
     public boolean isConvertibleToFBE() throws RemoteException {
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+            "no permission to access the crypt keeper");
 
         waitForReady();
 
@@ -2728,8 +2736,9 @@
 
     @Override
     public String getPassword() throws RemoteException {
-        mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE,
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
                 "only keyguard can retrieve password");
+
         if (!isReady()) {
             return new String();
         }
@@ -2752,6 +2761,9 @@
 
     @Override
     public void clearPassword() throws RemoteException {
+        mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL,
+                "only keyguard can clear password");
+
         if (!isReady()) {
             return;
         }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 96214d6..98b3b08 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -409,7 +409,6 @@
      */
     public void validateAccounts(int userId) {
         final UserAccounts accounts = getUserAccounts(userId);
-
         // Invalidate user-specific cache to make sure we catch any
         // removed authenticators.
         validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
@@ -426,15 +425,13 @@
                     + " isCeDatabaseAttached=" + accounts.openHelper.isCeDatabaseAttached()
                     + " userLocked=" + mLocalUnlockedUsers.get(accounts.userId));
         }
+
         if (invalidateAuthenticatorCache) {
             mAuthenticatorCache.invalidateCache(accounts.userId);
         }
 
-        final HashMap<String, Integer> knownAuth = new HashMap<>();
-        for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service :
-                mAuthenticatorCache.getAllServices(accounts.userId)) {
-            knownAuth.put(service.type.type, service.uid);
-        }
+        final HashMap<String, Integer> knownAuth = getAuthenticatorTypeAndUIDForUser(
+                mAuthenticatorCache, accounts.userId);
 
         synchronized (accounts.cacheLock) {
             final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
@@ -452,6 +449,7 @@
             // Create a list of authenticator type whose previous uid no longer exists
             HashSet<String> obsoleteAuthType = Sets.newHashSet();
             try {
+                SparseBooleanArray knownUids = null;
                 while (metaCursor.moveToNext()) {
                     String type = TextUtils.split(metaCursor.getString(0), META_KEY_DELIMITER)[1];
                     String uid = metaCursor.getString(1);
@@ -466,23 +464,48 @@
                         // Remove it from the knownAuth list if it's unchanged.
                         knownAuth.remove(type);
                     } else {
-                        // Only add it to the list if it no longer exists or uid different
-                        obsoleteAuthType.add(type);
-                        // And delete it from the TABLE_META
-                        db.delete(
-                                TABLE_META,
-                                META_KEY + "=? AND " + META_VALUE + "=?",
-                                new String[] {
-                                        META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + type,
-                                        uid}
-                                );
+                        /*
+                         * The authenticator is presently not cached and should only be triggered
+                         * when we think an authenticator has been removed (or is being updated).
+                         * But we still want to check if any data with the associated uid is
+                         * around. This is an (imperfect) signal that the package may be updating.
+                         *
+                         * A side effect of this is that an authenticator sharing a uid with
+                         * multiple apps won't get its credentials wiped as long as some app with
+                         * that uid is still on the device. But I suspect that this is a rare case.
+                         * And it isn't clear to me how an attacker could really exploit that
+                         * feature.
+                         *
+                         * The upshot is that we don't have to worry about accounts getting
+                         * uninstalled while the authenticator's package is being updated.
+                         *
+                         */
+                        if (knownUids == null) {
+                            knownUids = getUidsOfInstalledOrUpdatedPackagesAsUser(accounts.userId); 
+                        }
+                        if (!knownUids.get(Integer.parseInt(uid))) {
+                            // The authenticator is not presently available to the cache. And the
+                            // package no longer has a data directory (so we surmise it isn't updating).
+                            // So purge its data from the account databases.
+                            obsoleteAuthType.add(type);
+                            // And delete it from the TABLE_META
+                            db.delete(
+                                    TABLE_META,
+                                    META_KEY + "=? AND " + META_VALUE + "=?",
+                                    new String[] {
+                                            META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + type,
+                                            uid}
+                                    );
+                        }
                     }
                 }
             } finally {
                 metaCursor.close();
             }
 
-            // Add the newly registered authenticator to TABLE_META
+            // Add the newly registered authenticator to TABLE_META. If old authenticators have
+            // been renabled (after being updated for example), then we just overwrite the old
+            // values.
             Iterator<Entry<String, Integer>> iterator = knownAuth.entrySet().iterator();
             while (iterator.hasNext()) {
                 Entry<String, Integer> entry = iterator.next();
@@ -490,7 +513,7 @@
                 values.put(META_KEY,
                         META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + entry.getKey());
                 values.put(META_VALUE, entry.getValue());
-                db.insert(TABLE_META, null, values);
+                db.insertWithOnConflict(TABLE_META, null, values, SQLiteDatabase.CONFLICT_REPLACE);
             }
 
             Cursor cursor = db.query(TABLE_ACCOUNTS,
@@ -544,10 +567,32 @@
         }
     }
 
+    private SparseBooleanArray getUidsOfInstalledOrUpdatedPackagesAsUser(int userId) {
+        // Get the UIDs of all apps that might have data on the device. We want
+        // to preserve user data if the app might otherwise be storing data.
+        List<PackageInfo> pkgsWithData =
+                mPackageManager.getInstalledPackagesAsUser(
+                        PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
+        SparseBooleanArray knownUids = new SparseBooleanArray(pkgsWithData.size());
+        for (PackageInfo pkgInfo : pkgsWithData) {
+            if (pkgInfo.applicationInfo != null
+                    && (pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0) {
+                knownUids.put(pkgInfo.applicationInfo.uid, true);
+            }
+        }
+        return knownUids;
+    }
+
     private static HashMap<String, Integer> getAuthenticatorTypeAndUIDForUser(
             Context context,
             int userId) {
         AccountAuthenticatorCache authCache = new AccountAuthenticatorCache(context);
+        return getAuthenticatorTypeAndUIDForUser(authCache, userId);
+    }
+
+    private static HashMap<String, Integer> getAuthenticatorTypeAndUIDForUser(
+            IAccountAuthenticatorCache authCache,
+            int userId) {
         HashMap<String, Integer> knownAuth = new HashMap<>();
         for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service : authCache
                 .getAllServices(userId)) {
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index e9ed34b..3ed9969 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -304,6 +304,15 @@
      * @param crashInfo describing the failure
      */
     void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            crashApplicationInner(r, crashInfo);
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
+    void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) {
         long timeMillis = System.currentTimeMillis();
         String shortMsg = crashInfo.exceptionClassName;
         String longMsg = crashInfo.exceptionMessage;
@@ -317,49 +326,20 @@
         AppErrorResult result = new AppErrorResult();
         TaskRecord task;
         synchronized (mService) {
-            if (mService.mController != null) {
-                try {
-                    String name = r != null ? r.processName : null;
-                    int pid = r != null ? r.pid : Binder.getCallingPid();
-                    int uid = r != null ? r.info.uid : Binder.getCallingUid();
-                    if (!mService.mController.appCrashed(name, pid,
-                            shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
-                        if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
-                                && "Native crash".equals(crashInfo.exceptionClassName)) {
-                            Slog.w(TAG, "Skip killing native crashed app " + name
-                                    + "(" + pid + ") during testing");
-                        } else {
-                            Slog.w(TAG, "Force-killing crashed app " + name
-                                    + " at watcher's request");
-                            if (r != null) {
-                                r.kill("crash", true);
-                            } else {
-                                // Huh.
-                                Process.killProcess(pid);
-                                ActivityManagerService.killProcessGroup(uid, pid);
-                            }
-                        }
-                        return;
-                    }
-                } catch (RemoteException e) {
-                    mService.mController = null;
-                    Watchdog.getInstance().setActivityController(null);
-                }
+            /**
+             * If crash is handled by instance of {@link android.app.IActivityController},
+             * finish now and don't show the app error dialog.
+             */
+            if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace,
+                    timeMillis)) {
+                return;
             }
 
-            final long origId = Binder.clearCallingIdentity();
-
-            // If this process is running instrumentation, finish it.
+            /**
+             * If this process was running instrumentation, finish now - it will be handled in
+             * {@link ActivityManagerService#handleAppDiedLocked}.
+             */
             if (r != null && r.instrumentationClass != null) {
-                Slog.w(TAG, "Error in app " + r.processName
-                        + " running instrumentation " + r.instrumentationClass + ":");
-                if (shortMsg != null) Slog.w(TAG, "  " + shortMsg);
-                if (longMsg != null) Slog.w(TAG, "  " + longMsg);
-                Bundle info = new Bundle();
-                info.putString("shortMsg", shortMsg);
-                info.putString("longMsg", longMsg);
-                mService.finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info);
-                Binder.restoreCallingIdentity(origId);
                 return;
             }
 
@@ -375,7 +355,6 @@
             // If we can't identify the process or it's already exceeded its crash quota,
             // quit right away without showing a crash dialog.
             if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) {
-                Binder.restoreCallingIdentity(origId);
                 return;
             }
 
@@ -385,97 +364,90 @@
             task = data.task;
             msg.obj = data;
             mService.mUiHandler.sendMessage(msg);
-
-            Binder.restoreCallingIdentity(origId);
         }
 
         int res = result.get();
 
         Intent appErrorIntent = null;
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
-            if (res == AppErrorDialog.TIMEOUT) {
-                res = AppErrorDialog.FORCE_QUIT;
-            }
-            if (res == AppErrorDialog.RESET) {
-                String[] packageList = r.getPackageList();
-                if (packageList != null) {
-                    PackageManager pm = mContext.getPackageManager();
-                    final Semaphore s = new Semaphore(0);
-                    for (int i = 0; i < packageList.length; i++) {
-                        if (i < packageList.length - 1) {
-                            pm.deleteApplicationCacheFiles(packageList[i], null);
-                        } else {
-                            pm.deleteApplicationCacheFiles(packageList[i],
-                                    new IPackageDataObserver.Stub() {
-                                        @Override
-                                        public void onRemoveCompleted(String packageName,
-                                                boolean succeeded) {
-                                            s.release();
-                                        }
-                                    });
+        MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res);
+        if (res == AppErrorDialog.TIMEOUT) {
+            res = AppErrorDialog.FORCE_QUIT;
+        }
+        if (res == AppErrorDialog.RESET) {
+            String[] packageList = r.getPackageList();
+            if (packageList != null) {
+                PackageManager pm = mContext.getPackageManager();
+                final Semaphore s = new Semaphore(0);
+                for (int i = 0; i < packageList.length; i++) {
+                    if (i < packageList.length - 1) {
+                        pm.deleteApplicationCacheFiles(packageList[i], null);
+                    } else {
+                        pm.deleteApplicationCacheFiles(packageList[i],
+                                new IPackageDataObserver.Stub() {
+                                    @Override
+                                    public void onRemoveCompleted(String packageName,
+                                                                  boolean succeeded) {
+                                        s.release();
+                                    }
+                                });
 
-                            // Wait until cache has been cleared before we restart.
-                            try {
-                                s.acquire();
-                            } catch (InterruptedException e) {
-                            }
-                        }
-                    }
-                }
-                // If there was nothing to reset, just restart;
-                res = AppErrorDialog.RESTART;
-            }
-            synchronized (mService) {
-                if (res == AppErrorDialog.MUTE) {
-                    stopReportingCrashesLocked(r);
-                }
-                if (res == AppErrorDialog.RESTART) {
-                    mService.removeProcessLocked(r, false, true, "crash");
-                    if (task != null) {
+                        // Wait until cache has been cleared before we restart.
                         try {
-                            mService.startActivityFromRecents(task.taskId,
-                                    ActivityOptions.makeBasic().toBundle());
-                        } catch (IllegalArgumentException e) {
-                            // Hmm, that didn't work, app might have crashed before creating a
-                            // recents entry. Let's see if we have a safe-to-restart intent.
-                            if (task.intent.getCategories().contains(
-                                    Intent.CATEGORY_LAUNCHER)) {
-                                mService.startActivityInPackage(task.mCallingUid,
-                                        task.mCallingPackage, task.intent,
-                                        null, null, null, 0, 0,
-                                        ActivityOptions.makeBasic().toBundle(),
-                                        task.userId, null, null);
-                            }
+                            s.acquire();
+                        } catch (InterruptedException e) {
                         }
                     }
                 }
-                if (res == AppErrorDialog.FORCE_QUIT) {
-                    long orig = Binder.clearCallingIdentity();
-                    try {
-                        // Kill it with fire!
-                        mService.mStackSupervisor.handleAppCrashLocked(r);
-                        if (!r.persistent) {
-                            mService.removeProcessLocked(r, false, false, "crash");
-                            mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
-                        }
-                    } finally {
-                        Binder.restoreCallingIdentity(orig);
-                    }
-                }
-                if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
-                    appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
-                }
-                if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {
-                    // XXX Can't keep track of crash time for isolated processes,
-                    // since they don't have a persistent identity.
-                    mProcessCrashTimes.put(r.info.processName, r.uid,
-                            SystemClock.uptimeMillis());
-                }
             }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
+            // If there was nothing to reset, just restart;
+            res = AppErrorDialog.RESTART;
+        }
+        synchronized (mService) {
+            if (res == AppErrorDialog.MUTE) {
+                stopReportingCrashesLocked(r);
+            }
+            if (res == AppErrorDialog.RESTART) {
+                mService.removeProcessLocked(r, false, true, "crash");
+                if (task != null) {
+                    try {
+                        mService.startActivityFromRecents(task.taskId,
+                                ActivityOptions.makeBasic().toBundle());
+                    } catch (IllegalArgumentException e) {
+                        // Hmm, that didn't work, app might have crashed before creating a
+                        // recents entry. Let's see if we have a safe-to-restart intent.
+                        if (task.intent.getCategories().contains(
+                                Intent.CATEGORY_LAUNCHER)) {
+                            mService.startActivityInPackage(task.mCallingUid,
+                                    task.mCallingPackage, task.intent,
+                                    null, null, null, 0, 0,
+                                    ActivityOptions.makeBasic().toBundle(),
+                                    task.userId, null, null);
+                        }
+                    }
+                }
+            }
+            if (res == AppErrorDialog.FORCE_QUIT) {
+                long orig = Binder.clearCallingIdentity();
+                try {
+                    // Kill it with fire!
+                    mService.mStackSupervisor.handleAppCrashLocked(r);
+                    if (!r.persistent) {
+                        mService.removeProcessLocked(r, false, false, "crash");
+                        mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+                    }
+                } finally {
+                    Binder.restoreCallingIdentity(orig);
+                }
+            }
+            if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) {
+                appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo);
+            }
+            if (r != null && !r.isolated && res != AppErrorDialog.RESTART) {
+                // XXX Can't keep track of crash time for isolated processes,
+                // since they don't have a persistent identity.
+                mProcessCrashTimes.put(r.info.processName, r.uid,
+                        SystemClock.uptimeMillis());
+            }
         }
 
         if (appErrorIntent != null) {
@@ -487,6 +459,47 @@
         }
     }
 
+    private boolean handleAppCrashInActivityController(ProcessRecord r,
+                                                       ApplicationErrorReport.CrashInfo crashInfo,
+                                                       String shortMsg, String longMsg,
+                                                       String stackTrace, long timeMillis) {
+        if (mService.mController == null) {
+            return false;
+        }
+
+        try {
+            String name = r != null ? r.processName : null;
+            int pid = r != null ? r.pid : Binder.getCallingPid();
+            int uid = r != null ? r.info.uid : Binder.getCallingUid();
+            if (!mService.mController.appCrashed(name, pid,
+                    shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) {
+                if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))
+                        && "Native crash".equals(crashInfo.exceptionClassName)) {
+                    Slog.w(TAG, "Skip killing native crashed app " + name
+                            + "(" + pid + ") during testing");
+                } else {
+                    Slog.w(TAG, "Force-killing crashed app " + name
+                            + " at watcher's request");
+                    if (r != null) {
+                        if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null))
+                        {
+                            r.kill("crash", true);
+                        }
+                    } else {
+                        // Huh.
+                        Process.killProcess(pid);
+                        ActivityManagerService.killProcessGroup(uid, pid);
+                    }
+                }
+                return true;
+            }
+        } catch (RemoteException e) {
+            mService.mController = null;
+            Watchdog.getInstance().setActivityController(null);
+        }
+        return false;
+    }
+
     private boolean makeAppCrashingLocked(ProcessRecord app,
             String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) {
         app.crashing = true;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c6786de..d34ec86 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -974,7 +974,7 @@
 
     @Override
     public void setBatteryState(final int status, final int health, final int plugType,
-                                final int level, final int temp, final int volt) {
+            final int level, final int temp, final int volt, final int chargeCount) {
         enforceCallingPermission();
 
         // BatteryService calls us here and we may update external state. It would be wrong
@@ -987,7 +987,8 @@
                     if (mStats.isOnBattery() == onBattery) {
                         // The battery state has not changed, so we don't need to sync external
                         // stats immediately.
-                        mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
+                        mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
+                                chargeCount);
                         return;
                     }
                 }
@@ -996,7 +997,8 @@
                 // immediately here, we may not collect the relevant data later.
                 updateExternalStatsSync("battery-state", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
                 synchronized (mStats) {
-                    mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
+                    mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
+                            chargeCount);
                 }
             }
         });
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 5ad988a..1f7d312 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -333,6 +333,7 @@
             out.attribute(null, "sourceUserId", String.valueOf(jobStatus.getSourceUserId()));
             out.attribute(null, "uid", Integer.toString(jobStatus.getUid()));
             out.attribute(null, "priority", String.valueOf(jobStatus.getPriority()));
+            out.attribute(null, "flags", String.valueOf(jobStatus.getFlags()));
         }
 
         private void writeBundleToXml(PersistableBundle extras, XmlSerializer out)
@@ -543,6 +544,10 @@
                 if (val != null) {
                     jobBuilder.setPriority(Integer.parseInt(val));
                 }
+                val = parser.getAttributeValue(null, "flags");
+                if (val != null) {
+                    jobBuilder.setFlags(Integer.parseInt(val));
+                }
                 val = parser.getAttributeValue(null, "sourceUserId");
                 sourceUserId = val == null ? -1 : Integer.parseInt(val);
             } catch (NumberFormatException e) {
diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
index 88cf322..f5aac08 100644
--- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java
@@ -16,6 +16,7 @@
 
 package com.android.server.job.controllers;
 
+import android.app.job.JobInfo;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -97,7 +98,9 @@
     }
 
     private boolean updateConstraintsSatisfied(JobStatus jobStatus) {
-        final NetworkInfo info = mConnManager.getActiveNetworkInfoForUid(jobStatus.getSourceUid());
+        final boolean ignoreBlocked = (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+        final NetworkInfo info = mConnManager.getActiveNetworkInfoForUid(jobStatus.getSourceUid(),
+                ignoreBlocked);
         final boolean connected = (info != null) && info.isConnected();
         final boolean unmetered = connected && !info.isMetered();
         final boolean notRoaming = connected && !info.isRoaming();
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 590d075..19bede9 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -297,6 +297,10 @@
         return job.getPriority();
     }
 
+    public int getFlags() {
+        return job.getFlags();
+    }
+
     public boolean hasConnectivityConstraint() {
         return (requiredConstraints&CONSTRAINT_CONNECTIVITY) != 0;
     }
@@ -416,12 +420,12 @@
         // satisfied).
         // AppNotIdle implicit constraint must be satisfied
         // DeviceNotDozing implicit constraint must be satisfied
-        return (isConstraintsSatisfied()
-                || (!job.isPeriodic()
-                && hasDeadlineConstraint() && (satisfiedConstraints&CONSTRAINT_DEADLINE) != 0)
-                )
-                && (satisfiedConstraints & CONSTRAINT_APP_NOT_IDLE) != 0
-                && (satisfiedConstraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0;
+        final boolean deadlineSatisfied = (!job.isPeriodic() && hasDeadlineConstraint()
+                && (satisfiedConstraints & CONSTRAINT_DEADLINE) != 0);
+        final boolean notIdle = (satisfiedConstraints & CONSTRAINT_APP_NOT_IDLE) != 0;
+        final boolean notDozing = (satisfiedConstraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0
+                || (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0;
+        return (isConstraintsSatisfied() || deadlineSatisfied) && notIdle && notDozing;
     }
 
     static final int CONSTRAINTS_OF_INTEREST =
@@ -561,6 +565,10 @@
             if (job.getPriority() != 0) {
                 pw.print(prefix); pw.print("  Priority: "); pw.println(job.getPriority());
             }
+            if (job.getFlags() != 0) {
+                pw.print(prefix); pw.print("  Flags: ");
+                pw.println(Integer.toHexString(job.getFlags()));
+            }
             pw.print(prefix); pw.print("  Requires: charging=");
             pw.print(job.isRequireCharging()); pw.print(" deviceIdle=");
             pw.println(job.isRequireDeviceIdle());
@@ -613,6 +621,9 @@
             pw.print(prefix); pw.print("Satisfied constraints:");
             dumpConstraints(pw, satisfiedConstraints);
             pw.println();
+            pw.print(prefix); pw.print("Unsatisfied constraints:");
+            dumpConstraints(pw, (requiredConstraints & ~satisfiedConstraints));
+            pw.println();
         }
         if (changedAuthorities != null) {
             pw.print(prefix); pw.println("Changed authorities:");
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 30aab8c..50d9368 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -48,7 +48,6 @@
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
 import static android.net.NetworkPolicyManager.POLICY_NONE;
 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
-import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
 import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
 import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED;
@@ -349,6 +348,9 @@
     /** Foreground at UID granularity. */
     final SparseIntArray mUidState = new SparseIntArray();
 
+    /** Higher priority listener before general event dispatch */
+    private INetworkPolicyListener mConnectivityListener;
+
     private final RemoteCallbackList<INetworkPolicyListener>
             mListeners = new RemoteCallbackList<>();
 
@@ -1391,6 +1393,7 @@
                 final String tag = in.getName();
                 if (type == START_TAG) {
                     if (TAG_POLICY_LIST.equals(tag)) {
+                        final boolean oldValue = mRestrictBackground;
                         version = readIntAttribute(in, ATTR_VERSION);
                         if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) {
                             mRestrictBackground = readBooleanAttribute(
@@ -1398,6 +1401,12 @@
                         } else {
                             mRestrictBackground = false;
                         }
+                        if (mRestrictBackground != oldValue) {
+                            // Some early services may have read the default value,
+                            // so notify them that it's changed
+                            mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED,
+                                    mRestrictBackground ? 1 : 0, 0).sendToTarget();
+                        }
 
                     } else if (TAG_NETWORK_POLICY.equals(tag)) {
                         final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
@@ -1766,20 +1775,25 @@
     }
 
     @Override
+    public void setConnectivityListener(INetworkPolicyListener listener) {
+        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
+        if (mConnectivityListener != null) {
+            throw new IllegalStateException("Connectivity listener already registered");
+        }
+        mConnectivityListener = listener;
+    }
+
+    @Override
     public void registerListener(INetworkPolicyListener listener) {
         // TODO: create permission for observing network policy
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
         mListeners.register(listener);
-
-        // TODO: consider dispatching existing rules to new listeners
     }
 
     @Override
     public void unregisterListener(INetworkPolicyListener listener) {
         // TODO: create permission for observing network policy
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
         mListeners.unregister(listener);
     }
 
@@ -2754,8 +2768,8 @@
         final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
         final boolean isWhitelisted = mRestrictBackgroundWhitelistUids.get(uid);
 
-        int newRule = RULE_ALLOW_ALL;
-        final int oldRule = mUidRules.get(uid);
+        int newRule = RULE_UNKNOWN;
+        final int oldRule = mUidRules.get(uid, RULE_UNKNOWN);
 
         // First step: define the new rule based on user restrictions and foreground state.
         if (isForeground) {
@@ -2777,8 +2791,7 @@
                     + ", oldRule: " + ruleToString(oldRule));
         }
 
-
-        if (newRule == RULE_ALLOW_ALL) {
+        if (newRule == RULE_UNKNOWN) {
             mUidRules.delete(uid);
         } else {
             mUidRules.put(uid, newRule);
@@ -2858,6 +2871,45 @@
         }
     }
 
+    private void dispatchUidRulesChanged(INetworkPolicyListener listener, int uid, int uidRules) {
+        if (listener != null) {
+            try {
+                listener.onUidRulesChanged(uid, uidRules);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    private void dispatchMeteredIfacesChanged(INetworkPolicyListener listener,
+            String[] meteredIfaces) {
+        if (listener != null) {
+            try {
+                listener.onMeteredIfacesChanged(meteredIfaces);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    private void dispatchRestrictBackgroundChanged(INetworkPolicyListener listener,
+            boolean restrictBackground) {
+        if (listener != null) {
+            try {
+                listener.onRestrictBackgroundChanged(restrictBackground);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    private void dispatchRestrictBackgroundWhitelistChanged(INetworkPolicyListener listener,
+            int uid, boolean whitelisted) {
+        if (listener != null) {
+            try {
+                listener.onRestrictBackgroundWhitelistChanged(uid, whitelisted);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
     private Handler.Callback mHandlerCallback = new Handler.Callback() {
         @Override
         public boolean handleMessage(Message msg) {
@@ -2865,30 +2917,22 @@
                 case MSG_RULES_CHANGED: {
                     final int uid = msg.arg1;
                     final int uidRules = msg.arg2;
+                    dispatchUidRulesChanged(mConnectivityListener, uid, uidRules);
                     final int length = mListeners.beginBroadcast();
                     for (int i = 0; i < length; i++) {
                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
-                        if (listener != null) {
-                            try {
-                                listener.onUidRulesChanged(uid, uidRules);
-                            } catch (RemoteException e) {
-                            }
-                        }
+                        dispatchUidRulesChanged(listener, uid, uidRules);
                     }
                     mListeners.finishBroadcast();
                     return true;
                 }
                 case MSG_METERED_IFACES_CHANGED: {
                     final String[] meteredIfaces = (String[]) msg.obj;
+                    dispatchMeteredIfacesChanged(mConnectivityListener, meteredIfaces);
                     final int length = mListeners.beginBroadcast();
                     for (int i = 0; i < length; i++) {
                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
-                        if (listener != null) {
-                            try {
-                                listener.onMeteredIfacesChanged(meteredIfaces);
-                            } catch (RemoteException e) {
-                            }
-                        }
+                        dispatchMeteredIfacesChanged(listener, meteredIfaces);
                     }
                     mListeners.finishBroadcast();
                     return true;
@@ -2915,15 +2959,11 @@
                 }
                 case MSG_RESTRICT_BACKGROUND_CHANGED: {
                     final boolean restrictBackground = msg.arg1 != 0;
+                    dispatchRestrictBackgroundChanged(mConnectivityListener, restrictBackground);
                     final int length = mListeners.beginBroadcast();
                     for (int i = 0; i < length; i++) {
                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
-                        if (listener != null) {
-                            try {
-                                listener.onRestrictBackgroundChanged(restrictBackground);
-                            } catch (RemoteException e) {
-                            }
-                        }
+                        dispatchRestrictBackgroundChanged(listener, restrictBackground);
                     }
                     mListeners.finishBroadcast();
                     final Intent intent =
@@ -2947,18 +2987,16 @@
                     final boolean changed = msg.arg2 == 1;
                     final Boolean whitelisted = (Boolean) msg.obj;
 
+                    // First notify internal listeners...
                     if (whitelisted != null) {
+                        final boolean whitelistedBool = whitelisted.booleanValue();
+                        dispatchRestrictBackgroundWhitelistChanged(mConnectivityListener, uid,
+                                whitelistedBool);
                         final int length = mListeners.beginBroadcast();
                         for (int i = 0; i < length; i++) {
-                            // First notify internal listeners...
                             final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
-                            if (listener != null) {
-                                try {
-                                    listener.onRestrictBackgroundWhitelistChanged(uid,
-                                            whitelisted.booleanValue());
-                                } catch (RemoteException e) {
-                                }
-                            }
+                            dispatchRestrictBackgroundWhitelistChanged(listener, uid,
+                                    whitelistedBool);
                         }
                         mListeners.finishBroadcast();
                     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ba651fc..64581e8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -437,6 +437,8 @@
      */
     private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW;
 
+    static final String PLATFORM_PACKAGE_NAME = "android";
+
     static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer";
 
     static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName(
@@ -9725,7 +9727,9 @@
                 switch (grant) {
                     case GRANT_INSTALL: {
                         // Revoke this as runtime permission to handle the case of
-                        // a runtime permission being downgraded to an install one. Also in permission review mode we keep dangerous permissions for legacy apps
+                        // a runtime permission being downgraded to an install one.
+                        // Also in permission review mode we keep dangerous permissions
+                        // for legacy apps
                         for (int userId : UserManagerService.getInstance().getUserIds()) {
                             if (origPermissions.getRuntimePermissionState(
                                     bp.name, userId) != null) {
@@ -9773,10 +9777,21 @@
                                     && !appSupportsRuntimePermissions) {
                                 // For legacy apps that need a permission review, every new
                                 // runtime permission is granted but it is pending a review.
-                                if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
-                                    permissionsState.grantRuntimePermission(bp, userId);
-                                    flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
-                                    // We changed the permission and flags, hence have to write.
+                                // We also need to review only platform defined runtime
+                                // permissions as these are the only ones the platform knows
+                                // how to disable the API to simulate revocation as legacy
+                                // apps don't expect to run with revoked permissions.
+                                if (PLATFORM_PACKAGE_NAME.equals(bp.sourcePackage)) {
+                                    if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
+                                        flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
+                                        // We changed the flags, hence have to write.
+                                        changedRuntimePermissionUserIds = ArrayUtils.appendInt(
+                                                changedRuntimePermissionUserIds, userId);
+                                    }
+                                }
+                                if (permissionsState.grantRuntimePermission(bp, userId)
+                                        != PermissionsState.PERMISSION_OPERATION_FAILURE) {
+                                    // We changed the permission, hence have to write.
                                     changedRuntimePermissionUserIds = ArrayUtils.appendInt(
                                             changedRuntimePermissionUserIds, userId);
                                 }
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 1493bc7..e319407 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1441,6 +1441,18 @@
             return;
         }
 
+        // Do not change surface properties of opening apps if we are waiting for the
+        // transition to be ready. transitionGoodToGo could be not ready even after all
+        // opening apps are drawn. It's only waiting on isFetchingAppTransitionsSpecs()
+        // to get the animation spec. (For example, go into Recents and immediately open
+        // the same app again before the app's surface is destroyed or saved, the surface
+        // is always ready in the whole process.) If we go ahead here, the opening app
+        // will be shown with the full size before the correct animation spec arrives.
+        if (mService.mAppTransition.isReady() && isDummyAnimation() &&
+                mService.mOpeningApps.contains(w.mAppToken)) {
+            return;
+        }
+
         boolean displayed = false;
 
         computeShownFrameLocked();
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index b9e9ac8..3785cdc 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -383,6 +383,15 @@
         </activity>
 
         <activity
+                android:name="VideoViewCaptureActivity"
+                android:label="SurfaceView/GetBitmap with Video source">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.test.hwui.TEST" />
+            </intent-filter>
+        </activity>
+
+        <activity
                 android:name="GLTextureViewActivity"
                 android:label="TextureView/OpenGL">
             <intent-filter>
diff --git a/tests/HwAccelerationTest/res/raw/colorgrid_video.mp4 b/tests/HwAccelerationTest/res/raw/colorgrid_video.mp4
new file mode 100644
index 0000000..1be8bee
--- /dev/null
+++ b/tests/HwAccelerationTest/res/raw/colorgrid_video.mp4
Binary files differ
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java
index f658b7c..6fe2cb4 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java
@@ -23,6 +23,7 @@
 import android.os.Environment;
 import android.view.Gravity;
 import android.view.PixelCopy;
+import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 import android.view.View;
@@ -87,9 +88,42 @@
             android.util.Log.e("TextureView", "Cannot set preview texture target!", t);
         }
 
+        setCameraDisplayOrientation(this, 0, mCamera);
         mCamera.startPreview();
     }
 
+    public static void setCameraDisplayOrientation(Activity activity,
+            int cameraId, android.hardware.Camera camera) {
+        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
+        android.hardware.Camera.getCameraInfo(cameraId, info);
+        int rotation = activity.getWindowManager().getDefaultDisplay()
+                .getRotation();
+        int degrees = 0;
+        switch (rotation) {
+            case Surface.ROTATION_0:
+                degrees = 0;
+                break;
+            case Surface.ROTATION_90:
+                degrees = 90;
+                break;
+            case Surface.ROTATION_180:
+                degrees = 180;
+                break;
+            case Surface.ROTATION_270:
+                degrees = 270;
+                break;
+        }
+
+        int result;
+        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+            result = (info.orientation + degrees) % 360;
+            result = (360 - result) % 360; // compensate the mirror
+        } else { // back-facing
+            result = (info.orientation - degrees + 360) % 360;
+        }
+        camera.setDisplayOrientation(result);
+    }
+
     @Override
     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
     }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java
new file mode 100644
index 0000000..b87be80
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 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 com.android.test.hwui;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.view.PixelCopy;
+import android.view.View;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.Toast;
+import android.widget.VideoView;
+
+import java.io.FileOutputStream;
+
+public class VideoViewCaptureActivity extends Activity {
+    private VideoView mVideoView;
+    private int mVideoWidth, mVideoHeight;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mVideoView = new VideoView(this);
+        mVideoView.setOnPreparedListener(mp -> {
+            mp.setLooping(true);
+            mVideoWidth = mp.getVideoWidth();
+            mVideoHeight = mp.getVideoHeight();
+            mVideoView.start();
+        });
+
+        Uri uri = Uri.parse("android.resource://com.android.test.hwui/" + R.raw.colorgrid_video);
+        mVideoView.setVideoURI(uri);
+
+        Button button = new Button(this);
+        button.setText("Copy bitmap to /sdcard/surfaceview.png");
+        button.setOnClickListener((View v) -> {
+            final Bitmap b = Bitmap.createBitmap(
+                    mVideoWidth, mVideoHeight,
+                    Bitmap.Config.ARGB_8888);
+            PixelCopy.request(mVideoView, b,
+                    (int result) -> {
+                        if (result != PixelCopy.SUCCESS) {
+                            Toast.makeText(VideoViewCaptureActivity.this,
+                                    "Failed to copy", Toast.LENGTH_SHORT).show();
+                            return;
+                        }
+                        try {
+                            try (FileOutputStream out = new FileOutputStream(
+                                    Environment.getExternalStorageDirectory() + "/surfaceview.png");) {
+                                b.compress(Bitmap.CompressFormat.PNG, 100, out);
+                            }
+                        } catch (Exception e) {
+                            // Ignore
+                        }
+                    }, mVideoView.getHandler());
+        });
+
+        FrameLayout content = new FrameLayout(this);
+        LinearLayout layout = new LinearLayout(this);
+        layout.setOrientation(LinearLayout.VERTICAL);
+        layout.addView(button, LinearLayout.LayoutParams.MATCH_PARENT,
+                LinearLayout.LayoutParams.WRAP_CONTENT);
+        layout.addView(mVideoView, LinearLayout.LayoutParams.MATCH_PARENT,
+                LinearLayout.LayoutParams.MATCH_PARENT);
+
+        content.addView(layout, new FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.MATCH_PARENT,
+                FrameLayout.LayoutParams.MATCH_PARENT));
+        setContentView(content);
+    }
+}
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index 81ab3cc..fe7c3b9 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -330,7 +330,7 @@
         0x2764, # HEAVY BLACK HEART
     }
     assert missing_text_chars == set(), (
-        'Text style version of some emoji characters are missing.')
+        'Text style version of some emoji characters are missing: ' + repr(missing_text_chars))
 
 
 # Setting reverse to true returns a dictionary that maps the values to sets of
@@ -411,6 +411,20 @@
     _emoji_zwj_sequences = parse_unicode_datafile(
         path.join(ucd_path, 'emoji-zwj-sequences.txt'))
 
+    # filter modern pentathlon, as it seems likely to be removed from final spec
+    def is_excluded(n):
+        return n == 0x1f93b
+
+    def contains_excluded(t):
+        if type(t) == int:
+            return is_excluded(t)
+        return any(is_excluded(cp) for cp in t)
+
+    # filter modern pentathlon, as it seems likely to be removed from final spec
+    _emoji_properties['Emoji'] = set(
+        t for t in _emoji_properties['Emoji'] if not contains_excluded(t))
+    _emoji_sequences = dict(
+        (t, v) for (t, v) in _emoji_sequences.items() if not contains_excluded(t))
 
 def flag_sequence(territory_code):
     return tuple(0x1F1E6 + ord(ch) - ord('A') for ch in territory_code)
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index 663e1e2..f87f6c5 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -16,8 +16,6 @@
 LOCAL_PATH := $(my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
-
 #
 # Define rules to build temp_layoutlib.jar, which contains a subset of
 # the classes in framework.jar.  The layoutlib_create tool is used to
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index 16e5913..3dd8002 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -18,7 +18,6 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 LOCAL_JAVA_RESOURCE_DIRS := resources
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
 
 LOCAL_JAVA_LIBRARIES := \
 	layoutlib_api-prebuilt \
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 80e230c..f87269b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -861,7 +861,9 @@
                         resValue = mRenderResources.resolveResValue(resValue);
 
                         if (defaultPropMap != null) {
-                            defaultPropMap.put(attrName,
+                            defaultPropMap.put(
+                                    frameworkAttr ? SdkConstants.PREFIX_ANDROID + attrName :
+                                            attrName,
                                     new Property(preResolve, resValue.getValue()));
                         }
 
@@ -932,7 +934,8 @@
             @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException {
         List<Pair<String, Boolean>> attributes = searchAttrs(attrs);
 
-        BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
+        BridgeTypedArray ta =
+                Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false);
 
         PropertiesMap defaultPropMap = new PropertiesMap();
         // for each attribute, get its name so that we can search it in the style
@@ -943,11 +946,11 @@
                 // look for the value in the given style
                 ResourceValue resValue;
                 String attrName = attribute.getFirst();
+                boolean frameworkAttr = attribute.getSecond();
                 if (style != null) {
-                    resValue = mRenderResources.findItemInStyle(style, attrName,
-                            attribute.getSecond());
+                    resValue = mRenderResources.findItemInStyle(style, attrName, frameworkAttr);
                 } else {
-                    resValue = mRenderResources.findItemInTheme(attrName, attribute.getSecond());
+                    resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr);
                 }
 
                 if (resValue != null) {
@@ -955,8 +958,10 @@
                     String preResolve = resValue.getValue();
                     // resolve it to make sure there are no references left.
                     resValue = mRenderResources.resolveResValue(resValue);
-                    ta.bridgeSetValue(i, attrName, attribute.getSecond(), resValue);
-                    defaultPropMap.put(attrName, new Property(preResolve, resValue.getValue()));
+                    ta.bridgeSetValue(i, attrName, frameworkAttr, resValue);
+                    defaultPropMap.put(
+                            frameworkAttr ? SdkConstants.ANDROID_PREFIX + attrName : attrName,
+                            new Property(preResolve, resValue.getValue()));
                 }
             }
         }
diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk
index 5c062d0..8a81d0b 100644
--- a/tools/layoutlib/bridge/tests/Android.mk
+++ b/tools/layoutlib/bridge/tests/Android.mk
@@ -16,8 +16,6 @@
 
 include $(CLEAR_VARS)
 
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
-
 # Only compile source java files in this lib.
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_JAVA_RESOURCE_DIRS := res
diff --git a/tools/layoutlib/create/Android.mk b/tools/layoutlib/create/Android.mk
index 47377ae..c7f2c41 100644
--- a/tools/layoutlib/create/Android.mk
+++ b/tools/layoutlib/create/Android.mk
@@ -16,8 +16,6 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
-
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 
 LOCAL_JAR_MANIFEST := manifest.txt
diff --git a/tools/layoutlib/create/tests/Android.mk b/tools/layoutlib/create/tests/Android.mk
index c59528e..dafb9c6 100644
--- a/tools/layoutlib/create/tests/Android.mk
+++ b/tools/layoutlib/create/tests/Android.mk
@@ -15,8 +15,6 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
-
 # Only compile source java files in this lib.
 LOCAL_SRC_FILES := $(call all-java-files-under, com)