Merge "Ensure that OnCannedTextResponsesChanged callback is fired"
diff --git a/api/current.txt b/api/current.txt
index bdab385..463dee4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -30114,7 +30114,6 @@
     method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
     method public final void setConferenceables(java.util.List<android.telecom.Conferenceable>);
     method public final void setConnectionCapabilities(int);
-    method public final void setConnectionService(android.telecom.ConnectionService);
     method public final void setDialing();
     method public final void setDisconnected(android.telecom.DisconnectCause);
     method public final void setExtras(android.os.Bundle);
diff --git a/api/system-current.txt b/api/system-current.txt
index 1025a71..adb6cb8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -32316,7 +32316,6 @@
     method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
     method public final void setConferenceables(java.util.List<android.telecom.Conferenceable>);
     method public final void setConnectionCapabilities(int);
-    method public final void setConnectionService(android.telecom.ConnectionService);
     method public final void setDialing();
     method public final void setDisconnected(android.telecom.DisconnectCause);
     method public final void setExtras(android.os.Bundle);
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index 3e4a66d..9c401c7f 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -138,7 +138,9 @@
                     new AccountAuthenticatorResponse(response),
                         accountType, authTokenType, features, options);
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    result.keySet(); // force it to be unparcelled
+                    if (result != null) {
+                        result.keySet(); // force it to be unparcelled
+                    }
                     Log.v(TAG, "addAccount: result " + AccountManager.sanitizeResult(result));
                 }
                 if (result != null) {
@@ -160,7 +162,9 @@
                 final Bundle result = AbstractAccountAuthenticator.this.confirmCredentials(
                     new AccountAuthenticatorResponse(response), account, options);
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    result.keySet(); // force it to be unparcelled
+                    if (result != null) {
+                        result.keySet(); // force it to be unparcelled
+                    }
                     Log.v(TAG, "confirmCredentials: result "
                             + AccountManager.sanitizeResult(result));
                 }
@@ -185,7 +189,9 @@
                 result.putString(AccountManager.KEY_AUTH_TOKEN_LABEL,
                         AbstractAccountAuthenticator.this.getAuthTokenLabel(authTokenType));
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    result.keySet(); // force it to be unparcelled
+                    if (result != null) {
+                        result.keySet(); // force it to be unparcelled
+                    }
                     Log.v(TAG, "getAuthTokenLabel: result "
                             + AccountManager.sanitizeResult(result));
                 }
@@ -209,7 +215,9 @@
                         new AccountAuthenticatorResponse(response), account,
                         authTokenType, loginOptions);
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    result.keySet(); // force it to be unparcelled
+                    if (result != null) {
+                        result.keySet(); // force it to be unparcelled
+                    }
                     Log.v(TAG, "getAuthToken: result " + AccountManager.sanitizeResult(result));
                 }
                 if (result != null) {
@@ -234,7 +242,10 @@
                     new AccountAuthenticatorResponse(response), account,
                         authTokenType, loginOptions);
                 if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    result.keySet(); // force it to be unparcelled
+                    // Result may be null.
+                    if (result != null) {
+                        result.keySet(); // force it to be unparcelled
+                    }
                     Log.v(TAG, "updateCredentials: result "
                             + AccountManager.sanitizeResult(result));
                 }
@@ -490,7 +501,7 @@
      * <ul>
      * <li> {@link AccountManager#KEY_INTENT}, or
      * <li> {@link AccountManager#KEY_ACCOUNT_NAME} and {@link AccountManager#KEY_ACCOUNT_TYPE} of
-     * the account that was added, or
+     * the account whose credentials were updated, or
      * <li> {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} to
      * indicate an error
      * </ul>
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 9394d2c..8c84b4d 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -333,7 +333,7 @@
         try {
             return mService.getPassword(account);
         } catch (RemoteException e) {
-            // will never happen
+            // won't ever happen
             throw new RuntimeException(e);
         }
     }
@@ -362,7 +362,7 @@
         try {
             return mService.getUserData(account, key);
         } catch (RemoteException e) {
-            // will never happen
+            // won't ever happen
             throw new RuntimeException(e);
         }
     }
@@ -415,8 +415,10 @@
      *
      * <p>It is safe to call this method from the main thread.
      *
-     * <p>This method requires the caller to hold the permission
-     * {@link android.Manifest.permission#GET_ACCOUNTS}.
+     * <p>Clients of this method that have not been granted the
+     * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
+     * will only see those accounts managed by AbstractAccountAuthenticators whose
+     * signature matches the client.
      *
      * @return An array of {@link Account}, one for each account.  Empty
      *     (never null) if no accounts have been added.
@@ -438,8 +440,10 @@
      *
      * <p>It is safe to call this method from the main thread.
      *
-     * <p>This method requires the caller to hold the permission
-     * {@link android.Manifest.permission#GET_ACCOUNTS}.
+     * <p>Clients of this method that have not been granted the
+     * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
+     * will only see those accounts managed by AbstractAccountAuthenticators whose
+     * signature matches the client.
      *
      * @return An array of {@link Account}, one for each account.  Empty
      *     (never null) if no accounts have been added.
@@ -466,7 +470,7 @@
         try {
             return mService.getAccountsForPackage(packageName, uid);
         } catch (RemoteException re) {
-            // possible security exception
+            // won't ever happen
             throw new RuntimeException(re);
         }
     }
@@ -483,7 +487,7 @@
         try {
             return mService.getAccountsByTypeForPackage(type, packageName);
         } catch (RemoteException re) {
-            // possible security exception
+            // won't ever happen
             throw new RuntimeException(re);
         }
     }
@@ -497,9 +501,10 @@
      *
      * <p>It is safe to call this method from the main thread.
      *
