Merge "Fix Fragment.onCreate() not being called in some cases."
diff --git a/api/current.txt b/api/current.txt
index b1d9391..65935ae 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15851,9 +15851,12 @@
     field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5
     field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
     field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7
+    field public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; // 0x9
     field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
     field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
     field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
+    field public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6; // 0x6
+    field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8
   }
 
   public static abstract class FingerprintManager.AuthenticationCallback {
diff --git a/api/system-current.txt b/api/system-current.txt
index e34afc5..9e4bad8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -16663,9 +16663,12 @@
     field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5
     field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
     field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7
+    field public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; // 0x9
     field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
     field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
     field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
+    field public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6; // 0x6
+    field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8
   }
 
   public static abstract class FingerprintManager.AuthenticationCallback {
@@ -34501,6 +34504,7 @@
     method public void resetStatus();
     method public void resume();
     method public void suspend();
+    method public boolean unbind();
   }
 
   public static final class UpdateEngine.ErrorCodeConstants {
diff --git a/api/test-current.txt b/api/test-current.txt
index da4f6786..f089362 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -15904,9 +15904,12 @@
     field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5
     field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1
     field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7
+    field public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9; // 0x9
     field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4
     field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3
     field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2
+    field public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6; // 0x6
+    field public static final int FINGERPRINT_ERROR_VENDOR = 8; // 0x8
   }
 
   public static abstract class FingerprintManager.AuthenticationCallback {
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 1758a06..6ea0825 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -23,16 +23,19 @@
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.StructStat;
+import android.system.StructTimespec;
 import android.util.Log;
 
-import com.google.android.collect.Maps;
-
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ExponentiallyBucketedHistogram;
 import com.android.internal.util.XmlUtils;
 
 import dalvik.system.BlockGuard;
 
+import libcore.io.IoUtils;
+
+import com.google.android.collect.Maps;
+
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.BufferedInputStream;
@@ -50,8 +53,6 @@
 import java.util.WeakHashMap;
 import java.util.concurrent.CountDownLatch;
 
-import libcore.io.IoUtils;
-
 final class SharedPreferencesImpl implements SharedPreferences {
     private static final String TAG = "SharedPreferencesImpl";
     private static final boolean DEBUG = false;
@@ -80,7 +81,7 @@
     private boolean mLoaded = false;
 
     @GuardedBy("mLock")
-    private long mStatTimestamp;
+    private StructTimespec mStatTimestamp;
 
     @GuardedBy("mLock")
     private long mStatSize;
@@ -162,7 +163,7 @@
             mLoaded = true;
             if (map != null) {
                 mMap = map;
-                mStatTimestamp = stat.st_mtime;
+                mStatTimestamp = stat.st_mtim;
                 mStatSize = stat.st_size;
             } else {
                 mMap = new HashMap<>();
@@ -209,7 +210,7 @@
         }
 
         synchronized (mLock) {
-            return mStatTimestamp != stat.st_mtime || mStatSize != stat.st_size;
+            return !stat.st_mtim.equals(mStatTimestamp) || mStatSize != stat.st_size;
         }
     }
 
@@ -744,7 +745,7 @@
             try {
                 final StructStat stat = Os.stat(mFile.getPath());
                 synchronized (mLock) {
-                    mStatTimestamp = stat.st_mtime;
+                    mStatTimestamp = stat.st_mtim;
                     mStatSize = stat.st_size;
                 }
             } catch (ErrnoException e) {
diff --git a/core/java/android/database/sqlite/SQLiteConnectionPool.java b/core/java/android/database/sqlite/SQLiteConnectionPool.java
index cba7303..765f27e 100644
--- a/core/java/android/database/sqlite/SQLiteConnectionPool.java
+++ b/core/java/android/database/sqlite/SQLiteConnectionPool.java
@@ -19,12 +19,19 @@
 import android.app.ActivityManager;
 import android.database.sqlite.SQLiteDebug.DbStats;
 import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
 import android.os.OperationCanceledException;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.util.Log;
 import android.util.PrefixPrinter;
 import android.util.Printer;
 
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
 import dalvik.system.CloseGuard;
 
 import java.io.Closeable;
@@ -77,6 +84,15 @@
     // and logging a message about the connection pool being busy.
     private static final long CONNECTION_POOL_BUSY_MILLIS = 30 * 1000; // 30 seconds
 
+    // TODO b/63398887 Move to SQLiteGlobal
+    private static final long IDLE_CONNECTION_CLOSE_DELAY_MILLIS = SystemProperties
+            .getInt("persist.debug.sqlite.idle_connection_close_delay", 30000);
+
+    // TODO b/63398887 STOPSHIP.
+    // Temporarily enabled for testing across a broader set of dogfood devices.
+    private static final boolean CLOSE_IDLE_CONNECTIONS = SystemProperties
+            .getBoolean("persist.debug.sqlite.close_idle_connections", true);
+
     private final CloseGuard mCloseGuard = CloseGuard.get();
 
     private final Object mLock = new Object();
@@ -94,6 +110,9 @@
             new ArrayList<SQLiteConnection>();
     private SQLiteConnection mAvailablePrimaryConnection;
 
+    @GuardedBy("mLock")
+    private IdleConnectionHandler mIdleConnectionHandler;
+
     // Describes what should happen to an acquired connection when it is returned to the pool.
     enum AcquiredConnectionStatus {
         // The connection should be returned to the pool as usual.
@@ -154,6 +173,11 @@
             mConfiguration.lookasideSlotSize = 0;
         }
         setMaxConnectionPoolSizeLocked();
+
+        // Do not close idle connections for in-memory databases
+        if (CLOSE_IDLE_CONNECTIONS && !configuration.isInMemoryDb()) {
+            setupIdleConnectionHandler(Looper.getMainLooper(), IDLE_CONNECTION_CLOSE_DELAY_MILLIS);
+        }
     }
 
     @Override
@@ -351,7 +375,13 @@
      */
     public SQLiteConnection acquireConnection(String sql, int connectionFlags,
             CancellationSignal cancellationSignal) {
-        return waitForConnection(sql, connectionFlags, cancellationSignal);
+        SQLiteConnection con = waitForConnection(sql, connectionFlags, cancellationSignal);
+        synchronized (mLock) {
+            if (mIdleConnectionHandler != null) {
+                mIdleConnectionHandler.connectionAcquired(con);
+            }
+        }
+        return con;
     }
 
     /**
@@ -368,6 +398,9 @@
      */
     public void releaseConnection(SQLiteConnection connection) {
         synchronized (mLock) {
+            if (mIdleConnectionHandler != null) {
+                mIdleConnectionHandler.connectionReleased(connection);
+            }
             AcquiredConnectionStatus status = mAcquiredConnections.remove(connection);
             if (status == null) {
                 throw new IllegalStateException("Cannot perform this operation "
@@ -510,6 +543,27 @@
     }
 
     // Can't throw.
+    private boolean closeAvailableConnectionLocked(int connectionId) {
+        final int count = mAvailableNonPrimaryConnections.size();
+        for (int i = count - 1; i >= 0; i--) {
+            SQLiteConnection c = mAvailableNonPrimaryConnections.get(i);
+            if (c.getConnectionId() == connectionId) {
+                closeConnectionAndLogExceptionsLocked(c);
+                mAvailableNonPrimaryConnections.remove(i);
+                return true;
+            }
+        }
+
+        if (mAvailablePrimaryConnection != null
+                && mAvailablePrimaryConnection.getConnectionId() == connectionId) {
+            closeConnectionAndLogExceptionsLocked(mAvailablePrimaryConnection);
+            mAvailablePrimaryConnection = null;
+            return true;
+        }
+        return false;
+    }
+
+    // Can't throw.
     private void closeAvailableNonPrimaryConnectionsAndLogExceptionsLocked() {
         final int count = mAvailableNonPrimaryConnections.size();
         for (int i = 0; i < count; i++) {
@@ -532,6 +586,9 @@
     private void closeConnectionAndLogExceptionsLocked(SQLiteConnection connection) {
         try {
             connection.close(); // might throw
+            if (mIdleConnectionHandler != null) {
+                mIdleConnectionHandler.connectionClosed(connection);
+            }
         } catch (RuntimeException ex) {
             Log.e(TAG, "Failed to close connection, its fate is now in the hands "
                     + "of the merciful GC: " + connection, ex);
@@ -963,6 +1020,22 @@
         }
     }
 
+    /**
+     * Set up the handler based on the provided looper and delay.
+     */
+    @VisibleForTesting
+    public void setupIdleConnectionHandler(Looper looper, long delayMs) {
+        synchronized (mLock) {
+            mIdleConnectionHandler = new IdleConnectionHandler(looper, delayMs);
+        }
+    }
+
+    void disableIdleConnectionHandler() {
+        synchronized (mLock) {
+            mIdleConnectionHandler = null;
+        }
+    }
+
     private void throwIfClosedLocked() {
         if (!mIsOpen) {
             throw new IllegalStateException("Cannot perform this operation "
@@ -1078,4 +1151,42 @@
         public RuntimeException mException;
         public int mNonce;
     }
+
+    private class IdleConnectionHandler extends Handler {
+        private final long mDelay;
+
+        IdleConnectionHandler(Looper looper, long delay) {
+            super(looper);
+            mDelay = delay;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            // Skip the (obsolete) message if the handler has changed
+            synchronized (mLock) {
+                if (this != mIdleConnectionHandler) {
+                    return;
+                }
+                if (closeAvailableConnectionLocked(msg.what)) {
+                    if (Log.isLoggable(TAG, Log.DEBUG)) {
+                        Log.d(TAG, "Closed idle connection " + mConfiguration.label + " " + msg.what
+                                + " after " + mDelay);
+                    }
+                }
+            }
+        }
+
+        void connectionReleased(SQLiteConnection con) {
+            sendEmptyMessageDelayed(con.getConnectionId(), mDelay);
+        }
+
+        void connectionAcquired(SQLiteConnection con) {
+            // Remove any pending close operations
+            removeMessages(con.getConnectionId());
+        }
+
+        void connectionClosed(SQLiteConnection con) {
+            removeMessages(con.getConnectionId());
+        }
+    }
 }
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index ea2b89e..af6df155 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -1713,6 +1713,7 @@
                     if (!mHasAttachedDbsLocked) {
                         mHasAttachedDbsLocked = true;
                         disableWal = true;
+                        mConnectionPoolLocked.disableIdleConnectionHandler();
                     }
                 }
                 if (disableWal) {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index b51a791..5030865 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -99,8 +99,6 @@
     /**
      * The {@link FingerprintManager#remove} call failed. Typically this will happen when the
      * provided fingerprint id was incorrect.
-     *
-     * @hide
      */
     public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6;
 
@@ -112,7 +110,6 @@
     /**
      * Hardware vendors may extend this list if there are conditions that do not fall under one of
      * the above categories. Vendors are responsible for providing error strings for these errors.
-     * @hide
      */
     public static final int FINGERPRINT_ERROR_VENDOR = 8;
 
@@ -120,7 +117,6 @@
      * The operation was canceled because FINGERPRINT_ERROR_LOCKOUT occurred too many times.
      * Fingerprint authentication is disabled until the user unlocks with strong authentication
      * (PIN/Pattern/Password)
-     * @hide
      */
     public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9;
 
diff --git a/core/java/android/os/UpdateEngine.java b/core/java/android/os/UpdateEngine.java
index 8549cff..ee0b623 100644
--- a/core/java/android/os/UpdateEngine.java
+++ b/core/java/android/os/UpdateEngine.java
@@ -21,8 +21,6 @@
 import android.os.IUpdateEngineCallback;
 import android.os.RemoteException;
 
-import android.util.Log;
-
 /**
  * UpdateEngine handles calls to the update engine which takes care of A/B OTA
  * updates. It wraps up the update engine Binder APIs and exposes them as
@@ -90,6 +88,8 @@
     }
 
     private IUpdateEngine mUpdateEngine;
+    private IUpdateEngineCallback mUpdateEngineCallback = null;
+    private final Object mUpdateEngineCallbackLock = new Object();
 
     /**
      * Creates a new instance.
@@ -107,40 +107,42 @@
      */
     @SystemApi
     public boolean bind(final UpdateEngineCallback callback, final Handler handler) {
-        IUpdateEngineCallback updateEngineCallback = new IUpdateEngineCallback.Stub() {
-            @Override
-            public void onStatusUpdate(final int status, final float percent) {
-                if (handler != null) {
-                    handler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            callback.onStatusUpdate(status, percent);
-                        }
-                    });
-                } else {
-                    callback.onStatusUpdate(status, percent);
+        synchronized (mUpdateEngineCallbackLock) {
+            mUpdateEngineCallback = new IUpdateEngineCallback.Stub() {
+                @Override
+                public void onStatusUpdate(final int status, final float percent) {
+                    if (handler != null) {
+                        handler.post(new Runnable() {
+                            @Override
+                            public void run() {
+                                callback.onStatusUpdate(status, percent);
+                            }
+                        });
+                    } else {
+                        callback.onStatusUpdate(status, percent);
+                    }
                 }
-            }
 
-            @Override
-            public void onPayloadApplicationComplete(final int errorCode) {
-                if (handler != null) {
-                    handler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            callback.onPayloadApplicationComplete(errorCode);
-                        }
-                    });
-                } else {
-                    callback.onPayloadApplicationComplete(errorCode);
+                @Override
+                public void onPayloadApplicationComplete(final int errorCode) {
+                    if (handler != null) {
+                        handler.post(new Runnable() {
+                            @Override
+                            public void run() {
+                                callback.onPayloadApplicationComplete(errorCode);
+                            }
+                        });
+                    } else {
+                        callback.onPayloadApplicationComplete(errorCode);
+                    }
                 }
-            }
-        };
+            };
 
-        try {
-            return mUpdateEngine.bind(updateEngineCallback);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+            try {
+                return mUpdateEngine.bind(mUpdateEngineCallback);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
         }
     }
 
@@ -249,4 +251,23 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Unbinds the last bound callback function.
+     */
+    @SystemApi
+    public boolean unbind() {
+        synchronized (mUpdateEngineCallbackLock) {
+            if (mUpdateEngineCallback == null) {
+                return true;
+            }
+            try {
+                boolean result = mUpdateEngine.unbind(mUpdateEngineCallback);
+                mUpdateEngineCallback = null;
+                return result;
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
 }
diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java
index 2648604..68cf5cd 100644
--- a/core/java/com/android/internal/colorextraction/ColorExtractor.java
+++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java
@@ -97,14 +97,14 @@
     }
 
     /**
-     * Retrieve TYPE_NORMAL gradient colors considering wallpaper visibility.
+     * Retrieve gradient colors for a specific wallpaper.
      *
      * @param which FLAG_LOCK or FLAG_SYSTEM
      * @return colors
      */
     @NonNull
     public GradientColors getColors(int which) {
-        return getColors(which, TYPE_NORMAL);
+        return getColors(which, TYPE_DARK);
     }
 
     /**
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index c7f619d..398fb25 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -119,7 +119,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 161 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 162 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS;
@@ -10267,12 +10267,6 @@
         // If no app is holding a wakelock, then the distribution is normal.
         final int wakelockWeight = 50;
 
-        // Read the time spent for each cluster at various cpu frequencies.
-        final long[][] clusterSpeeds = new long[mKernelCpuSpeedReaders.length][];
-        for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
-            clusterSpeeds[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
-        }
-
         int numWakelocks = 0;
 
         // Calculate how many wakelocks we have to distribute amongst. The system is excluded.
@@ -10296,6 +10290,8 @@
         mTempTotalCpuUserTimeUs = 0;
         mTempTotalCpuSystemTimeUs = 0;
 
+        final SparseLongArray updatedUids = new SparseLongArray();
+
         // Read the CPU data for each UID. This will internally generate a snapshot so next time
         // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
         // we just ignore the data.
@@ -10353,32 +10349,7 @@
 
                         u.mUserCpuTime.addCountLocked(userTimeUs);
                         u.mSystemCpuTime.addCountLocked(systemTimeUs);
-
-                        // Add the cpu speeds to this UID. These are used as a ratio
-                        // for computing the power this UID used.
-                        final int numClusters = mPowerProfile.getNumCpuClusters();
-                        if (u.mCpuClusterSpeed == null || u.mCpuClusterSpeed.length !=
-                                numClusters) {
-                            u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
-                        }
-
-                        for (int cluster = 0; cluster < clusterSpeeds.length; cluster++) {
-                            final int speedsInCluster = mPowerProfile.getNumSpeedStepsInCpuCluster(
-                                    cluster);
-                            if (u.mCpuClusterSpeed[cluster] == null || speedsInCluster !=
-                                    u.mCpuClusterSpeed[cluster].length) {
-                                u.mCpuClusterSpeed[cluster] =
-                                        new LongSamplingCounter[speedsInCluster];
-                            }
-
-                            final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeed[cluster];
-                            for (int speed = 0; speed < clusterSpeeds[cluster].length; speed++) {
-                                if (cpuSpeeds[speed] == null) {
-                                    cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
-                                }
-                                cpuSpeeds[speed].addCountLocked(clusterSpeeds[cluster][speed]);
-                            }
-                        }
+                        updatedUids.put(u.getUid(), userTimeUs + systemTimeUs);
                     }
                 });
 
@@ -10418,6 +10389,8 @@
 
                     timer.mUid.mUserCpuTime.addCountLocked(userTimeUs);
                     timer.mUid.mSystemCpuTime.addCountLocked(systemTimeUs);
+                    final int uid = timer.mUid.getUid();
+                    updatedUids.put(uid, updatedUids.get(uid, 0) + userTimeUs + systemTimeUs);
 
                     final Uid.Proc proc = timer.mUid.getProcessStatsLocked("*wakelock*");
                     proc.addCpuTimeLocked(userTimeUs / 1000, systemTimeUs / 1000);
@@ -10442,6 +10415,8 @@
                 final Uid u = getUidStatsLocked(Process.SYSTEM_UID);
                 u.mUserCpuTime.addCountLocked(mTempTotalCpuUserTimeUs);
                 u.mSystemCpuTime.addCountLocked(mTempTotalCpuSystemTimeUs);
+                updatedUids.put(Process.SYSTEM_UID, updatedUids.get(Process.SYSTEM_UID, 0)
+                        + mTempTotalCpuUserTimeUs + mTempTotalCpuSystemTimeUs);
 
                 final Uid.Proc proc = u.getProcessStatsLocked("*lost*");
                 proc.addCpuTimeLocked((int) mTempTotalCpuUserTimeUs / 1000,
@@ -10449,6 +10424,51 @@
             }
         }
 
+        long totalCpuClustersTime = 0;
+        // Read the time spent for each cluster at various cpu frequencies.
+        final long[][] clusterSpeeds = new long[mKernelCpuSpeedReaders.length][];
+        for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
+            clusterSpeeds[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
+            if (clusterSpeeds[cluster] != null) {
+                for (int speed = clusterSpeeds[cluster].length - 1; speed >= 0; --speed) {
+                    totalCpuClustersTime += clusterSpeeds[cluster][speed];
+                }
+            }
+        }
+        if (totalCpuClustersTime != 0) {
+            // We have cpu times per freq aggregated over all uids but we need the times per uid.
+            // So, we distribute total time spent by an uid to different cpu freqs based on the
+            // amount of time cpu was running at that freq.
+            final int updatedUidsCount = updatedUids.size();
+            for (int i = 0; i < updatedUidsCount; ++i) {
+                final Uid u = getUidStatsLocked(updatedUids.keyAt(i));
+                final long appCpuTimeMs = updatedUids.valueAt(i) / 1000;
+                // Add the cpu speeds to this UID.
+                final int numClusters = mPowerProfile.getNumCpuClusters();
+                if (u.mCpuClusterSpeed == null || u.mCpuClusterSpeed.length !=
+                        numClusters) {
+                    u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
+                }
+
+                for (int cluster = 0; cluster < clusterSpeeds.length; cluster++) {
+                    final int speedsInCluster = clusterSpeeds[cluster].length;
+                    if (u.mCpuClusterSpeed[cluster] == null || speedsInCluster !=
+                            u.mCpuClusterSpeed[cluster].length) {
+                        u.mCpuClusterSpeed[cluster] = new LongSamplingCounter[speedsInCluster];
+                    }
+
+                    final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeed[cluster];
+                    for (int speed = 0; speed < speedsInCluster; speed++) {
+                        if (cpuSpeeds[speed] == null) {
+                            cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
+                        }
+                        cpuSpeeds[speed].addCountLocked(appCpuTimeMs * clusterSpeeds[cluster][speed]
+                                / totalCpuClustersTime);
+                    }
+                }
+            }
+        }
+
         // See if there is a difference in wakelocks between this collection and the last
         // collection.
         if (ArrayUtils.referenceEquals(mPartialTimers, mLastPartialTimers)) {
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index 8417856..9d52e19 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -33,29 +33,17 @@
                              long rawUptimeUs, int statsType) {
 
         app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
-
-        // Aggregate total time spent on each cluster.
-        long totalTime = 0;
         final int numClusters = mProfile.getNumCpuClusters();
-        for (int cluster = 0; cluster < numClusters; cluster++) {
-            final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster);
-            for (int speed = 0; speed < speedsForCluster; speed++) {
-                totalTime += u.getTimeAtCpuSpeed(cluster, speed, statsType);
-            }
-        }
-        totalTime = Math.max(totalTime, 1);
 
         double cpuPowerMaMs = 0;
         for (int cluster = 0; cluster < numClusters; cluster++) {
             final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster);
             for (int speed = 0; speed < speedsForCluster; speed++) {
-                final double ratio = (double) u.getTimeAtCpuSpeed(cluster, speed, statsType) /
-                        totalTime;
-                final double cpuSpeedStepPower = ratio * app.cpuTimeMs *
+                final double cpuSpeedStepPower = u.getTimeAtCpuSpeed(cluster, speed, statsType) *
                         mProfile.getAveragePowerForCpu(cluster, speed);
-                if (DEBUG && ratio != 0) {
+                if (DEBUG) {
                     Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
-                            + speed + " ratio=" + BatteryStatsHelper.makemAh(ratio) + " power="
+                            + speed + " power="
                             + BatteryStatsHelper.makemAh(cpuSpeedStepPower / (60 * 60 * 1000)));
                 }
                 cpuPowerMaMs += cpuSpeedStepPower;
diff --git a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
index f282fac..7295380 100644
--- a/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
@@ -17,8 +17,10 @@
 package com.android.internal.os;
 
 import android.annotation.Nullable;
+import android.os.SystemClock;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.TimeUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -50,6 +52,8 @@
 
     private long[] mCpuFreqs;
     private int mCpuFreqsCount;
+    private long mLastTimeReadMs;
+    private long mNowTimeMs;
 
     private SparseArray<long[]> mLastUidCpuFreqTimeMs = new SparseArray<>();
 
@@ -64,7 +68,9 @@
             return;
         }
         try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
+            mNowTimeMs = SystemClock.elapsedRealtime();
             readDelta(reader, callback);
+            mLastTimeReadMs = mNowTimeMs;
             mProcFileAvailable = true;
         } catch (IOException e) {
             mReadErrorCounter++;
@@ -115,16 +121,33 @@
             return;
         }
         final long[] deltaUidTimeMs = new long[size];
+        final long[] curUidTimeMs = new long[size];
         boolean notify = false;
         for (int i = 0; i < size; ++i) {
             // Times read will be in units of 10ms
             final long totalTimeMs = Long.parseLong(timesStr[i], 10) * 10;
             deltaUidTimeMs[i] = totalTimeMs - uidTimeMs[i];
-            uidTimeMs[i] = totalTimeMs;
+            // If there is malformed data for any uid, then we just log about it and ignore
+            // the data for that uid.
+            if (deltaUidTimeMs[i] < 0 || totalTimeMs < 0) {
+                final StringBuilder sb = new StringBuilder("Malformed cpu freq data for UID=")
+                        .append(uid).append("\n");
+                sb.append("data=").append("(").append(uidTimeMs[i]).append(",")
+                        .append(totalTimeMs).append(")").append("\n");
+                sb.append("times=").append("(")
+                        .append(TimeUtils.formatForLogging(mLastTimeReadMs)).append(",")
+                        .append(TimeUtils.formatForLogging(mNowTimeMs)).append(")");
+                Slog.wtf(TAG, sb.toString());
+                return;
+            }
+            curUidTimeMs[i] = totalTimeMs;
             notify = notify || (deltaUidTimeMs[i] > 0);
         }
-        if (callback != null && notify) {
-            callback.onUidCpuFreqTime(uid, deltaUidTimeMs);
+        if (notify) {
+            System.arraycopy(curUidTimeMs, 0, uidTimeMs, 0, size);
+            if (callback != null) {
+                callback.onUidCpuFreqTime(uid, deltaUidTimeMs);
+            }
         }
     }
 
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 08f30ed..5b40cd0 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -1088,7 +1088,7 @@
      * Start VM.  This thread becomes the main thread of the VM, and will
      * not return until the VM exits.
      */
-    char* slashClassName = toSlashClassName(className);
+    char* slashClassName = toSlashClassName(className != NULL ? className : "");
     jclass startClass = env->FindClass(slashClassName);
     if (startClass == NULL) {
         ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
index a4bfc94..06877915 100644
--- a/core/jni/android/graphics/Bitmap.h
+++ b/core/jni/android/graphics/Bitmap.h
@@ -19,9 +19,7 @@
 #include <jni.h>
 #include <android/bitmap.h>
 #include <SkBitmap.h>
-#include <SkColorTable.h>
 #include <SkImageInfo.h>
-#include <SkPixelRef.h>
 
 namespace android {
 
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 2132f3d..a9efb00 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -345,8 +345,10 @@
         return 0;
     }
 
-    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);
-    if (!event) {
+    MotionEvent* event;
+    if (nativePtr) {
+        event = reinterpret_cast<MotionEvent*>(nativePtr);
+    } else {
         event = new MotionEvent();
     }
 
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 644638d..dbc9e51 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -61,7 +61,7 @@
     <shortcode country="bh" pattern="\\d{1,5}" free="81181" />
 
     <!-- Brazil: 1-5 digits (standard system default, not country specific) -->
-    <shortcode country="br" pattern="\\d{1,5}" free="6000[012]\\d" />
+    <shortcode country="br" pattern="\\d{1,5}" free="6000[012]\\d|876|5500|9963" />
 
     <!-- Belarus: 4 digits -->
     <shortcode country="by" pattern="\\d{4}" premium="3336|4161|444[4689]|501[34]|7781" />
@@ -72,10 +72,16 @@
     <!-- Switzerland: 3-5 digits: http://www.swisscom.ch/fxres/kmu/thirdpartybusiness_code_of_conduct_en.pdf -->
     <shortcode country="ch" pattern="[2-9]\\d{2,4}" premium="543|83111|30118" free="98765" />
 
+    <!-- Chile: 4-5 digits (not confirmed), known premium codes listed -->
+    <shortcode country="cl" pattern="\\d{4,5}" free="9963" />
+
     <!-- China: premium shortcodes start with "1066", free shortcodes start with "1065":
          http://clients.txtnation.com/entries/197192-china-premium-sms-short-code-requirements -->
     <shortcode country="cn" premium="1066.*" free="1065.*" />
 
+    <!-- Colombia: 1-6 digits (not confirmed) -->
+    <shortcode country="co" pattern="\\d{1,6}" free="890350" />
+
     <!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
     <shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
 
@@ -84,7 +90,7 @@
     <shortcode country="cz" premium="9\\d{6,7}" free="116\\d{3}" />
 
     <!-- Germany: 4-5 digits plus 1232xxx (premium codes from http://www.vodafone.de/infofaxe/537.pdf and http://premiumdienste.eplus.de/pdf/kodex.pdf), plus EU. To keep the premium regex from being too large, it only includes payment processors that have been used by SMS malware, with the regular pattern matching the other premium short codes. -->
-    <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215|47529|70296|83782" />
+    <shortcode country="de" pattern="\\d{4,5}|1232\\d{3}" premium="11(?:111|833)|1232(?:013|021|060|075|286|358)|118(?:44|80|86)|20[25]00|220(?:21|22|88|99)|221(?:14|21)|223(?:44|53|77)|224[13]0|225(?:20|59|90)|226(?:06|10|20|26|30|40|56|70)|227(?:07|33|39|66|76|78|79|88|99)|228(?:08|11|66|77)|23300|30030|3[12347]000|330(?:33|55|66)|33(?:233|331|366|533)|34(?:34|567)|37000|40(?:040|123|444|[3568]00)|41(?:010|414)|44(?:000|044|344|44[24]|544)|50005|50100|50123|50555|51000|52(?:255|783)|54(?:100|2542)|55(?:077|[24]00|222|333|55|[12369]55)|56(?:789|886)|60800|6[13]000|66(?:[12348]66|566|766|777|88|999)|68888|70(?:07|123|777)|76766|77(?:007|070|222|444|[567]77)|80(?:008|123|888)|82(?:002|[378]00|323|444|472|474|488|727)|83(?:005|[169]00|333|830)|84(?:141|300|32[34]|343|488|499|777|888)|85888|86(?:188|566|640|644|650|677|868|888)|870[24]9|871(?:23|[49]9)|872(?:1[0-8]|49|99)|87499|875(?:49|55|99)|876(?:0[1367]|1[1245678]|54|99)|877(?:00|99)|878(?:15|25|3[567]|8[12])|87999|880(?:08|44|55|77|99)|88688|888(?:03|10|8|89)|8899|90(?:009|999)|99999" free="116\\d{3}|81214|81215|47529|70296|83782|3011|73240" />
 
     <!-- Denmark: see http://iprs.webspacecommerce.com/Denmark-Premium-Rate-Numbers -->
     <shortcode country="dk" pattern="\\d{4,5}" premium="1\\d{3}" free="116\\d{3}|4665" />
@@ -108,11 +114,14 @@
     <!-- United Kingdom (Great Britain): 4-6 digits, common codes [5-8]xxxx, plus EU:
          http://www.short-codes.com/media/Co-regulatoryCodeofPracticeforcommonshortcodes170206.pdf,
          visual voicemail code for EE: 887 -->
-    <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|2020|35890|61002|61202|887|83669|34664|40406|60174" />
+    <shortcode country="gb" pattern="\\d{4,6}" premium="[5-8]\\d{4}" free="116\\d{3}|2020|35890|61002|61202|887|83669|34664|40406|60174|7726|37726" />
 
     <!-- Georgia: 4 digits, known premium codes listed -->
     <shortcode country="ge" pattern="\\d{4}" premium="801[234]|888[239]" />
 
+    <!-- Ghana: 4 digits, known premium codes listed -->
+    <shortcode country="gh" pattern="\\d{4}" free="5041" />
+
     <!-- Greece: 5 digits (54xxx, 19yxx, x=0-9, y=0-5): http://www.cmtelecom.com/premium-sms/greece -->
     <shortcode country="gr" pattern="\\d{5}" premium="54\\d{3}|19[0-5]\\d{2}" free="116\\d{3}|12115" />
 
@@ -143,6 +152,9 @@
     <!-- Japan: 8083 used by SOFTBANK_DCB_2 -->
     <shortcode country="jp" free="8083" />
 
+    <!-- Kenya: 5 digits, known premium codes listed -->
+    <shortcode country="ke" pattern="\\d{5}" free="21725" />
+
     <!-- Kyrgyzstan: 4 digits, known premium codes listed -->
     <shortcode country="kg" pattern="\\d{4}" premium="415[2367]|444[69]" />
 
@@ -160,13 +172,16 @@
 
     <!-- Luxembourg: 5 digits, 6xxxx, plus EU:
          http://www.luxgsm.lu/assets/files/filepage/file_1253803400.pdf -->
-    <shortcode country="lu" premium="6\\d{4}" free="116\\d{3}|60231" />
+    <shortcode country="lu" premium="6\\d{4}" free="116\\d{3}|60231|64085" />
 
     <!-- Latvia: 4 digits, known premium codes listed, plus EU -->
     <shortcode country="lv" pattern="\\d{4}" premium="18(?:19|63|7[1-4])" free="116\\d{3}|1399" />
 
+    <!-- Macedonia: 1-6 digits (not confirmed), known premium codes listed -->
+    <shortcode country="mk" pattern="\\d{1,6}" free="129005|122" />
+
     <!-- Mexico: 4-5 digits (not confirmed), known premium codes listed -->
-    <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="46645|5050|26259|50025|50052" />
+    <shortcode country="mx" pattern="\\d{4,5}" premium="53035|7766" free="46645|5050|26259|50025|50052|9963" />
 
     <!-- Malaysia: 5 digits: http://www.skmm.gov.my/attachment/Consumer_Regulation/Mobile_Content_Services_FAQs.pdf -->
     <shortcode country="my" pattern="\\d{5}" premium="32298|33776" free="22099|28288" />
@@ -180,6 +195,9 @@
     <!-- New Zealand: 3-4 digits, known premium codes listed -->
     <shortcode country="nz" pattern="\\d{3,4}" premium="3903|8995|4679" free="3067|3068|4053" />
 
+    <!-- Peru: 4-5 digits (not confirmed), known premium codes listed -->
+    <shortcode country="pe" pattern="\\d{4,5}" free="9963" />
+
     <!-- Philippines -->
     <shortcode country="ph" free="2147|5495|5496" />
 
@@ -196,11 +214,14 @@
     <!-- Qatar: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="qa" pattern="\\d{1,5}" free="92451" />
 
+    <!-- Reunion (French Territory): 1-5 digits (not confirmed) -->
+    <shortcode country="re" pattern="\\d{1,5}" free="38600,36300,36303,959" />
+
     <!-- Romania: 4 digits, plus EU: http://www.simplus.ro/en/resources/glossary-of-terms/ -->
     <shortcode country="ro" pattern="\\d{4}" premium="12(?:63|66|88)|13(?:14|80)" free="116\\d{3}|3654|8360" />
 
     <!-- Russia: 4 digits, known premium codes listed: http://smscoin.net/info/pricing-russia/ -->
-    <shortcode country="ru" pattern="\\d{4}" premium="1(?:1[56]1|899)|2(?:09[57]|322|47[46]|880|990)|3[589]33|4161|44(?:4[3-9]|81)|77(?:33|81)|8424" />
+    <shortcode country="ru" pattern="\\d{4}" premium="1(?:1[56]1|899)|2(?:09[57]|322|47[46]|880|990)|3[589]33|4161|44(?:4[3-9]|81)|77(?:33|81)|8424" free="6954,8501"/>
 
     <!-- Saudi Arabia -->
     <shortcode country="sa" free="8145" />
@@ -237,4 +258,7 @@
     <!-- Vietnam: 1-5 digits (standard system default, not country specific) -->
     <shortcode country="vn" pattern="\\d{1,5}" free="5001|9055" />
 
+    <!-- Mayotte (French Territory): 1-5 digits (not confirmed) -->
+    <shortcode country="yt" pattern="\\d{1,5}" free="38600,36300,36303,959" />
+
 </shortcodes>
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteConnectionPoolTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteConnectionPoolTest.java
new file mode 100644
index 0000000..ed14a53
--- /dev/null
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteConnectionPoolTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.database.sqlite;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.os.HandlerThread;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+/**
+ * Tests for {@link SQLiteConnectionPool}
+ *
+ * <p>Run with:  bit FrameworksCoreTests:android.database.sqlite.SQLiteConnectionPoolTest
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class SQLiteConnectionPoolTest {
+    private static final String TAG = "SQLiteConnectionPoolTest";
+
+    private Context mContext;
+    private File mTestDatabase;
+    private SQLiteDatabaseConfiguration mTestConf;
+
+
+    @Before
+    public void setup() {
+        mContext = InstrumentationRegistry.getContext();
+        SQLiteDatabase db = SQLiteDatabase
+                .openOrCreateDatabase(mContext.getDatabasePath("pool_test"), null);
+        mTestDatabase = new File(db.getPath());
+        Log.i(TAG, "setup: created " + mTestDatabase);
+        db.close();
+        mTestConf = new SQLiteDatabaseConfiguration(mTestDatabase.getPath(), 0);
+    }
+
+    @After
+    public void teardown() {
+        if (mTestDatabase != null) {
+            Log.i(TAG, "teardown: deleting " + mTestDatabase);
+            SQLiteDatabase.deleteDatabase(mTestDatabase);
+        }
+    }
+
+    @Test
+    public void testCloseIdleConnections() throws InterruptedException {
+        HandlerThread thread = new HandlerThread("test-close-idle-connections-thread");
+        Log.i(TAG, "Starting " + thread.getName());
+        thread.start();
+        SQLiteConnectionPool pool = SQLiteConnectionPool.open(mTestConf);
+        pool.setupIdleConnectionHandler(thread.getLooper(), 100);
+        SQLiteConnection c1 = pool.acquireConnection("pragma user_version", 0, null);
+        assertEquals("First connection should be returned", 0, c1.getConnectionId());
+        pool.releaseConnection(c1);
+        SQLiteConnection c2 = pool.acquireConnection("pragma user_version", 0, null);
+        assertTrue("Returned connection should be the same", c1 == c2);
+        pool.releaseConnection(c2);
+        Thread.sleep(200);
+        SQLiteConnection c3 = pool.acquireConnection("pragma user_version", 0, null);
+        assertTrue("New connection should be returned", c1 != c3);
+        assertEquals("New connection should be returned", 1, c3.getConnectionId());
+        pool.releaseConnection(c3);
+        pool.close();
+        thread.quit();
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
index 620acae..7ab9569 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelUidCpuFreqTimeReaderTest.java
@@ -98,6 +98,14 @@
         }
         verifyNoMoreInteractions(mCallback);
 
+        // Verify that there won't be a callback if the proc file values didn't change.
+        Mockito.reset(mCallback, mBufferedReader);
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+        verify(mCallback).onCpuFreqs(freqs);
+        verifyNoMoreInteractions(mCallback);
+
         // Verify that calling with a null callback doesn't result in any crashes
         Mockito.reset(mCallback, mBufferedReader);
         final long[][] newTimes2 = new long[uids.length][freqs.length];
@@ -130,6 +138,91 @@
         verifyNoMoreInteractions(mCallback);
     }
 
+    @Test
+    public void testReadDelta_malformedData() throws Exception {
+        final long[] freqs = {1, 12, 123, 1234, 12345, 123456};
+        final int[] uids = {1, 22, 333, 4444, 5555};
+        final long[][] times = new long[uids.length][freqs.length];
+        for (int i = 0; i < uids.length; ++i) {
+            for (int j = 0; j < freqs.length; ++j) {
+                times[i][j] = uids[i] * freqs[j] * 10;
+            }
+        }
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, times));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+        verify(mCallback).onCpuFreqs(freqs);
+        for (int i = 0; i < uids.length; ++i) {
+            verify(mCallback).onUidCpuFreqTime(uids[i], times[i]);
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that there is no callback if any value in the proc file is -ve.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] newTimes1 = new long[uids.length][freqs.length];
+        for (int i = 0; i < uids.length; ++i) {
+            for (int j = 0; j < freqs.length; ++j) {
+                newTimes1[i][j] = (times[i][j] + uids[i] + freqs[j]) * 10;
+            }
+        }
+        newTimes1[uids.length - 1][freqs.length - 1] *= -1;
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+        verify(mCallback).onCpuFreqs(freqs);
+        for (int i = 0; i < uids.length; ++i) {
+            if (i == uids.length - 1) {
+                continue;
+            }
+            verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes1[i], times[i]));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified when the proc file had -ve value.
+        Mockito.reset(mCallback, mBufferedReader);
+        for (int i = 0; i < freqs.length; ++i) {
+            newTimes1[uids.length - 1][i] = times[uids.length - 1][i];
+        }
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes1));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+        verify(mCallback).onCpuFreqs(freqs);
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that there is no callback if the values in the proc file are decreased.
+        Mockito.reset(mCallback, mBufferedReader);
+        final long[][] newTimes2 = new long[uids.length][freqs.length];
+        for (int i = 0; i < uids.length; ++i) {
+            for (int j = 0; j < freqs.length; ++j) {
+                newTimes2[i][j] = (newTimes1[i][j] + uids[i] * freqs[j]) * 10;
+            }
+        }
+        newTimes2[uids.length - 1][freqs.length - 1] =
+                newTimes1[uids.length - 1][freqs.length - 1] - 222;
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes2));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+        verify(mCallback).onCpuFreqs(freqs);
+        for (int i = 0; i < uids.length; ++i) {
+            if (i == uids.length - 1) {
+                continue;
+            }
+            verify(mCallback).onUidCpuFreqTime(uids[i], subtract(newTimes2[i], newTimes1[i]));
+        }
+        verifyNoMoreInteractions(mCallback);
+
+        // Verify that the internal state was not modified when the proc file had decreasing values.
+        Mockito.reset(mCallback, mBufferedReader);
+        for (int i = 0; i < freqs.length; ++i) {
+            newTimes2[uids.length - 1][i] = newTimes1[uids.length - 1][i];
+        }
+        when(mBufferedReader.readLine())
+                .thenReturn(getFreqsLine(freqs), getUidTimesLines(uids, newTimes2));
+        mKernelUidCpuFreqTimeReader.readDelta(mBufferedReader, mCallback);
+        verify(mCallback).onCpuFreqs(freqs);
+        verifyNoMoreInteractions(mCallback);
+    }
+
     private long[] subtract(long[] a1, long[] a2) {
         long[] val = new long[a1.length];
         for (int i = 0; i < val.length; ++i) {
diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp
index 90b27c8..2dfa6d4 100644
--- a/libs/hwui/renderstate/OffscreenBufferPool.cpp
+++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp
@@ -179,8 +179,9 @@
         layer->region.clear();
         return layer;
     }
+    bool wideColorGamut = layer->wideColorGamut;
     putOrDelete(layer);
-    return get(renderState, width, height, layer->wideColorGamut);
+    return get(renderState, width, height, wideColorGamut);
 }
 
 void OffscreenBufferPool::dump() {
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 439fff3..5fc58dc 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -97,6 +97,9 @@
     <!-- Summary for Connected wifi network without internet -->
     <string name="wifi_connected_no_internet">Connected, no Internet</string>
 
+    <!-- Summary for networks failing to connect due to association rejection status 17, AP full -->
+    <string name="wifi_ap_unable_to_handle_new_sta">Access point temporarily full</string>
+
     <!-- Speed label for very slow network speed -->
     <string name="speed_label_very_slow">Very Slow</string>
     <!-- Speed label for slow network speed -->
@@ -110,6 +113,9 @@
     <!-- Speed label for very fast network speed -->
     <string name="speed_label_very_fast">Very Fast</string>
 
+    <!-- Summary text separator for preferences including a short description (eg. "Fast / Connected"). -->
+    <string name="preference_summary_default_combination"><xliff:g id="state" example="ON">%1$s</xliff:g> / <xliff:g id="description" example="High accuracy mode">%2$s</xliff:g></string>
+
     <!-- Bluetooth settings.  Message when a device is disconnected -->
     <string name="bluetooth_disconnected">Disconnected</string>
     <!-- Bluetooth settings.  Message when disconnecting from a device -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index e0a88e4..f5282b7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -673,13 +673,6 @@
         // Update to new summary
         StringBuilder summary = new StringBuilder();
 
-        // TODO(b/62354743): Standardize and international delimiter usage
-        final String concatenator = " / ";
-
-        if (mSpeed != Speed.NONE) {
-            summary.append(getSpeedLabel() + concatenator);
-        }
-
         if (isActive() && config != null && config.isPasspoint()) {
             // This is the active connection on passpoint
             summary.append(getSummary(mContext, getDetailedState(),
@@ -721,7 +714,17 @@
             summary.append(mContext.getString(R.string.wifi_not_in_range));
         } else { // In range, not disabled.
             if (config != null) { // Is saved network
-                summary.append(mContext.getString(R.string.wifi_remembered));
+                // Last attempt to connect to this failed. Show reason why
+                switch (config.recentFailure.getAssociationStatus()) {
+                    case WifiConfiguration.RecentFailure.STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
+                        summary.append(mContext.getString(
+                                R.string.wifi_ap_unable_to_handle_new_sta));
+                        break;
+                    default:
+                        // "Saved"
+                        summary.append(mContext.getString(R.string.wifi_remembered));
+                        break;
+                }
             }
         }
 
@@ -763,14 +766,15 @@
             }
         }
 
-        // Strip trailing delimiter if applicable
-        int concatLength = concatenator.length();
-        if (summary.length() >= concatLength && summary.substring(
-                summary.length() - concatLength, summary.length()).equals(concatenator)) {
-            summary.delete(summary.length() - concatLength, summary.length());
+        // If Speed label is present, use the preference combination to prepend it to the summary.
+        if (mSpeed != Speed.NONE) {
+            return mContext.getResources().getString(
+                    R.string.preference_summary_default_combination,
+                    getSpeedLabel(),
+                    summary.toString());
+        } else {
+            return summary.toString();
         }
-
-        return summary.toString();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index cb2aa94..a53e348 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -202,8 +202,7 @@
         return mDrawable;
     }
 
-    @VisibleForTesting
-    ColorExtractor.GradientColors getColors() {
+    public ColorExtractor.GradientColors getColors() {
         return mColors;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 9d699cf..917a56f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -16,11 +16,16 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.WallpaperColors;
+import android.content.Context;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.view.View;
 
+import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
+import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 
@@ -49,6 +54,7 @@
     private boolean mDockedLight;
     private int mLastStatusBarMode;
     private int mLastNavigationBarMode;
+    private final Color mDarkModeColor;
 
     /**
      * Whether the navigation bar should be light factoring in already how much alpha the scrim has
@@ -61,12 +67,14 @@
      */
     private boolean mHasLightNavigationBar;
     private boolean mScrimAlphaBelowThreshold;
+    private boolean mInvertLightNavBarWithScrim;
     private float mScrimAlpha;
 
     private final Rect mLastFullscreenBounds = new Rect();
     private final Rect mLastDockedBounds = new Rect();
 
-    public LightBarController() {
+    public LightBarController(Context ctx) {
+        mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
         mStatusBarIconController = Dependency.get(DarkIconDispatcher.class);
         mBatteryController = Dependency.get(BatteryController.class);
         mBatteryController.addCallback(this);
@@ -74,6 +82,7 @@
 
     public void setNavigationBar(LightBarTransitionsController navigationBar) {
         mNavigationBarController = navigationBar;
+        updateNavigation();
     }
 
     public void setFingerprintUnlockController(
@@ -119,7 +128,8 @@
             boolean last = mNavigationLight;
             mHasLightNavigationBar = isLight(vis, navigationBarMode,
                     View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
-            mNavigationLight = mHasLightNavigationBar && mScrimAlphaBelowThreshold;
+            mNavigationLight = mHasLightNavigationBar
+                    && (mScrimAlphaBelowThreshold || !mInvertLightNavBarWithScrim);
             if (mNavigationLight != last) {
                 updateNavigation();
             }
@@ -145,6 +155,15 @@
         }
     }
 
+    public void setScrimColor(GradientColors colors) {
+        boolean invertLightNavBarWithScrimBefore = mInvertLightNavBarWithScrim;
+        mInvertLightNavBarWithScrim = !colors.supportsDarkText();
+        if (mHasLightNavigationBar
+                && invertLightNavBarWithScrimBefore != mInvertLightNavBarWithScrim) {
+            reevaluate();
+        }
+    }
+
     private boolean isLight(int vis, int barMode, int flag) {
         boolean isTransparentBar = (barMode == MODE_TRANSPARENT
                 || barMode == MODE_LIGHTS_OUT_TRANSPARENT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 6bd959f..417bef8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -23,8 +23,8 @@
 import android.os.SystemClock;
 import android.util.TimeUtils;
 
-import com.android.systemui.Dumpable;
 import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
 import com.android.systemui.Interpolators;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.statusbar.CommandQueue;
@@ -55,7 +55,6 @@
     private ValueAnimator mTintAnimator;
     private float mDarkIntensity;
     private float mNextDarkIntensity;
-
     private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
         @Override
         public void run() {
@@ -130,6 +129,7 @@
     public void setIconsDark(boolean dark, boolean animate) {
         if (!animate) {
             setIconTintInternal(dark ? 1.0f : 0.0f);
+            mNextDarkIntensity = dark ? 1.0f : 0.0f;
         } else if (mTransitionPending) {
             deferIconTintChange(dark ? 1.0f : 0.0f);
         } else if (mTransitionDeferring) {
@@ -155,12 +155,12 @@
 
     private void animateIconTint(float targetDarkIntensity, long delay,
             long duration) {
+        if (mNextDarkIntensity == targetDarkIntensity) {
+            return;
+        }
         if (mTintAnimator != null) {
             mTintAnimator.cancel();
         }
-        if (mDarkIntensity == targetDarkIntensity) {
-            return;
-        }
         mNextDarkIntensity = targetDarkIntensity;
         mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
         mTintAnimator.addUpdateListener(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 6672f5e..a8b1c91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -315,6 +315,7 @@
                 mScrimInFront.setColors(mSystemColors, animateScrimInFront);
                 mScrimBehind.setColors(mSystemColors, animateScrimBehind);
             }
+            mLightBarController.setScrimColor(mScrimInFront.getColors());
         }
 
         if (mAnimateKeyguardFadingOut || mForceHideScrims) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 2afdab8..baa1444 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1110,7 +1110,7 @@
             }
         });
 
-        mLightBarController = new LightBarController();
+        mLightBarController = new LightBarController(context);
         if (mNavigationBar != null) {
             mNavigationBar.setLightBarController(mLightBarController);
         }
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index 663559f..9ef45ea 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -34,6 +34,7 @@
 import java.io.PrintWriter;
 import java.text.DateFormat;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -224,11 +225,18 @@
         pw.println("\nPlaybackActivityMonitor dump time: "
                 + DateFormat.getTimeInstance().format(new Date()));
         synchronized(mPlayerLock) {
-            for (AudioPlaybackConfiguration conf : mPlayers.values()) {
-                conf.dump(pw);
+            // all players
+            pw.println("\n  players:");
+            final List<Integer> piidIntList = new ArrayList<Integer>(mPlayers.keySet());
+            Collections.sort(piidIntList);
+            for (Integer piidInt : piidIntList) {
+                final AudioPlaybackConfiguration apc = mPlayers.get(piidInt);
+                if (apc != null) {
+                    apc.dump(pw);
+                }
             }
             // ducked players
-            pw.println("\n  ducked players:");
+            pw.println("\n  ducked players piids:");
             mDuckingManager.dump(pw);
             // players muted due to the device ringing or being in a call
             pw.print("\n  muted player piids:");
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1810174..32983ec 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8918,9 +8918,12 @@
             }
         }
 
-        boolean updatedPkgBetter = false;
+        final boolean isUpdatedPkg = updatedPkg != null;
+        final boolean isUpdatedSystemPkg = isUpdatedPkg
+                && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0;
+        boolean isUpdatedPkgBetter = false;
         // First check if this is a system package that may involve an update
-        if (updatedPkg != null && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
+        if (isUpdatedSystemPkg) {
             // If new package is not located in "/system/priv-app" (e.g. due to an OTA),
             // it needs to drop FLAG_PRIVILEGED.
             if (locationIsPrivileged(scanFile)) {
@@ -8964,10 +8967,6 @@
                             updatedChildPkg.versionCode = pkg.mVersionCode;
                         }
                     }
-
-                    throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at "
-                            + scanFile + " ignored: updated version " + ps.versionCode
-                            + " better than this " + pkg.mVersionCode);
                 } else {
                     // The current app on the system partition is better than
                     // what we have updated to on the data partition; switch
@@ -8994,12 +8993,44 @@
                     synchronized (mPackages) {
                         mSettings.enableSystemPackageLPw(ps.name);
                     }
-                    updatedPkgBetter = true;
+                    isUpdatedPkgBetter = true;
                 }
             }
         }
 
-        if (updatedPkg != null) {
+        String resourcePath = null;
+        String baseResourcePath = null;
+        if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !isUpdatedPkgBetter) {
+            if (ps != null && ps.resourcePathString != null) {
+                resourcePath = ps.resourcePathString;
+                baseResourcePath = ps.resourcePathString;
+            } else {
+                // Should not happen at all. Just log an error.
+                Slog.e(TAG, "Resource path not set for package " + pkg.packageName);
+            }
+        } else {
+            resourcePath = pkg.codePath;
+            baseResourcePath = pkg.baseCodePath;
+        }
+
+        // Set application objects path explicitly.
+        pkg.setApplicationVolumeUuid(pkg.volumeUuid);
+        pkg.setApplicationInfoCodePath(pkg.codePath);
+        pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath);
+        pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths);
+        pkg.setApplicationInfoResourcePath(resourcePath);
+        pkg.setApplicationInfoBaseResourcePath(baseResourcePath);
+        pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
+
+        // throw an exception if we have an update to a system application, but, it's not more
+        // recent than the package we've already scanned
+        if (isUpdatedSystemPkg && !isUpdatedPkgBetter) {
+            throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at "
+                    + scanFile + " ignored: updated version " + ps.versionCode
+                    + " better than this " + pkg.mVersionCode);
+        }
+
+        if (isUpdatedPkg) {
             // An updated system app will not have the PARSE_IS_SYSTEM flag set
             // initially
             policyFlags |= PackageParser.PARSE_IS_SYSTEM;
@@ -9019,7 +9050,7 @@
          * same name installed earlier.
          */
         boolean shouldHideSystemApp = false;
-        if (updatedPkg == null && ps != null
+        if (!isUpdatedPkg && ps != null
                 && (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
             /*
              * Check to make sure the signatures match first. If they don't,
@@ -9074,31 +9105,6 @@
             }
         }
 
-        // TODO: extend to support forward-locked splits
-        String resourcePath = null;
-        String baseResourcePath = null;
-        if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
-            if (ps != null && ps.resourcePathString != null) {
-                resourcePath = ps.resourcePathString;
-                baseResourcePath = ps.resourcePathString;
-            } else {
-                // Should not happen at all. Just log an error.
-                Slog.e(TAG, "Resource path not set for package " + pkg.packageName);
-            }
-        } else {
-            resourcePath = pkg.codePath;
-            baseResourcePath = pkg.baseCodePath;
-        }
-
-        // Set application objects path explicitly.
-        pkg.setApplicationVolumeUuid(pkg.volumeUuid);
-        pkg.setApplicationInfoCodePath(pkg.codePath);
-        pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath);
-        pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths);
-        pkg.setApplicationInfoResourcePath(resourcePath);
-        pkg.setApplicationInfoBaseResourcePath(baseResourcePath);
-        pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
-
         final int userId = ((user == null) ? 0 : user.getIdentifier());
         if (ps != null && ps.getInstantApp(userId)) {
             scanFlags |= SCAN_AS_INSTANT_APP;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 75fc25a..7e0b950 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -7832,21 +7832,17 @@
     }
 
     private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
-        WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
-                ? mStatusBar
-                : opaqueOrDimming;
-
-        if (statusColorWin != null) {
-            if (statusColorWin == opaque) {
-                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
-                // its light flag.
-                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
-                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
-                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
-            } else if (statusColorWin != null && statusColorWin.isDimming()) {
-                // Otherwise if it's dimming, clear the light flag.
-                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
-            }
+        final boolean onKeyguard = isStatusBarKeyguard() && !mKeyguardOccluded;
+        final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
+        if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
+            // If the top fullscreen-or-dimming window is also the top fullscreen, respect
+            // its light flag.
+            vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+            vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
+                    & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+        } else if (statusColorWin != null && statusColorWin.isDimming()) {
+            // Otherwise if it's dimming, clear the light flag.
+            vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
         }
         return vis;
     }
@@ -7856,7 +7852,7 @@
         final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
 
         final WindowState navColorWin;
-        if (imeWin != null && imeWin.isVisibleLw()) {
+        if (imeWin != null && imeWin.isVisibleLw() && mNavigationBarPosition == NAV_BAR_BOTTOM) {
             navColorWin = imeWin;
         } else {
             navColorWin = opaqueOrDimming;
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index a5797c0..184dd73 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -946,11 +946,6 @@
                         Slog.i(TAG, "HOST_STATE connected:" + connected);
                     }
 
-                    if ((mHideUsbNotification && connected)
-                            || (!mHideUsbNotification && !connected)) {
-                        break;
-                    }
-
                     mHideUsbNotification = false;
                     while (devices.hasNext()) {
                         Map.Entry pair = (Map.Entry) devices.next();
@@ -1053,12 +1048,22 @@
 
         private void updateUsbNotification(boolean force) {
             if (mNotificationManager == null || !mUseUsbNotification
-                    || ("0".equals(SystemProperties.get("persist.charging.notify")))
-                    // Dont show the notification when connected to a USB peripheral
-                    // and the link does not support PR_SWAP and DR_SWAP
-                    || (mHideUsbNotification && !mSupportsAllCombinations)) {
+                    || ("0".equals(SystemProperties.get("persist.charging.notify")))) {
                 return;
             }
+
+            // Dont show the notification when connected to a USB peripheral
+            // and the link does not support PR_SWAP and DR_SWAP
+            if (mHideUsbNotification && !mSupportsAllCombinations) {
+                if (mUsbNotificationId != 0) {
+                    mNotificationManager.cancelAsUser(null, mUsbNotificationId,
+                            UserHandle.ALL);
+                    mUsbNotificationId = 0;
+                    Slog.d(TAG, "Clear notification");
+                }
+                return;
+            }
+
             int id = 0;
             int titleRes = 0;
             Resources r = mContext.getResources();
@@ -1109,6 +1114,7 @@
                 if (mUsbNotificationId != 0) {
                     mNotificationManager.cancelAsUser(null, mUsbNotificationId,
                             UserHandle.ALL);
+                    Slog.d(TAG, "Clear notification");
                     mUsbNotificationId = 0;
                 }
                 if (id != 0) {
@@ -1165,6 +1171,7 @@
 
                     mNotificationManager.notifyAsUser(null, id, notification,
                             UserHandle.ALL);
+                    Slog.d(TAG, "push notification:" + title);
                     mUsbNotificationId = id;
                 }
             }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 13d54ab..a145327 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -420,12 +420,6 @@
 
     /**
      * @hide
-     * last failure
-     */
-    public String lastFailure;
-
-    /**
-     * @hide
      * last time we connected, this configuration had validated internet access
      */
     public boolean validatedInternetAccess;
@@ -1417,6 +1411,53 @@
 
     /**
      * @hide
+     * This class is intended to store extra failure reason information for the most recent
+     * connection attempt, so that it may be surfaced to the settings UI
+     */
+    public static class RecentFailure {
+
+        /**
+         * No recent failure, or no specific reason given for the recent connection failure
+         */
+        public static final int NONE = 0;
+        /**
+         * Connection to this network recently failed due to Association Rejection Status 17
+         * (AP is full)
+         */
+        public static final int STATUS_AP_UNABLE_TO_HANDLE_NEW_STA = 17;
+        /**
+         * Association Rejection Status code (NONE for success/non-association-rejection-fail)
+         */
+        private int mAssociationStatus = NONE;
+
+        /**
+         * @param status the association status code for the recent failure
+         */
+        public void setAssociationStatus(int status) {
+            mAssociationStatus = status;
+        }
+        /**
+         * Sets the RecentFailure to NONE
+         */
+        public void clear() {
+            mAssociationStatus = NONE;
+        }
+        /**
+         * Get the recent failure code
+         */
+        public int getAssociationStatus() {
+            return mAssociationStatus;
+        }
+    }
+
+    /**
+     * @hide
+     * RecentFailure member
+     */
+    final public RecentFailure recentFailure = new RecentFailure();
+
+    /**
+     * @hide
      * @return network selection status
      */
     public NetworkSelectionStatus getNetworkSelectionStatus() {
@@ -1705,7 +1746,8 @@
                 sbuf.append('\n');
             }
         }
-
+        sbuf.append("recentFailure: ").append("Association Rejection code: ")
+                .append(recentFailure.getAssociationStatus()).append("\n");
         return sbuf.toString();
     }
 
@@ -2029,7 +2071,6 @@
                 visibility = new Visibility(source.visibility);
             }
 
-            lastFailure = source.lastFailure;
             didSelfAdd = source.didSelfAdd;
             lastConnectUid = source.lastConnectUid;
             lastUpdateUid = source.lastUpdateUid;
@@ -2053,6 +2094,7 @@
             creationTime = source.creationTime;
             updateTime = source.updateTime;
             shared = source.shared;
+            recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus());
         }
     }
 
@@ -2119,6 +2161,7 @@
         dest.writeInt(noInternetAccessExpected ? 1 : 0);
         dest.writeInt(shared ? 1 : 0);
         dest.writeString(mPasspointManagementObjectTree);
+        dest.writeInt(recentFailure.getAssociationStatus());
     }
 
     /** Implement the Parcelable interface {@hide} */
@@ -2186,6 +2229,7 @@
                 config.noInternetAccessExpected = in.readInt() != 0;
                 config.shared = in.readInt() != 0;
                 config.mPasspointManagementObjectTree = in.readString();
+                config.recentFailure.setAssociationStatus(in.readInt());
                 return config;
             }