-     * <p>This method requires the caller to hold the permission
-     * {@link android.Manifest.permission#GET_ACCOUNTS} or share a uid with the
-     * authenticator that owns the account type.
+     * <p>Clients of this method that have not been granted the
+     * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
+     * will only see those accounts managed by AbstractAccountAuthenticators whose
+     * signature matches the client.
      *
      * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
      * GET_ACCOUNTS permission is needed for those platforms, irrespective of uid
@@ -585,7 +590,8 @@
      * {@link AccountManagerFuture} must not be used on the main thread.
      *
      * <p>This method requires the caller to hold the permission
-     * {@link android.Manifest.permission#GET_ACCOUNTS}.
+     * {@link android.Manifest.permission#GET_ACCOUNTS} or be a signature
+     * match with the AbstractAccountAuthenticator that manages the account.
      *
      * @param account The {@link Account} to test
      * @param features An array of the account features to check
@@ -628,9 +634,10 @@
      * <p>This method may be called from any thread, but the returned
      * {@link AccountManagerFuture} must not be used on the main thread.
      *
-     * <p>This method requires the caller to hold the permission
-     * {@link android.Manifest.permission#GET_ACCOUNTS} or share a uid with the
-     * authenticator that owns the account type.
+     * <p>Clients of this method that have not been granted the
+     * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
+     * will only see those accounts managed by AbstractAccountAuthenticators whose
+     * signature matches the client.
      *
      * @param type The type of accounts to return, must not be null
      * @param features An array of the account features to require,
@@ -701,7 +708,7 @@
         try {
             return mService.addAccountExplicitly(account, password, userdata);
         } catch (RemoteException e) {
-            // won't ever happen
+            // Can happen if there was a SecurityException was thrown.
             throw new RuntimeException(e);
         }
     }
@@ -966,7 +973,7 @@
         try {
             return mService.removeAccountExplicitly(account);
         } catch (RemoteException e) {
-            // won't ever happen
+            // May happen if the caller doesn't match the signature of the authenticator.
             throw new RuntimeException(e);
         }
     }
@@ -1114,7 +1121,7 @@
         try {
             mService.setUserData(account, key, value);
         } catch (RemoteException e) {
-            // won't ever happen
+            // Will happen if there is not signature match.
             throw new RuntimeException(e);
         }
     }
@@ -1733,7 +1740,7 @@
      *     with these fields if an activity was supplied and the account
      *     credentials were successfully updated:
      * <ul>
-     * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account created
+     * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account
      * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account
      * </ul>
      *
@@ -2501,10 +2508,12 @@
      * listeners are added in an Activity or Service's {@link Activity#onCreate}
      * and removed in {@link Activity#onDestroy}.
      *
-     * <p>It is safe to call this method from the main thread.
+     * <p>The listener will only be informed of accounts that would be returned
+     * to the caller via {@link #getAccounts()}. Typically this means that to
+     * get any accounts, the caller will need to be grated the GET_ACCOUNTS
+     * permission.
      *
-     * <p>This method requires the caller to hold the permission
-     * {@link android.Manifest.permission#GET_ACCOUNTS}.
+     * <p>It is safe to call this method from the main thread.
      *
      * @param listener The listener to send notifications to
      * @param handler {@link Handler} identifying the thread to use
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index f21422e..c505b0b 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -124,6 +124,12 @@
      *
      * <p> If provisioning fails, the managedProfile is removed so the device returns to its
      * previous state.
+     *
+     * <p>If launched with {@link android.app.Activity#startActivityForResult(Intent, int)} a
+     * result code of {@link android.app.Activity#RESULT_OK} implies that the synchronous part of
+     * the provisioning flow was successful, although this doesn't guarantee the full flow will
+     * succeed. Conversely a result code of {@link android.app.Activity#RESULT_CANCELED} implies
+     * that the user backed-out of provisioning, or some precondition for provisioning wasn't met.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_PROVISION_MANAGED_PROFILE
@@ -158,6 +164,10 @@
      *
      * <p> If provisioning fails, the device is factory reset.
      *
+     * <p>A result code of {@link android.app.Activity#RESULT_OK} implies that the synchronous part
+     * of the provisioning flow was successful, although this doesn't guarantee the full flow will
+     * succeed. Conversely a result code of {@link android.app.Activity#RESULT_CANCELED} implies
+     * that the user backed-out of provisioning, or some precondition for provisioning wasn't met.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_PROVISION_MANAGED_DEVICE
@@ -165,13 +175,19 @@
 
     /**
      * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
-     * allows a mobile device management application which starts managed provisioning to pass data
-     * to itself.
+     * allows a mobile device management application or NFC programmer application which starts
+     * managed provisioning to pass data to the management application instance after provisioning.
      * <p>
      * If used with {@link #ACTION_PROVISION_MANAGED_PROFILE} it can be used by the application that
      * sends the intent to pass data to itself on the newly created profile.
      * If used with {@link #ACTION_PROVISION_MANAGED_DEVICE} it allows passing data to the same
      * instance of the app on the primary user.
+     * Starting from {@link android.os.Build.VERSION_CODES#M}, if used with
+     * {@link #MIME_TYPE_PROVISIONING_NFC} as part of NFC managed device provisioning, the NFC
+     * message should contain a stringified {@link java.util.Properties} instance, whose string
+     * properties will be converted into a {@link android.os.PersistableBundle} and passed to the
+     * management application after provisioning.
+     *
      * <p>
      * In both cases the application receives the data in
      * {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with the action
@@ -587,7 +603,9 @@
      * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_HOST}, optional</li>
      * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_PORT} (convert to String), optional</li>
      * <li>{@link #EXTRA_PROVISIONING_WIFI_PROXY_BYPASS}, optional</li>
-     * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li></ul>
+     * <li>{@link #EXTRA_PROVISIONING_WIFI_PAC_URL}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional, supported from
+     * {@link android.os.Build.VERSION_CODES#M} </li></ul>
      *
      * <p>
      * As of {@link android.os.Build.VERSION_CODES#M}, the properties should contain
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 97afafa..1f3ff51 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1002,6 +1002,25 @@
     }
 
     /**
+     * Factory reset bluetooth settings.
+     *
+     * <p>Requires the {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
+     * permission
+     *
+     * @return true to indicate that the config file was successfully cleared
+     *
+     * @hide
+     */
+    public boolean factoryReset() {
+        try {
+            if (mService != null) {
+                return mService.factoryReset();
+            }
+        } catch (RemoteException e) {Log.e(TAG, "", e);}
+        return false;
+    }
+
+    /**
      * Get the UUIDs supported by the local Bluetooth adapter.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 7a894ae..66f3418 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -92,6 +92,7 @@
     ParcelFileDescriptor createSocketChannel(int type, in String serviceName, in ParcelUuid uuid, int port, int flag);
 
     boolean configHciSnoopLog(boolean enable);
+    boolean factoryReset();
 
     boolean isMultiAdvertisementSupported();
     boolean isPeripheralModeSupported();
diff --git a/core/java/android/os/NullVibrator.java b/core/java/android/os/NullVibrator.java
index f14d965..19b452f 100644
--- a/core/java/android/os/NullVibrator.java
+++ b/core/java/android/os/NullVibrator.java
@@ -43,7 +43,6 @@
      */
     @Override
     public void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) {
-        vibrate(milliseconds);
     }
 
     /**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f2bf6dc..601403c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -7567,6 +7567,13 @@
         }
 
         /**
+         * Value of the ringer before entering zen mode.
+         *
+         * @hide
+         */
+        public static final String ZEN_MODE_RINGER_LEVEL = "zen_mode_ringer_level";
+
+        /**
          * Opaque value, changes when persisted zen mode configuration changes.
          *
          * @hide
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index fa015b2..c3aed75 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -40,6 +40,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.MissingResourceException;
@@ -247,7 +248,7 @@
      * @return A list of features supported for the given language.
      */
     protected Set<String> onGetFeaturesForLanguage(String lang, String country, String variant) {
-        return null;
+        return new HashSet<String>();
     }
 
     private int getExpectedLanguageAvailableStatus(Locale locale) {
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 8364951..20fe61d 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -384,6 +384,10 @@
         assigned.
     */
     public Drawable getDrawable() {
+        if (mDrawable == mRecycleableBitmapDrawable) {
+            // Consider our cached version dirty since app code now has a reference to it
+            mRecycleableBitmapDrawable = null;
+        }
         return mDrawable;
     }
 
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index 98bfd7d..50569d7 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -678,7 +678,7 @@
         void startScroll(int start, int distance, int duration) {
             mFinished = false;
 
-            mStart = start;
+            mCurrentPosition = mStart = start;
             mFinal = start + distance;
 
             mStartTime = AnimationUtils.currentAnimationTimeMillis();
@@ -712,7 +712,7 @@
         boolean springback(int start, int min, int max) {
             mFinished = true;
 
-            mStart = mFinal = start;
+            mCurrentPosition = mStart = mFinal = start;
             mVelocity = 0;
 
             mStartTime = AnimationUtils.currentAnimationTimeMillis();
@@ -804,7 +804,7 @@
             final float totalDuration = (float) Math.sqrt(
                     2.0 * (distanceToApex + distanceToEdge) / Math.abs(mDeceleration));
             mStartTime -= (int) (1000.0f * (totalDuration - durationToApex));
-            mStart = end;
+            mCurrentPosition = mStart = end;
             mVelocity = (int) (- mDeceleration * totalDuration);
         }
 
@@ -873,7 +873,7 @@
                     // Duration from start to null velocity
                     if (mDuration < mSplineDuration) {
                         // If the animation was clamped, we reached the edge
-                        mStart = mFinal;
+                        mCurrentPosition = mStart = mFinal;
                         // TODO Better compute speed when edge was reached
                         mVelocity = (int) mCurrVelocity;
                         mDeceleration = getDeceleration(mVelocity);
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index da98a67..146c0f8 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -57,6 +57,11 @@
                 statsType);
         app.wifiTxBytes = u.getNetworkActivityBytes(BatteryStats.NETWORK_WIFI_TX_DATA,
                 statsType);
+
+        if (DEBUG && app.wifiPowerMah != 0) {
+            Log.d(TAG, "UID " + u.getUid() + ": idle=" + idleTime + "ms rx=" + rxTime + "ms tx=" +
+                    txTime + "ms power=" + BatteryStatsHelper.makemAh(app.wifiPowerMah));
+        }
     }
 
     @Override
diff --git a/core/java/com/android/internal/os/WifiPowerEstimator.java b/core/java/com/android/internal/os/WifiPowerEstimator.java
index c4e2ef6..3bd79f7e 100644
--- a/core/java/com/android/internal/os/WifiPowerEstimator.java
+++ b/core/java/com/android/internal/os/WifiPowerEstimator.java
@@ -16,11 +16,14 @@
 package com.android.internal.os;
 
 import android.os.BatteryStats;
+import android.util.Log;
 
 /**
  * Estimates WiFi power usage based on timers in BatteryStats.
  */
 public class WifiPowerEstimator extends PowerCalculator {
+    private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
+    private static final String TAG = "WifiPowerEstimator";
     private final double mWifiPowerPerPacket;
     private final double mWifiPowerOn;
     private final double mWifiPowerScan;
@@ -75,6 +78,10 @@
         }
 
         app.wifiPowerMah = wifiPacketPower + wifiLockPower + wifiScanPower + wifiBatchScanPower;
+        if (DEBUG && app.wifiPowerMah != 0) {
+            Log.d(TAG, "UID " + u.getUid() + ": power=" +
+                    BatteryStatsHelper.makemAh(app.wifiPowerMah));
+        }
     }
 
     @Override
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 2b39528..0bd8d85 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -72,6 +72,7 @@
 import com.android.internal.widget.BackgroundFallback;
 import com.android.internal.widget.DecorContentParent;
 import com.android.internal.widget.FloatingToolbar;
+import com.android.internal.widget.NonClientDecorView;
 import com.android.internal.widget.SwipeDismissLayout;
 
 import android.app.ActivityManager;
@@ -1270,7 +1271,7 @@
      * @param st The panel being initialized.
      */
     protected boolean initializePanelDecor(PanelFeatureState st) {
-        st.decorView = new DecorView(getContext(), st.featureId);
+        st.decorView = generateDecor(st.featureId);
         st.gravity = Gravity.CENTER | Gravity.BOTTOM;
         st.setStyle(getContext());
         TypedArray a = getContext().obtainStyledAttributes(null,
@@ -2204,6 +2205,9 @@
 
         private final Rect mFrameOffsets = new Rect();
 
+        // True if a non client area decor exists.
+        private boolean mHasNonClientDecor = false;
+
         private boolean mChanging;
 
         private Drawable mMenuBackground;
@@ -3148,53 +3152,59 @@
                 return;
             }
 
-            setPadding(mFramePadding.left + mBackgroundPadding.left, mFramePadding.top
-                    + mBackgroundPadding.top, mFramePadding.right + mBackgroundPadding.right,
+            setPadding(mFramePadding.left + mBackgroundPadding.left,
+                    mFramePadding.top + mBackgroundPadding.top,
+                    mFramePadding.right + mBackgroundPadding.right,
                     mFramePadding.bottom + mBackgroundPadding.bottom);
             requestLayout();
             invalidate();
 
             int opacity = PixelFormat.OPAQUE;
-            // Note: if there is no background, we will assume opaque. The
-            // common case seems to be that an application sets there to be
-            // no background so it can draw everything itself. For that,
-            // we would like to assume OPAQUE and let the app force it to
-            // the slower TRANSLUCENT mode if that is really what it wants.
-            Drawable bg = getBackground();
-            Drawable fg = getForeground();
-            if (bg != null) {
-                if (fg == null) {
-                    opacity = bg.getOpacity();
-                } else if (mFramePadding.left <= 0 && mFramePadding.top <= 0
-                        && mFramePadding.right <= 0 && mFramePadding.bottom <= 0) {
-                    // If the frame padding is zero, then we can be opaque
-                    // if either the frame -or- the background is opaque.
-                    int fop = fg.getOpacity();
-                    int bop = bg.getOpacity();
-                    if (false)
-                        Log.v(TAG, "Background opacity: " + bop + ", Frame opacity: " + fop);
-                    if (fop == PixelFormat.OPAQUE || bop == PixelFormat.OPAQUE) {
-                        opacity = PixelFormat.OPAQUE;
-                    } else if (fop == PixelFormat.UNKNOWN) {
-                        opacity = bop;
-                    } else if (bop == PixelFormat.UNKNOWN) {
-                        opacity = fop;
+            if (windowHasShadow()) {
+                // If the window has a shadow, it must be translucent.
+                opacity = PixelFormat.TRANSLUCENT;
+            } else{
+                // Note: If there is no background, we will assume opaque. The
+                // common case seems to be that an application sets there to be
+                // no background so it can draw everything itself. For that,
+                // we would like to assume OPAQUE and let the app force it to
+                // the slower TRANSLUCENT mode if that is really what it wants.
+                Drawable bg = getBackground();
+                Drawable fg = getForeground();
+                if (bg != null) {
+                    if (fg == null) {
+                        opacity = bg.getOpacity();
+                    } else if (mFramePadding.left <= 0 && mFramePadding.top <= 0
+                            && mFramePadding.right <= 0 && mFramePadding.bottom <= 0) {
+                        // If the frame padding is zero, then we can be opaque
+                        // if either the frame -or- the background is opaque.
+                        int fop = fg.getOpacity();
+                        int bop = bg.getOpacity();
+                        if (false)
+                            Log.v(TAG, "Background opacity: " + bop + ", Frame opacity: " + fop);
+                        if (fop == PixelFormat.OPAQUE || bop == PixelFormat.OPAQUE) {
+                            opacity = PixelFormat.OPAQUE;
+                        } else if (fop == PixelFormat.UNKNOWN) {
+                            opacity = bop;
+                        } else if (bop == PixelFormat.UNKNOWN) {
+                            opacity = fop;
+                        } else {
+                            opacity = Drawable.resolveOpacity(fop, bop);
+                        }
                     } else {
-                        opacity = Drawable.resolveOpacity(fop, bop);
+                        // For now we have to assume translucent if there is a
+                        // frame with padding... there is no way to tell if the
+                        // frame and background together will draw all pixels.
+                        if (false)
+                            Log.v(TAG, "Padding: " + mFramePadding);
+                        opacity = PixelFormat.TRANSLUCENT;
                     }
-                } else {
-                    // For now we have to assume translucent if there is a
-                    // frame with padding... there is no way to tell if the
-                    // frame and background together will draw all pixels.
-                    if (false)
-                        Log.v(TAG, "Padding: " + mFramePadding);
-                    opacity = PixelFormat.TRANSLUCENT;
                 }
+                if (false)
+                    Log.v(TAG, "Background: " + bg + ", Frame: " + fg);
             }
 
             if (false)
-                Log.v(TAG, "Background: " + bg + ", Frame: " + fg);
-            if (false)
                 Log.v(TAG, "Selected default opacity: " + opacity);
 
             mDefaultOpacity = opacity;
@@ -3401,8 +3411,7 @@
                         }
                     };
                 } else {
-                    ViewStub stub = (ViewStub) findViewById(
-                            R.id.action_mode_bar_stub);
+                    ViewStub stub = (ViewStub) findViewById(R.id.action_mode_bar_stub);
                     if (stub != null) {
                         mPrimaryActionModeView = (ActionBarContextView) stub.inflate();
                     }
@@ -3490,6 +3499,28 @@
                 .addOnPreDrawListener(mFloatingToolbarPreDrawListener);
         }
 
+        // Set when the window is free floating and a non client decor frame was added.
+        void enableNonClientDecor(boolean enable) {
+            if (mHasNonClientDecor != enable) {
+                mHasNonClientDecor = enable;
+                if (getForeground() != null) {
+                    drawableChanged();
+                }
+            }
+        }
+
+        // Returns true if the window has a non client decor.
+        private boolean windowHasNonClientDecor() {
+            return mHasNonClientDecor;
+        }
+
+        // Returns true if the Window is free floating and has a shadow. Note that non overlapping
+        // windows do not have a shadow since it could not be seen anyways (a small screen / tablet
+        // "tiles" the windows side by side but does not overlap them).
+        private boolean windowHasShadow() {
+            return windowHasNonClientDecor() && getElevation() > 0;
+        }
+
         /**
          * Clears out internal references when the action mode is destroyed.
          */
@@ -3599,8 +3630,8 @@
         }
     }
 
-    protected DecorView generateDecor() {
-        return new DecorView(getContext(), -1);
+    protected DecorView generateDecor(int featureId) {
+        return new DecorView(getContext(), featureId);
     }
 
     protected void setFeatureFromAttrs(int featureId, TypedArray attrs,
@@ -3879,8 +3910,15 @@
 
         mDecor.startChanging();
 
+        NonClientDecorView nonClientDecorView = createNonClientDecorView();
         View in = mLayoutInflater.inflate(layoutResource, null);
-        decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+        if (nonClientDecorView != null) {
+            decor.addView(nonClientDecorView,
+                    new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+            nonClientDecorView.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+        } else {
+            decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+        }
         mContentRoot = (ViewGroup) in;
 
         ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
@@ -3936,6 +3974,54 @@
         return contentParent;
     }
 
+    // Free floating overlapping windows require a non client decor with a caption and shadow..
+    private NonClientDecorView createNonClientDecorView() {
+        boolean needsDecor = true;
+        NonClientDecorView nonClientDecorView = null;
+
+        final WindowManager.LayoutParams attrs = getAttributes();
+        // TODO(skuhne): Use the associated stack to figure out if the window is on the free style
+        // desktop, the side by side desktop or the full screen desktop. With that informations the
+        // choice is fairly easy to decide.
+        // => This is only a kludge for now to suppress fullscreen windows, recents, launcher, etc..
+        boolean isFullscreen =
+                0 != ((mDecor.getWindowSystemUiVisibility() | mDecor.getSystemUiVisibility()) &
+                        (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION));
+        boolean isApplication = attrs.type != TYPE_BASE_APPLICATION &&
+                attrs.type != TYPE_APPLICATION;
+
+        // We do not show the non client decor if...
+        // - this is a floating dialog (which is not a real window, e.g. it cannot be maximized).
+        // - it is not an application (special windows have special functions, e.g text selector).
+        // - the application is full screen, drawing everything (since the decor would be out of the
+        //   screen in that case and could not be seen).
+        if (isFloating() || isFullscreen || isApplication) {
+            needsDecor = false;
+        }
+
+        if (needsDecor) {
+            // TODO(skuhne): If running in side by side mode on a device - turn off the shadow.
+            boolean windowHasShadow = true;
+            // Dependent on the brightness of the used title we either use the
+            // dark or the light button frame.
+            TypedValue value = new TypedValue();
+            getContext().getTheme().resolveAttribute(R.attr.colorPrimary, value, true);
+            if (Color.brightness(value.data) < 0.5) {
+                nonClientDecorView = (NonClientDecorView) mLayoutInflater.inflate(
+                        R.layout.non_client_decor_dark, null);
+            } else {
+                nonClientDecorView = (NonClientDecorView) mLayoutInflater.inflate(
+                        R.layout.non_client_decor_light, null);
+            }
+            nonClientDecorView.setPhoneWindow(this, windowHasShadow);
+        }
+
+        // Tell the Decor if it has a non client decor.
+        mDecor.enableNonClientDecor(needsDecor);
+
+        return nonClientDecorView;
+    }
+
     /** @hide */
     public void alwaysReadCloseOnTouchAttr() {
         mAlwaysReadCloseOnTouchAttr = true;
@@ -3943,7 +4029,7 @@
 
     private void installDecor() {
         if (mDecor == null) {
-            mDecor = generateDecor();
+            mDecor = generateDecor(-1);
             mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
             mDecor.setIsRootNamespace(true);
             if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
diff --git a/core/java/com/android/internal/widget/NonClientDecorView.java b/core/java/com/android/internal/widget/NonClientDecorView.java
new file mode 100644
index 0000000..57039b7
--- /dev/null
+++ b/core/java/com/android/internal/widget/NonClientDecorView.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2015 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.internal.widget;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.util.Log;
+import android.util.TypedValue;
+
+import android.view.ViewOutlineProvider;
+import android.view.WindowInsets;
+import com.android.internal.R;
+import com.android.internal.policy.PhoneWindow;
+
+import java.util.List;
+
+/**
+ * This class represents the special screen elements to control a window on free form
+ * environment. All thse screen elements are added in the "non client area" which is the area of
+ * the window which is handled by the OS and not the application.
+ * As such this class handles the following things:
+ * <ul>
+ * <li>The caption, containing the system buttons like maximize, close and such as well as
+ * allowing the user to drag the window around.</li>
+ * <li>The shadow - which is changing dependent on the window focus.</li>
+ * <li>The border around the client area (if there is one).</li>
+ * <li>The resize handles which allow to resize the window.</li>
+ * </ul>
+ * After creating the view, the function
+ * {@link #setPhoneWindow(PhoneWindow owner, boolean windowHasShadow)} needs to be called to make
+ * the connection to it's owning PhoneWindow.
+ * Note: At this time the application can change various attributes of the DecorView which
+ * will break things (in settle/unexpected ways):
+ * <ul>
+ * <li>setElevation</li>
+ * <li>setOutlineProvider</li>
+ * <li>setSurfaceFormat</li>
+ * <li>..</li>
+ * </ul>
+ * This will be mitigated once b/22527834 will be addressed.
+ */
+public class NonClientDecorView extends ViewGroup implements View.OnClickListener {
+    private final static String TAG = "NonClientDecorView";
+    // The height of a window which has focus in DIP.
+    private final int DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP = 20;
+    // The height of a window which has not in DIP.
+    private final int DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP = 5;
+
+    private PhoneWindow mOwner = null;
+    boolean mWindowHasShadow = false;
+
+    // The current focus state of the window for updating the window elevation.
+    boolean mWindowHasFocus = true;
+
+    // Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
+    // size calculation takes the shadow size into account. We set the elevation currently
+    // to max until the first layout command has been executed.
+    boolean mAllowUpdateElevation = false;
+
+    public NonClientDecorView(Context context) {
+        super(context);
+    }
+
+    public NonClientDecorView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public NonClientDecorView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+    }
+
+    public void setPhoneWindow(PhoneWindow owner, boolean windowHasShadow) {
+        mOwner = owner;
+        mWindowHasShadow = windowHasShadow;
+        if (mWindowHasShadow) {
+            // TODO(skuhne): Call setMaxElevation here as soon as b/22668382 got fixed.
+            updateElevation();
+        }
+        // By changing the outline provider to BOUNDS, the window can remove its
+        // background without removing the shadow.
+        mOwner.getDecorView().setOutlineProvider(ViewOutlineProvider.BOUNDS);
+        findViewById(R.id.maximize_window).setOnClickListener(this);
+        findViewById(R.id.close_window).setOnClickListener(this);
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (view.getId() == R.id.maximize_window) {
+            // TODO(skuhne): Add code to maximize window.
+        } else if (view.getId() == R.id.close_window) {
+            // TODO(skuhne): This is not the right way to kill an app and we should add a high level
+            // function for it.
+            final ActivityManager m =
+                    (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
+            List<RunningTaskInfo> runningTaskInfoList =  m.getRunningTasks(1);
+            if (!runningTaskInfoList.isEmpty()) {
+                try {
+                    ActivityManagerNative.getDefault().removeTask(runningTaskInfoList.get(0).id);
+                } catch (RemoteException ex) {
+                    Log.e(TAG, "Couldn't close task with the close button.");
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onWindowFocusChanged(boolean hasWindowFocus) {
+        mWindowHasFocus = hasWindowFocus;
+        updateElevation();
+        super.onWindowFocusChanged(hasWindowFocus);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        measureChildren(widthMeasureSpec, heightMeasureSpec);
+        final int width = MeasureSpec.getSize(widthMeasureSpec);
+        final int height = MeasureSpec.getSize(heightMeasureSpec);
+        setMeasuredDimension(width, height);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        // The system inset needs only to be applied to the caption. The client area of
+        // the window will automatically be adjusted by the the DecorView.
+        WindowInsets insets = getRootWindowInsets();
+        int systemMargin = insets.getSystemWindowInsetTop();
+
+        final int leftPos = getPaddingLeft();
+        final int rightPos = right - left - getPaddingRight();
+        final int topPos = getPaddingTop();
+        final int bottomPos = bottom - top - getPaddingBottom();
+
+        // On top we have the caption which has to fill left to right with a fixed height.
+        final int width = rightPos - leftPos;
+        final View caption = getChildAt(0);
+
+        // If the application changed its SystemUI metrics, we might also have to adapt
+        // our shadow elevation.
+        updateElevation();
+        mAllowUpdateElevation = true;
+
+        // Remove the decor temporarily if the window entered a full screen/immersive mode.
+        final int captionHeight = isFillingScreen() ? 0 : caption.getMeasuredHeight();
+        caption.layout(leftPos, topPos + systemMargin, leftPos + width,
+                topPos + systemMargin + captionHeight);
+
+        // Note: We should never have more then 1 additional item in here.
+        if (getChildCount() > 1) {
+            getChildAt(1).layout(leftPos, topPos + captionHeight, leftPos + width, bottomPos);
+        }
+    }
+
+    // Make sure that we never get more then one client area in our view.
+    @Override
+    public void addView(View child, int index, LayoutParams params) {
+        if (index >= 2 || getChildCount() >= 2) {
+            throw new IllegalStateException("NonClientDecorView can only handle 1 client view");
+        }
+        super.addView(child, index, params);
+    }
+
+    // Returns true when the window is filling the entire screen and the non client area
+    // should not be shown.
+    private boolean isFillingScreen() {
+        return (0 != ((getWindowSystemUiVisibility() | getSystemUiVisibility()) &
+                (View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+                        View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_LOW_PROFILE)));
+    }
+
+    // The shadow height gets controlled by the focus to visualize highlighted windows.
+    // Note: This will overwrite application elevation properties.
+    // Note: Windows which have (temporarily) changed their attributes to cover the SystemUI
+    //       will get no shadow as they are expected to be "full screen".
+    private void updateElevation() {
+        float elevation = 0;
+        if (mWindowHasShadow) {
+            boolean fill = isFillingScreen();
+            elevation = fill ? 0 :
+                    (mWindowHasFocus ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP :
+                            DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP);
+            if (!mAllowUpdateElevation && !fill) {
+                // TODO(skuhne): Change this to setMaxElevation as soon as b/22668382 got fixed
+                // and remove this cludge.
+                elevation = DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
+            }
+            // Convert the DP elevation into physical pixels.
+            elevation = dipToPx(elevation);
+        }
+        // Don't change the elevation if it didn't change since it can require some time.
+        if (mOwner.getDecorView().getElevation() != elevation) {
+            mOwner.setElevation(elevation);
+        }
+    }
+
+    private float dipToPx(float dip) {
+        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip,
+                getResources().getDisplayMetrics());
+    }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 6b07a47..fc15b964 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -20,6 +20,10 @@
     LOCAL_CFLAGS += -DENABLE_CPUSETS
 endif
 
+ifneq ($(ENABLE_SCHED_BOOST),)
+    LOCAL_CFLAGS += -DENABLE_SCHED_BOOST
+endif
+
 LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
 
 LOCAL_CFLAGS += -DU_USING_ICU_NAMESPACE=0
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index db88962..dbf63b5 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -408,6 +408,27 @@
   }
 }
 
+#ifdef ENABLE_SCHED_BOOST
+static void SetForkLoad(bool boost) {
+  // set scheduler knob to boost forked processes
+  pid_t currentPid = getpid();
+  // fits at most "/proc/XXXXXXX/sched_init_task_load\0"
+  char schedPath[35];
+  snprintf(schedPath, sizeof(schedPath), "/proc/%u/sched_init_task_load", currentPid);
+  int schedBoostFile = open(schedPath, O_WRONLY);
+  if (schedBoostFile < 0) {
+    ALOGW("Unable to set zygote scheduler boost");
+    return;
+  }
+  if (boost) {
+    write(schedBoostFile, "100\0", 4);
+  } else {
+    write(schedBoostFile, "0\0", 2);
+  }
+  close(schedBoostFile);
+}
+#endif
+
 // Utility routine to fork zygote and specialize the child process.
 static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                      jint debug_flags, jobjectArray javaRlimits,
@@ -418,6 +439,10 @@
                                      jstring instructionSet, jstring dataDir) {
   SetSigChldHandler();
 
+#ifdef ENABLE_SCHED_BOOST
+  SetForkLoad(true);
+#endif
+
   pid_t pid = fork();
 
   if (pid == 0) {
@@ -558,6 +583,12 @@
     }
   } else if (pid > 0) {
     // the parent process
+
+#ifdef ENABLE_SCHED_BOOST
+    // unset scheduler knob
+    SetForkLoad(false);
+#endif
+
   }
   return pid;
 }
diff --git a/core/res/res/drawable/decor_close_button_dark.xml b/core/res/res/drawable/decor_close_button_dark.xml
new file mode 100644
index 0000000..e5ea1f3
--- /dev/null
+++ b/core/res/res/drawable/decor_close_button_dark.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="true"
+          android:drawable="@drawable/ic_decor_close_button_dark_focused" />
+    <item android:drawable="@drawable/ic_decor_close_button_dark_unfocused" />
+</selector>
+
diff --git a/core/res/res/drawable/decor_close_button_light.xml b/core/res/res/drawable/decor_close_button_light.xml
new file mode 100644
index 0000000..b77b2bd
--- /dev/null
+++ b/core/res/res/drawable/decor_close_button_light.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="true"
+          android:drawable="@drawable/ic_decor_close_button_light_focused" />
+    <item android:drawable="@drawable/ic_decor_close_button_light_unfocused" />
+</selector>
+
diff --git a/core/res/res/drawable/decor_maximize_button_dark.xml b/core/res/res/drawable/decor_maximize_button_dark.xml
new file mode 100644
index 0000000..5ea372b
--- /dev/null
+++ b/core/res/res/drawable/decor_maximize_button_dark.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="true"
+          android:drawable="@drawable/ic_decor_maximize_button_dark_focused" />
+    <item android:drawable="@drawable/ic_decor_maximize_button_dark_unfocused" />
+</selector>
+
diff --git a/core/res/res/drawable/decor_maximize_button_light.xml b/core/res/res/drawable/decor_maximize_button_light.xml
new file mode 100644
index 0000000..5bda131
--- /dev/null
+++ b/core/res/res/drawable/decor_maximize_button_light.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="true"
+          android:drawable="@drawable/ic_decor_maximize_button_light_focused" />
+    <item android:drawable="@drawable/ic_decor_maximize_button_light_unfocused" />
+</selector>
+
diff --git a/core/res/res/drawable/ic_decor_close_button_dark_focused.xml b/core/res/res/drawable/ic_decor_close_button_dark_focused.xml
new file mode 100644
index 0000000..d7b167dd
--- /dev/null
+++ b/core/res/res/drawable/ic_decor_close_button_dark_focused.xml
@@ -0,0 +1,29 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <group android:scaleX="0.5"
+           android:scaleY="0.5"
+           android:translateX="8.0"
+           android:translateY="8.0" >
+        <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M6.9,4.0l-2.9,2.9 9.1,9.1 -9.1,9.200001 2.9,2.799999 9.1,-9.1 9.1,9.1 2.9,-2.799999 -9.1,-9.200001 9.1,-9.1 -2.9,-2.9 -9.1,9.2z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/ic_decor_close_button_dark_unfocused.xml b/core/res/res/drawable/ic_decor_close_button_dark_unfocused.xml
new file mode 100644
index 0000000..e2e81b9
--- /dev/null
+++ b/core/res/res/drawable/ic_decor_close_button_dark_unfocused.xml
@@ -0,0 +1,29 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <group android:scaleX="0.5"
+           android:scaleY="0.5"
+           android:translateX="8.0"
+           android:translateY="8.0" >
+        <path
+            android:fillColor="#33FFFFFF"
+            android:pathData="M6.9,4.0l-2.9,2.9 9.1,9.1 -9.1,9.200001 2.9,2.799999 9.1,-9.1 9.1,9.1 2.9,-2.799999 -9.1,-9.200001 9.1,-9.1 -2.9,-2.9 -9.1,9.2z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/ic_decor_close_button_light_focused.xml b/core/res/res/drawable/ic_decor_close_button_light_focused.xml
new file mode 100644
index 0000000..0794ed3
--- /dev/null
+++ b/core/res/res/drawable/ic_decor_close_button_light_focused.xml
@@ -0,0 +1,29 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <group android:scaleX="0.5"
+           android:scaleY="0.5"
+           android:translateX="8.0"
+           android:translateY="8.0" >
+        <path
+            android:fillColor="#ff000000"
+            android:pathData="M6.9,4.0l-2.9,2.9 9.1,9.1 -9.1,9.200001 2.9,2.799999 9.1,-9.1 9.1,9.1 2.9,-2.799999 -9.1,-9.200001 9.1,-9.1 -2.9,-2.9 -9.1,9.2z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/ic_decor_close_button_light_unfocused.xml b/core/res/res/drawable/ic_decor_close_button_light_unfocused.xml
new file mode 100644
index 0000000..bd1db51
--- /dev/null
+++ b/core/res/res/drawable/ic_decor_close_button_light_unfocused.xml
@@ -0,0 +1,29 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <group android:scaleX="0.5"
+           android:scaleY="0.5"
+           android:translateX="8.0"
+           android:translateY="8.0" >
+        <path
+            android:fillColor="#33000000"
+            android:pathData="M6.9,4.0l-2.9,2.9 9.1,9.1 -9.1,9.200001 2.9,2.799999 9.1,-9.1 9.1,9.1 2.9,-2.799999 -9.1,-9.200001 9.1,-9.1 -2.9,-2.9 -9.1,9.2z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/ic_decor_maximize_button_dark_focused.xml b/core/res/res/drawable/ic_decor_maximize_button_dark_focused.xml
new file mode 100644
index 0000000..73d808b
--- /dev/null
+++ b/core/res/res/drawable/ic_decor_maximize_button_dark_focused.xml
@@ -0,0 +1,32 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <group android:scaleX="0.5"
+           android:scaleY="0.5"
+           android:translateX="8.0"
+           android:translateY="8.0" >
+        <path
+            android:fillColor="#FFFFFFFF"
+            android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/>
+        <path
+            android:fillColor="#B2FFFFFF"
+            android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/ic_decor_maximize_button_dark_unfocused.xml b/core/res/res/drawable/ic_decor_maximize_button_dark_unfocused.xml
new file mode 100644
index 0000000..dc79e10
--- /dev/null
+++ b/core/res/res/drawable/ic_decor_maximize_button_dark_unfocused.xml
@@ -0,0 +1,32 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <group android:scaleX="0.5"
+           android:scaleY="0.5"
+           android:translateX="8.0"
+           android:translateY="8.0" >
+        <path
+            android:fillColor="#33FFFFFF"
+            android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/>
+        <path
+            android:fillColor="#33FFFFFF"
+            android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/ic_decor_maximize_button_light_focused.xml b/core/res/res/drawable/ic_decor_maximize_button_light_focused.xml
new file mode 100644
index 0000000..c23390e
--- /dev/null
+++ b/core/res/res/drawable/ic_decor_maximize_button_light_focused.xml
@@ -0,0 +1,32 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <group android:scaleX="0.5"
+           android:scaleY="0.5"
+           android:translateX="8.0"
+           android:translateY="8.0" >
+        <path
+            android:fillColor="#FF000000"
+            android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/>
+        <path
+            android:fillColor="#B2000000"
+            android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/ic_decor_maximize_button_light_unfocused.xml b/core/res/res/drawable/ic_decor_maximize_button_light_unfocused.xml
new file mode 100644
index 0000000..a194a39
--- /dev/null
+++ b/core/res/res/drawable/ic_decor_maximize_button_light_unfocused.xml
@@ -0,0 +1,32 @@
+<!--
+Copyright (C) 2015 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="32.0dp"
+        android:height="32.0dp"
+        android:viewportWidth="32.0"
+        android:viewportHeight="32.0">
+    <group android:scaleX="0.5"
+           android:scaleY="0.5"
+           android:translateX="8.0"
+           android:translateY="8.0" >
+        <path
+            android:fillColor="#33000000"
+            android:pathData="M2.0,4.0l0.0,16.0l28.0,0.0L30.0,4.0L2.0,4.0zM26.0,16.0L6.0,16.0L6.0,8.0l20.0,0.0L26.0,16.0z"/>
+        <path
+            android:fillColor="#33000000"
+            android:pathData="M2.0,24.0l28.0,0.0l0.0,4.0l-28.0,0.0z"/>
+    </group>
+</vector>
diff --git a/core/res/res/drawable/non_client_decor_title.xml b/core/res/res/drawable/non_client_decor_title.xml
new file mode 100644
index 0000000..e50daea
--- /dev/null
+++ b/core/res/res/drawable/non_client_decor_title.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="true"
+          android:drawable="@drawable/non_client_decor_title_focused" />
+    <item android:drawable="@drawable/non_client_decor_title_unfocused" />
+</selector>
diff --git a/core/res/res/drawable/non_client_decor_title_focused.xml b/core/res/res/drawable/non_client_decor_title_focused.xml
new file mode 100644
index 0000000..7d1c230
--- /dev/null
+++ b/core/res/res/drawable/non_client_decor_title_focused.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<shape android:shape="rectangle"
+       android:tintMode="multiply"
+       android:tint="#D8D8D8"
+       xmlns:android="http://schemas.android.com/apk/res/android">
+     <!-- Fading the primary color to 85% blackness -->
+     <solid android:color="?android:attr/colorPrimary" />
+</shape>
diff --git a/core/res/res/drawable/non_client_decor_title_unfocused.xml b/core/res/res/drawable/non_client_decor_title_unfocused.xml
new file mode 100644
index 0000000..2846d8ca
--- /dev/null
+++ b/core/res/res/drawable/non_client_decor_title_unfocused.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2015 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.
+-->
+
+<shape android:shape="rectangle"
+       android:tintMode="multiply"
+       android:tint="#F2F2F2"
+       xmlns:android="http://schemas.android.com/apk/res/android">
+     <!-- Fading the primary color to 95% blackness -->
+     <solid android:color="?android:attr/colorPrimary"/>
+</shape>
diff --git a/core/res/res/layout/non_client_decor_dark.xml b/core/res/res/layout/non_client_decor_dark.xml
new file mode 100644
index 0000000..00b4255
--- /dev/null
+++ b/core/res/res/layout/non_client_decor_dark.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2015, 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.
+*/
+-->
+
+<com.android.internal.widget.NonClientDecorView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="top|start"
+    android:descendantFocusability="beforeDescendants" >
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_gravity="end"
+        android:layout_height="wrap_content"
+        android:background="@drawable/non_client_decor_title" >
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+        <Button
+            android:id="@+id/maximize_window"
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:layout_margin="5dp"
+            android:padding="4dp"
+            android:layout_gravity="center_vertical|end"
+            android:contentDescription="@string/maximize_button_text"
+            android:background="@drawable/decor_maximize_button_dark" />
+         <Button
+            android:id="@+id/close_window"
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:layout_margin="5dp"
+            android:padding="4dp"
+            android:layout_gravity="center_vertical|end"
+            android:contentDescription="@string/close_button_text"
+            android:background="@drawable/decor_close_button_dark" />
+    </LinearLayout>
+</com.android.internal.widget.NonClientDecorView>
diff --git a/core/res/res/layout/non_client_decor_light.xml b/core/res/res/layout/non_client_decor_light.xml
new file mode 100644
index 0000000..0ce8fa7
--- /dev/null
+++ b/core/res/res/layout/non_client_decor_light.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2015, 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.
+*/
+-->
+
+<com.android.internal.widget.NonClientDecorView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="top|start"
+    android:descendantFocusability="beforeDescendants" >
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_gravity="end"
+        android:layout_height="wrap_content"
+        android:background="@drawable/non_client_decor_title" >
+        <TextView
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1" />
+        <Button
+            android:id="@+id/maximize_window"
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:layout_margin="5dp"
+            android:padding="4dp"
+            android:layout_gravity="center_vertical|end"
+            android:contentDescription="@string/maximize_button_text"
+            android:background="@drawable/decor_maximize_button_light" />
+         <Button
+            android:id="@+id/close_window"
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:layout_margin="5dp"
+            android:padding="4dp"
+            android:layout_gravity="center_vertical|end"
+            android:contentDescription="@string/close_button_text"
+            android:background="@drawable/decor_close_button_light" />
+    </LinearLayout>
+</com.android.internal.widget.NonClientDecorView>
diff --git a/core/res/res/values-mcc202-mnc05/config.xml b/core/res/res/values-mcc202-mnc05/config.xml
deleted file mode 100644
index c74f2d7..0000000
--- a/core/res/res/values-mcc202-mnc05/config.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2013, 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 my 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.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
-     for different hardware and product builds. -->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Array of ConnectivityManager.TYPE_xxxx values allowable for tethering -->
-    <!-- Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or
-    <!== [0,1,5,7] for TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI and TYPE_BLUETOOTH -->
-    <integer-array translatable="false" name="config_tether_upstream_types">
-      <item>1</item>
-      <item>4</item>
-      <item>7</item>
-      <item>9</item>
-    </integer-array>
-
-    <!-- String containing the apn value for tethering.  May be overriden by secure settings
-         TETHER_DUN_APN.  Value is a comma separated series of strings:
-         "name,apn,proxy,port,username,password,server,mmsc,mmsproxy,mmsport,mcc,mnc,auth,type",
-         Or string format of ApnSettingV3.
-         note that empty fields can be ommitted: "name,apn,,,,,,,,,310,260,,DUN" -->
-    <string-array translatable="false" name="config_tether_apndata">
-      <item>Vf Tethering,internet.vodafone.gr,,,,,,,,,202,05,,DUN</item>
-    </string-array>
-
-</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index aa15b5a..398c584 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -505,16 +505,16 @@
     <bool translatable="false" name="config_wifi_ssid_white_list_enable">true</bool>
 
     <!-- Idle Receive current for wifi radio. 0 by default-->
-    <integer translatable="false" name="config_wifi_idle_receive_cur_ma">1</integer>
+    <integer translatable="false" name="config_wifi_idle_receive_cur_ma">0</integer>
 
     <!-- Rx current for wifi radio. 0 by default-->
-    <integer translatable="false" name="config_wifi_active_rx_cur_ma">2</integer>
+    <integer translatable="false" name="config_wifi_active_rx_cur_ma">0</integer>
 
     <!-- Tx current for wifi radio. 0 by default-->
-    <integer translatable="false" name="config_wifi_tx_cur_ma">3</integer>
+    <integer translatable="false" name="config_wifi_tx_cur_ma">0</integer>
 
     <!-- Operating volatage for wifi radio. 0 by default-->
-    <integer translatable="false" name="config_wifi_operating_voltage_mv">4</integer>
+    <integer translatable="false" name="config_wifi_operating_voltage_mv">0</integer>
 
     <!-- Flag indicating whether the we should enable the automatic brightness in Settings.
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 7cdad4b..ac6204d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4056,6 +4056,12 @@
     <!-- Content description for the button that closes the floating toolbar overflow. [CHAR LIMIT=NONE] -->
     <string name="floating_toolbar_close_overflow_description">Close overflow</string>
 
+    <!-- Free style window strings -->
+    <!-- Accessibility text for the maximize window button -->
+    <string name="maximize_button_text">Maximize</string>
+    <!-- Accessibility text for the close window button -->
+    <string name="close_button_text">Close</string>
+
     <!-- Ellipsis character to appear in notification templates, e.g.
          notification_template_material_inbox.xml.
          DO NOT TRANSLATE -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5303d5f..a45d907 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1939,6 +1939,10 @@
 
   <!-- From Phone -->
   <java-symbol type="bool" name="config_built_in_sip_phone" />
+  <java-symbol type="id" name="maximize_window" />
+  <java-symbol type="id" name="close_window" />
+  <java-symbol type="layout" name="non_client_decor_light" />
+  <java-symbol type="layout" name="non_client_decor_dark" />
 
   <!-- From TelephonyProvider -->
   <java-symbol type="xml" name="apns" />
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index bdb1f58..6104264 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -156,6 +156,8 @@
 
     /**
      * @return An array of sample rates supported by the audio device.
+     *
+     * Note: an empty array indicates that the device supports arbitrary rates.
      */
     public @NonNull int[] getSampleRates() {
         return mPort.samplingRates();
@@ -166,6 +168,8 @@
      * {@link AudioFormat#CHANNEL_OUT_7POINT1}) for which this audio device can be configured.
      *
      * @see AudioFormat
+     *
+     * Note: an empty array indicates that the device supports arbitrary channel masks.
      */
     public @NonNull int[] getChannelMasks() {
         return mPort.channelMasks();
@@ -175,6 +179,8 @@
      * @return An array of channel index masks for which this audio device can be configured.
      *
      * @see AudioFormat
+     *
+     * Note: an empty array indicates that the device supports arbitrary channel index masks.
      */
     public @NonNull int[] getChannelIndexMasks() {
         return mPort.channelIndexMasks();
@@ -183,6 +189,8 @@
     /**
      * @return An array of channel counts (1, 2, 4, ...) for which this audio device
      * can be configured.
+     *
+     * Note: an empty array indicates that the device supports arbitrary channel counts.
      */
     public @NonNull int[] getChannelCounts() {
         int[] masks = getChannelMasks();
@@ -205,6 +213,8 @@
      * integer precision to that device.
      *
      * @see AudioFormat
+     *
+     * Note: an empty array indicates that the device supports arbitrary encodings.
      */
     public @NonNull int[] getEncodings() {
         return AudioFormat.filterPublicFormats(mPort.formats());
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index 89230fe..7197dc0 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -24,7 +24,7 @@
 import android.os.RemoteException;
 import android.util.Log;
 
-import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This class is the public application interface to the MIDI service.
@@ -61,8 +61,8 @@
     private final IMidiManager mService;
     private final IBinder mToken = new Binder();
 
-    private HashMap<DeviceCallback,DeviceListener> mDeviceListeners =
-        new HashMap<DeviceCallback,DeviceListener>();
+    private ConcurrentHashMap<DeviceCallback,DeviceListener> mDeviceListeners =
+        new ConcurrentHashMap<DeviceCallback,DeviceListener>();
 
     // Binder stub for receiving device notifications from MidiService
     private class DeviceListener extends IMidiDeviceListener.Stub {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 5183c35..55d85206 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -557,6 +557,7 @@
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
 
+        @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
             if (DEBUG) Log.d(TAG, "received broadcast " + action);
@@ -610,6 +611,7 @@
 
     private final BroadcastReceiver mBroadcastAllReceiver = new BroadcastReceiver() {
 
+        @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
             if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(action)) {
@@ -724,6 +726,7 @@
             return new SimData(state, slotId, subId);
         }
 
+        @Override
         public String toString() {
             return "SimData{state=" + simState + ",slotId=" + slotId + ",subId=" + subId + "}";
         }
@@ -939,7 +942,9 @@
     }
 
     private boolean shouldListenForFingerprint() {
-        return mKeyguardIsVisible && !mSwitchingUser;
+        return mKeyguardIsVisible && !mSwitchingUser &&
+                mTrustManager.hasUserAuthenticatedSinceBoot(
+                        ActivityManager.getCurrentUser());
     }
 
     private void startListeningForFingerprint() {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 9a63642..c9db29e 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -17,8 +17,10 @@
 package com.android.mtp;
 
 import android.content.ContentResolver;
+import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.database.MatrixCursor;
+import android.graphics.Point;
 import android.os.CancellationSignal;
 import android.os.ParcelFileDescriptor;
 import android.provider.DocumentsContract;
@@ -170,7 +172,37 @@
         try {
             final MtpDocument document =
                     mMtpManager.getDocument(identifier.mDeviceId, identifier.mObjectHandle);
-            return mPipeManager.readDocument(mMtpManager, identifier, document.getSize());
+            return mPipeManager.readDocument(mMtpManager, identifier);
+        } catch (IOException error) {
+            throw new FileNotFoundException(error.getMessage());
+        }
+    }
+
+    @Override
+    public AssetFileDescriptor openDocumentThumbnail(
+            String documentId,
+            Point sizeHint,
+            CancellationSignal signal) throws FileNotFoundException {
+        final Identifier identifier = Identifier.createFromDocumentId(documentId);
+        try {
+            return new AssetFileDescriptor(
+                    mPipeManager.readThumbnail(mMtpManager, identifier),
+                    0,
+                    AssetFileDescriptor.UNKNOWN_LENGTH);
+        } catch (IOException error) {
+            throw new FileNotFoundException(error.getMessage());
+        }
+    }
+
+    @Override
+    public void deleteDocument(String documentId) throws FileNotFoundException {
+        try {
+            final Identifier identifier = Identifier.createFromDocumentId(documentId);
+            final int parentHandle =
+                    mMtpManager.getParent(identifier.mDeviceId, identifier.mObjectHandle);
+            mMtpManager.deleteDocument(identifier.mDeviceId, identifier.mObjectHandle);
+            notifyChildDocumentsChange(new Identifier(
+                    identifier.mDeviceId, identifier.mStorageId, parentHandle).toDocumentId());
         } catch (IOException error) {
             throw new FileNotFoundException(error.getMessage());
         }
@@ -201,20 +233,6 @@
         }
     }
 
-    @Override
-    public void deleteDocument(String documentId) throws FileNotFoundException {
-        try {
-            final Identifier identifier = Identifier.createFromDocumentId(documentId);
-            final int parentHandle =
-                    mMtpManager.getParent(identifier.mDeviceId, identifier.mObjectHandle);
-            mMtpManager.deleteDocument(identifier.mDeviceId, identifier.mObjectHandle);
-            notifyChildDocumentsChange(new Identifier(
-                    identifier.mDeviceId, identifier.mStorageId, parentHandle).toDocumentId());
-        } catch (IOException error) {
-            throw new FileNotFoundException(error.getMessage());
-        }
-    }
-
     boolean hasOpenedDevices() {
         return mMtpManager.getOpenedDeviceIds().length != 0;
     }
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 5057451..d4ee668 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -21,6 +21,7 @@
 import android.hardware.usb.UsbDeviceConnection;
 import android.hardware.usb.UsbManager;
 import android.mtp.MtpDevice;
+import android.os.ParcelFileDescriptor;
 import android.util.SparseArray;
 
 import java.io.FileNotFoundException;
@@ -110,6 +111,11 @@
         return device.getObject(objectHandle, expectedSize);
     }
 
+    synchronized byte[] getThumbnail(int deviceId, int objectHandle) throws IOException {
+        final MtpDevice device = getDevice(deviceId);
+        return device.getThumbnail(objectHandle);
+    }
+
     synchronized void deleteDocument(int deviceId, int objectHandle) throws IOException {
         final MtpDevice device = getDevice(deviceId);
         if (!device.deleteObject(objectHandle)) {
@@ -126,6 +132,11 @@
         return result;
     }
 
+    synchronized void importFile(int deviceId, int objectHandle, ParcelFileDescriptor target)
+            throws IOException {
+        throw new UnsupportedOperationException("Importing files is not supported.");
+    }
+
     private MtpDevice getDevice(int deviceId) throws IOException {
         final MtpDevice device = mDevices.get(deviceId);
         if (device == null) {
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
index a2c7772..7f498f5 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/PipeManager.java
@@ -34,52 +34,78 @@
         this.mExecutor = executor;
     }
 
-    ParcelFileDescriptor readDocument(
-            final MtpManager model,
-            final Identifier identifier,
-            final int expectedSize) throws IOException {
-        final Task task = new Task() {
-            @Override
-            byte[] getBytes() throws IOException {
-                // TODO: Use importFile to ParcelFileDescripter after implementing this.
-                return model.getObject(
-                        identifier.mDeviceId, identifier.mObjectHandle, expectedSize);
-            }
-        };
+    ParcelFileDescriptor readDocument(MtpManager model, Identifier identifier) throws IOException {
+        final Task task = new ImportFileTask(model, identifier);
+        mExecutor.execute(task);
+        return task.getReadingFileDescriptor();
+    }
+
+    ParcelFileDescriptor readThumbnail(MtpManager model, Identifier identifier) throws IOException {
+        final Task task = new GetThumbnailTask(model, identifier);
         mExecutor.execute(task);
         return task.getReadingFileDescriptor();
     }
 
     private static abstract class Task implements Runnable {
-        private final ParcelFileDescriptor[] mDescriptors;
+        protected final MtpManager mModel;
+        protected final Identifier mIdentifier;
+        protected final ParcelFileDescriptor[] mDescriptors;
 
-        Task() throws IOException {
+        Task(MtpManager model, Identifier identifier) throws IOException {
+            mModel = model;
+            mIdentifier = identifier;
             mDescriptors = ParcelFileDescriptor.createReliablePipe();
         }
 
-        abstract byte[] getBytes() throws IOException;
-
-        @Override
-        public void run() {
-            try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
-                    new ParcelFileDescriptor.AutoCloseOutputStream(mDescriptors[1])) {
-                try {
-                    final byte[] bytes = getBytes();
-                    stream.write(bytes);
-                } catch (IOException error) {
-                    mDescriptors[1].closeWithError("Failed to load bytes.");
-                    return;
-                }
-            } catch (IOException closeError) {
-                Log.d(MtpDocumentsProvider.TAG, closeError.getMessage());
-            }
-        }
-
         ParcelFileDescriptor getReadingFileDescriptor() {
             return mDescriptors[0];
         }
     }
 
+    private static class ImportFileTask extends Task {
+        ImportFileTask(MtpManager model, Identifier identifier) throws IOException {
+            super(model, identifier);
+        }
+
+        @Override
+        public void run() {
+            try {
+                mModel.importFile(
+                        mIdentifier.mDeviceId, mIdentifier.mObjectHandle, mDescriptors[1]);
+                mDescriptors[1].close();
+            } catch (IOException error) {
+                try {
+                    mDescriptors[1].closeWithError("Failed to stream a file.");
+                } catch (IOException closeError) {
+                    Log.w(MtpDocumentsProvider.TAG, closeError.getMessage());
+                }
+            }
+        }
+    }
+
+    private static class GetThumbnailTask extends Task {
+        GetThumbnailTask(MtpManager model, Identifier identifier) throws IOException {
+            super(model, identifier);
+        }
+
+        @Override
+        public void run() {
+            try {
+                try (final ParcelFileDescriptor.AutoCloseOutputStream stream =
+                        new ParcelFileDescriptor.AutoCloseOutputStream(mDescriptors[1])) {
+                    try {
+                        stream.write(mModel.getThumbnail(
+                                mIdentifier.mDeviceId, mIdentifier.mObjectHandle));
+                    } catch (IOException error) {
+                        mDescriptors[1].closeWithError("Failed to stream a thumbnail.");
+                    }
+                }
+            } catch (IOException closeError) {
+                Log.w(MtpDocumentsProvider.TAG, closeError.getMessage());
+            }
+        }
+    }
+
     void close() {
         mExecutor.shutdown();
     }
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
index 3c295ee..35918e1 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/PipeManagerTest.java
@@ -27,30 +27,60 @@
 
 @SmallTest
 public class PipeManagerTest extends AndroidTestCase {
+    private static final byte[] HELLO_BYTES = new byte[] { 'h', 'e', 'l', 'l', 'o' };
+
+    private TestMtpManager mtpManager;
+    private ExecutorService executor;
+    private PipeManager pipeManager;
+
+    @Override
+    public void setUp() {
+        mtpManager = new TestMtpManager(getContext());
+        executor = Executors.newSingleThreadExecutor();
+        pipeManager = new PipeManager(executor);
+    }
+
     public void testReadDocument_basic() throws Exception {
-        final TestMtpManager mtpManager = new TestMtpManager(getContext());
-        final byte[] expectedBytes = new byte[] { 'h', 'e', 'l', 'l', 'o' };
-        mtpManager.setObjectBytes(0, 1, 5, expectedBytes);
-        final ExecutorService executor = Executors.newSingleThreadExecutor();
-        final PipeManager pipeManager = new PipeManager(executor);
+        mtpManager.setImportFileBytes(0, 1, HELLO_BYTES);
         final ParcelFileDescriptor descriptor = pipeManager.readDocument(
-                mtpManager, new Identifier(0, 0, 1), 5);
+                mtpManager, new Identifier(0, 0, 1));
+        assertDescriptor(descriptor, HELLO_BYTES);
+    }
+
+    public void testReadDocument_error() throws Exception {
+        final ParcelFileDescriptor descriptor =
+                pipeManager.readDocument(mtpManager, new Identifier(0, 0, 1));
+        assertDescriptorError(descriptor);
+    }
+
+    public void testReadThumbnail_basic() throws Exception {
+        mtpManager.setThumbnail(0, 1, HELLO_BYTES);
+        final ParcelFileDescriptor descriptor = pipeManager.readThumbnail(
+                mtpManager, new Identifier(0, 0, 1));
+        assertDescriptor(descriptor, HELLO_BYTES);
+    }
+
+    public void testReadThumbnail_error() throws Exception {
+        final ParcelFileDescriptor descriptor =
+                pipeManager.readThumbnail(mtpManager, new Identifier(0, 0, 1));
+        assertDescriptorError(descriptor);
+    }
+
+    private void assertDescriptor(ParcelFileDescriptor descriptor, byte[] expectedBytes)
+            throws IOException, InterruptedException {
+        executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
         try (final ParcelFileDescriptor.AutoCloseInputStream stream =
                 new ParcelFileDescriptor.AutoCloseInputStream(descriptor)) {
-            final byte[] results = new byte[100];
-            assertEquals(5, stream.read(results));
-            for (int i = 0; i < 5; i++) {
+            byte[] results = new byte[100];
+            assertEquals(expectedBytes.length, stream.read(results));
+            for (int i = 0; i < expectedBytes.length; i++) {
                 assertEquals(expectedBytes[i], results[i]);
             }
         }
     }
 
-    public void testReadDocument_error() throws Exception {
-        final TestMtpManager mtpManager = new TestMtpManager(getContext());
-        final ExecutorService executor = Executors.newSingleThreadExecutor();
-        final PipeManager pipeManager = new PipeManager(executor);
-        final ParcelFileDescriptor descriptor =
-                pipeManager.readDocument(mtpManager, new Identifier(0, 0, 1), 5);
+    private void assertDescriptorError(ParcelFileDescriptor descriptor)
+            throws InterruptedException {
         executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
         try {
             descriptor.checkError();
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
index 48bc3b5..725b765 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/TestMtpManager.java
@@ -17,6 +17,7 @@
 package com.android.mtp;
 
 import android.content.Context;
+import android.os.ParcelFileDescriptor;
 
 import java.io.IOException;
 import java.util.Arrays;
@@ -35,8 +36,9 @@
     private final Set<Integer> mOpenedDevices = new TreeSet<Integer>();
     private final Map<Integer, MtpRoot[]> mRoots = new HashMap<Integer, MtpRoot[]>();
     private final Map<String, MtpDocument> mDocuments = new HashMap<String, MtpDocument>();
-    private final Map<String, byte[]> mObjectBytes = new HashMap<String, byte[]>();
+    private final Map<String, byte[]> mThumbnailBytes = new HashMap<String, byte[]>();
     private final Map<String, Integer> mParents = new HashMap<String, Integer>();
+    private final Map<String, byte[]> mImportFileBytes = new HashMap<String, byte[]>();
 
     TestMtpManager(Context context) {
         super(context);
@@ -54,8 +56,12 @@
         mDocuments.put(pack(deviceId, objectHandle), document);
     }
 
-    void setObjectBytes(int deviceId, int objectHandle, int expectedSize, byte[] bytes) {
-        mObjectBytes.put(pack(deviceId, objectHandle, expectedSize), bytes);
+    void setImportFileBytes(int deviceId, int objectHandle, byte[] bytes) {
+        mImportFileBytes.put(pack(deviceId, objectHandle), bytes);
+    }
+
+    void setThumbnail(int deviceId, int objectHandle, byte[] bytes) {
+        mThumbnailBytes.put(pack(deviceId, objectHandle), bytes);
     }
 
     void setParent(int deviceId, int objectHandle, int parentObjectHandle) {
@@ -93,12 +99,25 @@
     }
 
     @Override
-    byte[] getObject(int deviceId, int storageId, int expectedSize) throws IOException {
-        final String key = pack(deviceId, storageId, expectedSize);
-        if (mObjectBytes.containsKey(key)) {
-            return mObjectBytes.get(key);
+    void importFile(int deviceId, int storageId, ParcelFileDescriptor target) throws IOException {
+        final String key = pack(deviceId, storageId);
+        if (mImportFileBytes.containsKey(key)) {
+            try (final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
+                    new ParcelFileDescriptor.AutoCloseOutputStream(target)) {
+                outputStream.write(mImportFileBytes.get(key));
+            }
         } else {
-            throw new IOException("getObject error: " + key);
+            throw new IOException("importFile error: " + key);
+        }
+    }
+
+    @Override
+    byte[] getThumbnail(int deviceId, int objectHandle) throws IOException {
+        final String key = pack(deviceId, objectHandle);
+        if (mThumbnailBytes.containsKey(key)) {
+            return mThumbnailBytes.get(key);
+        } else {
+            throw new IOException("getThumbnail error: " + key);
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 348d0ec..632a867 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -151,7 +151,7 @@
                 mScanResultCache.put(result.BSSID, result);
             }
         }
-        update(mInfo, mNetworkInfo);
+        update(mConfig, mInfo, mNetworkInfo);
         mRssi = getRssi();
         mSeen = getSeen();
     }
@@ -629,11 +629,18 @@
         return mConfig != null && mConfig.isPasspoint();
     }
 
-    /** Return whether the given {@link WifiInfo} is for this access point. */
-    private boolean isInfoForThisAccessPoint(WifiInfo info) {
+    /**
+     * Return whether the given {@link WifiInfo} is for this access point.
+     * If the current AP does not have a network Id then the config is used to
+     * match based on SSID and security.
+     */
+    private boolean isInfoForThisAccessPoint(WifiConfiguration config, WifiInfo info) {
         if (isPasspoint() == false && networkId != WifiConfiguration.INVALID_NETWORK_ID) {
             return networkId == info.getNetworkId();
-        } else {
+        } else if (config != null) {
+            return matches(config);
+        }
+        else {
             // Might be an ephemeral connection with no WifiConfiguration. Try matching on SSID.
             // (Note that we only do this if the WifiConfiguration explicitly equals INVALID).
             // TODO: Handle hex string SSIDs.
@@ -705,7 +712,7 @@
     }
 
     boolean update(ScanResult result) {
-        if (ssid.equals(result.SSID) && security == getSecurity(result)) {
+        if (matches(result)) {
             /* Update the LRU timestamp, if BSSID exists */
             mScanResultCache.get(result.BSSID);
 
@@ -735,9 +742,9 @@
         return false;
     }
 
-    boolean update(WifiInfo info, NetworkInfo networkInfo) {
+    boolean update(WifiConfiguration config, WifiInfo info, NetworkInfo networkInfo) {
         boolean reorder = false;
-        if (info != null && isInfoForThisAccessPoint(info)) {
+        if (info != null && isInfoForThisAccessPoint(config, info)) {
             reorder = (mInfo == null);
             mRssi = info.getRssi();
             mInfo = info;
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 33f993e..c28288e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -281,6 +281,19 @@
         return mScanResultCache.values();
     }
 
+    private WifiConfiguration getWifiConfigurationForNetworkId(int networkId) {
+        final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
+        if (configs != null) {
+            for (WifiConfiguration config : configs) {
+                if (mLastInfo != null && networkId == config.networkId &&
+                        !(config.selfAdded && config.numAssociation == 0)) {
+                    return config;
+                }
+            }
+        }
+        return null;
+    }
+
     private void updateAccessPoints() {
         // Swap the current access points into a cached list.
         List<AccessPoint> cachedAccessPoints = getAccessPoints();
@@ -295,21 +308,21 @@
          * correct SSID.  Maps SSID -> List of AccessPoints with the given SSID.  */
         Multimap<String, AccessPoint> apMap = new Multimap<String, AccessPoint>();
         WifiConfiguration connectionConfig = null;
+        if (mLastInfo != null) {
+            connectionConfig = getWifiConfigurationForNetworkId(mLastInfo.getNetworkId());
+        }
 
         final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
         if (configs != null) {
             mSavedNetworksExist = configs.size() != 0;
             for (WifiConfiguration config : configs) {
-                if (mLastInfo != null && mLastInfo.getNetworkId() == config.networkId) {
-                    connectionConfig = config;
-                }
                 if (config.selfAdded && config.numAssociation == 0) {
                     continue;
                 }
                 AccessPoint accessPoint = getCachedOrCreate(config, cachedAccessPoints);
                 if (mLastInfo != null && mLastNetworkInfo != null) {
                     if (config.isPasspoint() == false) {
-                        accessPoint.update(mLastInfo, mLastNetworkInfo);
+                        accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
                     }
                 }
                 if (mIncludeSaved) {
@@ -346,7 +359,7 @@
                 if (!found && mIncludeScans) {
                     AccessPoint accessPoint = getCachedOrCreate(result, cachedAccessPoints);
                     if (mLastInfo != null && mLastNetworkInfo != null) {
-                        accessPoint.update(mLastInfo, mLastNetworkInfo);
+                        accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
                     }
 
                     if (result.isPasspointNetwork()) {
@@ -437,9 +450,14 @@
             mLastNetworkInfo = networkInfo;
         }
 
+        WifiConfiguration connectionConfig = null;
+        if (mLastInfo != null) {
+            connectionConfig = getWifiConfigurationForNetworkId(mLastInfo.getNetworkId());
+        }
+
         boolean reorder = false;
         for (int i = mAccessPoints.size() - 1; i >= 0; --i) {
-            if (mAccessPoints.get(i).update(mLastInfo, mLastNetworkInfo)) {
+            if (mAccessPoints.get(i).update(connectionConfig, mLastInfo, mLastNetworkInfo)) {
                 reorder = true;
             }
         }
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index 477d9d7..2168e8b 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -63,4 +63,4 @@
         android:background="@drawable/recents_button_bg"
         android:visibility="invisible"
         android:src="@drawable/recents_dismiss_light" />
-</com.android.systemui.recents.views.TaskViewHeader>
\ No newline at end of file
+</com.android.systemui.recents.views.TaskViewHeader>
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index 2a3492b..45c020c 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -25,6 +25,7 @@
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -509,6 +510,7 @@
             }
         }
 
+        String[] uidPackageNames = getPackagesForUid(uid);
         ArrayMap<Callback, ArraySet<String>> callbackSpecs = null;
 
         ArrayList<Callback> callbacks = mOpModeWatchers.get(code);
@@ -516,12 +518,13 @@
             final int callbackCount = callbacks.size();
             for (int i = 0; i < callbackCount; i++) {
                 Callback callback = callbacks.get(i);
+                ArraySet<String> changedPackages = new ArraySet<>();
+                Collections.addAll(changedPackages, uidPackageNames);
                 callbackSpecs = new ArrayMap<>();
-                callbackSpecs.put(callback, null);
+                callbackSpecs.put(callback, changedPackages);
             }
         }
 
-        String[] uidPackageNames = getPackagesForUid(uid);
         for (String uidPackageName : uidPackageNames) {
             callbacks = mPackageModeWatchers.get(uidPackageName);
             if (callbacks != null) {
@@ -931,7 +934,6 @@
         }
         return noteOperationUnchecked(code, proxiedUid, proxiedPackageName,
                 Binder.getCallingUid(), proxyPackageName);
-
     }
 
     @Override
@@ -1266,7 +1268,7 @@
                         String tagName = parser.getName();
                         if (tagName.equals("pkg")) {
                             readPackage(parser);
-                        } if (tagName.equals("uid")) {
+                        } else if (tagName.equals("uid")) {
                             readUidOps(parser);
                         } else {
                             Slog.w(TAG, "Unknown element under <app-ops>: "
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 64ee5f1..4e11070 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -3555,7 +3555,7 @@
                     ? new File(Environment.getDataDirectory(), SYSTEM_PATH)
                     : Environment.getUserSystemDirectory(userId);
             final File inputMethodDir = new File(systemDir, INPUT_METHOD_PATH);
-            if (!inputMethodDir.mkdirs()) {
+            if (!inputMethodDir.exists() && !inputMethodDir.mkdirs()) {
                 Slog.w(TAG, "Couldn't create dir.: " + inputMethodDir.getAbsolutePath());
             }
             final File subtypeFile = new File(inputMethodDir, ADDITIONAL_SUBTYPES_FILE_NAME);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 32fd56a..83e8db0 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -527,14 +527,14 @@
                     + ", pid " + Binder.getCallingPid());
         }
         if (account == null) throw new IllegalArgumentException("account is null");
-        if (!isAccountManagedByCaller(account.type, callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot get secrets for accounts of type: %s",
                     callingUid,
                     account.type);
             throw new SecurityException(msg);
         }
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -627,14 +627,14 @@
         }
         if (account == null) throw new IllegalArgumentException("account is null");
         if (key == null) throw new IllegalArgumentException("key is null");
-        if (!isAccountManagedByCaller(account.type, callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot get user data for accounts of type: %s",
                     callingUid,
                     account.type);
             throw new SecurityException(msg);
         }
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -664,22 +664,32 @@
 
         final long identityToken = clearCallingIdentity();
         try {
-            Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
-                    authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
-            AuthenticatorDescription[] types =
-                    new AuthenticatorDescription[authenticatorCollection.size()];
-            int i = 0;
-            for (AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticator
-                    : authenticatorCollection) {
-                types[i] = authenticator.type;
-                i++;
-            }
-            return types;
+            return getAuthenticatorTypesInternal(userId);
+
         } finally {
             restoreCallingIdentity(identityToken);
         }
     }
 
+    /**
+     * Should only be called inside of a clearCallingIdentity block.
+     */
+    private AuthenticatorDescription[] getAuthenticatorTypesInternal(int userId) {
+        Collection<AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription>>
+                authenticatorCollection = mAuthenticatorCache.getAllServices(userId);
+        AuthenticatorDescription[] types =
+                new AuthenticatorDescription[authenticatorCollection.size()];
+        int i = 0;
+        for (AccountAuthenticatorCache.ServiceInfo<AuthenticatorDescription> authenticator
+                : authenticatorCollection) {
+            types[i] = authenticator.type;
+            i++;
+        }
+        return types;
+    }
+
+
+
     private boolean isCrossUser(int callingUid, int userId) {
         return (userId != UserHandle.getCallingUserId()
                 && callingUid != Process.myUid()
@@ -697,7 +707,8 @@
                     + ", pid " + Binder.getCallingPid());
         }
         if (account == null) throw new IllegalArgumentException("account is null");
-        if (!isAccountManagedByCaller(account.type, callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot explicitly add accounts of type: %s",
                     callingUid,
@@ -713,12 +724,10 @@
          */
 
         // fails if the account already exists
-        int uid = getCallingUid();
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
-            return addAccountInternal(accounts, account, password, extras, false, uid);
+            return addAccountInternal(accounts, account, password, extras, false, callingUid);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -794,25 +803,26 @@
         if (account == null) {
             throw new IllegalArgumentException("account is null");
         }
-        if (!isAccountManagedByCaller(account.type, callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot notify authentication for accounts of type: %s",
                     callingUid,
                     account.type);
             throw new SecurityException(msg);
         }
-        int userId = Binder.getCallingUserHandle().getIdentifier();
+
         if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
             return false;
         }
-        int user = UserHandle.getCallingUserId();
+
         long identityToken = clearCallingIdentity();
         try {
-            UserAccounts accounts = getUserAccounts(user);
+            UserAccounts accounts = getUserAccounts(userId);
+            return updateLastAuthenticatedTime(account);
         } finally {
             restoreCallingIdentity(identityToken);
         }
-        return updateLastAuthenticatedTime(account);
     }
 
     private boolean updateLastAuthenticatedTime(Account account) {
@@ -985,8 +995,9 @@
         if (response == null) throw new IllegalArgumentException("response is null");
         if (account == null) throw new IllegalArgumentException("account is null");
         if (features == null) throw new IllegalArgumentException("features is null");
-        checkReadAccountsPermitted(callingUid, account.type);
         int userId = UserHandle.getCallingUserId();
+        checkReadAccountsPermitted(callingUid, account.type, userId);
+
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -1062,14 +1073,14 @@
                 + ", pid " + Binder.getCallingPid());
         }
         if (accountToRename == null) throw new IllegalArgumentException("account is null");
-        if (!isAccountManagedByCaller(accountToRename.type, callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(accountToRename.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot rename accounts of type: %s",
                     callingUid,
                     accountToRename.type);
             throw new SecurityException(msg);
         }
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -1211,14 +1222,15 @@
          * authenticator.  This will let users remove accounts (via Settings in the system) but not
          * arbitrary applications (like competing authenticators).
          */
-        if (!isAccountManagedByCaller(account.type, callingUid) && !isSystemUid(callingUid)) {
+        UserHandle user = new UserHandle(userId);
+        if (!isAccountManagedByCaller(account.type, callingUid, user.getIdentifier())
+                && !isSystemUid(callingUid)) {
             String msg = String.format(
                     "uid %s cannot remove accounts of type: %s",
                     callingUid,
                     account.type);
             throw new SecurityException(msg);
         }
-
         if (!canUserModifyAccounts(userId)) {
             try {
                 response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED,
@@ -1235,10 +1247,7 @@
             }
             return;
         }
-
-        UserHandle user = new UserHandle(userId);
         long identityToken = clearCallingIdentity();
-
         UserAccounts accounts = getUserAccounts(userId);
         cancelNotification(getSigninRequiredNotificationId(accounts, account), user);
         synchronized(accounts.credentialsPermissionNotificationIds) {
@@ -1268,6 +1277,7 @@
                     + ", caller's uid " + callingUid
                     + ", pid " + Binder.getCallingPid());
         }
+        int userId = Binder.getCallingUserHandle().getIdentifier();
         if (account == null) {
             /*
              * Null accounts should result in returning false, as per
@@ -1275,22 +1285,18 @@
              */
             Log.e(TAG, "account is null");
             return false;
-        } else if (!isAccountManagedByCaller(account.type, callingUid)) {
+        } else if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot explicitly add accounts of type: %s",
                     callingUid,
                     account.type);
             throw new SecurityException(msg);
         }
-
         UserAccounts accounts = getUserAccountsForCaller();
-        int userId = Binder.getCallingUserHandle().getIdentifier();
         if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
             return false;
         }
-
         logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS);
-
         long identityToken = clearCallingIdentity();
         try {
             return removeAccountInternal(accounts, account);
@@ -1524,14 +1530,14 @@
         }
         if (account == null) throw new IllegalArgumentException("account is null");
         if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
-        if (!isAccountManagedByCaller(account.type, callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot peek the authtokens associated with accounts of type: %s",
                     callingUid,
                     account.type);
             throw new SecurityException(msg);
         }
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -1552,14 +1558,14 @@
         }
         if (account == null) throw new IllegalArgumentException("account is null");
         if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
-        if (!isAccountManagedByCaller(account.type, callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot set auth tokens associated with accounts of type: %s",
                     callingUid,
                     account.type);
             throw new SecurityException(msg);
         }
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -1578,14 +1584,14 @@
                     + ", pid " + Binder.getCallingPid());
         }
         if (account == null) throw new IllegalArgumentException("account is null");
-        if (!isAccountManagedByCaller(account.type, callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot set secrets for accounts of type: %s",
                     callingUid,
                     account.type);
             throw new SecurityException(msg);
         }
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -1642,14 +1648,14 @@
                     + ", pid " + Binder.getCallingPid());
         }
         if (account == null) throw new IllegalArgumentException("account is null");
-        if (!isAccountManagedByCaller(account.type, callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot clear passwords for accounts of type: %s",
                     callingUid,
                     account.type);
             throw new SecurityException(msg);
         }
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -1670,14 +1676,14 @@
         }
         if (key == null) throw new IllegalArgumentException("key is null");
         if (account == null) throw new IllegalArgumentException("account is null");
-        if (!isAccountManagedByCaller(account.type, callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(account.type, callingUid, userId)) {
             String msg = String.format(
                     "uid %s cannot set user data for accounts of type: %s",
                     callingUid,
                     account.type);
             throw new SecurityException(msg);
         }
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -1840,8 +1846,8 @@
 
         // skip the check if customTokens
         final int callerUid = Binder.getCallingUid();
-        final boolean permissionGranted = customTokens ||
-            permissionIsGranted(account, authTokenType, callerUid);
+        final boolean permissionGranted =
+                customTokens || permissionIsGranted(account, authTokenType, callerUid, userId);
 
         // Get the calling package. We will use it for the purpose of caching.
         final String callerPkg = loginOptions.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME);
@@ -2363,14 +2369,14 @@
         }
         if (response == null) throw new IllegalArgumentException("response is null");
         if (accountType == null) throw new IllegalArgumentException("accountType is null");
-        if (!isAccountManagedByCaller(accountType, callingUid) && !isSystemUid(callingUid)) {
+        int userId = UserHandle.getCallingUserId();
+        if (!isAccountManagedByCaller(accountType, callingUid, userId) && !isSystemUid(callingUid)) {
             String msg = String.format(
                     "uid %s cannot edit authenticator properites for account type: %s",
                     callingUid,
                     accountType);
             throw new SecurityException(msg);
         }
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts accounts = getUserAccounts(userId);
@@ -2493,20 +2499,22 @@
     }
 
     /**
-     * Returns the accounts for a specific user
+     * Returns the accounts visible to the client within the context of a specific user
      * @hide
      */
     public Account[] getAccounts(int userId) {
         int callingUid = Binder.getCallingUid();
-        if (!isReadAccountsPermitted(callingUid, null)) {
+        List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId);
+        if (visibleAccountTypes.isEmpty()) {
             return new Account[0];
         }
         long identityToken = clearCallingIdentity();
         try {
-            UserAccounts accounts = getUserAccounts(userId);
-            synchronized (accounts.cacheLock) {
-                return getAccountsFromCacheLocked(accounts, null, callingUid, null);
-            }
+            return getAccountsInternal(
+                    userId,
+                    callingUid,
+                    null,  // packageName
+                    visibleAccountTypes);
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -2588,22 +2596,52 @@
             callingUid = packageUid;
         }
 
-        // Authenticators should be able to see their own accounts regardless of permissions.
-        if (TextUtils.isEmpty(type) && !isReadAccountsPermitted(callingUid, type)) {
+        List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId);
+        if (visibleAccountTypes.isEmpty()
+                || (type != null && !visibleAccountTypes.contains(type))) {
             return new Account[0];
-        }
+        } else if (visibleAccountTypes.contains(type)) {
+            // Prune the list down to just the requested type.
+            visibleAccountTypes = new ArrayList<>();
+            visibleAccountTypes.add(type);
+        } // else aggregate all the visible accounts (it won't matter if the list is empty).
 
         long identityToken = clearCallingIdentity();
         try {
-            UserAccounts accounts = getUserAccounts(userId);
-            synchronized (accounts.cacheLock) {
-                return getAccountsFromCacheLocked(accounts, type, callingUid, callingPackage);
-            }
+            return getAccountsInternal(
+                    userId,
+                    callingUid,
+                    callingPackage,
+                    visibleAccountTypes);
         } finally {
             restoreCallingIdentity(identityToken);
         }
     }
 
+    private Account[] getAccountsInternal(
+            int userId,
+            int callingUid,
+            String callingPackage,
+            List<String> visibleAccountTypes) {
+        UserAccounts accounts = getUserAccounts(userId);
+        synchronized (accounts.cacheLock) {
+            UserAccounts userAccounts = getUserAccounts(userId);
+            ArrayList<Account> visibleAccounts = new ArrayList<>();
+            for (String visibleType : visibleAccountTypes) {
+                Account[] accountsForType = getAccountsFromCacheLocked(
+                        userAccounts, visibleType, callingUid, callingPackage);
+                if (accountsForType != null) {
+                    visibleAccounts.addAll(Arrays.asList(accountsForType));
+                }
+            }
+            Account[] result = new Account[visibleAccounts.size()];
+            for (int i = 0; i < visibleAccounts.size(); i++) {
+                result[i] = visibleAccounts.get(i);
+            }
+            return result;
+        }
+    }
+
     @Override
     public boolean addSharedAccountAsUser(Account account, int userId) {
         userId = handleIncomingUser(userId);
@@ -2739,8 +2777,12 @@
         }
         if (response == null) throw new IllegalArgumentException("response is null");
         if (type == null) throw new IllegalArgumentException("accountType is null");
-        if (!isReadAccountsPermitted(callingUid, type)) {
+        int userId = UserHandle.getCallingUserId();
+
+        List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId);
+        if (!visibleAccountTypes.contains(type)) {
             Bundle result = new Bundle();
+            // Need to return just the accounts that are from matching signatures.
             result.putParcelableArray(AccountManager.KEY_ACCOUNTS, new Account[0]);
             try {
                 response.onResult(result);
@@ -2749,7 +2791,6 @@
             }
             return;
         }
-        int userId = UserHandle.getCallingUserId();
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts userAccounts = getUserAccounts(userId);
@@ -2763,7 +2804,11 @@
                 onResult(response, result);
                 return;
             }
-            new GetAccountsByTypeAndFeatureSession(userAccounts, response, type, features,
+            new GetAccountsByTypeAndFeatureSession(
+                    userAccounts,
+                    response,
+                    type,
+                    features,
                     callingUid).bind();
         } finally {
             restoreCallingIdentity(identityToken);
@@ -3696,10 +3741,11 @@
         return false;
     }
 
-    private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
+    private boolean permissionIsGranted(
+            Account account, String authTokenType, int callerUid, int userId) {
         final boolean isPrivileged = isPrivileged(callerUid);
         final boolean fromAuthenticator = account != null
-                && isAccountManagedByCaller(account.type, callerUid);
+                && isAccountManagedByCaller(account.type, callerUid, userId);
         final boolean hasExplicitGrants = account != null
                 && hasExplicitlyGrantedPermission(account, authTokenType, callerUid);
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -3711,23 +3757,45 @@
         return fromAuthenticator || hasExplicitGrants || isPrivileged;
     }
 
-    private boolean isAccountManagedByCaller(String accountType, int callingUid) {
+    private boolean isAccountVisibleToCaller(String accountType, int callingUid, int userId) {
         if (accountType == null) {
             return false;
+        } else {
+            return getTypesVisibleToCaller(callingUid, userId).contains(accountType);
         }
-        final int callingUserId = UserHandle.getUserId(callingUid);
+    }
+
+    private boolean isAccountManagedByCaller(String accountType, int callingUid, int userId) {
+        if (accountType == null) {
+            return false;
+        } else {
+            return getTypesManagedByCaller(callingUid, userId).contains(accountType);
+        }
+    }
+
+    private List<String> getTypesVisibleToCaller(int callingUid, int userId) {
+        boolean isPermitted =
+                isPermitted(callingUid, Manifest.permission.GET_ACCOUNTS,
+                        Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
+        Log.i(TAG, String.format("getTypesVisibleToCaller: isPermitted? %s", isPermitted));
+        return getTypesForCaller(callingUid, userId, isPermitted);
+    }
+
+    private List<String> getTypesManagedByCaller(int callingUid, int userId) {
+        return getTypesForCaller(callingUid, userId, false);
+    }
+
+    private List<String> getTypesForCaller(
+            int callingUid, int userId, boolean isOtherwisePermitted) {
+        List<String> managedAccountTypes = new ArrayList<>();
         for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
-                mAuthenticatorCache.getAllServices(callingUserId)) {
-            if (serviceInfo.type.type.equals(accountType)) {
-                /*
-                 * We can't simply compare uids because uids can be recycled before the
-                 * authenticator cache is updated.
-                 */
-                final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid);
-                return sigChk == PackageManager.SIGNATURE_MATCH;
+                mAuthenticatorCache.getAllServices(userId)) {
+            final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid);
+            if (isOtherwisePermitted || sigChk == PackageManager.SIGNATURE_MATCH) {
+                managedAccountTypes.add(serviceInfo.type.type);
             }
         }
-        return false;
+        return managedAccountTypes;
     }
 
     private boolean isAccountPresentForCaller(String accountName, String accountType) {
@@ -3792,28 +3860,12 @@
         return false;
     }
 
-    private boolean isReadAccountsPermitted(int callingUid, String accountType) {
-        /*
-         * Settings app (which is in the same uid as AcocuntManagerService), apps with the
-         * GET_ACCOUNTS permission or authenticators that own the account type should be able to
-         * access accounts of the specified account.
-         */
-        boolean isPermitted =
-                isPermitted(callingUid, Manifest.permission.GET_ACCOUNTS,
-                        Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
-        boolean isAccountManagedByCaller = isAccountManagedByCaller(accountType, callingUid);
-        Log.w(TAG, String.format(
-                "isReadAccountPermitted: isPermitted: %s, isAM: %s",
-                isPermitted,
-                isAccountManagedByCaller));
-        return isPermitted || isAccountManagedByCaller;
-    }
-
     /** Succeeds if any of the specified permissions are granted. */
     private void checkReadAccountsPermitted(
             int callingUid,
-            String accountType) {
-        if (!isReadAccountsPermitted(callingUid, accountType)) {
+            String accountType,
+            int userId) {
+        if (!isAccountVisibleToCaller(accountType, callingUid, userId)) {
             String msg = String.format(
                     "caller uid %s cannot access %s accounts",
                     callingUid,
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 31fa5c4..57d7758 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -88,7 +88,6 @@
     private int mUser = UserHandle.USER_OWNER;
     private ZenModeConfig mConfig;
     private AudioManagerInternal mAudioManager;
-    private int mPreviousRingerMode = -1;
     private boolean mEffectsSuppressed;
 
     public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
@@ -236,7 +235,6 @@
         }
         pw.print(prefix); pw.print("mUser="); pw.println(mUser);
         dump(pw, prefix, "mConfig", mConfig);
-        pw.print(prefix); pw.print("mPreviousRingerMode="); pw.println(mPreviousRingerMode);
         pw.print(prefix); pw.print("mEffectsSuppressed="); pw.println(mEffectsSuppressed);
         mFiltering.dump(pw, prefix);
         mConditions.dump(pw, prefix);
@@ -357,6 +355,17 @@
         Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
     }
 
+    private int getPreviousRingerModeSetting() {
+        return Global.getInt(mContext.getContentResolver(),
+                Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
+    }
+
+    private void setPreviousRingerModeSetting(Integer previousRingerLevel) {
+        Global.putString(
+                mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
+                previousRingerLevel == null ? null : Integer.toString(previousRingerLevel));
+    }
+
     private boolean evaluateZenMode(String reason, boolean setRingerMode) {
         if (DEBUG) Log.d(TAG, "evaluateZenMode");
         final ArraySet<ZenRule> automaticRules = new ArraySet<ZenRule>();
@@ -430,16 +439,15 @@
             case Global.ZEN_MODE_NO_INTERRUPTIONS:
             case Global.ZEN_MODE_ALARMS:
                 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
-                    mPreviousRingerMode = ringerModeInternal;
+                    setPreviousRingerModeSetting(ringerModeInternal);
                     newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
                 }
                 break;
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
             case Global.ZEN_MODE_OFF:
                 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
-                    newRingerModeInternal = mPreviousRingerMode != -1 ? mPreviousRingerMode
-                            : AudioManager.RINGER_MODE_NORMAL;
-                    mPreviousRingerMode = -1;
+                    newRingerModeInternal = getPreviousRingerModeSetting();
+                    setPreviousRingerModeSetting(null);
                 }
                 break;
         }
@@ -593,7 +601,7 @@
                                 && mZenMode != Global.ZEN_MODE_ALARMS) {
                             newZen = Global.ZEN_MODE_ALARMS;
                         }
-                        mPreviousRingerMode = ringerModeOld;
+                        setPreviousRingerModeSetting(ringerModeOld);
                     }
                     break;
                 case AudioManager.RINGER_MODE_VIBRATE:
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 16571ea..454cdcf 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -5258,9 +5258,11 @@
     }
 
     private boolean shouldDispatchInputWhenNonInteractive() {
-        // Send events to keyguard while the screen is on.
-        if (isKeyguardShowingAndNotOccluded() && mDisplay != null
-                && mDisplay.getState() != Display.STATE_OFF) {
+        if (mDisplay == null || mDisplay.getState() == Display.STATE_OFF) {
+            return false;
+        }
+        // Send events to keyguard while the screen is on and it's showing.
+        if (isKeyguardShowingAndNotOccluded()) {
             return true;
         }
 
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 07fc23f..43f4047 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -579,8 +579,14 @@
     private void clearUserHasAuthenticated(int userId) {
         if (userId == UserHandle.USER_ALL) {
             mUserHasAuthenticated.clear();
+            synchronized (mUserHasAuthenticatedSinceBoot) {
+                mUserHasAuthenticatedSinceBoot.clear();
+            }
         } else {
             mUserHasAuthenticated.put(userId, false);
+            synchronized (mUserHasAuthenticatedSinceBoot) {
+                mUserHasAuthenticatedSinceBoot.put(userId, false);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/FocusedTaskFrame.java b/services/core/java/com/android/server/wm/FocusedTaskFrame.java
deleted file mode 100644
index d8e1095..0000000
--- a/services/core/java/com/android/server/wm/FocusedTaskFrame.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (C) 2013 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.server.wm;
-
-import static com.android.server.wm.WindowManagerService.DEBUG_SURFACE_TRACE;
-import static com.android.server.wm.WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
-
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.util.Slog;
-import android.view.Display;
-import android.view.Surface.OutOfResourcesException;
-import android.view.Surface;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-
-import com.android.server.wm.WindowStateAnimator.SurfaceTrace;
-
-class FocusedTaskFrame {
-    private static final String TAG = "FocusedTaskFrame";
-    private static final boolean DEBUG = false;
-    private static final int THICKNESS = 2;
-    private static final float ALPHA = 0.3f;
-
-    private final SurfaceControl mSurfaceControl;
-    private final Surface mSurface = new Surface();
-    private final Paint mInnerPaint = new Paint();
-    private final Paint mOuterPaint = new Paint();
-    private final Rect mBounds = new Rect();
-    private final Rect mLastBounds = new Rect();
-    private int mLayer = -1;
-
-    public FocusedTaskFrame(Display display, SurfaceSession session) {
-        SurfaceControl ctrl = null;
-        try {
-            if (DEBUG_SURFACE_TRACE) {
-                ctrl = new SurfaceTrace(session, "FocusedTaskFrame",
-                    1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
-            } else {
-                ctrl = new SurfaceControl(session, "FocusedTaskFrame",
-                    1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
-            }
-            ctrl.setLayerStack(display.getLayerStack());
-            ctrl.setAlpha(ALPHA);
-            mSurface.copyFrom(ctrl);
-        } catch (OutOfResourcesException e) {
-        }
-        mSurfaceControl = ctrl;
-
-        mInnerPaint.setStyle(Paint.Style.STROKE);
-        mInnerPaint.setStrokeWidth(THICKNESS);
-        mInnerPaint.setColor(Color.WHITE);
-        mOuterPaint.setStyle(Paint.Style.STROKE);
-        mOuterPaint.setStrokeWidth(THICKNESS);
-        mOuterPaint.setColor(Color.BLACK);
-    }
-
-    private void draw() {
-        if (mLastBounds.isEmpty()) {
-            // Currently unset. Set it.
-            mLastBounds.set(mBounds);
-        }
-
-        if (DEBUG) Slog.i(TAG, "draw: mBounds=" + mBounds + " mLastBounds=" + mLastBounds);
-
-        Canvas c = null;
-        try {
-            c = mSurface.lockCanvas(mLastBounds);
-        } catch (IllegalArgumentException e) {
-            Slog.e(TAG, "Unable to lock canvas", e);
-        } catch (Surface.OutOfResourcesException e) {
-            Slog.e(TAG, "Unable to lock canvas", e);
-        }
-        if (c == null) {
-            if (DEBUG) Slog.w(TAG, "Canvas is null...");
-            return;
-        }
-
-        c.drawRect(0, 0, mBounds.width(), mBounds.height(), mOuterPaint);
-        c.drawRect(THICKNESS, THICKNESS, mBounds.width() - THICKNESS, mBounds.height() - THICKNESS,
-                mInnerPaint);
-        if (DEBUG) Slog.w(TAG, "c.width=" + c.getWidth() + " c.height=" + c.getHeight()
-                + " c.clip=" + c .getClipBounds());
-        mSurface.unlockCanvasAndPost(c);
-        mLastBounds.set(mBounds);
-    }
-
-    private void setupSurface(boolean visible) {
-        if (mSurfaceControl == null) {
-            return;
-        }
-        if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setupSurface");
-        SurfaceControl.openTransaction();
-        try {
-            if (visible) {
-                mSurfaceControl.setPosition(mBounds.left, mBounds.top);
-                mSurfaceControl.setSize(mBounds.width(), mBounds.height());
-                mSurfaceControl.show();
-            } else {
-                mSurfaceControl.hide();
-            }
-        } finally {
-            SurfaceControl.closeTransaction();
-            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setupSurface");
-        }
-    }
-
-    void setVisibility(Task task) {
-        if (task == null || task.isFullscreen()) {
-            setupSurface(false);
-        } else {
-            task.getBounds(mBounds);
-            setupSurface(true);
-            if (!mBounds.equals(mLastBounds)) {
-                draw();
-            }
-        }
-    }
-
-    // Note: caller responsible for being inside
-    // Surface.openTransaction() / closeTransaction()
-    void setLayer(int layer) {
-        if (mLayer == layer) {
-            return;
-        }
-        mLayer = layer;
-        mSurfaceControl.setLayer(mLayer);
-    }
-}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index b9740af..7578256 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -709,8 +709,6 @@
                 mService.scheduleAnimationLocked();
             }
 
-            mService.setFocusedTaskLayer();
-
             if (mService.mWatermark != null) {
                 mService.mWatermark.drawIfNeeded();
             }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 20e24bb..4b6f479 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -250,11 +250,6 @@
     static final int LAYER_OFFSET_DIM = 1;
 
     /**
-     * FocusedTaskFrame layer is immediately above focused window.
-     */
-    static final int LAYER_OFFSET_FOCUSED_TASK = 1;
-
-    /**
      * Animation thumbnail is as far as possible below the window above
      * the thumbnail (or in other words as far as possible above the window
      * below it).
@@ -445,9 +440,6 @@
     StrictModeFlash mStrictModeFlash;
     CircularDisplayMask mCircularDisplayMask;
     EmulatorDisplayOverlay mEmulatorDisplayOverlay;
-    FocusedTaskFrame mFocusedTaskFrame;
-
-    int mFocusedTaskLayer;
 
     final float[] mTmpFloats = new float[9];
     final Rect mTmpContentRect = new Rect();
@@ -990,8 +982,6 @@
         SurfaceControl.openTransaction();
         try {
             createWatermarkInTransaction();
-            mFocusedTaskFrame = new FocusedTaskFrame(
-                    getDefaultDisplayContentLocked().getDisplay(), mFxSession);
         } finally {
             SurfaceControl.closeTransaction();
         }
@@ -4074,34 +4064,14 @@
         }
     }
 
-    /** Call while in a Surface transaction. */
-    void setFocusedTaskLayer() {
-        mFocusedTaskLayer = 0;
+    void setFocusTaskRegion() {
         if (mFocusedApp != null) {
-            final WindowList windows = mFocusedApp.allAppWindows;
-            for (int i = windows.size() - 1; i >= 0; --i) {
-                final WindowState win = windows.get(i);
-                final int animLayer = win.mWinAnimator.mAnimLayer;
-                if (win.mAttachedWindow == null && win.isVisibleLw() &&
-                        animLayer > mFocusedTaskLayer) {
-                    mFocusedTaskLayer = animLayer + LAYER_OFFSET_FOCUSED_TASK;
-                }
-            }
-        }
-        if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedTaskFrame to layer=" + mFocusedTaskLayer);
-        mFocusedTaskFrame.setLayer(mFocusedTaskLayer);
-    }
-
-    void setFocusedTaskFrame() {
-        Task task = null;
-        if (mFocusedApp != null) {
-            task = mFocusedApp.mTask;
+            final Task task = mFocusedApp.mTask;
             final DisplayContent displayContent = task.getDisplayContent();
             if (displayContent != null) {
                 displayContent.setTouchExcludeRegion(task);
             }
         }
-        mFocusedTaskFrame.setVisibility(task);
     }
 
     @Override
@@ -4129,15 +4099,7 @@
             if (changed) {
                 mFocusedApp = newFocus;
                 mInputMonitor.setFocusedAppLw(newFocus);
-                setFocusedTaskFrame();
-                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedApp");
-                SurfaceControl.openTransaction();
-                try {
-                    setFocusedTaskLayer();
-                } finally {
-                    SurfaceControl.closeTransaction();
-                    if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedApp");
-                }
+                setFocusTaskRegion();
             }
 
             if (moveFocusNow && changed) {
@@ -10409,7 +10371,7 @@
         if (updateInputWindowsNeeded) {
             mInputMonitor.updateInputWindowsLw(false /*force*/);
         }
-        setFocusedTaskFrame();
+        setFocusTaskRegion();
 
         // Check to see if we are now in a state where the screen should
         // be enabled, because the window obscured flags have changed.
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 706dcfb..7b277c5 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -253,12 +253,6 @@
     //**********************************************************************************************
 
     /**
-     * TODO: Remove this -- retained so the build won't break.  However, future work will remove it.
-     * @hide
-     */
-    public static final String EXTRA_CALL_HISTORY_INFO = "android.telecom.EXTRA_CALL_HISTORY_INFO";
-
-    /**
      * Connection extra key used to store the last forwarded number associated with the current
      * connection.  Used to communicate to the user interface that the connection was forwarded via
      * the specified number.
@@ -1594,7 +1588,7 @@
         return mUnmodifiableConferenceables;
     }
 
-    /*
+    /**
      * @hide
      */
     public final void setConnectionService(ConnectionService connectionService) {
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index e9c41a1..b5e4342 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -259,6 +259,14 @@
             = "carrier_allow_turnoff_ims_bool";
 
     /**
+     * Flag specifying whether IMS instant lettering is available for the carrier.  {@code True} if
+     * instant lettering is available for the carrier, {@code false} otherwise.
+     * @hide
+     */
+    public static final String KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL =
+            "carrier_instant_lettering_available_bool";
+
+    /**
      * If Voice Radio Technology is RIL_RADIO_TECHNOLOGY_LTE:14 or RIL_RADIO_TECHNOLOGY_UNKNOWN:0
      * this is the value that should be used instead. A configuration value of
      * RIL_RADIO_TECHNOLOGY_UNKNOWN:0 means there is no replacement value and that the default
@@ -393,6 +401,7 @@
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONING_REQUIRED_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true);
         sDefaults.putBoolean(KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL, true);
+        sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false);
         sDefaults.putBoolean(KEY_DISABLE_CDMA_ACTIVATION_CODE_BOOL, false);
         sDefaults.putBoolean(KEY_DTMF_TYPE_ENABLED_BOOL, false);
         sDefaults.putBoolean(KEY_ENABLE_DIALER_KEY_VIBRATION_BOOL, true);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a8066d8..88612e9 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -2060,6 +2060,8 @@
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     *   OR
+     *   {@link android.Manifest.permission#READ_SMS}
      * <p>
      * The default SMS app can also use this.
      */
@@ -2073,6 +2075,8 @@
      * <p>
      * Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     *   OR
+     *   {@link android.Manifest.permission#READ_SMS}
      * <p>
      * The default SMS app can also use this.
      *
diff --git a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
index 2e515fb..6a61090 100644
--- a/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/android/content/res/BridgeTypedArray.java
@@ -239,15 +239,12 @@
     public int getInt(int index, int defValue) {
         String s = getString(index);
         try {
-            if (s != null) {
-                return convertValueToInt(s, defValue);
-            }
+            return convertValueToInt(s, defValue);
         } catch (NumberFormatException e) {
             Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT,
                     String.format("\"%1$s\" in attribute \"%2$s\" is not a valid integer",
                             s, mNames[index]),
                     null);
-            return defValue;
         }
         return defValue;
     }
@@ -949,7 +946,7 @@
      * "XXXXXXXX" > 80000000.
      */
     private static int convertValueToInt(@Nullable String charSeq, int defValue) {
-        if (null == charSeq)
+        if (null == charSeq || charSeq.isEmpty())
             return defValue;
 
         int sign = 1;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
index c72c979..cbd0415 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/Layout.java
@@ -131,6 +131,7 @@
         HardwareConfig hwConfig = getParams().getHardwareConfig();
         Density density = hwConfig.getDensity();
         boolean isRtl = Bridge.isLocaleRtl(getParams().getLocale());
+        setLayoutDirection(isRtl? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR);
 
         NavigationBar navBar = null;
         if (mBuilder.hasNavBar()) {