Merge "Import translations. DO NOT MERGE" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 90d63b0..047f8d5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -14832,7 +14832,6 @@
   }
 
   public static final class MediaDrm.MediaDrmStateException extends java.lang.IllegalStateException {
-    ctor public MediaDrm.MediaDrmStateException(int, java.lang.String);
     method public java.lang.String getDiagnosticInfo();
   }
 
@@ -27278,7 +27277,7 @@
     method public boolean isSpeaking();
     method public int playEarcon(java.lang.String, int, android.os.Bundle, java.lang.String);
     method public deprecated int playEarcon(java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>);
-    method public int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>, java.lang.String);
+    method public int playSilence(long, int, java.lang.String);
     method public deprecated int playSilence(long, int, java.util.HashMap<java.lang.String, java.lang.String>);
     method public int setAudioAttributes(android.media.AudioAttributes);
     method public deprecated int setEngineByPackageName(java.lang.String);
@@ -27366,7 +27365,7 @@
   public abstract class TextToSpeechService extends android.app.Service {
     ctor public TextToSpeechService();
     method public android.os.IBinder onBind(android.content.Intent);
-    method protected java.lang.String onGetDefaultVoiceNameFor(java.lang.String, java.lang.String, java.lang.String);
+    method public java.lang.String onGetDefaultVoiceNameFor(java.lang.String, java.lang.String, java.lang.String);
     method protected java.util.Set<java.lang.String> onGetFeaturesForLanguage(java.lang.String, java.lang.String, java.lang.String);
     method protected abstract java.lang.String[] onGetLanguage();
     method public java.util.List<android.speech.tts.Voice> onGetVoices();
@@ -27396,6 +27395,7 @@
     method public int getQuality();
     method public boolean isNetworkConnectionRequired();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
     field public static final int LATENCY_HIGH = 400; // 0x190
     field public static final int LATENCY_LOW = 200; // 0xc8
     field public static final int LATENCY_NORMAL = 300; // 0x12c
@@ -28045,328 +28045,16 @@
 
 package android.telecom {
 
-  public final class AudioState implements android.os.Parcelable {
-    ctor public AudioState(boolean, int, int);
-    ctor public AudioState(android.telecom.AudioState);
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-    field public static final int ROUTE_BLUETOOTH = 2; // 0x2
-    field public static final int ROUTE_EARPIECE = 1; // 0x1
-    field public static final int ROUTE_SPEAKER = 8; // 0x8
-    field public static final int ROUTE_WIRED_HEADSET = 4; // 0x4
-    field public static final int ROUTE_WIRED_OR_EARPIECE = 5; // 0x5
-    field public final boolean isMuted;
-    field public final int route;
-    field public final int supportedRouteMask;
-  }
-
-  public abstract class Conference {
-    ctor public Conference(android.telecom.PhoneAccountHandle);
-    method public final boolean addConnection(android.telecom.Connection);
-    method public final void destroy();
-    method public final android.telecom.AudioState getAudioState();
-    method public final int getCapabilities();
-    method public final java.util.List<android.telecom.Connection> getConnections();
-    method public final android.telecom.PhoneAccountHandle getPhoneAccountHandle();
-    method public final int getState();
-    method public void onAudioStateChanged(android.telecom.AudioState);
-    method public void onDisconnect();
-    method public void onHold();
-    method public void onMerge();
-    method public void onPlayDtmfTone(char);
-    method public void onSeparate(android.telecom.Connection);
-    method public void onStopDtmfTone();
-    method public void onSwap();
-    method public void onUnhold();
-    method public final void removeConnection(android.telecom.Connection);
-    method public final void setActive();
-    method public final void setCapabilities(int);
-    method public final void setDisconnected(android.telecom.DisconnectCause);
-    method public final void setOnHold();
-  }
-
-  public abstract class Connection {
-    ctor public Connection();
-    method public static android.telecom.Connection createCanceledConnection();
-    method public static android.telecom.Connection createFailedConnection(android.telecom.DisconnectCause);
-    method public final void destroy();
-    method public final android.net.Uri getAddress();
-    method public final int getAddressPresentation();
-    method public final boolean getAudioModeIsVoip();
-    method public final android.telecom.AudioState getAudioState();
-    method public final int getCallCapabilities();
-    method public final java.lang.String getCallerDisplayName();
-    method public final int getCallerDisplayNamePresentation();
-    method public final android.telecom.Conference getConference();
-    method public final java.util.List<android.telecom.Connection> getConferenceableConnections();
-    method public final android.telecom.DisconnectCause getDisconnectCause();
-    method public final int getState();
-    method public final android.telecom.StatusHints getStatusHints();
-    method public final boolean isRingbackRequested();
-    method public void onAbort();
-    method public void onAnswer();
-    method public void onAudioStateChanged(android.telecom.AudioState);
-    method public void onConferenceWith(android.telecom.Connection);
-    method public void onDisconnect();
-    method public void onHold();
-    method public void onPlayDtmfTone(char);
-    method public void onPostDialContinue(boolean);
-    method public void onReject();
-    method public void onSeparate();
-    method public void onStateChanged(int);
-    method public void onStopDtmfTone();
-    method public void onUnhold();
-    method public final void setActive();
-    method public final void setAddress(android.net.Uri, int);
-    method public final void setAudioModeIsVoip(boolean);
-    method public final void setCallCapabilities(int);
-    method public final void setCallerDisplayName(java.lang.String, int);
-    method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
-    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 setInitialized();
-    method public final void setInitializing();
-    method public final void setOnHold();
-    method public final void setPostDialWait(java.lang.String);
-    method public final void setRingbackRequested(boolean);
-    method public final void setRinging();
-    method public final void setStatusHints(android.telecom.StatusHints);
-    method public static java.lang.String stateToString(int);
-    field public static final int STATE_ACTIVE = 4; // 0x4
-    field public static final int STATE_DIALING = 3; // 0x3
-    field public static final int STATE_DISCONNECTED = 6; // 0x6
-    field public static final int STATE_HOLDING = 5; // 0x5
-    field public static final int STATE_INITIALIZING = 0; // 0x0
-    field public static final int STATE_NEW = 1; // 0x1
-    field public static final int STATE_RINGING = 2; // 0x2
-  }
-
-  public final class ConnectionRequest implements android.os.Parcelable {
-    ctor public ConnectionRequest(android.telecom.PhoneAccountHandle, android.net.Uri, android.os.Bundle);
-    method public int describeContents();
-    method public android.telecom.PhoneAccountHandle getAccountHandle();
-    method public android.net.Uri getAddress();
-    method public android.os.Bundle getExtras();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-  }
-
-  public abstract class ConnectionService extends android.app.Service {
-    ctor public ConnectionService();
-    method public final void addConference(android.telecom.Conference);
-    method public final void conferenceRemoteConnections(android.telecom.RemoteConnection, android.telecom.RemoteConnection);
-    method public final android.telecom.RemoteConnection createRemoteIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
-    method public final android.telecom.RemoteConnection createRemoteOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
-    method public final java.util.Collection<android.telecom.Connection> getAllConnections();
-    method public final android.os.IBinder onBind(android.content.Intent);
-    method public void onConference(android.telecom.Connection, android.telecom.Connection);
-    method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
-    method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest);
-    method public void onRemoteConferenceAdded(android.telecom.RemoteConference);
-    field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService";
-  }
-
-  public final class DisconnectCause implements android.os.Parcelable {
-    ctor public DisconnectCause(int);
-    ctor public DisconnectCause(int, java.lang.String);
-    ctor public DisconnectCause(int, java.lang.CharSequence, java.lang.CharSequence, java.lang.String);
-    ctor public DisconnectCause(int, java.lang.CharSequence, java.lang.CharSequence, java.lang.String, int);
-    method public int describeContents();
-    method public int getCode();
-    method public java.lang.CharSequence getDescription();
-    method public java.lang.CharSequence getLabel();
-    method public java.lang.String getReason();
-    method public int getTone();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int BUSY = 7; // 0x7
-    field public static final int CANCELED = 4; // 0x4
-    field public static final android.os.Parcelable.Creator CREATOR;
-    field public static final int ERROR = 1; // 0x1
-    field public static final int LOCAL = 2; // 0x2
-    field public static final int MISSED = 5; // 0x5
-    field public static final int OTHER = 9; // 0x9
-    field public static final int REJECTED = 6; // 0x6
-    field public static final int REMOTE = 3; // 0x3
-    field public static final int RESTRICTED = 8; // 0x8
-    field public static final int UNKNOWN = 0; // 0x0
-  }
-
-  public class GatewayInfo implements android.os.Parcelable {
-    method public int describeContents();
-    method public android.net.Uri getGatewayAddress();
-    method public java.lang.String getGatewayProviderPackageName();
-    method public android.net.Uri getOriginalAddress();
-    method public boolean isEmpty();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-  }
-
-  public class PhoneAccount implements android.os.Parcelable {
-    method public static android.telecom.PhoneAccount.Builder builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
-    method public int describeContents();
-    method public android.telecom.PhoneAccountHandle getAccountHandle();
-    method public android.net.Uri getAddress();
-    method public int getCapabilities();
-    method public android.graphics.drawable.Drawable getIcon(android.content.Context);
-    method public int getIconResId();
-    method public java.lang.CharSequence getLabel();
-    method public java.lang.CharSequence getShortDescription();
-    method public android.net.Uri getSubscriptionAddress();
-    method public java.util.List<java.lang.String> getSupportedUriSchemes();
-    method public boolean hasCapabilities(int);
-    method public boolean supportsUriScheme(java.lang.String);
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
-    field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
-    field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
-    field public static final android.os.Parcelable.Creator CREATOR;
-    field public static final java.lang.String SCHEME_SIP = "sip";
-    field public static final java.lang.String SCHEME_TEL = "tel";
-    field public static final java.lang.String SCHEME_VOICEMAIL = "voicemail";
-  }
-
-  public static class PhoneAccount.Builder {
-    ctor public PhoneAccount.Builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
-    ctor public PhoneAccount.Builder(android.telecom.PhoneAccount);
-    method public android.telecom.PhoneAccount build();
-    method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri);
-    method public android.telecom.PhoneAccount.Builder setCapabilities(int);
-    method public android.telecom.PhoneAccount.Builder setIconResId(int);
-    method public android.telecom.PhoneAccount.Builder setShortDescription(java.lang.CharSequence);
-    method public android.telecom.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri);
-    method public android.telecom.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
-  }
-
-  public class PhoneAccountHandle implements android.os.Parcelable {
-    ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String);
-    method public int describeContents();
-    method public android.content.ComponentName getComponentName();
-    method public java.lang.String getId();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-  }
-
-  public final class PhoneCapabilities {
-    method public static java.lang.String toString(int);
-    field public static final int ADD_CALL = 16; // 0x10
-    field public static final int ALL = 12543; // 0x30ff
-    field public static final int DISCONNECT_FROM_CONFERENCE = 8192; // 0x2000
-    field public static final int HOLD = 1; // 0x1
-    field public static final int MANAGE_CONFERENCE = 128; // 0x80
-    field public static final int MERGE_CONFERENCE = 4; // 0x4
-    field public static final int MUTE = 64; // 0x40
-    field public static final int RESPOND_VIA_TEXT = 32; // 0x20
-    field public static final int SEPARATE_FROM_CONFERENCE = 4096; // 0x1000
-    field public static final int SUPPORT_HOLD = 2; // 0x2
-    field public static final int SWAP_CONFERENCE = 8; // 0x8
-  }
-
-  public final class RemoteConference {
-    method public void disconnect();
-    method public final int getCallCapabilities();
-    method public final java.util.List<android.telecom.RemoteConnection> getConnections();
-    method public android.telecom.DisconnectCause getDisconnectCause();
-    method public final int getState();
-    method public void hold();
-    method public void playDtmfTone(char);
-    method public final void registerCallback(android.telecom.RemoteConference.Callback);
-    method public void separate(android.telecom.RemoteConnection);
-    method public void setAudioState(android.telecom.AudioState);
-    method public void stopDtmfTone();
-    method public void unhold();
-    method public final void unregisterCallback(android.telecom.RemoteConference.Callback);
-  }
-
-  public static abstract class RemoteConference.Callback {
-    ctor public RemoteConference.Callback();
-    method public void onCapabilitiesChanged(android.telecom.RemoteConference, int);
-    method public void onConnectionAdded(android.telecom.RemoteConference, android.telecom.RemoteConnection);
-    method public void onConnectionRemoved(android.telecom.RemoteConference, android.telecom.RemoteConnection);
-    method public void onDestroyed(android.telecom.RemoteConference);
-    method public void onDisconnected(android.telecom.RemoteConference, android.telecom.DisconnectCause);
-    method public void onStateChanged(android.telecom.RemoteConference, int, int);
-  }
-
-  public final class RemoteConnection {
-    method public void abort();
-    method public void answer();
-    method public void disconnect();
-    method public android.net.Uri getAddress();
-    method public int getAddressPresentation();
-    method public int getCallCapabilities();
-    method public java.lang.CharSequence getCallerDisplayName();
-    method public int getCallerDisplayNamePresentation();
-    method public android.telecom.RemoteConference getConference();
-    method public java.util.List<android.telecom.RemoteConnection> getConferenceableConnections();
-    method public android.telecom.DisconnectCause getDisconnectCause();
-    method public int getState();
-    method public android.telecom.StatusHints getStatusHints();
-    method public void hold();
-    method public boolean isRingbackRequested();
-    method public boolean isVoipAudioMode();
-    method public void playDtmfTone(char);
-    method public void postDialContinue(boolean);
-    method public void registerCallback(android.telecom.RemoteConnection.Callback);
-    method public void reject();
-    method public void setAudioState(android.telecom.AudioState);
-    method public void stopDtmfTone();
-    method public void unhold();
-    method public void unregisterCallback(android.telecom.RemoteConnection.Callback);
-  }
-
-  public static abstract class RemoteConnection.Callback {
-    ctor public RemoteConnection.Callback();
-    method public void onAddressChanged(android.telecom.RemoteConnection, android.net.Uri, int);
-    method public void onCallCapabilitiesChanged(android.telecom.RemoteConnection, int);
-    method public void onCallerDisplayNameChanged(android.telecom.RemoteConnection, java.lang.String, int);
-    method public void onConferenceChanged(android.telecom.RemoteConnection, android.telecom.RemoteConference);
-    method public void onConferenceableConnectionsChanged(android.telecom.RemoteConnection, java.util.List<android.telecom.RemoteConnection>);
-    method public void onDestroyed(android.telecom.RemoteConnection);
-    method public void onDisconnected(android.telecom.RemoteConnection, android.telecom.DisconnectCause);
-    method public void onPostDialWait(android.telecom.RemoteConnection, java.lang.String);
-    method public void onRingbackRequested(android.telecom.RemoteConnection, boolean);
-    method public void onStateChanged(android.telecom.RemoteConnection, int);
-    method public void onStatusHintsChanged(android.telecom.RemoteConnection, android.telecom.StatusHints);
-    method public void onVoipAudioChanged(android.telecom.RemoteConnection, boolean);
-  }
-
-  public final class StatusHints implements android.os.Parcelable {
-    ctor public StatusHints(android.content.ComponentName, java.lang.CharSequence, int, android.os.Bundle);
-    method public int describeContents();
-    method public android.os.Bundle getExtras();
-    method public android.graphics.drawable.Drawable getIcon(android.content.Context);
-    method public int getIconResId();
-    method public java.lang.CharSequence getLabel();
-    method public android.content.ComponentName getPackageName();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-  }
-
   public class TelecomManager {
-    method public void addNewIncomingCall(android.telecom.PhoneAccountHandle, android.os.Bundle);
     method public void cancelMissedCallsNotification();
-    method public void clearAccounts();
-    method public android.telecom.PhoneAccountHandle getConnectionManager();
-    method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
-    method public java.util.List<android.telecom.PhoneAccountHandle> getPhoneAccountsForPackage();
     method public boolean handleMmi(java.lang.String);
-    method public boolean hasMultipleCallCapableAccounts();
     method public boolean isInCall();
-    method public void registerPhoneAccount(android.telecom.PhoneAccount);
     method public void showInCallScreen(boolean);
-    method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle);
-    field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
-    field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
     field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
     field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
     field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
-    field public static final java.lang.String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
     field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
     field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
-    field public static final java.lang.String EXTRA_CONNECTION_SERVICE = "android.telecom.extra.CONNECTION_SERVICE";
-    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
     field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 85d4839..005baed 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2303,19 +2303,27 @@
      * call this method.
      * 
      * @param packageName The name of the package to be stopped.
+     * @param userId The user for which the running package is to be stopped.
      * 
      * @hide This is not available to third party applications due to
      * it allowing them to break other applications by stopping their
      * services, removing their alarms, etc.
      */
-    public void forceStopPackage(String packageName) {
+    public void forceStopPackageAsUser(String packageName, int userId) {
         try {
-            ActivityManagerNative.getDefault().forceStopPackage(packageName,
-                    UserHandle.myUserId());
+            ActivityManagerNative.getDefault().forceStopPackage(packageName, userId);
         } catch (RemoteException e) {
         }
     }
-    
+
+    /**
+     * @see #forceStopPackageAsUser(String, int)
+     * @hide
+     */
+    public void forceStopPackage(String packageName) {
+        forceStopPackageAsUser(packageName, UserHandle.myUserId());
+    }
+
     /**
      * Get the device configuration attributes.
      */
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 7d0d27f..dd49009 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5132,6 +5132,8 @@
         // process.
         if (!ActivityManager.isHighEndGfx()) {
             HardwareRenderer.disable(true);
+        } else {
+            HardwareRenderer.enableForegroundTrimming();
         }
         ActivityThread thread = new ActivityThread();
         thread.attach(true);
diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java
index bc2e6ca..555d20b 100644
--- a/core/java/android/app/ActivityTransitionState.java
+++ b/core/java/android/app/ActivityTransitionState.java
@@ -67,6 +67,12 @@
     private ExitTransitionCoordinator mCalledExitCoordinator;
 
     /**
+     * The ExitTransitionCoordinator used to return to a previous Activity when called with
+     * {@link android.app.Activity#finishAfterTransition()}.
+     */
+    private ExitTransitionCoordinator mReturnExitCoordinator;
+
+    /**
      * We must be able to cancel entering transitions to stop changing the Window to
      * opaque when we exit before making the Window opaque.
      */
@@ -218,6 +224,10 @@
             mEnterTransitionCoordinator.stop();
             mEnterTransitionCoordinator = null;
         }
+        if (mReturnExitCoordinator != null) {
+            mReturnExitCoordinator.stop();
+            mReturnExitCoordinator = null;
+        }
     }
 
     public void onResume() {
@@ -260,12 +270,12 @@
                     }
                 }
 
-                ExitTransitionCoordinator exitCoordinator =
+                mReturnExitCoordinator =
                         new ExitTransitionCoordinator(activity, mEnteringNames, null, null, true);
                 if (enterViewsTransition != null && decor != null) {
                     enterViewsTransition.resume(decor);
                 }
-                exitCoordinator.startExit(activity.mResultCode, activity.mResultData);
+                mReturnExitCoordinator.startExit(activity.mResultCode, activity.mResultData);
             }
             return true;
         }
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 216d6ba..add67f2 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -30,6 +30,7 @@
 import android.view.ViewGroup;
 import android.view.ViewGroupOverlay;
 import android.view.ViewTreeObserver;
+import android.view.Window;
 
 import java.util.ArrayList;
 
@@ -265,10 +266,14 @@
     }
 
     protected void prepareEnter() {
+        ViewGroup decorView = getDecor();
+        if (mActivity == null || decorView == null) {
+            return;
+        }
         mActivity.overridePendingTransition(0, 0);
         if (!mIsReturning) {
             mWasOpaque = mActivity.convertToTranslucent(null, null);
-            Drawable background = getDecor().getBackground();
+            Drawable background = decorView.getBackground();
             if (background != null) {
                 getWindow().setBackgroundDrawable(null);
                 background = background.mutate();
@@ -282,18 +287,26 @@
 
     @Override
     protected Transition getViewsTransition() {
+        Window window = getWindow();
+        if (window == null) {
+            return null;
+        }
         if (mIsReturning) {
-            return getWindow().getReenterTransition();
+            return window.getReenterTransition();
         } else {
-            return getWindow().getEnterTransition();
+            return window.getEnterTransition();
         }
     }
 
     protected Transition getSharedElementTransition() {
+        Window window = getWindow();
+        if (window == null) {
+            return null;
+        }
         if (mIsReturning) {
-            return getWindow().getSharedElementReenterTransition();
+            return window.getSharedElementReenterTransition();
         } else {
-            return getWindow().getSharedElementEnterTransition();
+            return window.getSharedElementEnterTransition();
         }
     }
 
@@ -518,15 +531,29 @@
     }
 
     public void stop() {
-        makeOpaque();
-        mIsCanceled = true;
-        mResultReceiver = null;
+        // Restore the background to its previous state since the
+        // Activity is stopping.
         if (mBackgroundAnimator != null) {
             mBackgroundAnimator.end();
             mBackgroundAnimator = null;
+        } else if (mWasOpaque) {
+            ViewGroup decorView = getDecor();
+            if (decorView != null) {
+                Drawable drawable = decorView.getBackground();
+                if (drawable != null) {
+                    drawable.setAlpha(1);
+                }
+            }
         }
+        makeOpaque();
+        mIsCanceled = true;
+        mResultReceiver = null;
         mActivity = null;
         moveSharedElementsFromOverlay();
+        if (mTransitioningViews != null) {
+            showViews(mTransitioningViews, true);
+        }
+        showViews(mSharedElements, true);
         clearState();
     }
 
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index d4d3eda..dd3df47 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -255,6 +255,16 @@
         }
     }
 
+    public void stop() {
+        if (mIsReturning && mActivity != null) {
+            // Override the previous ActivityOptions. We don't want the
+            // activity to have options since we're essentially canceling the
+            // transition and finishing right now.
+            mActivity.convertToTranslucent(null, null);
+            finish();
+        }
+    }
+
     private void startExitTransition() {
         Transition transition = getExitTransition();
         ViewGroup decorView = getDecor();
@@ -425,13 +435,14 @@
 
     private void finish() {
         stopCancel();
-        mActivity.mActivityTransitionState.clear();
+        if (mActivity != null) {
+            mActivity.mActivityTransitionState.clear();
+            mActivity.finish();
+            mActivity.overridePendingTransition(0, 0);
+            mActivity = null;
+        }
         // Clear the state so that we can't hold any references accidentally and leak memory.
-        mHandler.removeMessages(MSG_CANCEL);
         mHandler = null;
-        mActivity.finish();
-        mActivity.overridePendingTransition(0, 0);
-        mActivity = null;
         mSharedElementBundle = null;
         if (mBackgroundAnimator != null) {
             mBackgroundAnimator.cancel();
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a19fbd3..702ac6b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -7498,23 +7498,32 @@
 
         final String action = getAction();
         if (ACTION_CHOOSER.equals(action)) {
+            // Inspect contained intents to see if we need to migrate extras. We
+            // don't promote ClipData to the parent, since ChooserActivity will
+            // already start the picked item as the caller, and we can't combine
+            // the flags in a safe way.
+
+            boolean migrated = false;
             try {
-                // Inspect target intent to see if we need to migrate
-                final Intent target = getParcelableExtra(EXTRA_INTENT);
-                if (target != null && target.migrateExtraStreamToClipData()) {
-                    // Since we migrated in child, we need to promote ClipData
-                    // and flags to ourselves to grant.
-                    setClipData(target.getClipData());
-                    addFlags(target.getFlags() & (FLAG_GRANT_READ_URI_PERMISSION
-                            | FLAG_GRANT_WRITE_URI_PERMISSION
-                            | FLAG_GRANT_PERSISTABLE_URI_PERMISSION
-                            | FLAG_GRANT_PREFIX_URI_PERMISSION));
-                    return true;
-                } else {
-                    return false;
+                final Intent intent = getParcelableExtra(EXTRA_INTENT);
+                if (intent != null) {
+                    migrated |= intent.migrateExtraStreamToClipData();
                 }
             } catch (ClassCastException e) {
             }
+            try {
+                final Parcelable[] intents = getParcelableArrayExtra(EXTRA_INITIAL_INTENTS);
+                if (intents != null) {
+                    for (int i = 0; i < intents.length; i++) {
+                        final Intent intent = (Intent) intents[i];
+                        if (intent != null) {
+                            migrated |= intent.migrateExtraStreamToClipData();
+                        }
+                    }
+                }
+            } catch (ClassCastException e) {
+            }
+            return migrated;
 
         } else if (ACTION_SEND.equals(action)) {
             try {
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 186623a..73b93c6 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -16,6 +16,7 @@
 
 package android.content.res;
 
+import android.annotation.Nullable;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -728,15 +729,13 @@
     }
 
     /**
-     * Retrieve the Drawable for the attribute at <var>index</var>.  This
-     * gets the resource ID of the selected attribute, and uses
-     * {@link Resources#getDrawable Resources.getDrawable} of the owning
-     * Resources object to retrieve its Drawable.
+     * Retrieve the Drawable for the attribute at <var>index</var>.
      *
      * @param index Index of attribute to retrieve.
      *
      * @return Drawable for the attribute, or null if not defined.
      */
+    @Nullable
     public Drawable getDrawable(int index) {
         if (mRecycled) {
             throw new RuntimeException("Cannot make calls to a recycled instance!");
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index c525348..55ca486 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -391,9 +391,9 @@
      * <p>Not all the auto-focus modes may be supported by a
      * given camera device. This entry lists the valid modes for
      * {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} for this camera device.</p>
-     * <p>All camera devices will support OFF mode, and all camera devices with
-     * adjustable focuser units (<code>{@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance} &gt; 0</code>)
-     * will support AUTO mode.</p>
+     * <p>All LIMITED and FULL mode camera devices will support OFF mode, and all
+     * camera devices with adjustable focuser units
+     * (<code>{@link CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE android.lens.info.minimumFocusDistance} &gt; 0</code>) will support AUTO mode.</p>
      *
      * @see CaptureRequest#CONTROL_AF_MODE
      * @see CameraCharacteristics#LENS_INFO_MINIMUM_FOCUS_DISTANCE
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
index 6aab53c..e96c15f 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
@@ -16,8 +16,8 @@
 
 package android.hardware.camera2.legacy;
 
+import android.hardware.camera2.impl.CameraDeviceImpl;
 import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.utils.CameraBinderDecorator;
 import android.os.Handler;
 import android.util.Log;
 
@@ -53,7 +53,7 @@
             "CAPTURING"};
 
     private int mCurrentState = STATE_UNCONFIGURED;
-    private int mCurrentError = CameraBinderDecorator.NO_ERROR;
+    private int mCurrentError = NO_CAPTURE_ERROR;
 
     private RequestHolder mCurrentRequest = null;
 
@@ -87,7 +87,7 @@
      * </p>
      *
      * @param error the error to set.  Should be one of the error codes defined in
-     *      {@link android.hardware.camera2.utils.CameraBinderDecorator}.
+     *      {@link CameraDeviceImpl.CameraDeviceCallbacks}.
      */
     public synchronized void setError(int error) {
         mCurrentError = error;
@@ -102,11 +102,11 @@
      * {@link CameraDeviceStateListener#onConfiguring()} will be called.
      * </p>
      *
-     * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+     * @return {@code false} if an error has occurred.
      */
-    public synchronized int setConfiguring() {
+    public synchronized boolean setConfiguring() {
         doStateTransition(STATE_CONFIGURING);
-        return mCurrentError;
+        return mCurrentError == NO_CAPTURE_ERROR;
     }
 
     /**
@@ -117,11 +117,11 @@
      * {@link CameraDeviceStateListener#onIdle()} will be called.
      * </p>
      *
-     * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+     * @return {@code false} if an error has occurred.
      */
-    public synchronized int setIdle() {
+    public synchronized boolean setIdle() {
         doStateTransition(STATE_IDLE);
-        return mCurrentError;
+        return mCurrentError == NO_CAPTURE_ERROR;
     }
 
     /**
@@ -137,13 +137,13 @@
      * @param captureError Report a recoverable error for a single request using a valid
      *                     error code for {@code ICameraDeviceCallbacks}, or
      *                     {@link #NO_CAPTURE_ERROR}
-     * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+     * @return {@code false} if an error has occurred.
      */
-    public synchronized int setCaptureStart(final RequestHolder request, long timestamp,
+    public synchronized boolean setCaptureStart(final RequestHolder request, long timestamp,
                                             int captureError) {
         mCurrentRequest = request;
         doStateTransition(STATE_CAPTURING, timestamp, captureError);
-        return mCurrentError;
+        return mCurrentError == NO_CAPTURE_ERROR;
     }
 
     /**
@@ -161,16 +161,16 @@
      * @param captureError Report a recoverable error for a single buffer or result using a valid
      *                     error code for {@code ICameraDeviceCallbacks}, or
      *                     {@link #NO_CAPTURE_ERROR}.
-     * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+     * @return {@code false} if an error has occurred.
      */
-    public synchronized int setCaptureResult(final RequestHolder request,
+    public synchronized boolean setCaptureResult(final RequestHolder request,
                                              final CameraMetadataNative result,
                                              final int captureError) {
         if (mCurrentState != STATE_CAPTURING) {
             Log.e(TAG, "Cannot receive result while in state: " + mCurrentState);
-            mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
+            mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
             doStateTransition(STATE_ERROR);
-            return mCurrentError;
+            return mCurrentError == NO_CAPTURE_ERROR;
         }
 
         if (mCurrentHandler != null && mCurrentListener != null) {
@@ -190,7 +190,7 @@
                 });
             }
         }
-        return mCurrentError;
+        return mCurrentError == NO_CAPTURE_ERROR;
     }
 
     /**
@@ -206,7 +206,7 @@
     }
 
     private void doStateTransition(int newState) {
-        doStateTransition(newState, /*timestamp*/0, CameraBinderDecorator.NO_ERROR);
+        doStateTransition(newState, /*timestamp*/0, NO_CAPTURE_ERROR);
     }
 
     private void doStateTransition(int newState, final long timestamp, final int error) {
@@ -233,7 +233,7 @@
             case STATE_CONFIGURING:
                 if (mCurrentState != STATE_UNCONFIGURED && mCurrentState != STATE_IDLE) {
                     Log.e(TAG, "Cannot call configure while in state: " + mCurrentState);
-                    mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
+                    mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
                     doStateTransition(STATE_ERROR);
                     break;
                 }
@@ -255,7 +255,7 @@
 
                 if (mCurrentState != STATE_CONFIGURING && mCurrentState != STATE_CAPTURING) {
                     Log.e(TAG, "Cannot call idle while in state: " + mCurrentState);
-                    mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
+                    mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
                     doStateTransition(STATE_ERROR);
                     break;
                 }
@@ -274,7 +274,7 @@
             case STATE_CAPTURING:
                 if (mCurrentState != STATE_IDLE && mCurrentState != STATE_CAPTURING) {
                     Log.e(TAG, "Cannot call capture while in state: " + mCurrentState);
-                    mCurrentError = CameraBinderDecorator.INVALID_OPERATION;
+                    mCurrentError = CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE;
                     doStateTransition(STATE_ERROR);
                     break;
                 }
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index 4aa330d..e19f587 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -87,6 +87,15 @@
         mSurfaceIdCounter = 0;
     }
 
+    private static int translateErrorsFromCamera1(int errorCode) {
+        switch (errorCode) {
+            case CameraBinderDecorator.EACCES:
+                return CameraBinderDecorator.PERMISSION_DENIED;
+            default:
+                return errorCode;
+        }
+    }
+
     /**
      * Create a separate looper/thread for the camera to run on; open the camera.
      *
@@ -130,8 +139,7 @@
             // Save the looper so that we can terminate this thread
             // after we are done with it.
             mLooper = Looper.myLooper();
-            mInitErrors = mCamera.cameraInitUnspecified(mCameraId);
-
+            mInitErrors = translateErrorsFromCamera1(mCamera.cameraInitUnspecified(mCameraId));
             mStartDone.open();
             Looper.loop();  // Blocks forever until #close is called.
         }
diff --git a/core/java/android/hardware/camera2/legacy/GLThreadManager.java b/core/java/android/hardware/camera2/legacy/GLThreadManager.java
index 2c584ef..c8e0147 100644
--- a/core/java/android/hardware/camera2/legacy/GLThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/GLThreadManager.java
@@ -17,6 +17,7 @@
 package android.hardware.camera2.legacy;
 
 import android.graphics.SurfaceTexture;
+import android.hardware.camera2.impl.CameraDeviceImpl;
 import android.os.ConditionVariable;
 import android.os.Handler;
 import android.os.Message;
@@ -42,6 +43,8 @@
 
     private CaptureCollector mCaptureCollector;
 
+    private final CameraDeviceState mDeviceState;
+
     private final SurfaceTextureRenderer mTextureRenderer;
 
     private final RequestHandlerThread mGLHandlerThread;
@@ -76,42 +79,47 @@
             if (mCleanup) {
                 return true;
             }
-            switch (msg.what) {
-                case MSG_NEW_CONFIGURATION:
-                    ConfigureHolder configure = (ConfigureHolder) msg.obj;
-                    mTextureRenderer.cleanupEGLContext();
-                    mTextureRenderer.configureSurfaces(configure.surfaces);
-                    mCaptureCollector = checkNotNull(configure.collector);
-                    configure.condition.open();
-                    mConfigured = true;
-                    break;
-                case MSG_NEW_FRAME:
-                    if (mDroppingFrames) {
-                        Log.w(TAG, "Ignoring frame.");
+            try {
+                switch (msg.what) {
+                    case MSG_NEW_CONFIGURATION:
+                        ConfigureHolder configure = (ConfigureHolder) msg.obj;
+                        mTextureRenderer.cleanupEGLContext();
+                        mTextureRenderer.configureSurfaces(configure.surfaces);
+                        mCaptureCollector = checkNotNull(configure.collector);
+                        configure.condition.open();
+                        mConfigured = true;
                         break;
-                    }
-                    if (DEBUG) {
-                        mPrevCounter.countAndLog();
-                    }
-                    if (!mConfigured) {
-                        Log.e(TAG, "Dropping frame, EGL context not configured!");
-                    }
-                    mTextureRenderer.drawIntoSurfaces(mCaptureCollector);
-                    break;
-                case MSG_CLEANUP:
-                    mTextureRenderer.cleanupEGLContext();
-                    mCleanup = true;
-                    mConfigured = false;
-                    break;
-                case MSG_DROP_FRAMES:
-                    mDroppingFrames = true;
-                    break;
-                case MSG_ALLOW_FRAMES:
-                    mDroppingFrames = false;
-                    break;
-                default:
-                    Log.e(TAG, "Unhandled message " + msg.what + " on GLThread.");
-                    break;
+                    case MSG_NEW_FRAME:
+                        if (mDroppingFrames) {
+                            Log.w(TAG, "Ignoring frame.");
+                            break;
+                        }
+                        if (DEBUG) {
+                            mPrevCounter.countAndLog();
+                        }
+                        if (!mConfigured) {
+                            Log.e(TAG, "Dropping frame, EGL context not configured!");
+                        }
+                        mTextureRenderer.drawIntoSurfaces(mCaptureCollector);
+                        break;
+                    case MSG_CLEANUP:
+                        mTextureRenderer.cleanupEGLContext();
+                        mCleanup = true;
+                        mConfigured = false;
+                        break;
+                    case MSG_DROP_FRAMES:
+                        mDroppingFrames = true;
+                        break;
+                    case MSG_ALLOW_FRAMES:
+                        mDroppingFrames = false;
+                        break;
+                    default:
+                        Log.e(TAG, "Unhandled message " + msg.what + " on GLThread.");
+                        break;
+                }
+            } catch (Exception e) {
+                Log.e(TAG, "Received exception on GL render thread: ", e);
+                mDeviceState.setError(CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
             }
             return true;
         }
@@ -122,11 +130,13 @@
      *
      * @param cameraId the camera id for this thread.
      * @param facing direction the camera is facing.
+     * @param state {@link CameraDeviceState} to use for error handling.
      */
-    public GLThreadManager(int cameraId, int facing) {
+    public GLThreadManager(int cameraId, int facing, CameraDeviceState state) {
         mTextureRenderer = new SurfaceTextureRenderer(facing);
         TAG = String.format("CameraDeviceGLThread-%d", cameraId);
         mGLHandlerThread = new RequestHandlerThread(TAG, mGLHandlerCb);
+        mDeviceState = state;
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 9143152..a724b41 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -26,6 +26,7 @@
 import android.hardware.camera2.params.StreamConfiguration;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.hardware.camera2.utils.ArrayUtils;
+import android.hardware.camera2.utils.CameraBinderDecorator;
 import android.hardware.camera2.utils.LongParcelable;
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.utils.CameraRuntimeException;
@@ -288,17 +289,18 @@
             }
         }
 
-        int error = mDeviceState.setConfiguring();
-        if (error == NO_ERROR) {
+        boolean success = false;
+        if (mDeviceState.setConfiguring()) {
             mRequestThreadManager.configure(outputs);
-            error = mDeviceState.setIdle();
+            success = mDeviceState.setIdle();
         }
 
-        if (error == NO_ERROR) {
+        if (success) {
             mConfiguredSurfaces = outputs != null ? new ArrayList<>(outputs) : null;
+        } else {
+            return CameraBinderDecorator.INVALID_OPERATION;
         }
-
-        return error;
+        return CameraBinderDecorator.NO_ERROR;
     }
 
     /**
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 907d2ae..618195a 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -34,7 +34,6 @@
 import android.hardware.camera2.utils.ArrayUtils;
 import android.hardware.camera2.utils.ListUtils;
 import android.hardware.camera2.utils.ParamsUtils;
-import android.hardware.camera2.utils.SizeAreaComparator;
 import android.util.Log;
 import android.util.Range;
 import android.util.Size;
@@ -88,6 +87,9 @@
 
     static final int UNKNOWN_MODE = -1;
 
+    // Maximum difference between a preview size aspect ratio and a jpeg size aspect ratio
+    private static final float PREVIEW_ASPECT_RATIO_TOLERANCE = 0.01f;
+
     /*
      * Development hijinks: Lie about not supporting certain capabilities
      *
@@ -103,6 +105,7 @@
     static final boolean LIE_ABOUT_AWB_STATE = false;
     static final boolean LIE_ABOUT_AWB = false;
 
+
     /**
      * Create characteristics for a legacy device by mapping the {@code parameters}
      * and {@code info}
@@ -262,6 +265,64 @@
          * remapping to public format constants.
          */
         List<Camera.Size> previewSizes = p.getSupportedPreviewSizes();
+        List<Camera.Size> jpegSizes = p.getSupportedPictureSizes();
+        /*
+         * Work-around for b/17589233:
+         * - Some HALs's largest preview size aspect ratio does not match the largest JPEG size AR
+         * - This causes a large amount of problems with focus/metering because it's relative to
+         *   preview, making the difference between the JPEG and preview viewport inaccessible
+         * - This boils down to metering or focusing areas being "arbitrarily" cropped
+         *   in the capture result.
+         * - Work-around the HAL limitations by removing all of the largest preview sizes
+         *   until we get one with the same aspect ratio as the jpeg size.
+         */
+        {
+            SizeAreaComparator areaComparator = new SizeAreaComparator();
+
+            // Sort preview to min->max
+            Collections.sort(previewSizes, areaComparator);
+
+            Camera.Size maxJpegSize = SizeAreaComparator.findLargestByArea(jpegSizes);
+            float jpegAspectRatio = maxJpegSize.width * 1.0f / maxJpegSize.height;
+
+            if (VERBOSE) {
+                Log.v(TAG, String.format("mapScalerStreamConfigs - largest JPEG area %dx%d, AR=%f",
+                        maxJpegSize.width, maxJpegSize.height, jpegAspectRatio));
+            }
+
+            // Now remove preview sizes from the end (largest->smallest) until aspect ratio matches
+            while (!previewSizes.isEmpty()) {
+                int index = previewSizes.size() - 1; // max is always at the end
+                Camera.Size size = previewSizes.get(index);
+
+                float previewAspectRatio = size.width * 1.0f / size.height;
+
+                if (Math.abs(jpegAspectRatio - previewAspectRatio) >=
+                        PREVIEW_ASPECT_RATIO_TOLERANCE) {
+                    previewSizes.remove(index); // Assume removing from end is O(1)
+
+                    if (VERBOSE) {
+                        Log.v(TAG, String.format(
+                                "mapScalerStreamConfigs - removed preview size %dx%d, AR=%f "
+                                        + "was not the same",
+                                size.width, size.height, previewAspectRatio));
+                    }
+                } else {
+                    break;
+                }
+            }
+
+            if (previewSizes.isEmpty()) {
+                // Fall-back to the original faulty behavior, but at least work
+                Log.w(TAG, "mapScalerStreamConfigs - failed to find any preview size matching " +
+                        "JPEG aspect ratio " + jpegAspectRatio);
+                previewSizes = p.getSupportedPreviewSizes();
+            }
+
+            // Sort again, this time in descending order max->min
+            Collections.sort(previewSizes, Collections.reverseOrder(areaComparator));
+        }
+
         appendStreamConfig(availableStreamConfigs,
                 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, previewSizes);
         appendStreamConfig(availableStreamConfigs,
@@ -279,7 +340,6 @@
             }
         }
 
-        List<Camera.Size> jpegSizes = p.getSupportedPictureSizes();
         appendStreamConfig(availableStreamConfigs,
                 HAL_PIXEL_FORMAT_BLOB, p.getSupportedPictureSizes());
         /*
@@ -620,7 +680,7 @@
 
         if (thumbnailSizes != null) {
             Size[] sizes = convertSizeListToArray(thumbnailSizes);
-            Arrays.sort(sizes, new SizeAreaComparator());
+            Arrays.sort(sizes, new android.hardware.camera2.utils.SizeAreaComparator());
             m.set(JPEG_AVAILABLE_THUMBNAIL_SIZES, sizes);
         }
     }
diff --git a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
index 72d2d81..61f7b8b 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyRequestMapper.java
@@ -648,6 +648,8 @@
                 return Camera.Parameters.WHITE_BALANCE_CLOUDY_DAYLIGHT;
             case CONTROL_AWB_MODE_TWILIGHT:
                 return Camera.Parameters.WHITE_BALANCE_TWILIGHT;
+            case CONTROL_AWB_MODE_SHADE:
+                return Parameters.WHITE_BALANCE_SHADE;
             default:
                 Log.w(TAG, "convertAwbModeToLegacy - unrecognized control.awbMode" + mode);
                 return Camera.Parameters.WHITE_BALANCE_AUTO;
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index 87ee1ee..788b6d8 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -98,6 +98,7 @@
     private SurfaceTexture mDummyTexture;
     private Surface mDummySurface;
 
+    private final Object mIdleLock = new Object();
     private final FpsCounter mPrevCounter = new FpsCounter("Incoming Preview");
     private final FpsCounter mRequestCounter = new FpsCounter("Incoming Requests");
 
@@ -173,6 +174,14 @@
         }
     }
 
+    private final Camera.ErrorCallback mErrorCallback = new Camera.ErrorCallback() {
+        @Override
+        public void onError(int i, Camera camera) {
+            Log.e(TAG, "Received error " + i + " from the Camera1 ErrorCallback");
+            mDeviceState.setError(CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
+        }
+    };
+
     private final ConditionVariable mReceivedJpeg = new ConditionVariable(false);
 
     private final Camera.PictureCallback mJpegCallback = new Camera.PictureCallback() {
@@ -405,7 +414,7 @@
 
         // TODO: Detect and optimize single-output paths here to skip stream teeing.
         if (mGLThreadManager == null) {
-            mGLThreadManager = new GLThreadManager(mCameraId, facing);
+            mGLThreadManager = new GLThreadManager(mCameraId, facing, mDeviceState);
             mGLThreadManager.start();
         }
         mGLThreadManager.waitUntilStarted();
@@ -617,9 +626,20 @@
                                     CameraDeviceImpl.CameraDeviceCallbacks.ERROR_CAMERA_DEVICE);
                             break;
                         }
-                        mDeviceState.setIdle();
-                        break;
-                    } else {
+
+                        synchronized (mIdleLock) {
+                            // Retry the the request queue.
+                            nextBurst = mRequestQueue.getNext();
+
+                            // If we still have no queued requests, go idle.
+                            if (nextBurst == null) {
+                                mDeviceState.setIdle();
+                                break;
+                            }
+                        }
+                    }
+
+                    if (nextBurst != null) {
                         // Queue another capture if we did not get the last burst.
                         handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
                     }
@@ -831,6 +851,7 @@
         mFaceDetectMapper = new LegacyFaceDetectMapper(mCamera, mCharacteristics);
         mCaptureCollector = new CaptureCollector(MAX_IN_FLIGHT_REQUESTS, mDeviceState);
         mRequestThread = new RequestHandlerThread(name, mRequestHandlerCb);
+        mCamera.setErrorCallback(mErrorCallback);
     }
 
     /**
@@ -883,8 +904,11 @@
     public int submitCaptureRequests(List<CaptureRequest> requests, boolean repeating,
             /*out*/LongParcelable frameNumber) {
         Handler handler = mRequestThread.waitAndGetHandler();
-        int ret = mRequestQueue.submit(requests, repeating, frameNumber);
-        handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
+        int ret;
+        synchronized (mIdleLock) {
+            ret = mRequestQueue.submit(requests, repeating, frameNumber);
+            handler.sendEmptyMessage(MSG_SUBMIT_CAPTURE_REQUEST);
+        }
         return ret;
     }
 
diff --git a/core/java/android/hardware/camera2/legacy/SizeAreaComparator.java b/core/java/android/hardware/camera2/legacy/SizeAreaComparator.java
new file mode 100644
index 0000000..75a5bab
--- /dev/null
+++ b/core/java/android/hardware/camera2/legacy/SizeAreaComparator.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.hardware.camera2.legacy;
+
+import android.hardware.Camera;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Comparator for api1 {@link Camera.Size} objects by the area.
+ *
+ * <p>This comparator totally orders by rectangle area. Tie-breaks on width.</p>
+ */
+@SuppressWarnings("deprecation")
+public class SizeAreaComparator implements Comparator<Camera.Size> {
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public int compare(Camera.Size size, Camera.Size size2) {
+        checkNotNull(size, "size must not be null");
+        checkNotNull(size2, "size2 must not be null");
+
+        if (size.equals(size2)) {
+            return 0;
+        }
+
+        long width = size.width;
+        long width2 = size2.width;
+        long area = width * size.height;
+        long area2 = width2 * size2.height;
+
+        if (area == area2) {
+            return (width > width2) ? 1 : -1;
+        }
+
+        return (area > area2) ? 1 : -1;
+    }
+
+    /**
+     * Get the largest api1 {@code Camera.Size} from the list by comparing each size's area
+     * by each other using {@link SizeAreaComparator}.
+     *
+     * @param sizes a non-{@code null} list of non-{@code null} sizes
+     * @return a non-{@code null} size
+     *
+     * @throws NullPointerException if {@code sizes} or any elements in it were {@code null}
+     */
+    public static Camera.Size findLargestByArea(List<Camera.Size> sizes) {
+        checkNotNull(sizes, "sizes must not be null");
+
+        return Collections.max(sizes, new SizeAreaComparator());
+    }
+}
diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java
index f1fa3eb..b268986 100644
--- a/core/java/android/net/IpPrefix.java
+++ b/core/java/android/net/IpPrefix.java
@@ -172,7 +172,7 @@
     /**
      * Returns a string representation of this {@code IpPrefix}.
      *
-     * @return a string such as {@code "192.0.2.0/24"} or {@code "2001:db8:1:2::"}.
+     * @return a string such as {@code "192.0.2.0/24"} or {@code "2001:db8:1:2::/64"}.
      */
     public String toString() {
         try {
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 3d6a132..662c576 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -381,7 +381,8 @@
         return new RouteInfo(
             route.getDestination(),
             route.getGateway(),
-            mIfaceName);
+            mIfaceName,
+            route.getType());
     }
 
     /**
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index b83198d..74d4ac2 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -107,27 +107,13 @@
     public static final int EVENT_UID_RANGES_REMOVED = BASE + 6;
 
     /**
-     * Sent by the NetworkAgent to ConnectivityService to block all routes for a certain address
-     * family (AF_INET or AF_INET6) on this Network. For VPNs only.
-     * obj = Integer representing the family (AF_INET or AF_INET6)
-     */
-    public static final int EVENT_BLOCK_ADDRESS_FAMILY = BASE + 7;
-
-    /**
-     * Sent by the NetworkAgent to ConnectivityService to unblock routes for a certain address
-     * family (AF_INET or AF_INET6) on this Network. For VPNs only.
-     * obj = Integer representing the family (AF_INET or AF_INET6)
-     */
-    public static final int EVENT_UNBLOCK_ADDRESS_FAMILY = BASE + 8;
-
-    /**
      * Sent by ConnectivitySerice to the NetworkAgent to inform the agent of the
      * networks status - whether we could use the network or could not, due to
      * either a bad network configuration (no internet link) or captive portal.
      *
      * arg1 = either {@code VALID_NETWORK} or {@code INVALID_NETWORK}
      */
-    public static final int CMD_REPORT_NETWORK_STATUS = BASE + 9;
+    public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7;
 
     public static final int VALID_NETWORK = 1;
     public static final int INVALID_NETWORK = 2;
@@ -137,7 +123,7 @@
      * explicitly selected.  This should be sent before the NetworkInfo is marked
      * CONNECTED so it can be given special treatment at that time.
      */
-    public static final int EVENT_SET_EXPLICITLY_SELECTED = BASE + 10;
+    public static final int EVENT_SET_EXPLICITLY_SELECTED = BASE + 8;
 
     public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
             NetworkCapabilities nc, LinkProperties lp, int score) {
@@ -273,21 +259,6 @@
     }
 
     /**
-     * Called by the VPN code when it wants to block an address family from being routed, typically
-     * because the VPN network doesn't support that family.
-     */
-    public void blockAddressFamily(int family) {
-        queueOrSendMessage(EVENT_BLOCK_ADDRESS_FAMILY, family);
-    }
-
-    /**
-     * Called by the VPN code when it wants to unblock an address family from being routed.
-     */
-    public void unblockAddressFamily(int family) {
-        queueOrSendMessage(EVENT_UNBLOCK_ADDRESS_FAMILY, family);
-    }
-
-    /**
      * Called by the bearer to indicate this network was manually selected by the user.
      * This should be called before the NetworkInfo is marked CONNECTED so that this
      * Network can be given special treatment at that time.
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index a4ec80c..cfd20a0 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -62,6 +62,23 @@
      */
     private final String mInterface;
 
+
+    /** Unicast route. @hide */
+    public static final int RTN_UNICAST = 1;
+
+    /** Unreachable route. @hide */
+    public static final int RTN_UNREACHABLE = 7;
+
+    /** Throw route. @hide */
+    public static final int RTN_THROW = 9;
+
+    /**
+     * The type of this route; one of the RTN_xxx constants above.
+     */
+    private final int mType;
+
+    // Derived data members.
+    // TODO: remove these.
     private final boolean mIsHost;
     private final boolean mHasGateway;
 
@@ -82,7 +99,26 @@
      *
      * @hide
      */
-    public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
+    public RouteInfo(IpPrefix destination, InetAddress gateway, String iface, int type) {
+        switch (type) {
+            case RTN_UNICAST:
+            case RTN_UNREACHABLE:
+            case RTN_THROW:
+                // TODO: It would be nice to ensure that route types that don't have nexthops or
+                // interfaces, such as unreachable or throw, can't be created if an interface or
+                // a gateway is specified. This is a bit too complicated to do at the moment
+                // because:
+                //
+                // - LinkProperties sets the interface on routes added to it, and modifies the
+                //   interfaces of all the routes when its interface name changes.
+                // - Even when the gateway is null, we store a non-null gateway here.
+                //
+                // For now, we just rely on the code that sets routes to do things properly.
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown route type " + type);
+        }
+
         if (destination == null) {
             if (gateway != null) {
                 if (gateway instanceof Inet4Address) {
@@ -117,10 +153,18 @@
         mDestination = destination;  // IpPrefix objects are immutable.
         mGateway = gateway;          // InetAddress objects are immutable.
         mInterface = iface;          // Strings are immutable.
+        mType = type;
         mIsHost = isHost();
     }
 
     /**
+     *  @hide
+     */
+    public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
+        this(destination, gateway, iface, RTN_UNICAST);
+    }
+
+    /**
      * @hide
      */
     public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
@@ -150,6 +194,8 @@
 
     /**
      * @hide
+     *
+     * TODO: Remove this.
      */
     public RouteInfo(LinkAddress destination, InetAddress gateway) {
         this(destination, gateway, null);
@@ -188,6 +234,13 @@
     /**
      * @hide
      */
+    public RouteInfo(IpPrefix destination, int type) {
+        this(destination, null, null, type);
+    }
+
+    /**
+     * @hide
+     */
     public static RouteInfo makeHostRoute(InetAddress host, String iface) {
         return makeHostRoute(host, null, iface);
     }
@@ -249,12 +302,23 @@
     }
 
     /**
+     * Retrieves the type of this route.
+     *
+     * @return The type of this route; one of the {@code RTN_xxx} constants defined in this class.
+     *
+     * @hide
+     */
+    public int getType() {
+        return mType;
+    }
+
+    /**
      * Indicates if this route is a default route (ie, has no destination specified).
      *
      * @return {@code true} if the destination has a prefix length of 0.
      */
     public boolean isDefaultRoute() {
-        return mDestination.getPrefixLength() == 0;
+        return mType == RTN_UNICAST && mDestination.getPrefixLength() == 0;
     }
 
     /**
@@ -345,9 +409,18 @@
     public String toString() {
         String val = "";
         if (mDestination != null) val = mDestination.toString();
-        val += " ->";
-        if (mGateway != null) val += " " + mGateway.getHostAddress();
-        if (mInterface != null) val += " " + mInterface;
+        if (mType == RTN_UNREACHABLE) {
+            val += " unreachable";
+        } else if (mType == RTN_THROW) {
+            val += " throw";
+        } else {
+            val += " ->";
+            if (mGateway != null) val += " " + mGateway.getHostAddress();
+            if (mInterface != null) val += " " + mInterface;
+            if (mType != RTN_UNICAST) {
+                val += " unknown type " + mType;
+            }
+        }
         return val;
     }
 
@@ -364,7 +437,8 @@
 
         return Objects.equals(mDestination, target.getDestination()) &&
                 Objects.equals(mGateway, target.getGateway()) &&
-                Objects.equals(mInterface, target.getInterface());
+                Objects.equals(mInterface, target.getInterface()) &&
+                mType == target.getType();
     }
 
     /**
@@ -373,7 +447,8 @@
     public int hashCode() {
         return (mDestination.hashCode() * 41)
                 + (mGateway == null ? 0 :mGateway.hashCode() * 47)
-                + (mInterface == null ? 0 :mInterface.hashCode() * 67);
+                + (mInterface == null ? 0 :mInterface.hashCode() * 67)
+                + (mType * 71);
     }
 
     /**
@@ -391,6 +466,7 @@
         byte[] gatewayBytes = (mGateway == null) ? null : mGateway.getAddress();
         dest.writeByteArray(gatewayBytes);
         dest.writeString(mInterface);
+        dest.writeInt(mType);
     }
 
     /**
@@ -408,8 +484,9 @@
             } catch (UnknownHostException e) {}
 
             String iface = in.readString();
+            int type = in.readInt();
 
-            return new RouteInfo(dest, gateway, iface);
+            return new RouteInfo(dest, gateway, iface, type);
         }
 
         public RouteInfo[] newArray(int size) {
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index b3e28ea..fca15ac 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -410,7 +410,4 @@
 
     void addInterfaceToLocalNetwork(String iface, in List<RouteInfo> routes);
     void removeInterfaceFromLocalNetwork(String iface);
-
-    void blockAddressFamily(int family, int netId, String iface);
-    void unblockAddressFamily(int family, int netId, String iface);
 }
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 9cbedab..882a3c8 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -61,6 +61,8 @@
     private static final int MINUTES_MS = 60 * SECONDS_MS;
     private static final int ZERO_VALUE_MS = 20 * SECONDS_MS;
 
+    private static final boolean DEFAULT_ALLOW_EVENTS = true;
+
     private static final int XML_VERSION = 1;
     private static final String ZEN_TAG = "zen";
     private static final String ZEN_ATT_VERSION = "version";
@@ -68,6 +70,7 @@
     private static final String ALLOW_ATT_CALLS = "calls";
     private static final String ALLOW_ATT_MESSAGES = "messages";
     private static final String ALLOW_ATT_FROM = "from";
+    private static final String ALLOW_ATT_EVENTS = "events";
     private static final String SLEEP_TAG = "sleep";
     private static final String SLEEP_ATT_MODE = "mode";
 
@@ -91,6 +94,7 @@
 
     public boolean allowCalls;
     public boolean allowMessages;
+    public boolean allowEvents = DEFAULT_ALLOW_EVENTS;
     public int allowFrom = SOURCE_ANYONE;
 
     public String sleepMode;
@@ -108,6 +112,7 @@
     public ZenModeConfig(Parcel source) {
         allowCalls = source.readInt() == 1;
         allowMessages = source.readInt() == 1;
+        allowEvents = source.readInt() == 1;
         if (source.readInt() == 1) {
             sleepMode = source.readString();
         }
@@ -134,6 +139,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(allowCalls ? 1 : 0);
         dest.writeInt(allowMessages ? 1 : 0);
+        dest.writeInt(allowEvents ? 1 : 0);
         if (sleepMode != null) {
             dest.writeInt(1);
             dest.writeString(sleepMode);
@@ -167,6 +173,7 @@
             .append("allowCalls=").append(allowCalls)
             .append(",allowMessages=").append(allowMessages)
             .append(",allowFrom=").append(sourceToString(allowFrom))
+            .append(",allowEvents=").append(allowEvents)
             .append(",sleepMode=").append(sleepMode)
             .append(",sleepStart=").append(sleepStartHour).append('.').append(sleepStartMinute)
             .append(",sleepEnd=").append(sleepEndHour).append('.').append(sleepEndMinute)
@@ -200,6 +207,7 @@
         return other.allowCalls == allowCalls
                 && other.allowMessages == allowMessages
                 && other.allowFrom == allowFrom
+                && other.allowEvents == allowEvents
                 && Objects.equals(other.sleepMode, sleepMode)
                 && other.sleepStartHour == sleepStartHour
                 && other.sleepStartMinute == sleepStartMinute
@@ -213,7 +221,7 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(allowCalls, allowMessages, allowFrom, sleepMode,
+        return Objects.hash(allowCalls, allowMessages, allowFrom, allowEvents, sleepMode,
                 sleepStartHour, sleepStartMinute, sleepEndHour, sleepEndMinute,
                 Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds),
                 exitCondition, exitConditionComponent);
@@ -281,6 +289,7 @@
                 if (ALLOW_TAG.equals(tag)) {
                     rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS, false);
                     rt.allowMessages = safeBoolean(parser, ALLOW_ATT_MESSAGES, false);
+                    rt.allowEvents = safeBoolean(parser, ALLOW_ATT_EVENTS, DEFAULT_ALLOW_EVENTS);
                     rt.allowFrom = safeInt(parser, ALLOW_ATT_FROM, SOURCE_ANYONE);
                     if (rt.allowFrom < SOURCE_ANYONE || rt.allowFrom > MAX_SOURCE) {
                         throw new IndexOutOfBoundsException("bad source in config:" + rt.allowFrom);
@@ -323,6 +332,7 @@
         out.startTag(null, ALLOW_TAG);
         out.attribute(null, ALLOW_ATT_CALLS, Boolean.toString(allowCalls));
         out.attribute(null, ALLOW_ATT_MESSAGES, Boolean.toString(allowMessages));
+        out.attribute(null, ALLOW_ATT_EVENTS, Boolean.toString(allowEvents));
         out.attribute(null, ALLOW_ATT_FROM, Integer.toString(allowFrom));
         out.endTag(null, ALLOW_TAG);
 
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 9be220e..120c9e3 100644
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -1216,17 +1216,12 @@
      *
      * @param durationInMs The duration of the silence.
      * @param queueMode {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}.
-     * @param params Parameters for the request. Can be null.
-     *            Engine specific parameters may be passed in but the parameter keys
-     *            must be prefixed by the name of the engine they are intended for. For example
-     *            the keys "com.svox.pico_foo" and "com.svox.pico:bar" will be passed to the
-     *            engine named "com.svox.pico" if it is being used.
      * @param utteranceId An unique identifier for this request.
      *
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilence operation.
      */
     public int playSilence(final long durationInMs, final int queueMode,
-            final HashMap<String, String> params, final String utteranceId) {
+            final String utteranceId) {
         return runAction(new Action<Integer>() {
             @Override
             public Integer run(ITextToSpeechService service) throws RemoteException {
@@ -1258,12 +1253,12 @@
      *
      * @return {@link #ERROR} or {@link #SUCCESS} of <b>queuing</b> the playSilence operation.
      * @deprecated As of API level 20, replaced by
-     *         {@link #playSilence(long, int, HashMap, String)}.
+     *         {@link #playSilence(long, int, String)}.
      */
     @Deprecated
     public int playSilence(final long durationInMs, final int queueMode,
             final HashMap<String, String> params) {
-        return playSilence(durationInMs, queueMode, params,
+        return playSilence(durationInMs, queueMode,
                            params == null ? null : params.get(Engine.KEY_PARAM_UTTERANCE_ID));
     }
 
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index d00a433..079467a 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -317,7 +317,7 @@
 
      * @return A name of the default voice for a given locale.
      */
-    protected String onGetDefaultVoiceNameFor(String lang, String country, String variant) {
+    public String onGetDefaultVoiceNameFor(String lang, String country, String variant) {
         int localeStatus = onIsLanguageAvailable(lang, country, variant);
         Locale iso3Locale = null;
         switch (localeStatus) {
diff --git a/core/java/android/speech/tts/Voice.java b/core/java/android/speech/tts/Voice.java
index a1fa51d..dcf5980 100644
--- a/core/java/android/speech/tts/Voice.java
+++ b/core/java/android/speech/tts/Voice.java
@@ -91,9 +91,6 @@
         Collections.addAll(this.mFeatures, in.readStringArray());
     }
 
-    /**
-     * @hide
-     */
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(mName);
@@ -104,17 +101,11 @@
         dest.writeStringList(new ArrayList<String>(mFeatures));
     }
 
-    /**
-     * @hide
-     */
     @Override
     public int describeContents() {
         return 0;
     }
 
-    /**
-     * @hide
-     */
     public static final Parcelable.Creator<Voice> CREATOR = new Parcelable.Creator<Voice>() {
         @Override
         public Voice createFromParcel(Parcel in) {
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index edb3798..904e33f 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -186,6 +186,18 @@
         }
     }
 
+    public static boolean sTrimForeground = false;
+
+    /**
+     * Controls whether or not the hardware renderer should aggressively
+     * trim memory. Note that this must not be set for any process that
+     * uses WebView! This should be only used by system_process or similar
+     * that do not go into the background.
+     */
+    public static void enableForegroundTrimming() {
+        sTrimForeground = true;
+    }
+
     /**
      * Indicates whether hardware acceleration is available under any form for
      * the view hierarchy.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 4e1db90..6d3b419 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -836,6 +836,11 @@
                 break;
             }
 
+            // Ignore invisible views as they are not interactive.
+            if (sibling.getVisibility() != View.VISIBLE) {
+                continue;
+            }
+
             // If sibling is not interactive we do not care.
             if (!sibling.isClickable() && !sibling.isLongClickable()) {
                 continue;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 43ab4ef..b1d3d45 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -804,6 +804,9 @@
         if (mAppVisible != visible) {
             mAppVisible = visible;
             scheduleTraversals();
+            if (!mAppVisible) {
+                WindowManagerGlobal.trimForeground();
+            }
         }
     }
 
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index c39ec97..08160c8 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -375,6 +375,9 @@
                 mDyingViews.remove(view);
             }
         }
+        if (HardwareRenderer.sTrimForeground && HardwareRenderer.isAvailable()) {
+            doTrimForeground();
+        }
     }
 
     private int findViewLocked(View view, boolean required) {
@@ -413,6 +416,35 @@
             }
 
             HardwareRenderer.trimMemory(level);
+
+            if (HardwareRenderer.sTrimForeground) {
+                doTrimForeground();
+            }
+        }
+    }
+
+    public static void trimForeground() {
+        if (HardwareRenderer.sTrimForeground && HardwareRenderer.isAvailable()) {
+            WindowManagerGlobal wm = WindowManagerGlobal.getInstance();
+            wm.doTrimForeground();
+        }
+    }
+
+    private void doTrimForeground() {
+        boolean hasVisibleWindows = false;
+        synchronized (mLock) {
+            for (int i = mRoots.size() - 1; i >= 0; --i) {
+                if (mRoots.get(i).getHostVisibility() == View.VISIBLE
+                        && mRoots.get(i).mAttachInfo.mHardwareRenderer != null) {
+                    hasVisibleWindows = true;
+                } else {
+                    mRoots.get(i).destroyHardwareResources();
+                }
+            }
+        }
+        if (!hasVisibleWindows) {
+            HardwareRenderer.trimMemory(
+                    ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
         }
     }
 
@@ -428,7 +460,7 @@
                 for (int i = 0; i < count; i++) {
                     ViewRootImpl root = mRoots.get(i);
                     String name = getWindowName(root);
-                    pw.printf("\n\t%s", name);
+                    pw.printf("\n\t%s (visibility=%d)", name, root.getHostVisibility());
 
                     HardwareRenderer renderer =
                             root.getView().mAttachInfo.mHardwareRenderer;
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index d458ee4..673f075 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -955,14 +955,19 @@
      */
     public void screenTurningOn(ScreenOnListener screenOnListener);
 
+    /**
+     * Called when the device has turned the screen off.
+     */
+    public void screenTurnedOff();
+
     public interface ScreenOnListener {
         void onScreenOn();
     }
 
     /**
-     * Return whether the system is awake.
+     * Return whether the default display is on and not blocked by a black surface.
      */
-    public boolean isAwake();
+    public boolean isScreenOn();
 
     /**
      * Tell the policy that the lid switch has changed state.
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index af53ec8..2b8b4dc 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -611,6 +611,12 @@
     private final int[] mScrollOffset = new int[2];
     private final int[] mScrollConsumed = new int[2];
 
+    // Used for offsetting MotionEvents that we feed to the VelocityTracker.
+    // In the future it would be nice to be able to give this to the VelocityTracker
+    // directly, or alternatively put a VT into absolute-positioning mode that only
+    // reads the raw screen-coordinate x/y values.
+    private int mNestedYOffset = 0;
+
     // True when the popup should be hidden because of a call to
     // dispatchDisplayHint()
     private boolean mPopupHidden;
@@ -3330,6 +3336,7 @@
             scrollConsumedCorrection = mScrollConsumed[1];
             if (vtev != null) {
                 vtev.offsetLocation(0, mScrollOffset[1]);
+                mNestedYOffset += mScrollOffset[1];
             }
         }
         final int deltaY = rawDeltaY;
@@ -3399,6 +3406,7 @@
                             lastYCorrection -= mScrollOffset[1];
                             if (vtev != null) {
                                 vtev.offsetLocation(0, mScrollOffset[1]);
+                                mNestedYOffset += mScrollOffset[1];
                             }
                         } else {
                             final boolean atOverscrollEdge = overScrollBy(0, overscroll,
@@ -3582,6 +3590,10 @@
         final MotionEvent vtev = MotionEvent.obtain(ev);
 
         final int actionMasked = ev.getActionMasked();
+        if (actionMasked == MotionEvent.ACTION_DOWN) {
+            mNestedYOffset = 0;
+        }
+        vtev.offsetLocation(0, mNestedYOffset);
         switch (actionMasked) {
             case MotionEvent.ACTION_DOWN: {
                 onTouchDown(ev);
@@ -4144,7 +4156,7 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        int action = ev.getAction();
+        final int actionMasked = ev.getActionMasked();
         View v;
 
         if (mPositionScroller != null) {
@@ -4163,7 +4175,7 @@
             return true;
         }
 
-        switch (action & MotionEvent.ACTION_MASK) {
+        switch (actionMasked) {
         case MotionEvent.ACTION_DOWN: {
             int touchMode = mTouchMode;
             if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) {
@@ -4190,6 +4202,7 @@
             mLastY = Integer.MIN_VALUE;
             initOrResetVelocityTracker();
             mVelocityTracker.addMovement(ev);
+            mNestedYOffset = 0;
             startNestedScroll(SCROLL_AXIS_VERTICAL);
             if (touchMode == TOUCH_MODE_FLING) {
                 return true;
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index dd312a6..a90b392 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -142,6 +142,7 @@
      */
     private final int[] mScrollOffset = new int[2];
     private final int[] mScrollConsumed = new int[2];
+    private int mNestedYOffset;
 
     /**
      * The StrictMode "critical time span" objects to catch animation
@@ -516,6 +517,7 @@
                     mLastMotionY = y;
                     initVelocityTrackerIfNotExists();
                     mVelocityTracker.addMovement(ev);
+                    mNestedYOffset = 0;
                     if (mScrollStrictSpan == null) {
                         mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll");
                     }
@@ -586,9 +588,14 @@
 
         MotionEvent vtev = MotionEvent.obtain(ev);
 
-        final int action = ev.getAction();
+        final int actionMasked = ev.getActionMasked();
 
-        switch (action & MotionEvent.ACTION_MASK) {
+        if (actionMasked == MotionEvent.ACTION_DOWN) {
+            mNestedYOffset = 0;
+        }
+        vtev.offsetLocation(0, mNestedYOffset);
+
+        switch (actionMasked) {
             case MotionEvent.ACTION_DOWN: {
                 if (getChildCount() == 0) {
                     return false;
@@ -630,6 +637,7 @@
                 if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
                     deltaY -= mScrollConsumed[1];
                     vtev.offsetLocation(0, mScrollOffset[1]);
+                    mNestedYOffset += mScrollOffset[1];
                 }
                 if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
                     final ViewParent parent = getParent();
@@ -666,6 +674,7 @@
                     if (dispatchNestedScroll(0, scrolledDeltaY, 0, unconsumedY, mScrollOffset)) {
                         mLastMotionY -= mScrollOffset[1];
                         vtev.offsetLocation(0, mScrollOffset[1]);
+                        mNestedYOffset += mScrollOffset[1];
                     } else if (canOverscroll) {
                         final int pulledToY = oldY + deltaY;
                         if (pulledToY < 0) {
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 4995ea1..a92cb74 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -3570,6 +3570,10 @@
             return mOwner != null || mRestarting;
         }
 
+        public boolean isRestarting() {
+            return mRestarting;
+        }
+
         void add(ServiceState other) {
             addDurations(other);
             mRunCount += other.mRunCount;
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 8f8ce95..ac915d1 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.inputmethod;
 
+import android.app.AppOpsManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -637,6 +638,25 @@
     }
 
     /**
+     * Returns true if a package name belongs to a UID.
+     *
+     * <p>This is a simple wrapper of {@link AppOpsManager#checkPackage(int, String)}.</p>
+     * @param appOpsManager the {@link AppOpsManager} object to be used for the validation.
+     * @param uid the UID to be validated.
+     * @param packageName the package name.
+     * @return {@code true} if the package name belongs to the UID.
+     */
+    public static boolean checkIfPackageBelongsToUid(final AppOpsManager appOpsManager,
+            final int uid, final String packageName) {
+        try {
+            appOpsManager.checkPackage(uid, packageName);
+            return true;
+        } catch (SecurityException e) {
+            return false;
+        }
+    }
+
+    /**
      * Utility class for putting and getting settings for InputMethod
      * TODO: Move all putters and getters of settings to this class.
      */
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 40c9ed2..4dde217 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -458,7 +458,7 @@
                 Log.v(TAG, "Preloading resource #" + Integer.toHexString(id));
             }
             if (id != 0) {
-                if (mResources.getDrawable(id) == null) {
+                if (mResources.getDrawable(id, null) == null) {
                     throw new IllegalArgumentException(
                             "Unable to find preloaded drawable resource #0x"
                             + Integer.toHexString(id)
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 09c5f3a..e38f3d4 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -45,6 +45,7 @@
 };
 struct audio_attributes_fields_t {
     jfieldID  fieldRecSource;    // AudioAttributes.mSource
+    jfieldID  fieldFlags;        // AudioAttributes.mFlags
     jfieldID  fieldFormattedTags;// AudioAttributes.mFormattedTags
 };
 static audio_attributes_fields_t javaAudioAttrFields;
@@ -212,9 +213,13 @@
     strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
     env->ReleaseStringUTFChars(jtags, tags);
     paa->source = (audio_source_t) env->GetIntField(jaa, javaAudioAttrFields.fieldRecSource);
+    paa->flags = (audio_flags_mask_t)env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
+    ALOGV("AudioRecord_setup for source=%d tags=%s flags=%08x", paa->source, paa->tags, paa->flags);
 
-    ALOGV("AudioRecord_setup for source=%d tags=%s", paa->source, paa->tags);
-
+    audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;
+    if (paa->flags & AUDIO_FLAG_HW_HOTWORD) {
+        flags = AUDIO_INPUT_FLAG_HW_HOTWORD;
+    }
     // create the callback information:
     // this data will be passed with every AudioRecord callback
     audiorecord_callback_cookie *lpCallbackData = new audiorecord_callback_cookie;
@@ -232,7 +237,9 @@
         lpCallbackData,// void* user
         0,             // notificationFrames,
         true,          // threadCanCallJava
-        sessionId);
+        sessionId,
+        AudioRecord::TRANSFER_DEFAULT,
+        flags);
 
     if (status != NO_ERROR) {
         ALOGE("Error creating AudioRecord instance: initialization check failed with status %d.",
@@ -638,10 +645,12 @@
     }
     jclass audioAttributesClassRef = (jclass)env->NewGlobalRef(audioAttrClass);
     javaAudioAttrFields.fieldRecSource = env->GetFieldID(audioAttributesClassRef, "mSource", "I");
+    javaAudioAttrFields.fieldFlags = env->GetFieldID(audioAttributesClassRef, "mFlags", "I");
     javaAudioAttrFields.fieldFormattedTags =
             env->GetFieldID(audioAttributesClassRef, "mFormattedTags", "Ljava/lang/String;");
     env->DeleteGlobalRef(audioAttributesClassRef);
     if (javaAudioAttrFields.fieldRecSource == NULL
+            || javaAudioAttrFields.fieldFlags == NULL
             || javaAudioAttrFields.fieldFormattedTags == NULL) {
         ALOGE("Can't initialize AudioAttributes fields");
         return -1;
diff --git a/core/res/res/drawable-hdpi/ic_menu_refresh.png b/core/res/res/drawable-hdpi/ic_menu_refresh.png
deleted file mode 100644
index e13315f..0000000
--- a/core/res/res/drawable-hdpi/ic_menu_refresh.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_notification_cast_on.png b/core/res/res/drawable-hdpi/ic_notification_cast_on.png
deleted file mode 100644
index 3eaf13a..0000000
--- a/core/res/res/drawable-hdpi/ic_notification_cast_on.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-ldpi/ic_menu_refresh.png b/core/res/res/drawable-ldpi/ic_menu_refresh.png
deleted file mode 100644
index b25dc06..0000000
--- a/core/res/res/drawable-ldpi/ic_menu_refresh.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_menu_refresh.png b/core/res/res/drawable-mdpi/ic_menu_refresh.png
deleted file mode 100644
index 30b660f..0000000
--- a/core/res/res/drawable-mdpi/ic_menu_refresh.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_notification_cast_on.png b/core/res/res/drawable-mdpi/ic_notification_cast_on.png
deleted file mode 100644
index 42de8c4..0000000
--- a/core/res/res/drawable-mdpi/ic_notification_cast_on.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_menu_refresh.png b/core/res/res/drawable-xhdpi/ic_menu_refresh.png
deleted file mode 100644
index 9e9f10e..0000000
--- a/core/res/res/drawable-xhdpi/ic_menu_refresh.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_notification_cast_on.png b/core/res/res/drawable-xhdpi/ic_notification_cast_on.png
deleted file mode 100644
index 142065b..0000000
--- a/core/res/res/drawable-xhdpi/ic_notification_cast_on.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_menu_refresh.png b/core/res/res/drawable-xxhdpi/ic_menu_refresh.png
deleted file mode 100644
index 580f4cf..0000000
--- a/core/res/res/drawable-xxhdpi/ic_menu_refresh.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png b/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png
deleted file mode 100644
index d562602..0000000
--- a/core/res/res/drawable-xxhdpi/ic_notification_cast_on.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/ic_ab_back_material.xml b/core/res/res/drawable/ic_ab_back_material.xml
index 72d7981..e4bc6ccfb 100644
--- a/core/res/res/drawable/ic_ab_back_material.xml
+++ b/core/res/res/drawable/ic_ab_back_material.xml
@@ -21,6 +21,6 @@
         android:autoMirrored="true"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M20.000000,11.000000L7.800000,11.000000l5.600000,-5.600000L12.000000,4.000000l-8.000000,8.000000l8.000000,8.000000l1.400000,-1.400000L7.800000,13.000000L20.000000,13.000000L20.000000,11.000000z"
+        android:pathData="M20,11L7.8,11l5.6,-5.6L12,4l-8,8l8,8l1.4,-1.4L7.8,13L20,13L20,11z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/ic_dialog_alert_material.xml b/core/res/res/drawable/ic_dialog_alert_material.xml
index 3bb4d2c..26daea7 100644
--- a/core/res/res/drawable/ic_dialog_alert_material.xml
+++ b/core/res/res/drawable/ic_dialog_alert_material.xml
@@ -20,6 +20,6 @@
         android:viewportHeight="24.0"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M1.000000,21.000000l22.000000,0.000000L12.000000,2.000000L1.000000,21.000000zM13.000000,18.000000l-2.000000,0.000000l0.000000,-2.000000l2.000000,0.000000L13.000000,18.000000zM13.000000,14.000000l-2.000000,0.000000l0.000000,-4.000000l2.000000,0.000000L13.000000,14.000000z"
+        android:pathData="M1,21l22,0L12,2L1,21zM13,18l-2,0l0,-2l2,0L13,18zM13,14l-2,0l0,-4l2,0L13,14z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/ic_go_search_api_material.xml b/core/res/res/drawable/ic_go_search_api_material.xml
index 21c7249..67ef281 100644
--- a/core/res/res/drawable/ic_go_search_api_material.xml
+++ b/core/res/res/drawable/ic_go_search_api_material.xml
@@ -20,6 +20,6 @@
         android:viewportHeight="24.0"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M10.000000,6.000000l-1.400000,1.400000 4.599999,4.600000 -4.599999,4.600000 1.400000,1.400000 6.000000,-6.000000z"
+        android:pathData="M10,6l-1.4,1.4 4.599999,4.6 -4.599999,4.6 1.4,1.4 6,-6z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/ic_menu_copy_material.xml b/core/res/res/drawable/ic_menu_copy_material.xml
index da3912b..c03723b 100644
--- a/core/res/res/drawable/ic_menu_copy_material.xml
+++ b/core/res/res/drawable/ic_menu_copy_material.xml
@@ -21,6 +21,6 @@
         android:autoMirrored="true"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M16.000000,1.000000L4.000000,1.000000C2.900000,1.000000 2.000000,1.900000 2.000000,3.000000l0.000000,14.000000l2.000000,0.000000L4.000000,3.000000l12.000000,0.000000L16.000000,1.000000zM19.000000,5.000000L8.000000,5.000000C6.900000,5.000000 6.000000,5.900000 6.000000,7.000000l0.000000,14.000000c0.000000,1.100000 0.900000,2.000000 2.000000,2.000000l11.000000,0.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L21.000000,7.000000C21.000000,5.900000 20.100000,5.000000 19.000000,5.000000zM19.000000,21.000000L8.000000,21.000000L8.000000,7.000000l11.000000,0.000000L19.000000,21.000000z"
+        android:pathData="M16,1L4,1C2.9,1 2,1.9 2,3l0,14l2,0L4,3l12,0L16,1zM19,5L8,5C6.9,5 6,5.9 6,7l0,14c0,1.1 0.9,2 2,2l11,0c1.1,0 2,-0.9 2,-2L21,7C21,5.9 20.1,5 19,5zM19,21L8,21L8,7l11,0L19,21z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/ic_menu_cut_material.xml b/core/res/res/drawable/ic_menu_cut_material.xml
index 54db72a..aec6685 100644
--- a/core/res/res/drawable/ic_menu_cut_material.xml
+++ b/core/res/res/drawable/ic_menu_cut_material.xml
@@ -21,6 +21,6 @@
         android:autoMirrored="true"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M10.000000,6.000000c0.000000,-2.200000 -1.800000,-4.000000 -4.000000,-4.000000S2.000000,3.800000 2.000000,6.000000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000c0.600000,0.000000 1.100000,-0.100000 1.600000,-0.400000L10.000000,12.000000l-2.400000,2.400000C7.100000,14.100000 6.600000,14.000000 6.000000,14.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000s4.000000,-1.800000 4.000000,-4.000000c0.000000,-0.600000 -0.100000,-1.100000 -0.400000,-1.600000L12.000000,14.000000l7.000000,7.000000l4.000000,0.000000L9.600000,7.600000C9.900000,7.100000 10.000000,6.600000 10.000000,6.000000zM6.000000,8.000000C4.900000,8.000000 4.000000,7.100000 4.000000,6.000000s0.900000,-2.000000 2.000000,-2.000000c1.100000,0.000000 2.000000,0.900000 2.000000,2.000000S7.100000,8.000000 6.000000,8.000000zM6.000000,20.000000c-1.100000,0.000000 -2.000000,-0.900000 -2.000000,-2.000000s0.900000,-2.000000 2.000000,-2.000000c1.100000,0.000000 2.000000,0.900000 2.000000,2.000000S7.100000,20.000000 6.000000,20.000000zM12.000000,11.500000c0.300000,0.000000 0.500000,0.200000 0.500000,0.500000c0.000000,0.300000 -0.200000,0.500000 -0.500000,0.500000c-0.300000,0.000000 -0.500000,-0.200000 -0.500000,-0.500000C11.500000,11.700000 11.700000,11.500000 12.000000,11.500000zM23.000000,3.000000l-4.000000,0.000000l-6.000000,6.000000l2.000000,2.000000L23.000000,3.000000z"
+        android:pathData="M10,6c0,-2.2 -1.8,-4 -4,-4S2,3.8 2,6c0,2.2 1.8,4 4,4c0.6,0 1.1,-0.1 1.6,-0.4L10,12l-2.4,2.4C7.1,14.1 6.6,14 6,14c-2.2,0 -4,1.8 -4,4c0,2.2 1.8,4 4,4s4,-1.8 4,-4c0,-0.6 -0.1,-1.1 -0.4,-1.6L12,14l7,7l4,0L9.6,7.6C9.9,7.1 10,6.6 10,6zM6,8C4.9,8 4,7.1 4,6s0.9,-2 2,-2c1.1,0 2,0.9 2,2S7.1,8 6,8zM6,20c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2c1.1,0 2,0.9 2,2S7.1,20 6,20zM12,11.5c0.3,0 0.5,0.2 0.5,0.5c0,0.3 -0.2,0.5 -0.5,0.5c-0.3,0 -0.5,-0.2 -0.5,-0.5C11.5,11.7 11.7,11.5 12,11.5zM23,3l-4,0l-6,6l2,2L23,3z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/ic_menu_moreoverflow_material.xml b/core/res/res/drawable/ic_menu_moreoverflow_material.xml
index c128570..502ad69 100644
--- a/core/res/res/drawable/ic_menu_moreoverflow_material.xml
+++ b/core/res/res/drawable/ic_menu_moreoverflow_material.xml
@@ -20,6 +20,6 @@
         android:viewportHeight="24.0"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M12.000000,8.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000s-0.900000,-2.000000 -2.000000,-2.000000c-1.100000,0.000000 -2.000000,0.900000 -2.000000,2.000000S10.900000,8.000000 12.000000,8.000000zM12.000000,10.000000c-1.100000,0.000000 -2.000000,0.900000 -2.000000,2.000000s0.900000,2.000000 2.000000,2.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000S13.100000,10.000000 12.000000,10.000000zM12.000000,16.000000c-1.100000,0.000000 -2.000000,0.900000 -2.000000,2.000000s0.900000,2.000000 2.000000,2.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000S13.100000,16.000000 12.000000,16.000000z"
+        android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2S10.9,8 12,8zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,10 12,10zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,16 12,16z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/ic_menu_paste_material.xml b/core/res/res/drawable/ic_menu_paste_material.xml
index 5f847cb..ee24267 100644
--- a/core/res/res/drawable/ic_menu_paste_material.xml
+++ b/core/res/res/drawable/ic_menu_paste_material.xml
@@ -21,6 +21,6 @@
         android:autoMirrored="true"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M19.000000,2.000000l-4.200000,0.000000c-0.400000,-1.200000 -1.500000,-2.000000 -2.800000,-2.000000c-1.300000,0.000000 -2.400000,0.800000 -2.800000,2.000000L5.000000,2.000000C3.900000,2.000000 3.000000,2.900000 3.000000,4.000000l0.000000,16.000000c0.000000,1.100000 0.900000,2.000000 2.000000,2.000000l14.000000,0.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000L21.000000,4.000000C21.000000,2.900000 20.100000,2.000000 19.000000,2.000000zM12.000000,2.000000c0.600000,0.000000 1.000000,0.400000 1.000000,1.000000s-0.400000,1.000000 -1.000000,1.000000c-0.600000,0.000000 -1.000000,-0.400000 -1.000000,-1.000000S11.400000,2.000000 12.000000,2.000000zM19.000000,20.000000L5.000000,20.000000L5.000000,4.000000l2.000000,0.000000l0.000000,3.000000l10.000000,0.000000L17.000000,4.000000l2.000000,0.000000L19.000000,20.000000z"
+        android:pathData="M19,2l-4.2,0c-0.4,-1.2 -1.5,-2 -2.8,-2c-1.3,0 -2.4,0.8 -2.8,2L5,2C3.9,2 3,2.9 3,4l0,16c0,1.1 0.9,2 2,2l14,0c1.1,0 2,-0.9 2,-2L21,4C21,2.9 20.1,2 19,2zM12,2c0.6,0 1,0.4 1,1s-0.4,1 -1,1c-0.6,0 -1,-0.4 -1,-1S11.4,2 12,2zM19,20L5,20L5,4l2,0l0,3l10,0L17,4l2,0L19,20z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/ic_menu_refresh.xml b/core/res/res/drawable/ic_menu_refresh.xml
new file mode 100644
index 0000000..e0fbccb
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_refresh.xml
@@ -0,0 +1,25 @@
+<!--
+Copyright (C) 2014 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="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:pathData="M17.6,6.4C16.2,4.9 14.2,4 12,4c-4.4,0 -8,3.6 -8,8s3.6,8 8,8c3.7,0 6.8,-2.6 7.7,-6l-2.1,0c-0.8,2.3 -3,4 -5.6,4c-3.3,0 -6,-2.7 -6,-6s2.7,-6 6,-6c1.7,0 3.1,0.7 4.2,1.8L13,11l7,0L20,4L17.6,6.4z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/core/res/res/drawable/ic_menu_selectall_material.xml b/core/res/res/drawable/ic_menu_selectall_material.xml
index 11e63fd..fd05c72 100644
--- a/core/res/res/drawable/ic_menu_selectall_material.xml
+++ b/core/res/res/drawable/ic_menu_selectall_material.xml
@@ -21,6 +21,6 @@
         android:autoMirrored="true"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M3.000000,5.000000l2.000000,0.000000L5.000000,3.000000C3.900000,3.000000 3.000000,3.900000 3.000000,5.000000zM3.000000,13.000000l2.000000,0.000000l0.000000,-2.000000L3.000000,11.000000L3.000000,13.000000zM7.000000,21.000000l2.000000,0.000000l0.000000,-2.000000L7.000000,19.000000L7.000000,21.000000zM3.000000,9.000000l2.000000,0.000000L5.000000,7.000000L3.000000,7.000000L3.000000,9.000000zM13.000000,3.000000l-2.000000,0.000000l0.000000,2.000000l2.000000,0.000000L13.000000,3.000000zM19.000000,3.000000l0.000000,2.000000l2.000000,0.000000C21.000000,3.900000 20.100000,3.000000 19.000000,3.000000zM5.000000,21.000000l0.000000,-2.000000L3.000000,19.000000C3.000000,20.100000 3.900000,21.000000 5.000000,21.000000zM3.000000,17.000000l2.000000,0.000000l0.000000,-2.000000L3.000000,15.000000L3.000000,17.000000zM9.000000,3.000000L7.000000,3.000000l0.000000,2.000000l2.000000,0.000000L9.000000,3.000000zM11.000000,21.000000l2.000000,0.000000l0.000000,-2.000000l-2.000000,0.000000L11.000000,21.000000zM19.000000,13.000000l2.000000,0.000000l0.000000,-2.000000l-2.000000,0.000000L19.000000,13.000000zM19.000000,21.000000c1.100000,0.000000 2.000000,-0.900000 2.000000,-2.000000l-2.000000,0.000000L19.000000,21.000000zM19.000000,9.000000l2.000000,0.000000L21.000000,7.000000l-2.000000,0.000000L19.000000,9.000000zM19.000000,17.000000l2.000000,0.000000l0.000000,-2.000000l-2.000000,0.000000L19.000000,17.000000zM15.000000,21.000000l2.000000,0.000000l0.000000,-2.000000l-2.000000,0.000000L15.000000,21.000000zM15.000000,5.000000l2.000000,0.000000L17.000000,3.000000l-2.000000,0.000000L15.000000,5.000000zM7.000000,17.000000l10.000000,0.000000L17.000000,7.000000L7.000000,7.000000L7.000000,17.000000zM9.000000,9.000000l6.000000,0.000000l0.000000,6.000000L9.000000,15.000000L9.000000,9.000000z"
+        android:pathData="M3,5l2,0L5,3C3.9,3 3,3.9 3,5zM3,13l2,0l0,-2L3,11L3,13zM7,21l2,0l0,-2L7,19L7,21zM3,9l2,0L5,7L3,7L3,9zM13,3l-2,0l0,2l2,0L13,3zM19,3l0,2l2,0C21,3.9 20.1,3 19,3zM5,21l0,-2L3,19C3,20.1 3.9,21 5,21zM3,17l2,0l0,-2L3,15L3,17zM9,3L7,3l0,2l2,0L9,3zM11,21l2,0l0,-2l-2,0L11,21zM19,13l2,0l0,-2l-2,0L19,13zM19,21c1.1,0 2,-0.9 2,-2l-2,0L19,21zM19,9l2,0L21,7l-2,0L19,9zM19,17l2,0l0,-2l-2,0L19,17zM15,21l2,0l0,-2l-2,0L15,21zM15,5l2,0L17,3l-2,0L15,5zM7,17l10,0L17,7L7,7L7,17zM9,9l6,0l0,6L9,15L9,9z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/ic_menu_share_material.xml b/core/res/res/drawable/ic_menu_share_material.xml
index b7c238f..6c351c9 100644
--- a/core/res/res/drawable/ic_menu_share_material.xml
+++ b/core/res/res/drawable/ic_menu_share_material.xml
@@ -20,6 +20,6 @@
         android:viewportHeight="24.0"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M18.000000,16.100000c-0.800000,0.000000 -1.500000,0.300000 -2.000000,0.800000l-7.100000,-4.200000C9.000000,12.500000 9.000000,12.200000 9.000000,12.000000s0.000000,-0.500000 -0.100000,-0.700000L16.000000,7.200000C16.500000,7.700000 17.200001,8.000000 18.000000,8.000000c1.700000,0.000000 3.000000,-1.300000 3.000000,-3.000000s-1.300000,-3.000000 -3.000000,-3.000000s-3.000000,1.300000 -3.000000,3.000000c0.000000,0.200000 0.000000,0.500000 0.100000,0.700000L8.000000,9.800000C7.500000,9.300000 6.800000,9.000000 6.000000,9.000000c-1.700000,0.000000 -2.900000,1.200000 -2.900000,2.900000s1.300000,3.000000 3.000000,3.000000c0.800000,0.000000 1.500000,-0.300000 2.000000,-0.800000l7.100000,4.200000c-0.100000,0.300000 -0.100000,0.500000 -0.100000,0.700000c0.000000,1.600000 1.300000,2.900000 2.900000,2.900000s2.900000,-1.300000 2.900000,-2.900000S19.600000,16.100000 18.000000,16.100000z"
+        android:pathData="M18,16.1c-0.8,0 -1.5,0.3 -2,0.8l-7.1,-4.2C9,12.5 9,12.2 9,12s0,-0.5 -0.1,-0.7L16,7.2C16.5,7.7 17.200001,8 18,8c1.7,0 3,-1.3 3,-3s-1.3,-3 -3,-3s-3,1.3 -3,3c0,0.2 0,0.5 0.1,0.7L8,9.8C7.5,9.3 6.8,9 6,9c-1.7,0 -2.9,1.2 -2.9,2.9s1.3,3 3,3c0.8,0 1.5,-0.3 2,-0.8l7.1,4.2c-0.1,0.3 -0.1,0.5 -0.1,0.7c0,1.6 1.3,2.9 2.9,2.9s2.9,-1.3 2.9,-2.9S19.6,16.1 18,16.1z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/ic_notification_cast_connecting.xml b/core/res/res/drawable/ic_notification_cast_connecting.xml
deleted file mode 100644
index a390bce..0000000
--- a/core/res/res/drawable/ic_notification_cast_connecting.xml
+++ /dev/null
@@ -1,26 +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 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.
- */
--->
-<animation-list
-        xmlns:android="http://schemas.android.com/apk/res/android"
-        android:oneshot="false">
-    <item android:drawable="@drawable/ic_notification_cast_0" android:duration="500" />
-    <item android:drawable="@drawable/ic_notification_cast_1" android:duration="500" />
-    <item android:drawable="@drawable/ic_notification_cast_2" android:duration="500" />
-    <item android:drawable="@drawable/ic_notification_cast_1" android:duration="500" />
-</animation-list>
diff --git a/core/res/res/drawable/ic_search_api_material.xml b/core/res/res/drawable/ic_search_api_material.xml
index ac1aae3..70367bd 100644
--- a/core/res/res/drawable/ic_search_api_material.xml
+++ b/core/res/res/drawable/ic_search_api_material.xml
@@ -20,6 +20,6 @@
         android:viewportHeight="24.0"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M15.500000,14.000000l-0.800000,0.000000l-0.300000,-0.300000c1.000000,-1.100000 1.600000,-2.600000 1.600000,-4.200000C16.000000,5.900000 13.100000,3.000000 9.500000,3.000000C5.900000,3.000000 3.000000,5.900000 3.000000,9.500000S5.900000,16.000000 9.500000,16.000000c1.600000,0.000000 3.100000,-0.600000 4.200000,-1.600000l0.300000,0.300000l0.000000,0.800000l5.000000,5.000000l1.500000,-1.500000L15.500000,14.000000zM9.500000,14.000000C7.000000,14.000000 5.000000,12.000000 5.000000,9.500000S7.000000,5.000000 9.500000,5.000000C12.000000,5.000000 14.000000,7.000000 14.000000,9.500000S12.000000,14.000000 9.500000,14.000000z"
+        android:pathData="M15.5,14l-0.8,0l-0.3,-0.3c1,-1.1 1.6,-2.6 1.6,-4.2C16,5.9 13.1,3 9.5,3C5.9,3 3,5.9 3,9.5S5.9,16 9.5,16c1.6,0 3.1,-0.6 4.2,-1.6l0.3,0.3l0,0.8l5,5l1.5,-1.5L15.5,14zM9.5,14C7,14 5,12 5,9.5S7,5 9.5,5C12,5 14,7 14,9.5S12,14 9.5,14z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/ic_voice_search_api_material.xml b/core/res/res/drawable/ic_voice_search_api_material.xml
index 8c1e803..a026218 100644
--- a/core/res/res/drawable/ic_voice_search_api_material.xml
+++ b/core/res/res/drawable/ic_voice_search_api_material.xml
@@ -20,6 +20,6 @@
         android:viewportHeight="24.0"
         android:tint="?attr/colorControlNormal">
     <path
-        android:pathData="M12.000000,14.000000c1.700000,0.000000 3.000000,-1.300000 3.000000,-3.000000l0.000000,-6.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,6.000000C9.000000,12.700000 10.300000,14.000000 12.000000,14.000000zM17.299999,11.000000c0.000000,3.000000 -2.500000,5.100000 -5.300000,5.100000c-2.800000,0.000000 -5.300000,-2.100000 -5.300000,-5.100000L5.000000,11.000000c0.000000,3.400000 2.700000,6.200000 6.000000,6.700000L11.000000,21.000000l2.000000,0.000000l0.000000,-3.300000c3.300000,-0.500000 6.000000,-3.300000 6.000000,-6.700000L17.299999,11.000001z"
+        android:pathData="M12,14c1.7,0 3,-1.3 3,-3l0,-6c0,-1.7 -1.3,-3 -3,-3c-1.7,0 -3,1.3 -3,3l0,6C9,12.7 10.3,14 12,14zM17.299999,11c0,3 -2.5,5.1 -5.3,5.1c-2.8,0 -5.3,-2.1 -5.3,-5.1L5,11c0,3.4 2.7,6.2 6,6.7L11,21l2,0l0,-3.3c3.3,-0.5 6,-3.3 6,-6.7L17.299999,11.000001z"
         android:fillColor="@color/white"/>
 </vector>
diff --git a/core/res/res/drawable/stat_notify_disabled_data.xml b/core/res/res/drawable/stat_notify_disabled_data.xml
index 9089d08..4f6ea7f 100644
--- a/core/res/res/drawable/stat_notify_disabled_data.xml
+++ b/core/res/res/drawable/stat_notify_disabled_data.xml
@@ -20,5 +20,5 @@
         android:viewportHeight="48.0">
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M26.000000,4.100000l0.000000,6.100000c6.800000,1.000000 12.000000,6.800000 12.000000,13.800000c0.000000,1.800000 -0.400000,3.500000 -1.000000,5.100000l5.200000,3.100000c1.100000,-2.500000 1.800000,-5.200000 1.800000,-8.100000C44.000000,13.600000 36.099998,5.100000 26.000000,4.100000zM24.000000,38.000000c-7.700000,0.000000 -14.000000,-6.300000 -14.000000,-14.000000c0.000000,-7.100000 5.200000,-12.900000 12.000000,-13.800000L22.000000,4.100000C11.900000,5.100000 4.000000,13.600000 4.000000,24.000000c0.000000,11.000000 8.900000,20.000000 20.000000,20.000000c6.600000,0.000000 12.500000,-3.200000 16.100000,-8.200000l-5.200000,-3.100000C32.299999,36.000000 28.400000,38.000000 24.000000,38.000000z"/>
+        android:pathData="M26,4.1l0,6.1c6.8,1 12,6.8 12,13.8c0,1.8 -0.4,3.5 -1,5.1l5.2,3.1c1.1,-2.5 1.8,-5.2 1.8,-8.1C44,13.6 36.099998,5.1 26,4.1zM24,38c-7.7,0 -14,-6.3 -14,-14c0,-7.1 5.2,-12.9 12,-13.8L22,4.1C11.9,5.1 4,13.6 4,24c0,11 8.9,20 20,20c6.6,0 12.5,-3.2 16.1,-8.2l-5.2,-3.1C32.299999,36 28.4,38 24,38z"/>
 </vector>
diff --git a/core/res/res/drawable/stat_notify_wifi_in_range.xml b/core/res/res/drawable/stat_notify_wifi_in_range.xml
index 9a5407d..a271ca5 100644
--- a/core/res/res/drawable/stat_notify_wifi_in_range.xml
+++ b/core/res/res/drawable/stat_notify_wifi_in_range.xml
@@ -20,8 +20,8 @@
         android:viewportHeight="24.0">
     <path
         android:fillColor="#4DFFFFFF"
-        android:pathData="M19.100000,14.000000l-3.400000,0.000000l0.000000,-1.500000c0.000000,-1.800000 0.800000,-2.800000 1.500000,-3.400000C18.100000,8.300000 19.200001,8.000000 20.600000,8.000000c1.200000,0.000000 2.300000,0.300000 3.100000,0.800000l1.900000,-2.300000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.500000,-8.100000L19.100000,14.000000z"/>
+        android:pathData="M19.1,14l-3.4,0l0,-1.5c0,-1.8 0.8,-2.8 1.5,-3.4C18.1,8.3 19.200001,8 20.6,8c1.2,0 2.3,0.3 3.1,0.8l1.9,-2.3C25.1,6.1 20.299999,2.1 13,2.1S0.9,6.1 0.4,6.5L13,22l0,0l0,0l0,0l0,0l6.5,-8.1L19.1,14z"/>
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M19.500000,17.799999c0.000000,-0.800000 0.100000,-1.300000 0.200000,-1.600000c0.200000,-0.300000 0.500000,-0.700000 1.100000,-1.200000c0.400000,-0.400000 0.700000,-0.800000 1.000000,-1.100000s0.400000,-0.800000 0.400000,-1.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.400000,-1.200000c-0.300000,-0.300000 -0.700000,-0.400000 -1.200000,-0.400000c-0.400000,0.000000 -0.800000,0.100000 -1.100000,0.300000c-0.300000,0.200000 -0.400000,0.600000 -0.400000,1.100000l-1.900000,0.000000c0.000000,-1.000000 0.300000,-1.700000 1.000000,-2.200000c0.600000,-0.500000 1.500000,-0.800000 2.500000,-0.800000c1.100000,0.000000 2.000000,0.300000 2.600000,0.800000c0.600000,0.500000 0.900000,1.300000 0.900000,2.300000c0.000000,0.700000 -0.200000,1.300000 -0.600000,1.800000c-0.400000,0.600000 -0.900000,1.100000 -1.500000,1.600000c-0.300000,0.300000 -0.500000,0.500000 -0.600000,0.700000c-0.100000,0.200000 -0.100000,0.600000 -0.100000,1.000000L19.500000,17.700001zM21.400000,21.000000l-1.900000,0.000000l0.000000,-1.800000l1.900000,0.000000L21.400000,21.000000z"/>
+        android:pathData="M19.5,17.799999c0,-0.8 0.1,-1.3 0.2,-1.6c0.2,-0.3 0.5,-0.7 1.1,-1.2c0.4,-0.4 0.7,-0.8 1,-1.1s0.4,-0.8 0.4,-1.2c0,-0.5 -0.1,-0.9 -0.4,-1.2c-0.3,-0.3 -0.7,-0.4 -1.2,-0.4c-0.4,0 -0.8,0.1 -1.1,0.3c-0.3,0.2 -0.4,0.6 -0.4,1.1l-1.9,0c0,-1 0.3,-1.7 1,-2.2c0.6,-0.5 1.5,-0.8 2.5,-0.8c1.1,0 2,0.3 2.6,0.8c0.6,0.5 0.9,1.3 0.9,2.3c0,0.7 -0.2,1.3 -0.6,1.8c-0.4,0.6 -0.9,1.1 -1.5,1.6c-0.3,0.3 -0.5,0.5 -0.6,0.7c-0.1,0.2 -0.1,0.6 -0.1,1L19.5,17.700001zM21.4,21l-1.9,0l0,-1.8l1.9,0L21.4,21z"/>
 </vector>
diff --git a/core/res/res/drawable/stat_sys_tether_wifi.xml b/core/res/res/drawable/stat_sys_tether_wifi.xml
index 4396962..23dc849 100644
--- a/core/res/res/drawable/stat_sys_tether_wifi.xml
+++ b/core/res/res/drawable/stat_sys_tether_wifi.xml
@@ -21,5 +21,5 @@
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M24.000000,22.000000c-2.200000,0.000000 -4.000000,1.800000 -4.000000,4.000000c0.000000,2.200000 1.800000,4.000000 4.000000,4.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000C28.000000,23.799999 26.200001,22.000000 24.000000,22.000000zM36.000000,26.000000c0.000000,-6.600000 -5.400000,-12.000000 -12.000000,-12.000000c-6.600000,0.000000 -12.000000,5.400000 -12.000000,12.000000c0.000000,4.400000 2.400000,8.300000 6.000000,10.400000l2.000000,-3.500000c-2.400000,-1.400000 -4.000000,-3.900000 -4.000000,-6.900000c0.000000,-4.400000 3.600000,-8.000000 8.000000,-8.000000s8.000000,3.600000 8.000000,8.000000c0.000000,3.000000 -1.600000,5.500000 -4.000000,6.900000l2.000000,3.500000C33.599998,34.299999 36.000000,30.400000 36.000000,26.000000zM24.000000,6.000000C13.000000,6.000000 4.000000,15.000000 4.000000,26.000000c0.000000,7.400000 4.000000,13.800000 10.000000,17.299999l2.000000,-3.500000c-4.800000,-2.800000 -8.000000,-7.900000 -8.000000,-13.800000c0.000000,-8.800000 7.200000,-16.000000 16.000000,-16.000000s16.000000,7.200000 16.000000,16.000000c0.000000,5.900000 -3.200000,11.100000 -8.000000,13.800000l2.000000,3.500000c6.000000,-3.500000 10.000000,-9.900000 10.000000,-17.299999C44.000000,15.000000 35.000000,6.000000 24.000000,6.000000z"/>
+        android:pathData="M24,22c-2.2,0 -4,1.8 -4,4c0,2.2 1.8,4 4,4c2.2,0 4,-1.8 4,-4C28,23.799999 26.200001,22 24,22zM36,26c0,-6.6 -5.4,-12 -12,-12c-6.6,0 -12,5.4 -12,12c0,4.4 2.4,8.3 6,10.4l2,-3.5c-2.4,-1.4 -4,-3.9 -4,-6.9c0,-4.4 3.6,-8 8,-8s8,3.6 8,8c0,3 -1.6,5.5 -4,6.9l2,3.5C33.599998,34.299999 36,30.4 36,26zM24,6C13,6 4,15 4,26c0,7.4 4,13.8 10,17.299999l2,-3.5c-4.8,-2.8 -8,-7.9 -8,-13.8c0,-8.8 7.2,-16 16,-16s16,7.2 16,16c0,5.9 -3.2,11.1 -8,13.8l2,3.5c6,-3.5 10,-9.9 10,-17.299999C44,15 35,6 24,6z"/>
 </vector>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 2e3dd46..a01a154 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -108,7 +108,7 @@
     <string name="serviceClassPAD" msgid="3235259085648271037">"PAD"</string>
     <string name="roamingText0" msgid="7170335472198694945">"रोमिंग संकेतक चालू"</string>
     <string name="roamingText1" msgid="5314861519752538922">"रोमिंग संकेतक बंद"</string>
-    <string name="roamingText2" msgid="8969929049081268115">"रोमिंग संकेतक चमक रहा है"</string>
+    <string name="roamingText2" msgid="8969929049081268115">"रोमिंग संकेतक स्क्रीन की रोशनी रहा है"</string>
     <string name="roamingText3" msgid="5148255027043943317">"मोहल्‍ले से बाहर"</string>
     <string name="roamingText4" msgid="8808456682550796530">"भवन से बाहर"</string>
     <string name="roamingText5" msgid="7604063252850354350">"रोमिंग - पसंदीदा सिस्‍टम"</string>
@@ -588,7 +588,7 @@
     <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"सीधे CDMA टेबलेट सेटअप प्रारंभ करें"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"सीधे CDMA फ़ोन सेटअप प्रारंभ करें"</string>
     <string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"ऐप्स को CDMA प्रावधान प्रारंभ करने देता है. दुर्भावनापूर्ण ऐप्स अनावश्‍यक रूप से CDMA प्रावधान प्रारंभ कर सकते हैं."</string>
-    <string name="permlab_locationUpdates" msgid="7785408253364335740">"स्‍थान के बारे में नई जानकारी की सूचनाओं को नियंत्रित करें"</string>
+    <string name="permlab_locationUpdates" msgid="7785408253364335740">"स्‍थान के बारे में नई जानकारी की नोटिफिकेशन को नियंत्रित करें"</string>
     <string name="permdesc_locationUpdates" msgid="1120741557891438876">"एप को रेडियो से स्‍थान के बारे में नई जानकारी की सूचनाएं सक्षम/अक्षम करने देता है. सामान्‍य ऐप्स द्वारा उपयोग करने के लिए नहीं."</string>
     <string name="permlab_checkinProperties" msgid="7855259461268734914">"चेकइन गुणों में पहुंचें"</string>
     <string name="permdesc_checkinProperties" msgid="4024526968630194128">"ऐप्स  को चेकइन सेवा द्वारा अपलोड किए गए गुणों पर पढ़ें/लिखें पहुंच देता है. सामान्‍य ऐप्स द्वारा उपयोग करने के लिए नहीं."</string>
@@ -726,8 +726,8 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"ऐप्स को नेटवर्क नीतियां प्रबंधित करने और ऐप्स-विशिष्‍ट नियमों को परिभाषित करने देता है."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"नेटवर्क उपयोग हिसाब बदलें"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"ऐप्स  को यह संशोधित करने देता है कि ऐप्स की तुलना में नेटवर्क उपयोग का मूल्यांकन कैसे किया जाता है. सामान्‍य ऐप्स द्वारा उपयोग करने के लिए नहीं."</string>
-    <string name="permlab_accessNotifications" msgid="7673416487873432268">"सूचनाओं तक पहुंचें"</string>
-    <string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप्स  को सूचनाओं को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य ऐप्स  के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"नोटिफिकेशन तक पहुंचें"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप्स  को नोटिफिकेशन को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य ऐप्स  के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"नोटिफिकेशन श्रवणकर्ता सेवा से जुड़ें"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"धारक को नोटिफिकेशन श्रवणकर्ता सेवा के शीर्ष स्तरीय इंटरफ़ेस से जुड़ने देती है. सामान्य ऐप्स  के लिए कभी भी आवश्यक नहीं होनी चाहिए."</string>
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"किसी स्थिति प्रदाता सेवा से आबद्ध हों"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index a40c056..e8cb675 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1229,7 +1229,7 @@
     <string name="smv_application" msgid="3307209192155442829">"ແອັບຯ <xliff:g id="APPLICATION">%1$s</xliff:g> (ໂປຣເຊສ <xliff:g id="PROCESS">%2$s</xliff:g>) ໄດ້ລະເມີດນະໂຍບາຍ StrictMode ທີ່ບັງຄັບໃຊ້ດ້ວຍໂຕເອງ."</string>
     <string name="smv_process" msgid="5120397012047462446">"ໂປຣເຊສ <xliff:g id="PROCESS">%1$s</xliff:g> ລະເມີດນະໂຍບາຍບັງຄັບໃຊ້ເອງ StrictMode."</string>
     <string name="android_upgrading_title" msgid="1584192285441405746">"ກຳລັງອັບເກຣດ Android..."</string>
-    <string name="android_upgrading_apk" msgid="7904042682111526169">"ກຳລັງປັບປຸງປະສິດຕິພາບແອັບຯທີ <xliff:g id="NUMBER_0">%1$d</xliff:g> ຈາກທັງໝົດ <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
+    <string name="android_upgrading_apk" msgid="7904042682111526169">"ກຳລັງ​ປັບປຸງ​ປະສິດທິພາບ​ແອັບຯ​ທີ <xliff:g id="NUMBER_0">%1$d</xliff:g> ຈາກ​ທັງ​ໝົດ <xliff:g id="NUMBER_1">%2$d</xliff:g> ແອັບຯ."</string>
     <string name="android_upgrading_starting_apps" msgid="451464516346926713">"ກຳລັງເປີດແອັບຯ."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"ກຳລັງສຳເລັດການເປີດລະບົບ."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> ກຳລັງເຮັດວຽກ"</string>
diff --git a/core/res/res/values-mcc310-mnc150/config.xml b/core/res/res/values-mcc310-mnc150/config.xml
index f1936f4..3f9330d 100644
--- a/core/res/res/values-mcc310-mnc150/config.xml
+++ b/core/res/res/values-mcc310-mnc150/config.xml
@@ -33,4 +33,8 @@
         <item>315</item>
         <item>316</item>
     </string-array>
+    <string-array translatable="false" name="config_twoDigitNumberPattern">
+        <item>"0"</item>
+        <item>"00"</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 746eb4f..ae2f866 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1640,7 +1640,7 @@
     <string name="accessibility_enabled" msgid="1381972048564547685">"Włączono ułatwienia dostępu."</string>
     <string name="enable_accessibility_canceled" msgid="3833923257966635673">"Ułatwienia dostępu zostały anulowane."</string>
     <string name="user_switched" msgid="3768006783166984410">"Bieżący użytkownik: <xliff:g id="NAME">%1$s</xliff:g>."</string>
-    <string name="user_switching_message" msgid="2871009331809089783">"Przełączam na <xliff:g id="NAME">%1$s</xliff:g>…"</string>
+    <string name="user_switching_message" msgid="2871009331809089783">"Przełączam na użytkownika <xliff:g id="NAME">%1$s</xliff:g>…"</string>
     <string name="owner_name" msgid="2716755460376028154">"Właściciel"</string>
     <string name="error_message_title" msgid="4510373083082500195">"Błąd"</string>
     <string name="error_message_change_not_allowed" msgid="1347282344200417578">"Ta zmiana nie jest dozwolona przez administratora"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 08beb14..1ef185f 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1131,7 +1131,7 @@
     <item quantity="other" msgid="2973062968038355991">"<xliff:g id="COUNT">%d</xliff:g> gün içinde"</item>
   </plurals>
     <string name="preposition_for_date" msgid="9093949757757445117">"<xliff:g id="DATE">%s</xliff:g> tarihinde"</string>
-    <string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g> saatinde"</string>
+    <string name="preposition_for_time" msgid="5506831244263083793">"<xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="preposition_for_year" msgid="5040395640711867177">"<xliff:g id="YEAR">%s</xliff:g> yılında"</string>
     <string name="day" msgid="8144195776058119424">"gün"</string>
     <string name="days" msgid="4774547661021344602">"gün"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a153273..38f146b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -405,6 +405,15 @@
     <!-- Integer indicating associated full scan max num passive channels -->
     <integer translatable="false" name="config_wifi_framework_associated_partial_scan_max_num_passive_channels">3</integer>
 
+    <!-- Integer indicating number of association errors leading to blacklisting of the network -->
+    <integer translatable="false" name="config_wifi_framework_max_connection_errors_to_blacklist">4</integer>
+
+    <!-- Integer indicating number of authentication errors leading to blacklisting of the network -->
+    <integer translatable="false" name="config_wifi_framework_max_auth_errors_to_blacklist">4</integer>
+
+    <!-- Integer indicating minimum blacklisting delay of a wofo configuration due to connectin or auth errors -->
+    <integer translatable="false" name="config_wifi_framework_network_black_list_min_time_milli">120000</integer>
+
     <!-- Boolean indicating associated scan are allowed -->
     <bool translatable="false" name="config_wifi_framework_enable_associated_autojoin_scan">true</bool>
 
@@ -992,9 +1001,11 @@
     <!-- 2 means give warning -->
     <integer name="config_datause_notification_type">2</integer>
 
-    <!-- If Voice Radio Technology is RIL_RADIO_TECHNOLOGY_LTE:14 this is the value
-         that should be used instead. A value of RIL_RADIO_TECHNOLOGY_UNKNOWN:0 means
-         there is no replacement value and VoLTE is assumed to be supported -->
+    <!-- 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 assumption
+         for phone type (GSM) should be used. -->
     <integer name="config_volte_replacement_rat">0</integer>
 
     <!-- Flag indicating whether the current device is "voice capable".
@@ -1791,7 +1802,7 @@
         <item>SUPL_PORT=7275</item>
         <item>NTP_SERVER=north-america.pool.ntp.org</item>
         <item>SUPL_VER=0x20000</item>
-        <item>SUPL_MODE=0x01</item>
+        <item>SUPL_MODE=1</item>
     </string-array>
 
     <!-- If there is no preload VM number in the sim card, carriers such as
@@ -1823,4 +1834,14 @@
     <!-- Flag indicating whether radio is to be restarted on the error of
          PDP_FAIL_REGULAR_DEACTIVATION/0x24 -->
     <bool name="config_restart_radio_on_pdp_fail_regular_deactivation">false</bool>
+
+    <!-- networks that don't want data deactivate when shutdown the phone
+         note this is dependent on the operator of the network we're on,
+         not operator on the SIM -->
+    <string-array translatable="false" name="networks_not_clear_data">
+        <item>71203</item>
+        <item>71606</item>
+        <item>71610</item>
+        <item>732101</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index a794b62..8ebcd6d 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2583,4 +2583,13 @@
     <public type="raw" name="loaderror" id="0x01100000" />
     <!-- WebView error page for when domain lookup fails. @hide @SystemApi -->
     <public type="raw" name="nodomain" id="0x01100001" />
+
+    <!-- ===============================================================
+         Insert space from public API 21 attributes to private attributes
+         =============================================================== -->
+    <eat-comment />
+
+    <!-- @hide -->
+    <public-padding type="attr" name="private_resource_pad" end="0x01010500" />
+
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 50da1fa..fd4b40f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4409,17 +4409,6 @@
     <!-- Title text to append when the display is secure.  [CHAR LIMIT=30] -->
     <string name="display_manager_overlay_display_secure_suffix">, secure</string>
 
-    <!-- Title of the notification to indicate the process of connecting to a wifi display.  [CHAR LIMIT=50] -->
-    <string name="wifi_display_notification_connecting_title">Casting screen</string>
-    <!-- Message of the notification to indicate the process of connecting to a wifi display.  [CHAR LIMIT=80] -->
-    <string name="wifi_display_notification_connecting_message">Connecting to <xliff:g id="name">%1$s</xliff:g></string>
-    <!-- Title of the notification to indicate an active wifi display connection.  [CHAR LIMIT=50] -->
-    <string name="wifi_display_notification_connected_title">Casting screen</string>
-    <!-- Message of the notification to indicate an active wifi display connection.  [CHAR LIMIT=80] -->
-    <string name="wifi_display_notification_connected_message">Connected to <xliff:g id="name">%1$s</xliff:g></string>
-    <!-- Label of a button to disconnect an active wifi display connection.  [CHAR LIMIT=25] -->
-    <string name="wifi_display_notification_disconnect">Disconnect</string>
-
     <!-- Keyguard strings -->
     <!-- Label shown on emergency call button in keyguard -->
     <string name="kg_emergency_call_label">Emergency call</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3a3847e..5c246a4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -330,7 +330,10 @@
   <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_tx_packet_threshold" />
   <java-symbol type="integer" name="config_wifi_framework_associated_partial_scan_rx_packet_threshold" />
   <java-symbol type="integer" name="config_wifi_framework_network_switch_tx_packet_threshold" />
-  <java-symbol type="integer" name="config_wifi_framework_network_switch_tx_packet_threshold" />
+  <java-symbol type="integer" name="config_wifi_framework_network_switch_rx_packet_threshold" />
+  <java-symbol type="integer" name="config_wifi_framework_max_connection_errors_to_blacklist" />
+  <java-symbol type="integer" name="config_wifi_framework_max_auth_errors_to_blacklist" />
+  <java-symbol type="integer" name="config_wifi_framework_network_black_list_min_time_milli" />
   <java-symbol type="integer" name="config_bluetooth_max_advertisers" />
   <java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
   <java-symbol type="integer" name="config_cursorWindowSize" />
@@ -1185,8 +1188,6 @@
   <java-symbol type="drawable" name="ic_media_route_off_holo_dark" />
   <java-symbol type="drawable" name="ic_media_route_connecting_holo_dark" />
   <java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" />
-  <java-symbol type="drawable" name="ic_notification_cast_connecting" />
-  <java-symbol type="drawable" name="ic_notification_cast_on" />
   <java-symbol type="drawable" name="cling_button" />
   <java-symbol type="drawable" name="cling_arrow_up" />
   <java-symbol type="drawable" name="cling_bg" />
@@ -1723,11 +1724,6 @@
   <java-symbol type="string" name="vpn_lockdown_error" />
   <java-symbol type="string" name="vpn_lockdown_config" />
   <java-symbol type="string" name="wallpaper_binding_label" />
-  <java-symbol type="string" name="wifi_display_notification_connecting_title" />
-  <java-symbol type="string" name="wifi_display_notification_connecting_message" />
-  <java-symbol type="string" name="wifi_display_notification_connected_title" />
-  <java-symbol type="string" name="wifi_display_notification_connected_message" />
-  <java-symbol type="string" name="wifi_display_notification_disconnect" />
   <java-symbol type="style" name="Theme.Dialog.AppError" />
   <java-symbol type="style" name="Theme.Micro.Dialog.Alert" />
   <java-symbol type="style" name="Theme.Leanback.Dialog.Alert" />
@@ -2067,4 +2063,5 @@
   <java-symbol type="id" name="textSpacerNoButtons" />
   <java-symbol type="array" name="dial_string_replace" />
   <java-symbol type="bool" name="config_restart_radio_on_pdp_fail_regular_deactivation" />
+  <java-symbol type="array" name="networks_not_clear_data" />
 </resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 7b0efd9..3c2e302 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -771,8 +771,6 @@
         <item name="textCheckMark">@drawable/indicator_check_mark_light</item>
         <item name="textCheckMarkInverse">@drawable/indicator_check_mark_dark</item>
 
-        <item name="windowBackground">@color/background_material_light</item>
-
         <item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_light</item>
         <item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_light</item>
 
@@ -809,8 +807,6 @@
         <item name="textCheckMark">@drawable/indicator_check_mark_dark</item>
         <item name="textCheckMarkInverse">@drawable/indicator_check_mark_light</item>
 
-        <item name="windowBackground">@color/background_material_dark</item>
-
         <item name="fastScrollPreviewBackgroundLeft">@drawable/fastscroll_label_left_holo_dark</item>
         <item name="fastScrollPreviewBackgroundRight">@drawable/fastscroll_label_right_holo_dark</item>
 
@@ -1227,6 +1223,7 @@
 
     <!-- Default theme for Settings and activities launched from Settings. -->
     <style name="Theme.Material.Settings" parent="Theme.Material.Light.DarkActionBar">
+        <item name="colorBackground">@color/white</item>
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
         <item name="colorAccent">@color/material_deep_teal_500</item>
@@ -1239,6 +1236,7 @@
     </style>
 
     <style name="Theme.Material.Settings.BaseDialog" parent="Theme.Material.Light.BaseDialog">
+        <item name="colorBackground">@color/white</item>
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
         <item name="colorAccent">@color/material_deep_teal_500</item>
@@ -1247,6 +1245,7 @@
     <style name="Theme.Material.Settings.Dialog" parent="Theme.Material.Settings.BaseDialog" />
 
     <style name="Theme.Material.Settings.Dialog.BaseAlert" parent="Theme.Material.Light.Dialog.BaseAlert">
+        <item name="colorBackground">@color/white</item>
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
         <item name="colorAccent">@color/material_deep_teal_500</item>
@@ -1255,18 +1254,21 @@
     <style name="Theme.Material.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.BaseAlert" />
 
     <style name="Theme.Material.Settings.Dialog.Presentation" parent="Theme.Material.Light.Dialog.Presentation">
+        <item name="colorBackground">@color/white</item>
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
         <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
     <style name="Theme.Material.Settings.SearchBar" parent="Theme.Material.Light.SearchBar">
+        <item name="colorBackground">@color/white</item>
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
         <item name="colorAccent">@color/material_deep_teal_500</item>
     </style>
 
     <style name="Theme.Material.Settings.CompactMenu" parent="Theme.Material.Light.CompactMenu">
+        <item name="colorBackground">@color/white</item>
         <item name="colorPrimary">@color/material_blue_grey_900</item>
         <item name="colorPrimaryDark">@color/material_blue_grey_950</item>
         <item name="colorAccent">@color/material_deep_teal_500</item>
diff --git a/data/keyboards/Vendor_0b05_Product_4500.kl b/data/keyboards/Vendor_0b05_Product_4500.kl
new file mode 100644
index 0000000..a7d519e
--- /dev/null
+++ b/data/keyboards/Vendor_0b05_Product_4500.kl
@@ -0,0 +1,42 @@
+# Copyright (C) 2014 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.
+
+# Asus Gamepad
+
+key 304 BUTTON_A
+key 305 BUTTON_B
+key 307 BUTTON_X
+key 308 BUTTON_Y
+key 310 BUTTON_L1
+key 311 BUTTON_R1
+key 316 BUTTON_MODE
+key 317 BUTTON_THUMBL
+key 318 BUTTON_THUMBR
+
+key 158 BACK
+key 172 HOME
+
+axis 0x00 X
+axis 0x01 Y
+axis 0x02 Z
+axis 0x05 RZ
+axis 0x09 RTRIGGER
+axis 0x0a LTRIGGER
+axis 0x10 HAT_X
+axis 0x11 HAT_Y
+
+led 0x00 CONTROLLER_1
+led 0x01 CONTROLLER_2
+led 0x02 CONTROLLER_3
+led 0x03 CONTROLLER_4
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
index beea0ca..87185b1 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -408,7 +408,7 @@
 <p>The Java interface for OpenGL ES 3.1 on Android is provided with {@code GLES31}. When
 using OpenGL ES 3.1, be sure that you declare it in your manifest file with the
 <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a>
-tag and the {@code android:glEsVversion} attribute. For example:</p>
+tag and the {@code android:glEsVersion} attribute. For example:</p>
 
 <pre>
 &lt;manifest&gt;
diff --git a/docs/html/tools/index.jd b/docs/html/tools/index.jd
index f9d452c..73f8969 100644
--- a/docs/html/tools/index.jd
+++ b/docs/html/tools/index.jd
@@ -1,16 +1,16 @@
 page.title=Developer Tools
 @jd:body
 
-    
-<img src="{@docRoot}images/tools-home.png" style="float:right;" height="415" width="763" />
+
+<img src="{@docRoot}images/tools-home.png" style="float:right;" height="347" width="400" />
 
 <div style="position:relative;height:0">
-<div style="position:absolute;width:420px"> 
+<div style="position:absolute;width:420px">
   <p>The Android Developer Tools (ADT) plugin for Eclipse provides
     a professional-grade development environment for building
   Android apps. It's a full Java IDE with advanced features to help you build, test, debug,
   and package your Android apps. </p>
-  <p>Free, open-source, and runs on most major OS platforms.<br>To get started, 
+  <p>Free, open-source, and runs on most major OS platforms.<br>To get started,
   <a href="{@docRoot}sdk/index.html">download the Android SDK.</a></p>
 </div>
 </div>
@@ -21,11 +21,11 @@
 <h3>Full Java IDE</h3>
 
   <ul>
-    <li>Android-specific refactoring, quick fixes, integrated navigation between Java and XML resources.</li> 
-    <li>Enhanced XML editors for Android XML resources.</li> 
-    <li>Static analysis tools to catch performance, usability, and correctness problems.</li> 
-    <li>Build support for complex projects, command-line support for CI through Ant. Includes ProGuard and app-signing. </li> 
-    <li>Template-based wizard to create standard Android projects and components.</li> 
+    <li>Android-specific refactoring, quick fixes, integrated navigation between Java and XML resources.</li>
+    <li>Enhanced XML editors for Android XML resources.</li>
+    <li>Static analysis tools to catch performance, usability, and correctness problems.</li>
+    <li>Build support for complex projects, command-line support for CI through Ant. Includes ProGuard and app-signing. </li>
+    <li>Template-based wizard to create standard Android projects and components.</li>
   </ul>
 </div>
 
@@ -34,7 +34,7 @@
 
 <h3>Graphical UI Builders</h3>
   <ul>
-    <li>Build rich Android UI with drag and drop. 
+    <li>Build rich Android UI with drag and drop.
     <li>Visualize your UI on tablets, phones, and other devices. Switch themes, locales, even platform versions instantly, without building.</li>
     <li>Visual refactoring lets you extracts layout for inclusion, convert layouts, extract styles.</li>
     <li>Editor support for working with custom UI components.</li>
@@ -71,9 +71,9 @@
 <h3>Develop on Hardware Devices</h3>
 
   <ul>
-    <li>Use any commercial Android hardware device or multiple devices.</li> 
-    <li>Deploy your app to connected devices directy from the IDE.</li> 
-    <li>Live, on-device debugging, testing, and profiling.</li> 
+    <li>Use any commercial Android hardware device or multiple devices.</li>
+    <li>Deploy your app to connected devices directy from the IDE.</li>
+    <li>Live, on-device debugging, testing, and profiling.</li>
   </ul>
 </div>
 
@@ -100,7 +100,7 @@
   </ul>
 
 <h3>Testing</h3>
-    
+
   <ul>
     <li>Fully instrumentated, scriptable test environment.</li>
     <li>Integrated reports using standard test UI.</li>
@@ -108,7 +108,7 @@
   </ul>
 
 <h3>Native Development</h3>
-    
+
   <ul>
     <li>Support for compiling and packaging existing code written in C or C++.</li>
     <li>Support for packaging multiple architectures in a single binary, for broad compatibility.</li>
diff --git a/docs/html/training/graphics/opengl/environment.jd b/docs/html/training/graphics/opengl/environment.jd
index 77faabf..6b00c76 100644
--- a/docs/html/training/graphics/opengl/environment.jd
+++ b/docs/html/training/graphics/opengl/environment.jd
@@ -68,8 +68,7 @@
 </pre>
 
 <p>If your application uses texture compression, you must also declare which compression formats
-you support so that devices that do not support theses formats do not try to run your
-application:</p>
+your app supports, so that it is only installed on compatible devices.</p>
 
 <pre>
 &lt;supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" /&gt;
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index ace5eab..bbb0b50 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -1456,12 +1456,12 @@
 
         /* Setters and Getters, used by animator from AnimatedVectorDrawable. */
         @SuppressWarnings("unused")
-        int getStroke() {
+        int getStrokeColor() {
             return mStrokeColor;
         }
 
         @SuppressWarnings("unused")
-        void setStroke(int strokeColor) {
+        void setStrokeColor(int strokeColor) {
             mStrokeColor = strokeColor;
         }
 
@@ -1476,32 +1476,32 @@
         }
 
         @SuppressWarnings("unused")
-        float getstrokeAlpha() {
+        float getStrokeAlpha() {
             return mStrokeAlpha;
         }
 
         @SuppressWarnings("unused")
-        void setstrokeAlpha(float strokeAlpha) {
+        void setStrokeAlpha(float strokeAlpha) {
             mStrokeAlpha = strokeAlpha;
         }
 
         @SuppressWarnings("unused")
-        int getFill() {
+        int getFillColor() {
             return mFillColor;
         }
 
         @SuppressWarnings("unused")
-        void setFill(int fillColor) {
+        void setFillColor(int fillColor) {
             mFillColor = fillColor;
         }
 
         @SuppressWarnings("unused")
-        float getfillAlpha() {
+        float getFillAlpha() {
             return mFillAlpha;
         }
 
         @SuppressWarnings("unused")
-        void setfillAlpha(float fillAlpha) {
+        void setFillAlpha(float fillAlpha) {
             mFillAlpha = fillAlpha;
         }
 
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index 3681637..9cedd5a 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -71,7 +71,7 @@
     static inline bool paintWillNotDraw(const SkPaint& paint) {
         return paint.getAlpha() == 0
                 && !paint.getColorFilter()
-                && getXfermode(paint.getXfermode()) != SkXfermode::kClear_Mode;
+                && getXfermode(paint.getXfermode()) == SkXfermode::kSrcOver_Mode;
     }
 
     // TODO: move to a method on android:Paint
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index 56fa546..25dfee6 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -194,8 +194,17 @@
      */
     public final static int FLAG_HW_AV_SYNC = 0x1 << 4;
 
+    /**
+     * @hide
+     * Flag requesting capture from the source used for hardware hotword detection.
+     * To be used with capture preset MediaRecorder.AudioSource.HOTWORD or
+     * MediaRecorder.AudioSource.VOICE_RECOGNITION.
+     */
+    @SystemApi
+    public final static int FLAG_HW_HOTWORD = 0x1 << 5;
+
     private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
-            FLAG_BEACON | FLAG_HW_AV_SYNC;
+            FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD;
     private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED | FLAG_HW_AV_SYNC;
 
     private int mUsage = USAGE_UNKNOWN;
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 2ef9289..5fb4f12 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -709,10 +709,10 @@
         }
 
         /**
-         * Retrieve a human readable diagnostic information string
-         * associated with the exception. DO NOT SHOW THIS TO END-USERS!
-         * This string will not be localized or generally comprehensible
-         * to end-users.
+         * Retrieve a developer-readable diagnostic information string
+         * associated with the exception. Do not show this to end-users,
+         * since this string will not be localized or generally
+         * comprehensible to end-users.
          */
         public String getDiagnosticInfo() {
             return mDiagnosticInfo;
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index 1490732..3b8cb19 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -190,6 +190,9 @@
         private final int mErrorCode;
         private final String mDiagnosticInfo;
 
+        /**
+         * @hide
+         */
         public MediaDrmStateException(int errorCode, String detailMessage) {
             super(detailMessage);
             mErrorCode = errorCode;
@@ -211,9 +214,9 @@
         }
 
         /**
-         * Retrieve a human readable diagnostic information string
-         * associated with the exception. DO NOT SHOW THIS TO END-USERS!
-         * This string will not be localized or generally comprehensible
+         * Retrieve a developer-readable diagnostic information string
+         * associated with the exception. Do not show this to end-users,
+         * since this string will not be localized or generally comprehensible
          * to end-users.
          */
         public String getDiagnosticInfo() {
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index be86741..cfbf3af 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -434,6 +434,14 @@
         return mSessionBinder;
     }
 
+    /**
+     * @hide
+     */
+    public boolean controlsSameSession(MediaController other) {
+        if (other == null) return false;
+        return mSessionBinder.asBinder() == other.getSessionBinder().asBinder();
+    }
+
     private void addCallbackLocked(Callback cb, Handler handler) {
         if (getHandlerForCallbackLocked(cb) != null) {
             Log.w(TAG, "Callback is already added, ignoring");
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/MutexFileProvider.java b/packages/PrintSpooler/src/com/android/printspooler/model/MutexFileProvider.java
index 1f48638..0df5e3c 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/MutexFileProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/MutexFileProvider.java
@@ -93,7 +93,7 @@
     public void releaseFile() {
         synchronized (mLock) {
             if (mOwnerThread != Thread.currentThread()) {
-                throw new IllegalStateException("Not acquired");
+                return;
             }
 
             if (DEBUG) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index f779f87..eb2c920 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -125,7 +125,7 @@
         if (mLastRenderSpec == null) {
             mScheduledPreloadFirstShownPage = firstShownPage;
             mScheduledPreloadLastShownPage = lastShownPage;
-        } else {
+        } else if (mState == STATE_OPENED) {
             mRenderer.startPreload(firstShownPage, lastShownPage, mLastRenderSpec);
         }
     }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index 20e774f..fbf7204 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -312,10 +312,6 @@
                         + ", pageIndexInFile: " + pageIndexInFile);
             }
 
-            if (provider != null && provider.getPageIndex() != pageIndexInFile) {
-                mPageContentRepository.releasePageContentProvider(provider);
-            }
-
             provider = mPageContentRepository.acquirePageContentProvider(
                     pageIndexInFile, content);
             mBoundPagesInAdapter.put(position, null);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 56497d7..aa42c75 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -471,10 +471,6 @@
                 requestCreatePdfFileOrFinish();
             } break;
 
-            case STATE_PRINT_CANCELED: {
-                doFinish();
-            } break;
-
             default: {
                 updatePrintPreviewController(document.changed);
 
@@ -2393,6 +2389,7 @@
                 if (tempFile != null) {
                     tempFile.delete();
                 }
+                mFileProvider.releaseFile();
             }
         }
 
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index bddd691..1d629fd 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -48,6 +48,7 @@
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index bfeac9d..d0fba20 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -76,7 +76,7 @@
             android:layout_alignParentEnd="true"
             android:background="@drawable/btn_borderless_rect"
             android:clickable="true"
-            android:contentDescription="@null"
+            android:contentDescription="@string/accessibility_desc_settings"
             android:scaleType="center"
             android:src="@drawable/ic_settings" />
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index b07e993..6cc890b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -199,8 +199,8 @@
                     if (mPulsing && mDreaming) {
                         mPulsing = false;
                         turnDisplayOff();
-                        mWakeLock.release();
                     }
+                    mWakeLock.release(); // needs to be unconditional to balance acquire
                 }
             });
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 2fafb2c..fdebdd3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -30,6 +30,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.ImageView;
 import android.widget.TextView;
 
@@ -360,6 +361,7 @@
             listener = mTeardownDetailWhenDone;
             fireScanStateChanged(false);
         }
+        sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         fireShowingDetail(show ? detailAdapter : null);
         mClipper.animateCircularClip(x, y, show, listener);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index cb685fe..6ef6e9e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -123,7 +123,7 @@
     }
 
     public void userSwitch(int newUserId) {
-        mHandler.obtainMessage(H.USER_SWITCH, newUserId).sendToTarget();
+        mHandler.obtainMessage(H.USER_SWITCH, newUserId, 0).sendToTarget();
     }
 
     public void fireToggleStateChanged(boolean state) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
index 3ed3d30..0ab6626 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs;
 
+import android.app.ActivityManager;
 import android.content.Context;
 import android.database.ContentObserver;
 import android.os.Handler;
@@ -28,32 +29,33 @@
     private final Context mContext;
     private final String mSettingName;
 
+    private boolean mListening;
+    private int mUserId;
+
     protected abstract void handleValueChanged(int value);
 
     public SecureSetting(Context context, Handler handler, String settingName) {
         super(handler);
         mContext = context;
         mSettingName = settingName;
-        rebindForCurrentUser();
-    }
-
-    public void rebindForCurrentUser() {
+        mUserId = ActivityManager.getCurrentUser();
         setListening(true);
     }
 
     public int getValue() {
-        return Secure.getInt(mContext.getContentResolver(), mSettingName, 0);
+        return Secure.getIntForUser(mContext.getContentResolver(), mSettingName, 0, mUserId);
     }
 
     public void setValue(int value) {
-        Secure.putInt(mContext.getContentResolver(), mSettingName, value);
+        Secure.putIntForUser(mContext.getContentResolver(), mSettingName, value, mUserId);
     }
 
     @Override
     public void setListening(boolean listening) {
+        mListening = listening;
         if (listening) {
             mContext.getContentResolver().registerContentObserver(
-                    Secure.getUriFor(mSettingName), false, this);
+                    Secure.getUriFor(mSettingName), false, this, mUserId);
         } else {
             mContext.getContentResolver().unregisterContentObserver(this);
         }
@@ -63,4 +65,12 @@
     public void onChange(boolean selfChange) {
         handleValueChanged(getValue());
     }
+
+    public void setUserId(int userId) {
+        mUserId = userId;
+        if (mListening) {
+            setListening(false);
+            setListening(true);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index a62bbff..01849c1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -71,7 +71,8 @@
 
     @Override
     protected void handleUserSwitch(int newUserId) {
-        mSetting.rebindForCurrentUser();
+        mSetting.setUserId(newUserId);
+        handleRefreshState(mSetting.getValue());
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
index a4161f9..e2464c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardAffordanceView.java
@@ -497,4 +497,13 @@
     public void setIsLeft(boolean left) {
         mIsLeft = left;
     }
+
+    @Override
+    public boolean performClick() {
+        if (isClickable()) {
+            return super.performClick();
+        } else {
+            return false;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 754fade..fceed2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -284,10 +284,13 @@
         if (mAccessibilityController == null) {
             return;
         }
-        mLockIcon.setClickable(mUnlockMethodCache.isTrustManaged()
-                || mAccessibilityController.isTouchExplorationEnabled());
-        mLockIcon.setLongClickable(mAccessibilityController.isTouchExplorationEnabled()
-                && mUnlockMethodCache.isTrustManaged());
+        boolean clickToUnlock = mAccessibilityController.isTouchExplorationEnabled();
+        boolean clickToForceLock = mUnlockMethodCache.isTrustManaged()
+                && !mAccessibilityController.isAccessibilityEnabled();
+        boolean longClickToForceLock = mUnlockMethodCache.isTrustManaged()
+                && !clickToForceLock;
+        mLockIcon.setClickable(clickToForceLock || clickToUnlock);
+        mLockIcon.setLongClickable(longClickToForceLock);
         mLockIcon.setFocusable(mAccessibilityController.isAccessibilityEnabled());
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 67c7723..95c5020 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -317,7 +317,7 @@
                     }
                     mJustPeeked = false;
                 }
-                if (-h >= mUnlockFalsingThreshold) {
+                if (-h >= getFalsingThreshold()) {
                     mTouchAboveFalsingThreshold = true;
                 }
                 if (!mJustPeeked && (!waitForTouchSlop || mTracking) && !isTrackingBlocked()) {
@@ -370,6 +370,11 @@
         return !waitForTouchSlop || mTracking;
     }
 
+    private int getFalsingThreshold() {
+        float factor = mStatusBar.isScreenOnComingFromTouch() ? 1.5f : 1.0f;
+        return (int) (mUnlockFalsingThreshold * factor);
+    }
+
     protected abstract boolean hasConflictingGestures();
 
     protected void onTrackingStopped(boolean expand) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 90f9cdd..71fef65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -262,6 +262,7 @@
     private StatusBarWindowManager mStatusBarWindowManager;
     private UnlockMethodCache mUnlockMethodCache;
     private DozeServiceHost mDozeServiceHost;
+    private boolean mScreenOnComingFromTouch;
 
     int mPixelFormat;
     Object mQueueLock = new Object();
@@ -1758,7 +1759,7 @@
                 }
             }
 
-            if (controller != mMediaController) {
+            if (!sameSessions(mMediaController, controller)) {
                 // We have a new media session
 
                 if (mMediaController != null) {
@@ -1807,6 +1808,12 @@
         updateMediaMetaData(metaDataChanged);
     }
 
+    private boolean sameSessions(MediaController a, MediaController b) {
+        if (a == b) return true;
+        if (a == null) return false;
+        return a.controlsSameSession(b);
+    }
+
     /**
      * Hide the album artwork that is fading out and release its bitmap.
      */
@@ -2112,10 +2119,14 @@
         return mNotificationPanel.isQsExpanded();
     }
 
+    public boolean isScreenOnComingFromTouch() {
+        return mScreenOnComingFromTouch;
+    }
+
     public boolean isFalsingThresholdNeeded() {
         boolean onKeyguard = getBarState() == StatusBarState.KEYGUARD;
         boolean isMethodInsecure = mUnlockMethodCache.isMethodInsecure();
-        return onKeyguard && (isMethodInsecure || mDozing);
+        return onKeyguard && (isMethodInsecure || mDozing || mScreenOnComingFromTouch);
     }
 
     @Override  // NotificationData.Environment
@@ -3903,6 +3914,7 @@
 
     public void onScreenTurnedOff() {
         mScreenOnFromKeyguard = false;
+        mScreenOnComingFromTouch = false;
         mStackScroller.setAnimationsEnabled(false);
     }
 
@@ -4005,10 +4017,13 @@
         return !mNotificationData.getActiveNotifications().isEmpty();
     }
 
-    public void wakeUpIfDozing(long time) {
+    public void wakeUpIfDozing(long time, boolean fromTouch) {
         if (mDozing && mScrimController.isPulsing()) {
             PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
             pm.wakeUp(time);
+            if (fromTouch) {
+                mScreenOnComingFromTouch = true;
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 90be92d..5353f25 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -148,7 +148,7 @@
 
         if (!mDozing || mPulseCallback != null) {
             // Pulse suppressed.
-            mPulseCallback.onPulseFinished();
+            callback.onPulseFinished();
             return;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index cb9abfd..b0f3ea1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -623,7 +623,10 @@
         mSettingsButton.setTranslationX(values.settingsTranslation);
         mSettingsButton.setRotation(values.settingsRotation);
         applyAlpha(mEmergencyCallsOnly, values.emergencyCallsOnlyAlpha);
-        applyAlpha(mAlarmStatus, values.alarmStatusAlpha);
+        if (!mShowingDetail) {
+            // Otherwise it needs to stay invisible
+            applyAlpha(mAlarmStatus, values.alarmStatusAlpha);
+        }
         applyAlpha(mDateCollapsed, values.dateCollapsedAlpha);
         applyAlpha(mDateExpanded, values.dateExpandedAlpha);
         applyAlpha(mBatteryLevel, values.batteryLevelAlpha);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 89ce257..4c86990 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -132,7 +132,7 @@
             case KeyEvent.KEYCODE_VOLUME_DOWN:
             case KeyEvent.KEYCODE_VOLUME_UP:
                 if (down) {
-                    mService.wakeUpIfDozing(event.getEventTime());
+                    mService.wakeUpIfDozing(event.getEventTime(), false);
                 }
         }
         if (mService.interceptMediaKey(event)) {
@@ -164,7 +164,7 @@
             intercept = mDragDownHelper.onInterceptTouchEvent(ev);
             // wake up on a touch down event, if dozing
             if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
-                mService.wakeUpIfDozing(ev.getEventTime());
+                mService.wakeUpIfDozing(ev.getEventTime(), true);
             }
         }
         if (!intercept) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index eb0be05..e344954 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -55,6 +55,7 @@
     private final Object mProjectionLock = new Object();
 
     private boolean mDiscovering;
+    private boolean mCallbackRegistered;
     private MediaProjectionInfo mProjection;
 
     public CastControllerImpl(Context context) {
@@ -70,6 +71,7 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("CastController state:");
         pw.print("  mDiscovering="); pw.println(mDiscovering);
+        pw.print("  mCallbackRegistered="); pw.println(mCallbackRegistered);
         pw.print("  mCallbacks.size="); pw.println(mCallbacks.size());
         pw.print("  mRoutes.size="); pw.println(mRoutes.size());
         for (int i = 0; i < mRoutes.size(); i++) {
@@ -83,11 +85,17 @@
     public void addCallback(Callback callback) {
         mCallbacks.add(callback);
         fireOnCastDevicesChanged(callback);
+        synchronized (mDiscoveringLock) {
+            handleDiscoveryChangeLocked();
+        }
     }
 
     @Override
     public void removeCallback(Callback callback) {
         mCallbacks.remove(callback);
+        synchronized (mDiscoveringLock) {
+            handleDiscoveryChangeLocked();
+        }
     }
 
     @Override
@@ -96,12 +104,23 @@
             if (mDiscovering == request) return;
             mDiscovering = request;
             if (DEBUG) Log.d(TAG, "setDiscovering: " + request);
-            if (request) {
-                mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback,
-                        MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
-            } else {
-                mMediaRouter.removeCallback(mMediaCallback);
-            }
+            handleDiscoveryChangeLocked();
+        }
+    }
+
+    private void handleDiscoveryChangeLocked() {
+        if (mCallbackRegistered) {
+            mMediaRouter.removeCallback(mMediaCallback);
+            mCallbackRegistered = false;
+        }
+        if (mDiscovering) {
+            mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback,
+                    MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
+            mCallbackRegistered = true;
+        } else if (mCallbacks.size() != 0) {
+            mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback,
+                    MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
+            mCallbackRegistered = true;
         }
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 7b41391..dfcdaa0 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -68,6 +68,7 @@
 import android.view.WindowManagerGlobal;
 import android.view.WindowManagerInternal;
 import android.view.WindowManagerPolicy.WindowManagerFuncs;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.AdapterView;
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
@@ -625,6 +626,12 @@
      * What each item in the global actions dialog must be able to support.
      */
     private interface Action {
+        /**
+         * @return Text that will be announced when dialog is created.  null
+         *     for none.
+         */
+        CharSequence getLabelForAccessibility(Context context);
+
         View create(Context context, View convertView, ViewGroup parent, LayoutInflater inflater);
 
         void onPress();
@@ -692,6 +699,14 @@
 
         abstract public void onPress();
 
+        public CharSequence getLabelForAccessibility(Context context) {
+            if (mMessage != null) {
+                return mMessage;
+            } else {
+                return context.getString(mMessageResId);
+            }
+        }
+
         public View create(
                 Context context, View convertView, ViewGroup parent, LayoutInflater inflater) {
             View v = inflater.inflate(R.layout.global_actions_item, parent, false);
@@ -781,6 +796,11 @@
 
         }
 
+        @Override
+        public CharSequence getLabelForAccessibility(Context context) {
+            return context.getString(mMessageResId);
+        }
+
         public View create(Context context, View convertView, ViewGroup parent,
                 LayoutInflater inflater) {
             willCreate();
@@ -897,6 +917,11 @@
             return index;
         }
 
+        @Override
+        public CharSequence getLabelForAccessibility(Context context) {
+            return null;
+        }
+
         public View create(Context context, View convertView, ViewGroup parent,
                 LayoutInflater inflater) {
             View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false);
@@ -1045,6 +1070,7 @@
         private final Context mContext;
         private final int mWindowTouchSlop;
         private final AlertController mAlert;
+        private final MyAdapter mAdapter;
 
         private EnableAccessibilityController mEnableAccessibilityController;
 
@@ -1055,6 +1081,7 @@
             super(context, getDialogTheme(context));
             mContext = context;
             mAlert = new AlertController(mContext, this, getWindow());
+            mAdapter = (MyAdapter) params.mAdapter;
             mWindowTouchSlop = ViewConfiguration.get(context).getScaledWindowTouchSlop();
             params.apply(mAlert);
         }
@@ -1149,6 +1176,20 @@
         }
 
         @Override
+        public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+                for (int i = 0; i < mAdapter.getCount(); ++i) {
+                    CharSequence label =
+                            mAdapter.getItem(i).getLabelForAccessibility(getContext());
+                    if (label != null) {
+                        event.getText().add(label);
+                    }
+                }
+            }
+            return super.dispatchPopulateAccessibilityEvent(event);
+        }
+
+        @Override
         public boolean onKeyDown(int keyCode, KeyEvent event) {
             if (mAlert.onKeyDown(keyCode, event)) {
                 return true;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index aa49d37..006f5db 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -199,7 +199,7 @@
      */
     private WindowState mKeyguardScrim;
     private boolean mKeyguardHidden;
-    private boolean mKeyguardDrawn;
+    private boolean mKeyguardDrawnOnce;
 
     /* Table of Application Launch keys.  Maps from key codes to intent categories.
      *
@@ -284,10 +284,6 @@
 
     boolean mBootMessageNeedsHiding;
     KeyguardServiceDelegate mKeyguardDelegate;
-    // The following are only accessed on the mHandler thread.
-    boolean mKeyguardDrawComplete;
-    boolean mWindowManagerDrawComplete;
-    ScreenOnListener mScreenOnListener;
     final Runnable mWindowManagerDrawCallback = new Runnable() {
         @Override
         public void run() {
@@ -351,8 +347,12 @@
     boolean mLidControlsSleep;
     int mShortPressOnPowerBehavior = -1;
     int mLongPressOnPowerBehavior = -1;
-    boolean mAwakeEarly = false;
-    boolean mAwakeFully = false;
+    boolean mAwake;
+    boolean mScreenOnEarly;
+    boolean mScreenOnFully;
+    ScreenOnListener mScreenOnListener;
+    boolean mKeyguardDrawComplete;
+    boolean mWindowManagerDrawComplete;
     boolean mOrientationSensorEnabled = false;
     int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mHasSoftInput = false;
@@ -543,12 +543,10 @@
     private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
     private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
     private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
-    private static final int MSG_WAKING_UP = 8;
     private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
     private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
     private static final int MSG_HIDE_BOOT_MESSAGE = 11;
     private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
-    private static final int MSG_SCREEN_TURNING_ON = 13;
 
     private class PolicyHandler extends Handler {
         @Override
@@ -584,18 +582,12 @@
                     if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
                     finishWindowsDrawn();
                     break;
-                case MSG_WAKING_UP:
-                    handleWakingUp();
-                    break;
                 case MSG_HIDE_BOOT_MESSAGE:
                     handleHideBootMessage();
                     break;
                 case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
                     launchVoiceAssistWithWakeLock(msg.arg1 != 0);
                     break;
-                case MSG_SCREEN_TURNING_ON:
-                    handleScreenTurningOn((ScreenOnListener)msg.obj);
-                    break;
             }
         }
     }
@@ -766,11 +758,11 @@
         }
         //Could have been invoked due to screen turning on or off or
         //change of the currently visible window's orientation
-        if (localLOGV) Slog.v(TAG, "Screen status="+mAwakeEarly+
-                ", current orientation="+mCurrentAppOrientation+
-                ", SensorEnabled="+mOrientationSensorEnabled);
+        if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
+                + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
+                + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled);
         boolean disable = true;
-        if (mAwakeEarly) {
+        if (mScreenOnEarly && mAwake) {
             if (needSensorRunningLp()) {
                 disable = false;
                 //enable listener if not already enabled
@@ -1332,7 +1324,7 @@
     }
 
     private boolean shouldEnableWakeGestureLp() {
-        return mWakeGestureEnabledSetting && !mAwakeEarly
+        return mWakeGestureEnabledSetting && !mAwake
                 && (!mLidControlsSleep || mLidState != LID_CLOSED)
                 && mWakeGestureListener.isSupported();
     }
@@ -4728,45 +4720,51 @@
         }
     }
 
+    // Called on the PowerManager's Notifier thread.
     @Override
     public void goingToSleep(int why) {
         EventLog.writeEvent(70000, 0);
         if (DEBUG_WAKEUP) Slog.i(TAG, "Going to sleep...");
+
+        // We must get this work done here because the power manager will drop
+        // the wake lock and let the system suspend once this function returns.
         synchronized (mLock) {
-            mAwakeEarly = false;
-            mAwakeFully = false;
-        }
-        if (mKeyguardDelegate != null) {
-            mKeyguardDelegate.onScreenTurnedOff(why);
-        }
-        synchronized (mLock) {
+            mAwake = false;
+            mKeyguardDrawComplete = false;
             updateWakeGestureListenerLp();
             updateOrientationListenerLp();
             updateLockScreenTimeout();
         }
+
+        if (mKeyguardDelegate != null) {
+            mKeyguardDelegate.onScreenTurnedOff(why);
+        }
     }
 
+    // Called on the PowerManager's Notifier thread.
     @Override
     public void wakingUp() {
         EventLog.writeEvent(70000, 1);
         if (DEBUG_WAKEUP) Slog.i(TAG, "Waking up...");
-        mHandler.obtainMessage(MSG_WAKING_UP).sendToTarget();
-    }
 
-    // Called on the mHandler thread.
-    private void handleWakingUp() {
+        // Since goToSleep performs these functions synchronously, we must
+        // do the same here.  We cannot post this work to a handler because
+        // that might cause it to become reordered with respect to what
+        // may happen in a future call to goToSleep.
         synchronized (mLock) {
-            mAwakeEarly = true;
+            mAwake = true;
+            mKeyguardDrawComplete = false;
+            if (mKeyguardDelegate != null) {
+                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
+                mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
+            }
+
             updateWakeGestureListenerLp();
             updateOrientationListenerLp();
             updateLockScreenTimeout();
         }
 
-        mKeyguardDrawComplete = false;
-        mWindowManagerDrawComplete = false; // wait for later call to screenTurningOn
         if (mKeyguardDelegate != null) {
-            mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
-            mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
             mKeyguardDelegate.onScreenTurnedOn(mKeyguardDelegateCallback);
             // ... eventually calls finishKeyguardDrawn
         } else {
@@ -4775,94 +4773,130 @@
         }
     }
 
-    // Called on the mHandler thread.
     private void finishKeyguardDrawn() {
-        if (!mKeyguardDrawComplete) {
+        synchronized (mLock) {
+            if (!mAwake || mKeyguardDrawComplete) {
+                return; // spurious
+            }
+
             mKeyguardDrawComplete = true;
-            mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
-            finishScreenTurningOn();
+            if (mKeyguardDelegate != null) {
+                mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
+            }
+        }
+
+        finishScreenTurningOn();
+    }
+
+    // Called on the DisplayManager's DisplayPowerController thread.
+    @Override
+    public void screenTurnedOff() {
+        if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off...");
+
+        synchronized (mLock) {
+            mScreenOnEarly = false;
+            mScreenOnFully = false;
+            mWindowManagerDrawComplete = false;
+            mScreenOnListener = null;
+            updateOrientationListenerLp();
         }
     }
 
+    // Called on the DisplayManager's DisplayPowerController thread.
     @Override
     public void screenTurningOn(final ScreenOnListener screenOnListener) {
-        EventLog.writeEvent(70000, 1);
         if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...");
-        mHandler.obtainMessage(MSG_SCREEN_TURNING_ON, screenOnListener).sendToTarget();
-    }
 
-    // Called on the mHandler thread.
-    private void handleScreenTurningOn(ScreenOnListener screenOnListener) {
-        mScreenOnListener = screenOnListener;
+        synchronized (mLock) {
+            mScreenOnEarly = true;
+            mScreenOnFully = false;
+            mWindowManagerDrawComplete = false;
+            mScreenOnListener = screenOnListener;
+            updateOrientationListenerLp();
+        }
 
-        mWindowManagerDrawComplete = false;
         mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
                 WAITING_FOR_DRAWN_TIMEOUT);
         // ... eventually calls finishWindowsDrawn
     }
 
-    // Called on the mHandler thread.
     private void finishWindowsDrawn() {
-        if (!mWindowManagerDrawComplete) {
+        synchronized (mLock) {
+            if (!mScreenOnEarly || mWindowManagerDrawComplete) {
+                return; // spurious
+            }
+
             mWindowManagerDrawComplete = true;
-            finishScreenTurningOn();
         }
+
+        finishScreenTurningOn();
     }
 
-    // Called on the mHandler thread.
     private void finishScreenTurningOn() {
-        if (DEBUG_WAKEUP) Slog.d(TAG,
-                "finishScreenTurningOn: mAwakeEarly=" + mAwakeEarly
-                        + " mKeyguardDrawComplete=" + mKeyguardDrawComplete
-                        + " mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
-        boolean awake;
+        final ScreenOnListener listener;
+        final boolean enableScreen;
         synchronized (mLock) {
-            if ((mAwakeEarly && !mKeyguardDrawComplete)
-                    || !mWindowManagerDrawComplete) {
-                return;
+            if (DEBUG_WAKEUP) Slog.d(TAG,
+                    "finishScreenTurningOn: mAwake=" + mAwake
+                            + ", mScreenOnEarly=" + mScreenOnEarly
+                            + ", mScreenOnFully=" + mScreenOnFully
+                            + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
+                            + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
+
+            if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete
+                    || (mAwake && !mKeyguardDrawComplete)) {
+                return; // spurious or not ready yet
             }
 
-            if (mAwakeEarly) {
-                mAwakeFully = true;
-            }
-            awake = mAwakeFully;
-        }
-
-        if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
-
-        if (mScreenOnListener != null) {
-            mScreenOnListener.onScreenOn();
+            if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on...");
+            listener = mScreenOnListener;
             mScreenOnListener = null;
+            mScreenOnFully = true;
+
+            // Remember the first time we draw the keyguard so we know when we're done with
+            // the main part of booting and can enable the screen and hide boot messages.
+            if (!mKeyguardDrawnOnce && mAwake) {
+                mKeyguardDrawnOnce = true;
+                enableScreen = true;
+                if (mBootMessageNeedsHiding) {
+                    mBootMessageNeedsHiding = false;
+                    hideBootMessages();
+                }
+            } else {
+                enableScreen = false;
+            }
         }
 
-        if (awake) {
-            setKeyguardDrawnFirstTime();
+        if (listener != null) {
+            listener.onScreenOn();
+        }
 
-            if (mBootMessageNeedsHiding) {
-                handleHideBootMessage();
-                mBootMessageNeedsHiding = false;
+        if (enableScreen) {
+            try {
+                mWindowManager.enableScreenIfNeeded();
+            } catch (RemoteException unhandled) {
             }
         }
     }
 
     private void handleHideBootMessage() {
-        if (mBootMsgDialog == null) {
-            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: boot message not up");
-            return;
+        synchronized (mLock) {
+            if (!mKeyguardDrawnOnce) {
+                mBootMessageNeedsHiding = true;
+                return; // keyguard hasn't drawn the first time yet, not done booting
+            }
         }
-        if (!mKeyguardDrawComplete || !mWindowManagerDrawComplete) {
-            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: deferring until keyguard ready");
-            mBootMessageNeedsHiding = true;
-            return;
+
+        if (mBootMsgDialog != null) {
+            if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
+            mBootMsgDialog.dismiss();
+            mBootMsgDialog = null;
         }
-        if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing");
-        mBootMsgDialog.dismiss();
-        mBootMsgDialog = null;
     }
 
     @Override
-    public boolean isAwake() {
-        return mAwakeFully;
+    public boolean isScreenOn() {
+        return mScreenOnFully;
     }
 
     /** {@inheritDoc} */
@@ -4936,20 +4970,10 @@
         }
     }
 
-    private void setKeyguardDrawnFirstTime() {
-        synchronized (mLock) {
-            mKeyguardDrawn = true;
-        }
-        try {
-            mWindowManager.enableScreenIfNeeded();
-        } catch (RemoteException unhandled) {
-        }
-    }
-
     @Override
     public boolean isKeyguardDrawnLw() {
         synchronized (mLock) {
-            return mKeyguardDrawn;
+            return mKeyguardDrawnOnce;
         }
     }
 
@@ -5380,7 +5404,7 @@
 
     private void updateLockScreenTimeout() {
         synchronized (mScreenLockTimeout) {
-            boolean enable = (mAllowLockscreenWhenOn && mAwakeEarly &&
+            boolean enable = (mAllowLockscreenWhenOn && mAwake &&
                     mKeyguardDelegate != null && mKeyguardDelegate.isSecure());
             if (mLockScreenTimerActive != enable) {
                 if (enable) {
@@ -5918,9 +5942,13 @@
                 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
                 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
         pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
-        pw.print(prefix); pw.print("mAwakeEarly="); pw.print(mAwakeEarly);
-                pw.print(" mAwakeFully="); pw.print(mAwakeFully);
-                pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled);
+        pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
+        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
+                pw.print(" mScreenOnFully="); pw.println(mScreenOnFully);
+        pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete);
+                pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete);
+        pw.print(prefix); pw.print("mOrientationSensorEnabled=");
+                pw.println(mOrientationSensorEnabled);
         pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft);
                 pw.print(","); pw.print(mOverscanScreenTop);
                 pw.print(") "); pw.print(mOverscanScreenWidth);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
index aac02ad..e9ca5c9 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -295,6 +295,7 @@
                 stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
         lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
         lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+        lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
         lp.setTitle("KeyguardScrim");
         WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         wm.addView(view, lp);
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index d05de69..86cfdb9 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -434,6 +434,8 @@
             }
         }
 
+        clearProvidersAndHostsTagsLocked();
+
         loadGroupWidgetProvidersLocked(newProfileIds);
         loadGroupStateLocked(newProfileIds);
     }
@@ -2372,6 +2374,20 @@
         }
     }
 
+    private void clearProvidersAndHostsTagsLocked() {
+        final int providerCount = mProviders.size();
+        for (int i = 0; i < providerCount; i++) {
+            Provider provider = mProviders.get(i);
+            provider.tag = TAG_UNDEFINED;
+        }
+
+        final int hostCount = mHosts.size();
+        for (int i = 0; i < hostCount; i++) {
+            Host host = mHosts.get(i);
+            host.tag = TAG_UNDEFINED;
+        }
+    }
+
     private boolean writeProfileStateToFileLocked(FileOutputStream stream, int userId) {
         int N;
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 967681b..a3c64d0 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -979,12 +979,10 @@
         enforceAccessPermission();
         final int uid = Binder.getCallingUid();
         final ArrayList<NetworkInfo> result = Lists.newArrayList();
-        synchronized (mRulesLock) {
-            for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
-                    networkType++) {
-                if (getNetworkInfoForType(networkType) != null) {
-                    result.add(getFilteredNetworkInfo(networkType, uid));
-                }
+        for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
+                networkType++) {
+            if (getNetworkInfoForType(networkType) != null) {
+                result.add(getFilteredNetworkInfo(networkType, uid));
             }
         }
         return result.toArray(new NetworkInfo[result.size()]);
@@ -1078,15 +1076,13 @@
         enforceAccessPermission();
         final int uid = Binder.getCallingUid();
         final ArrayList<NetworkState> result = Lists.newArrayList();
-        synchronized (mRulesLock) {
-            for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
-                    networkType++) {
-                if (getNetworkInfoForType(networkType) != null) {
-                    final NetworkInfo info = getFilteredNetworkInfo(networkType, uid);
-                    final LinkProperties lp = getLinkPropertiesForTypeInternal(networkType);
-                    final NetworkCapabilities netcap = getNetworkCapabilitiesForType(networkType);
-                    result.add(new NetworkState(info, lp, netcap));
-                }
+        for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
+                networkType++) {
+            if (getNetworkInfoForType(networkType) != null) {
+                final NetworkInfo info = getFilteredNetworkInfo(networkType, uid);
+                final LinkProperties lp = getLinkPropertiesForTypeInternal(networkType);
+                final NetworkCapabilities netcap = getNetworkCapabilitiesForType(networkType);
+                result.add(new NetworkState(info, lp, netcap));
             }
         }
         return result.toArray(new NetworkState[result.size()]);
@@ -1888,36 +1884,6 @@
                     }
                     break;
                 }
-                case NetworkAgent.EVENT_BLOCK_ADDRESS_FAMILY: {
-                    NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
-                    if (nai == null) {
-                        loge("EVENT_BLOCK_ADDRESS_FAMILY from unknown NetworkAgent");
-                        break;
-                    }
-                    try {
-                        mNetd.blockAddressFamily((Integer) msg.obj, nai.network.netId,
-                                nai.linkProperties.getInterfaceName());
-                    } catch (Exception e) {
-                        // Never crash!
-                        loge("Exception in blockAddressFamily: " + e);
-                    }
-                    break;
-                }
-                case NetworkAgent.EVENT_UNBLOCK_ADDRESS_FAMILY: {
-                    NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
-                    if (nai == null) {
-                        loge("EVENT_UNBLOCK_ADDRESS_FAMILY from unknown NetworkAgent");
-                        break;
-                    }
-                    try {
-                        mNetd.unblockAddressFamily((Integer) msg.obj, nai.network.netId,
-                                nai.linkProperties.getInterfaceName());
-                    } catch (Exception e) {
-                        // Never crash!
-                        loge("Exception in blockAddressFamily: " + e);
-                    }
-                    break;
-                }
                 case NetworkAgent.EVENT_SET_EXPLICITLY_SELECTED: {
                     NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
                     if (nai == null) {
@@ -4132,8 +4098,9 @@
         if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
                 == false) {
             final int uidRules;
+            final int uid = Binder.getCallingUid();
             synchronized(mRulesLock) {
-                uidRules = mUidRules.get(Binder.getCallingUid(), RULE_ALLOW_ALL);
+                uidRules = mUidRules.get(uid, RULE_ALLOW_ALL);
             }
             if ((uidRules & RULE_REJECT_METERED) != 0) {
                 // we could silently fail or we can filter the available nets to only give
@@ -4273,13 +4240,17 @@
         LinkProperties newLp = networkAgent.linkProperties;
         int netId = networkAgent.network.netId;
 
+        // The NetworkAgentInfo does not know whether clatd is running on its network or not. Before
+        // we do anything else, make sure its LinkProperties are accurate.
+        mClat.fixupLinkProperties(networkAgent, oldLp);
+
         updateInterfaces(newLp, oldLp, netId);
         updateMtu(newLp, oldLp);
-        updateTcpBufferSizes(networkAgent);
         // TODO - figure out what to do for clat
 //        for (LinkProperties lp : newLp.getStackedLinks()) {
 //            updateMtu(lp, null);
 //        }
+        updateTcpBufferSizes(networkAgent);
         final boolean flushDns = updateRoutes(newLp, oldLp, netId);
         updateDnses(newLp, oldLp, netId, flushDns);
         updateClat(newLp, oldLp, networkAgent);
@@ -4287,23 +4258,14 @@
     }
 
     private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo na) {
-        // Update 464xlat state.
-        if (mClat.requiresClat(na)) {
+        final boolean wasRunningClat = mClat.isRunningClat(na);
+        final boolean shouldRunClat = Nat464Xlat.requiresClat(na);
 
-            // If the connection was previously using clat, but is not using it now, stop the clat
-            // daemon. Normally, this happens automatically when the connection disconnects, but if
-            // the disconnect is not reported, or if the connection's LinkProperties changed for
-            // some other reason (e.g., handoff changes the IP addresses on the link), it would
-            // still be running. If it's not running, then stopping it is a no-op.
-            if (Nat464Xlat.isRunningClat(oldLp) && !Nat464Xlat.isRunningClat(newLp)) {
-                mClat.stopClat();
-            }
-            // If the link requires clat to be running, then start the daemon now.
-            if (na.networkInfo.isConnected()) {
-                mClat.startClat(na);
-            } else {
-                mClat.stopClat();
-            }
+        if (!wasRunningClat && shouldRunClat) {
+            // Start clatd. If it's already been started but is not running yet, this is a no-op.
+            mClat.startClat(na);
+        } else if (wasRunningClat && !shouldRunClat) {
+            mClat.stopClat();
         }
     }
 
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 060c8e3..1623eac 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -40,6 +40,7 @@
 import android.app.ActivityManagerNative;
 import android.app.AppGlobals;
 import android.app.AlertDialog;
+import android.app.AppOpsManager;
 import android.app.IUserSwitchObserver;
 import android.app.KeyguardManager;
 import android.app.Notification;
@@ -175,6 +176,7 @@
     private InputMethodFileManager mFileManager;
     private final HardKeyboardListener mHardKeyboardListener;
     private final WindowManagerService mWindowManagerService;
+    private final AppOpsManager mAppOpsManager;
 
     final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1);
 
@@ -643,6 +645,7 @@
             }
         }, true /*asyncHandler*/);
         mWindowManagerService = windowManager;
+        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         mHardKeyboardListener = new HardKeyboardListener();
         mHasFeature = context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_INPUT_METHODS);
@@ -1746,6 +1749,20 @@
             throw new IllegalArgumentException("Unknown id: " + id);
         }
 
+        if (mCurClient != null && mCurAttribute != null) {
+            final int uid = mCurClient.uid;
+            final String packageName = mCurAttribute.packageName;
+            if (SystemConfig.getInstance().getFixedImeApps().contains(packageName)) {
+                if (InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, uid, packageName)) {
+                    return;
+                }
+                // TODO: Do we need to lock the input method when the application reported an
+                // incorrect package name?
+                Slog.e(TAG, "Ignoring FixedImeApps due to the validation failure. uid=" + uid
+                        + " package=" + packageName);
+            }
+        }
+
         // See if we need to notify a subtype change within the same IME.
         if (id.equals(mCurMethodId)) {
             final int subtypeCount = info.getSubtypeCount();
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index adfbb16..b708c3f 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -115,16 +115,20 @@
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            // Update keystore settings for profiles which use the same password as their parent
             if (Intent.ACTION_USER_ADDED.equals(intent.getAction())) {
                 final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                final int userSysUid = UserHandle.getUid(userHandle, Process.SYSTEM_UID);
+                final KeyStore ks = KeyStore.getInstance();
+
+                // Clear up keystore in case anything was left behind by previous users
+                ks.resetUid(userSysUid);
+
+                // If this user has a parent, sync with its keystore password
                 final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE);
                 final UserInfo parentInfo = um.getProfileParent(userHandle);
                 if (parentInfo != null) {
-                    final KeyStore ks = KeyStore.getInstance();
-                    final int profileUid = UserHandle.getUid(userHandle, Process.SYSTEM_UID);
-                    final int parentUid = UserHandle.getUid(parentInfo.id, Process.SYSTEM_UID);
-                    ks.syncUid(parentUid, profileUid);
+                    final int parentSysUid = UserHandle.getUid(parentInfo.id, Process.SYSTEM_UID);
+                    ks.syncUid(parentSysUid, userSysUid);
                 }
             }
         }
@@ -530,6 +534,10 @@
         } finally {
             db.endTransaction();
         }
+
+        final KeyStore ks = KeyStore.getInstance();
+        final int userUid = UserHandle.getUid(userId, Process.SYSTEM_UID);
+        ks.resetUid(userUid);
     }
 
     private void writeFile(String name, byte[] hash) {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 1318f66..822007a 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -25,8 +25,9 @@
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.NetworkStats.UID_ALL;
 import static android.net.TrafficStats.UID_TETHERING;
-import static android.system.OsConstants.AF_INET;
-import static android.system.OsConstants.AF_INET6;
+import static android.net.RouteInfo.RTN_THROW;
+import static android.net.RouteInfo.RTN_UNICAST;
+import static android.net.RouteInfo.RTN_UNREACHABLE;
 import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult;
 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
 import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
@@ -955,11 +956,21 @@
         final Command cmd = new Command("network", "route", action, netId);
 
         // create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
-        final LinkAddress la = route.getDestinationLinkAddress();
         cmd.appendArg(route.getInterface());
-        cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength());
-        if (route.hasGateway()) {
-            cmd.appendArg(route.getGateway().getHostAddress());
+        cmd.appendArg(route.getDestination().toString());
+
+        switch (route.getType()) {
+            case RouteInfo.RTN_UNICAST:
+                if (route.hasGateway()) {
+                    cmd.appendArg(route.getGateway().getHostAddress());
+                }
+                break;
+            case RouteInfo.RTN_UNREACHABLE:
+                cmd.appendArg("unreachable");
+                break;
+            case RouteInfo.RTN_THROW:
+                cmd.appendArg("throw");
+                break;
         }
 
         try {
@@ -2118,36 +2129,4 @@
     public void removeInterfaceFromLocalNetwork(String iface) {
         modifyInterfaceInNetwork("remove", "local", iface);
     }
-
-    @Override
-    public void blockAddressFamily(int family, int netId, String iface) {
-        modifyAddressFamily("add", family, netId, iface);
-    }
-
-    @Override
-    public void unblockAddressFamily(int family, int netId, String iface) {
-        modifyAddressFamily("remove", family, netId, iface);
-    }
-
-    private void modifyAddressFamily(String action, int family, int netId, String iface) {
-        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
-
-        final Command cmd = new Command("network", "route", action, netId, iface);
-
-        if (family == AF_INET) {
-            cmd.appendArg(Inet4Address.ANY.getHostAddress() + "/0");
-        } else if (family == AF_INET6) {
-            cmd.appendArg(Inet6Address.ANY.getHostAddress() + "/0");
-        } else {
-            throw new IllegalStateException(family + " is neither " + AF_INET + " nor " + AF_INET6);
-        }
-
-        cmd.appendArg("unreachable");
-
-        try {
-            mConnector.execute(cmd);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 37c23bb..164a4f7 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -99,8 +99,6 @@
 
         int phoneId;
 
-        boolean isLegacyApp;
-
         @Override
         public String toString() {
             return "{pkgForDebug=" + pkgForDebug + " callerUid=" + callerUid + " subId=" + subId +
@@ -156,10 +154,6 @@
 
     private VoLteServiceState mVoLteServiceState = new VoLteServiceState();
 
-    private long mDefaultSubId;
-
-    private int mDefaultPhoneIdForDefaultSubId;
-
     private DataConnectionRealTimeInfo mDcRtInfo = new DataConnectionRealTimeInfo();
 
     private int mRingingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
@@ -201,23 +195,8 @@
                     }
                     break;
                 }
-                case MSG_UPDATE_DEFAULT_SUB: {
-                    if (VDBG) {
-                        log("MSG_UPDATE_DEFAULT_SUB subid=" + mDefaultSubId
-                                + " phoneId=" + mDefaultPhoneIdForDefaultSubId);
-                    }
-                    // Default subscription id changed, update the changed default subscription
-                    // id in  all the legacy application listener records.
-                    synchronized (mRecords) {
-                        for (Record r : mRecords) {
-                            // FIXME: Be sure we're using isLegacyApp correctly!
-                            if (r.isLegacyApp == true) {
-                                r.subId = mDefaultSubId;
-                                r.phoneId = mDefaultPhoneIdForDefaultSubId;
-                            }
-                        }
-                    }
-                    break;
+                case MSG_UPDATE_DEFAULT_SUB: {// do nothing
+                    if (VDBG) log(TAG + "MSG_UPDATE_DEFAULT_SUB");
                 }
             }
         }
@@ -233,13 +212,8 @@
                 if (DBG) log("onReceive: userHandle=" + userHandle);
                 mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED, userHandle, 0));
             } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_SUBSCRIPTION_CHANGED)) {
-                mDefaultSubId = intent.getLongExtra(PhoneConstants.SUBSCRIPTION_KEY,
-                        SubscriptionManager.getDefaultSubId());
-                mDefaultPhoneIdForDefaultSubId = intent.getIntExtra(PhoneConstants.SLOT_KEY,
-                        SubscriptionManager.getPhoneId(mDefaultSubId));
                 if (DBG) {
-                    log("onReceive: mDefaultSubId=" + mDefaultSubId
-                            + " mDefaultPhoneIdForDefaultSubId=" + mDefaultPhoneIdForDefaultSubId);
+                    log(TAG + "onReceive: ACTION_DEFAULT_SUBSCRIPTION_CHANGED");
                 }
                 mHandler.sendMessage(mHandler.obtainMessage(MSG_UPDATE_DEFAULT_SUB, 0, 0));
             }
@@ -260,10 +234,6 @@
         mBatteryStats = BatteryStatsService.getService();
         mConnectedApns = new ArrayList<String>();
 
-        // Initialize default subId and its phoneId.
-        mDefaultSubId = SubscriptionManager.getDefaultSubId();
-        mDefaultPhoneIdForDefaultSubId = SubscriptionManager.getPhoneId(mDefaultSubId);
-
         int numPhones = TelephonyManager.getDefault().getPhoneCount();
         if (DBG) log("TelephonyRegistor: ctor numPhones=" + numPhones);
         mNumPhones = numPhones;
@@ -322,25 +292,23 @@
     @Override
     public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
             boolean notifyNow) {
-        listen(pkgForDebug, callback, events, notifyNow, mDefaultSubId, true);
+        listenForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, pkgForDebug, callback, events,
+            notifyNow);
     }
 
     @Override
     public void listenForSubscriber(long subId, String pkgForDebug, IPhoneStateListener callback,
             int events, boolean notifyNow) {
-        listen(pkgForDebug, callback, events, notifyNow, subId, false);
+        listen(pkgForDebug, callback, events, notifyNow, subId);
     }
 
     private void listen(String pkgForDebug, IPhoneStateListener callback, int events,
-            boolean notifyNow, long subId, boolean isLegacyApp) {
+            boolean notifyNow, long subId) {
         int callerUid = UserHandle.getCallingUserId();
         int myUid = UserHandle.myUserId();
-        int phoneId = SubscriptionManager.getPhoneId(subId);
         if (VDBG) {
             log("listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events)
-                + " notifyNow=" + notifyNow + " subId=" + subId + " phoneId=" + phoneId
-                + " isLegacyApp=" + isLegacyApp
-                + " myUid=" + myUid
+                + " notifyNow=" + notifyNow + " subId=" + subId + " myUid=" + myUid
                 + " callerUid=" + callerUid);
         }
         if (events != 0) {
@@ -364,28 +332,23 @@
                     r.callback = callback;
                     r.pkgForDebug = pkgForDebug;
                     r.callerUid = callerUid;
-                    r.subId = subId;
-                    r.phoneId = phoneId;
-                    r.isLegacyApp = isLegacyApp;
-                    // Legacy applications pass invalid subId(-1), based on
-                    // the received subId value update the isLegacyApp field
-                    if ((r.subId <= 0) || (r.subId == SubscriptionManager.INVALID_SUB_ID)) {
-                        r.subId = mDefaultSubId;
-                        r.phoneId = mDefaultPhoneIdForDefaultSubId;
-                        r.isLegacyApp = true; // subId & phoneId are updated when default changes.
+                    // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
+                    // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
+                    if (!SubscriptionManager.isValidSubId(subId)) {
+                        r.subId = SubscriptionManager.DEFAULT_SUB_ID;
+                     } else {//APP specify subID
+                        r.subId = subId;
                     }
-                    if (r.subId == SubscriptionManager.DEFAULT_SUB_ID) {
-                        r.subId = mDefaultSubId;
-                        r.phoneId = mDefaultPhoneIdForDefaultSubId;
-                        r.isLegacyApp = true; // subId & phoneId are updated when default changes.
-                        if (DBG) log("listen: DEFAULT_SUB_ID");
-                    }
+                    r.phoneId = SubscriptionManager.getPhoneId(r.subId);
+
                     mRecords.add(r);
                     if (DBG) log("listen: add new record");
                 }
+
+                int phoneId = r.phoneId;
                 r.events = events;
                 if (DBG) {
-                    log("listen: r=" + r + " subId=" + subId + " phoneId=" + phoneId);
+                    log("listen: r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId);
                 }
                 if (VDBG) toStringLogSSC("listen");
                 if (notifyNow && validatePhoneId(phoneId)) {
@@ -525,11 +488,15 @@
         if (!checkNotifyPermission("notifyCallState()")) {
             return;
         }
+
+        if (VDBG) {
+            log("notifyCallState: state=" + state + " incomingNumber=" + incomingNumber);
+        }
+
         synchronized (mRecords) {
             for (Record r : mRecords) {
                 if (((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) &&
-                    (r.isLegacyApp == true)) {
-                    // FIXME: why does isLegacyApp need to be true?
+                        (r.subId == SubscriptionManager.DEFAULT_SUB_ID)) {
                     try {
                         r.callback.onCallStateChanged(state, incomingNumber);
                     } catch (RemoteException ex) {
@@ -539,7 +506,7 @@
             }
             handleRemoveListLocked();
         }
-        broadcastCallStateChanged(state, incomingNumber, mDefaultSubId);
+        broadcastCallStateChanged(state, incomingNumber, SubscriptionManager.DEFAULT_SUB_ID);
     }
 
     public void notifyCallStateForSubscriber(long subId, int state, String incomingNumber) {
@@ -557,8 +524,8 @@
                 mCallIncomingNumber[phoneId] = incomingNumber;
                 for (Record r : mRecords) {
                     if (((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) &&
-                            (r.phoneId == phoneId) &&
-                            (r.isLegacyApp == false)) { // FIXME: why isLegacyApp false?
+                            (r.subId == subId) &&
+                            (r.subId != SubscriptionManager.DEFAULT_SUB_ID)) {
                         try {
                             r.callback.onCallStateChanged(state, incomingNumber);
                         } catch (RemoteException ex) {
@@ -572,20 +539,12 @@
         broadcastCallStateChanged(state, incomingNumber, subId);
     }
 
-     public void notifyServiceState(ServiceState state) {
-         notifyServiceStateForSubscriber(mDefaultSubId, state);
-     }
-
-    public void notifyServiceStateForSubscriber(long subId, ServiceState state) {
+    public void notifyServiceStateForPhoneId(int phoneId, long subId, ServiceState state) {
         if (!checkNotifyPermission("notifyServiceState()")){
             return;
         }
-        if (subId == SubscriptionManager.DEFAULT_SUB_ID) {
-            subId = mDefaultSubId;
-            if (VDBG) log("notifyServiceStateForSubscriber: using mDefaultSubId=" + mDefaultSubId);
-        }
+
         synchronized (mRecords) {
-            int phoneId = SubscriptionManager.getPhoneId(subId);
             if (VDBG) {
                 log("notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + phoneId
                     + " state=" + state);
@@ -601,7 +560,8 @@
                                 + " phoneId=" + phoneId + " state=" + state);
                     }
                     if (((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) &&
-                        (r.phoneId == phoneId)) {
+                            ((r.subId == subId) ||
+                            (r.subId == SubscriptionManager.DEFAULT_SUB_ID))) {
                         try {
                             if (DBG) {
                                 log("notifyServiceStateForSubscriber: callback.onSSC r=" + r
@@ -623,7 +583,7 @@
     }
 
     public void notifySignalStrength(SignalStrength signalStrength) {
-        notifySignalStrengthForSubscriber(mDefaultSubId, signalStrength);
+        notifySignalStrengthForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, signalStrength);
     }
 
     public void notifySignalStrengthForSubscriber(long subId, SignalStrength signalStrength) {
@@ -646,7 +606,8 @@
                                 + " phoneId=" + phoneId + " ss=" + signalStrength);
                     }
                     if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) &&
-                        (r.phoneId == phoneId)) {
+                            ((r.subId == subId) ||
+                            (r.subId == SubscriptionManager.DEFAULT_SUB_ID))) {
                         try {
                             if (DBG) {
                                 log("notifySignalStrengthForSubscriber: callback.onSsS r=" + r
@@ -659,7 +620,8 @@
                         }
                     }
                     if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) &&
-                        (r.phoneId == phoneId)) {
+                            ((r.subId == subId) ||
+                            (r.subId == SubscriptionManager.DEFAULT_SUB_ID))) {
                         try {
                             int gsmSignalStrength = signalStrength.getGsmSignalStrength();
                             int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
@@ -683,7 +645,7 @@
     }
 
     public void notifyCellInfo(List<CellInfo> cellInfo) {
-         notifyCellInfoForSubscriber(mDefaultSubId, cellInfo);
+         notifyCellInfoForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, cellInfo);
     }
 
     public void notifyCellInfoForSubscriber(long subId, List<CellInfo> cellInfo) {
@@ -700,8 +662,9 @@
             if (validatePhoneId(phoneId)) {
                 mCellInfo.set(phoneId, cellInfo);
                 for (Record r : mRecords) {
-                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)
-                            && r.subId == subId) {
+                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
+                            ((r.subId == subId) ||
+                            (r.subId == SubscriptionManager.DEFAULT_SUB_ID))) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyCellInfo: mCellInfo=" + cellInfo + " r=" + r);
@@ -742,25 +705,22 @@
         }
     }
 
-    public void notifyMessageWaitingChanged(boolean mwi) {
-        notifyMessageWaitingChangedForSubscriber(mDefaultSubId, mwi);
-    }
-
-    public void notifyMessageWaitingChangedForSubscriber(long subId, boolean mwi) {
+    @Override
+    public void notifyMessageWaitingChangedForPhoneId(int phoneId, long subId, boolean mwi) {
         if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
             return;
         }
         if (VDBG) {
-            log("notifyMessageWaitingChangedForSubscriber: subId=" + subId
+            log("notifyMessageWaitingChangedForSubscriberPhoneID: subId=" + phoneId
                 + " mwi=" + mwi);
         }
         synchronized (mRecords) {
-            int phoneId = SubscriptionManager.getPhoneId(subId);
             if (validatePhoneId(phoneId)) {
                 mMessageWaiting[phoneId] = mwi;
                 for (Record r : mRecords) {
                     if (((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) &&
-                        (r.phoneId == phoneId)) {
+                            ((r.subId == subId) ||
+                            (r.subId == SubscriptionManager.DEFAULT_SUB_ID))) {
                         try {
                             r.callback.onMessageWaitingIndicatorChanged(mwi);
                         } catch (RemoteException ex) {
@@ -774,7 +734,7 @@
     }
 
     public void notifyCallForwardingChanged(boolean cfi) {
-        notifyCallForwardingChangedForSubscriber(mDefaultSubId, cfi);
+        notifyCallForwardingChangedForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, cfi);
     }
 
     public void notifyCallForwardingChangedForSubscriber(long subId, boolean cfi) {
@@ -791,7 +751,8 @@
                 mCallForwarding[phoneId] = cfi;
                 for (Record r : mRecords) {
                     if (((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) &&
-                        (r.phoneId == phoneId)) {
+                            ((r.subId == subId) ||
+                            (r.subId == SubscriptionManager.DEFAULT_SUB_ID))) {
                         try {
                             r.callback.onCallForwardingIndicatorChanged(cfi);
                         } catch (RemoteException ex) {
@@ -805,7 +766,7 @@
     }
 
     public void notifyDataActivity(int state) {
-        notifyDataActivityForSubscriber(mDefaultSubId, state);
+        notifyDataActivityForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, state);
     }
 
     public void notifyDataActivityForSubscriber(long subId, int state) {
@@ -831,8 +792,8 @@
     public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
             String reason, String apn, String apnType, LinkProperties linkProperties,
             NetworkCapabilities networkCapabilities, int networkType, boolean roaming) {
-        notifyDataConnectionForSubscriber(mDefaultSubId, state, isDataConnectivityPossible,
-            reason, apn, apnType, linkProperties,
+        notifyDataConnectionForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, state,
+            isDataConnectivityPossible,reason, apn, apnType, linkProperties,
             networkCapabilities, networkType, roaming);
     }
 
@@ -888,7 +849,8 @@
                 }
                 for (Record r : mRecords) {
                     if (((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) &&
-                            (r.phoneId == phoneId)) {
+                            ((r.subId == subId) ||
+                            (r.subId == SubscriptionManager.DEFAULT_SUB_ID))) {
                         try {
                             log("Notify data connection state changed on sub: " +
                                     subId);
@@ -921,7 +883,8 @@
     }
 
     public void notifyDataConnectionFailed(String reason, String apnType) {
-         notifyDataConnectionFailedForSubscriber(mDefaultSubId, reason, apnType);
+         notifyDataConnectionFailedForSubscriber(SubscriptionManager.DEFAULT_SUB_ID,
+                 reason, apnType);
     }
 
     public void notifyDataConnectionFailedForSubscriber(long subId,
@@ -954,7 +917,7 @@
     }
 
     public void notifyCellLocation(Bundle cellLocation) {
-         notifyCellLocationForSubscriber(mDefaultSubId, cellLocation);
+         notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUB_ID, cellLocation);
     }
 
     public void notifyCellLocationForSubscriber(long subId, Bundle cellLocation) {
@@ -972,8 +935,9 @@
             if (validatePhoneId(phoneId)) {
                 mCellLocation[phoneId] = cellLocation;
                 for (Record r : mRecords) {
-                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)
-                            && r.subId == subId) {
+                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
+                            ((r.subId == subId) ||
+                            (r.subId == SubscriptionManager.DEFAULT_SUB_ID))) {
                         try {
                             if (DBG_LOC) {
                                 log("notifyCellLocation: cellLocation=" + cellLocation
@@ -1134,7 +1098,6 @@
                 pw.println("  mCellLocation=" + mCellLocation[i]);
                 pw.println("  mCellInfo=" + mCellInfo.get(i));
             }
-            pw.println("  mDefaultSubId=" + mDefaultSubId);
             pw.println("  mDcRtInfo=" + mDcRtInfo);
             pw.println("registrations: count=" + recordCount);
             for (Record r : mRecords) {
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 888fa1a..d480f68 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -1787,7 +1787,7 @@
                         "User is not allowed to add an account!");
             } catch (RemoteException re) {
             }
-            showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED);
+            showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId);
             return;
         }
         if (!canUserModifyAccountsForType(userId, accountType)) {
@@ -1796,7 +1796,8 @@
                         "User cannot modify accounts of this type (policy).");
             } catch (RemoteException re) {
             }
-            showCantAddAccount(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE);
+            showCantAddAccount(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
+                    userId);
             return;
         }
 
@@ -1861,7 +1862,7 @@
                         "User is not allowed to add an account!");
             } catch (RemoteException re) {
             }
-            showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED);
+            showCantAddAccount(AccountManager.ERROR_CODE_USER_RESTRICTED, userId);
             return;
         }
         if (!canUserModifyAccountsForType(userId, accountType)) {
@@ -1870,7 +1871,8 @@
                         "User cannot modify accounts of this type (policy).");
             } catch (RemoteException re) {
             }
-            showCantAddAccount(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE);
+            showCantAddAccount(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
+                    userId);
             return;
         }
 
@@ -1906,13 +1908,13 @@
         }
     }
 
-    private void showCantAddAccount(int errorCode) {
+    private void showCantAddAccount(int errorCode, int userId) {
         Intent cantAddAccount = new Intent(mContext, CantAddAccountActivity.class);
         cantAddAccount.putExtra(CantAddAccountActivity.EXTRA_ERROR_CODE, errorCode);
         cantAddAccount.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         long identityToken = clearCallingIdentity();
         try {
-            mContext.startActivity(cantAddAccount);
+            mContext.startActivityAsUser(cantAddAccount, new UserHandle(userId));
         } finally {
             restoreCallingIdentity(identityToken);
         }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 1f537be..1b49029 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -895,6 +895,11 @@
             while (clist.size() > 0) {
                 ConnectionRecord r = clist.get(0);
                 removeConnectionLocked(r, null, null);
+                if (clist.size() > 0 && clist.get(0) == r) {
+                    // In case it didn't get removed above, do it now.
+                    Slog.wtf(TAG, "Connection " + r + " not removed for binder " + binder);
+                    clist.remove(0);
+                }
 
                 if (r.binding.service.app != null) {
                     // This could have made the service less important.
@@ -2351,7 +2356,7 @@
     void serviceTimeout(ProcessRecord proc) {
         String anrMessage = null;
 
-        synchronized(this) {
+        synchronized(mAm) {
             if (proc.executingServices.size() == 0 || proc.thread == null) {
                 return;
             }
@@ -2647,7 +2652,7 @@
             int opti, boolean dumpAll) {
         ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
 
-        synchronized (this) {
+        synchronized (mAm) {
             int[] users = mAm.getUsersLocked();
             if ("all".equals(name)) {
                 for (int user : users) {
@@ -2721,7 +2726,7 @@
     private void dumpService(String prefix, FileDescriptor fd, PrintWriter pw,
             final ServiceRecord r, String[] args, boolean dumpAll) {
         String innerPrefix = prefix + "  ";
-        synchronized (this) {
+        synchronized (mAm) {
             pw.print(prefix); pw.print("SERVICE ");
                     pw.print(r.shortName); pw.print(" ");
                     pw.print(Integer.toHexString(System.identityHashCode(r)));
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9228fc6..2d6b4a2 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -937,13 +937,6 @@
     private boolean mRunningVoice = false;
 
     /**
-     * Set while the keyguard is waiting for an activity to draw.
-     * In this state, if we are sleeping, we allow Activities to launch
-     * so that they can draw before Keyguard dismisses itself.
-     */
-    private boolean mKeyguardWaitingForDraw = false;
-
-    /**
      * State of external calls telling us if the device is asleep.
      */
     private boolean mWentToSleep = false;
@@ -1993,9 +1986,12 @@
         @Override
         public void onPackageRemoved(String packageName, int uid) {
             // Remove all tasks with activities in the specified package from the list of recent tasks
+            final int eventUserId = getChangingUserId();
             synchronized (ActivityManagerService.this) {
                 for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
                     TaskRecord tr = mRecentTasks.get(i);
+                    if (tr.userId != eventUserId) continue;
+
                     ComponentName cn = tr.intent.getComponent();
                     if (cn != null && cn.getPackageName().equals(packageName)) {
                         // If the package name matches, remove the task and kill the process
@@ -2013,28 +2009,36 @@
 
         @Override
         public void onPackageModified(String packageName) {
+            final int eventUserId = getChangingUserId();
             final PackageManager pm = mContext.getPackageManager();
             final ArrayList<Pair<Intent, Integer>> recentTaskIntents =
                     new ArrayList<Pair<Intent, Integer>>();
+            final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
             final ArrayList<Integer> tasksToRemove = new ArrayList<Integer>();
             // Copy the list of recent tasks so that we don't hold onto the lock on
             // ActivityManagerService for long periods while checking if components exist.
             synchronized (ActivityManagerService.this) {
                 for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
                     TaskRecord tr = mRecentTasks.get(i);
+                    if (tr.userId != eventUserId) continue;
+
                     recentTaskIntents.add(new Pair<Intent, Integer>(tr.intent, tr.taskId));
                 }
             }
             // Check the recent tasks and filter out all tasks with components that no longer exist.
-            Intent tmpI = new Intent();
             for (int i = recentTaskIntents.size() - 1; i >= 0; i--) {
                 Pair<Intent, Integer> p = recentTaskIntents.get(i);
                 ComponentName cn = p.first.getComponent();
                 if (cn != null && cn.getPackageName().equals(packageName)) {
+                    if (componentsKnownToExist.contains(cn)) {
+                        // If we know that the component still exists in the package, then skip
+                        continue;
+                    }
                     try {
-                        // Add the task to the list to remove if the component no longer exists
-                        tmpI.setComponent(cn);
-                        if (pm.queryIntentActivities(tmpI, PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
+                        ActivityInfo info = pm.getActivityInfo(cn, eventUserId);
+                        if (info != null && info.isEnabled()) {
+                            componentsKnownToExist.add(cn);
+                        } else {
                             tasksToRemove.add(p.second);
                         }
                     } catch (Exception e) {}
@@ -2053,11 +2057,12 @@
         @Override
         public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
             // Force stop the specified packages
+            int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
             if (packages != null) {
                 for (String pkg : packages) {
                     synchronized (ActivityManagerService.this) {
-                        if (forceStopPackageLocked(pkg, -1, false, false, false, false, false, 0,
-                                "finished booting")) {
+                        if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
+                                userId, "finished booting")) {
                             return true;
                         }
                     }
@@ -2623,6 +2628,11 @@
     final void removeLruProcessLocked(ProcessRecord app) {
         int lrui = mLruProcesses.lastIndexOf(app);
         if (lrui >= 0) {
+            if (!app.killed) {
+                Slog.wtf(TAG, "Removing process that hasn't been killed: " + app);
+                Process.killProcessQuiet(app.pid);
+                Process.killProcessGroup(app.info.uid, app.pid);
+            }
             if (lrui <= mLruProcessActivityStart) {
                 mLruProcessActivityStart--;
             }
@@ -3206,6 +3216,7 @@
             app.setPid(startResult.pid);
             app.usingWrapper = startResult.usingWrapper;
             app.removed = false;
+            app.killed = false;
             app.killedByAm = false;
             checkTime(startTime, "startProcess: starting to update pids map");
             synchronized (mPidsSelfLocked) {
@@ -4804,15 +4815,16 @@
        appDiedLocked(app, app.pid, app.thread);
     }
 
-    final void appDiedLocked(ProcessRecord app, int pid,
-            IApplicationThread thread) {
+    final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread) {
 
         BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
         synchronized (stats) {
             stats.noteProcessDiedLocked(app.info.uid, pid);
         }
 
+        Process.killProcessQuiet(pid);
         Process.killProcessGroup(app.info.uid, pid);
+        app.killed = true;
 
         // Clean up already done if the process has been re-started.
         if (app.pid == pid && app.thread != null &&
@@ -6249,7 +6261,10 @@
             synchronized (this) {
                 if (DEBUG_LOCKSCREEN) logLockScreen("");
                 mWindowManager.keyguardWaitingForActivityDrawn();
-                mKeyguardWaitingForDraw = true;
+                if (mLockScreenShown) {
+                    mLockScreenShown = false;
+                    comeOutOfSleepIfNeededLocked();
+                }
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -6266,7 +6281,7 @@
         }
 
         // Register receivers to handle package update events
-        mPackageMonitor.register(mContext, Looper.getMainLooper(), false);
+        mPackageMonitor.register(mContext, Looper.getMainLooper(), UserHandle.ALL, false);
 
         // Let system services know.
         mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
@@ -9952,7 +9967,7 @@
     }
 
     public boolean isSleeping() {
-        return mSleeping && !mKeyguardWaitingForDraw;
+        return mSleeping;
     }
 
     void goingToSleep() {
@@ -9973,7 +9988,6 @@
         if (mWentToSleep && !mRunningVoice) {
             if (!mSleeping) {
                 mSleeping = true;
-                mKeyguardWaitingForDraw = false;
                 mStackSupervisor.goingToSleepLocked();
 
                 // Initialize the wake times of all processes.
@@ -10082,7 +10096,6 @@
             try {
                 if (DEBUG_LOCKSCREEN) logLockScreen(" shown=" + shown);
                 mLockScreenShown = shown;
-                mKeyguardWaitingForDraw = false;
                 comeOutOfSleepIfNeededLocked();
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -18964,6 +18977,7 @@
                 }
                 if (tr.getRootActivity() != null) {
                     moveTaskToFrontLocked(tr.taskId, 0, null);
+                    return;
                 }
             }
 
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 0817dd8..7c48f3e 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -100,6 +100,7 @@
     boolean treatLikeActivity;  // Bound using BIND_TREAT_LIKE_ACTIVITY
     boolean bad;                // True if disabled in the bad process list
     boolean killedByAm;         // True when proc has been killed by activity manager, not for RAM
+    boolean killed;             // True once we know the process has been killed
     boolean procStateChanged;   // Keep track of whether we changed 'setAdj'.
     String waitingToKill;       // Process is waiting to be killed when in the bg, and reason
     IBinder forcingToForeground;// Token that is forcing this process to be foreground
@@ -303,8 +304,9 @@
                 pw.print(" lastLowMemory=");
                 TimeUtils.formatDuration(lastLowMemory, now, pw);
                 pw.print(" reportLowMemory="); pw.println(reportLowMemory);
-        if (killedByAm || waitingToKill != null) {
-            pw.print(prefix); pw.print("killedByAm="); pw.print(killedByAm);
+        if (killed || killedByAm || waitingToKill != null) {
+            pw.print(prefix); pw.print("killed="); pw.print(killed);
+                    pw.print(" killedByAm="); pw.print(killedByAm);
                     pw.print(" waitingToKill="); pw.println(waitingToKill);
         }
         if (debugging || crashing || crashDialog != null || notResponding
@@ -514,6 +516,7 @@
             Process.killProcessQuiet(pid);
             Process.killProcessGroup(info.uid, pid);
             if (!persistent) {
+                killed = true;
                 killedByAm = true;
             }
         }
diff --git a/services/core/java/com/android/server/am/ProcessStatsService.java b/services/core/java/com/android/server/am/ProcessStatsService.java
index 7ec14c2..28e46a4 100644
--- a/services/core/java/com/android/server/am/ProcessStatsService.java
+++ b/services/core/java/com/android/server/am/ProcessStatsService.java
@@ -146,7 +146,9 @@
                         final ArrayMap<String, ProcessStats.ServiceState> services = pkg.mServices;
                         for (int isvc=services.size()-1; isvc>=0; isvc--) {
                             final ProcessStats.ServiceState service = services.valueAt(isvc);
-                            if (service.isInUse()) {
+                            if (service.isRestarting()) {
+                                service.setRestarting(true, memFactor, now);
+                            } else if (service.isInUse()) {
                                 if (service.mStartedState != ProcessStats.STATE_NOTHING) {
                                     service.setStarted(true, memFactor, now);
                                 }
@@ -157,7 +159,6 @@
                                     service.setExecuting(true, memFactor, now);
                                 }
                             }
-
                         }
                     }
                 }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 73c9783..4dfd23b 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -783,7 +783,7 @@
     int findEffectiveRootIndex() {
         int effectiveNdx = 0;
         final int topActivityNdx = mActivities.size() - 1;
-        for (int activityNdx = 0; activityNdx < topActivityNdx; ++activityNdx) {
+        for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
             final ActivityRecord r = mActivities.get(activityNdx);
             if (r.finishing) {
                 continue;
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index 096ab66..c382be0 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -89,17 +89,20 @@
      * @param network the NetworkAgentInfo corresponding to the network.
      * @return true if the network requires clat, false otherwise.
      */
-    public boolean requiresClat(NetworkAgentInfo network) {
-        int netType = network.networkInfo.getType();
-        LinkProperties lp = network.linkProperties;
+    public static boolean requiresClat(NetworkAgentInfo nai) {
+        final int netType = nai.networkInfo.getType();
+        final boolean connected = nai.networkInfo.isConnected();
+        final boolean hasIPv4Address =
+                (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false;
+        Slog.d(TAG, "requiresClat: netType=" + netType +
+                    ", connected=" + connected +
+                    ", hasIPv4Address=" + hasIPv4Address);
         // Only support clat on mobile for now.
-        Slog.d(TAG, "requiresClat: netType=" + netType + ", hasIPv4Address=" +
-               lp.hasIPv4Address());
-        return netType == TYPE_MOBILE && !lp.hasIPv4Address();
+        return netType == TYPE_MOBILE && connected && !hasIPv4Address;
     }
 
-    public static boolean isRunningClat(LinkProperties lp) {
-      return lp != null && lp.getAllInterfaceNames().contains(CLAT_INTERFACE_NAME);
+    public boolean isRunningClat(NetworkAgentInfo network) {
+        return mNetworkMessenger == network.messenger;
     }
 
     /**
@@ -149,14 +152,6 @@
         }
     }
 
-    public boolean isStarted() {
-        return mIsStarted;
-    }
-
-    public boolean isRunning() {
-        return mIsRunning;
-    }
-
     private void updateConnectivityService() {
         Message msg = mHandler.obtainMessage(
             NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED, mBaseLP);
@@ -165,6 +160,21 @@
         msg.sendToTarget();
     }
 
+    // Copies the stacked clat link in oldLp, if any, to the LinkProperties in nai.
+    public void fixupLinkProperties(NetworkAgentInfo nai, LinkProperties oldLp) {
+        if (isRunningClat(nai) &&
+                nai.linkProperties != null &&
+                !nai.linkProperties.getAllInterfaceNames().contains(CLAT_INTERFACE_NAME)) {
+            Slog.d(TAG, "clatd running, updating NAI for " + nai.linkProperties.getInterfaceName());
+            for (LinkProperties stacked: oldLp.getStackedLinks()) {
+                if (CLAT_INTERFACE_NAME.equals(stacked.getInterfaceName())) {
+                    nai.linkProperties.addStackedLink(stacked);
+                    break;
+                }
+            }
+        }
+    }
+
     @Override
     public void interfaceAdded(String iface) {
         if (iface.equals(CLAT_INTERFACE_NAME)) {
@@ -175,17 +185,18 @@
             // Create the LinkProperties for the clat interface by fetching the
             // IPv4 address for the interface and adding an IPv4 default route,
             // then stack the LinkProperties on top of the link it's running on.
-            // Although the clat interface is a point-to-point tunnel, we don't
-            // point the route directly at the interface because some apps don't
-            // understand routes without gateways (see, e.g., http://b/9597256
-            // http://b/9597516). Instead, set the next hop of the route to the
-            // clat IPv4 address itself (for those apps, it doesn't matter what
-            // the IP of the gateway is, only that there is one).
             try {
                 InterfaceConfiguration config = mNMService.getInterfaceConfig(iface);
                 LinkAddress clatAddress = config.getLinkAddress();
                 mLP.clear();
                 mLP.setInterfaceName(iface);
+
+                // Although the clat interface is a point-to-point tunnel, we don't
+                // point the route directly at the interface because some apps don't
+                // understand routes without gateways (see, e.g., http://b/9597256
+                // http://b/9597516). Instead, set the next hop of the route to the
+                // clat IPv4 address itself (for those apps, it doesn't matter what
+                // the IP of the gateway is, only that there is one).
                 RouteInfo ipv4Default = new RouteInfo(new LinkAddress(Inet4Address.ANY, 0),
                                                       clatAddress.getAddress(), iface);
                 mLP.addRoute(ipv4Default);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index afc2a39..3f6b71a 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -18,6 +18,8 @@
 
 import static android.Manifest.permission.BIND_VPN_SERVICE;
 import static android.os.UserHandle.PER_USER_RANGE;
+import static android.net.RouteInfo.RTN_THROW;
+import static android.net.RouteInfo.RTN_UNREACHABLE;
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_INET6;
 
@@ -38,6 +40,7 @@
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkManagementEventObserver;
+import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.LocalSocket;
@@ -105,8 +108,6 @@
     private String mPackage;
     private int mOwnerUID;
     private String mInterface;
-    private boolean mAllowIPv4;
-    private boolean mAllowIPv6;
     private Connection mConnection;
     private LegacyVpnRunner mLegacyVpnRunner;
     private PendingIntent mStatusIntent;
@@ -342,33 +343,47 @@
         return mNetworkInfo;
     }
 
-    private void agentConnect() {
+    private LinkProperties makeLinkProperties() {
+        boolean allowIPv4 = mConfig.allowIPv4;
+        boolean allowIPv6 = mConfig.allowIPv6;
+
         LinkProperties lp = new LinkProperties();
+
         lp.setInterfaceName(mInterface);
 
-        boolean hasDefaultRoute = false;
-        for (RouteInfo route : mConfig.routes) {
-            lp.addRoute(route);
-            if (route.isDefaultRoute()) hasDefaultRoute = true;
+        if (mConfig.addresses != null) {
+            for (LinkAddress address : mConfig.addresses) {
+                lp.addLinkAddress(address);
+                allowIPv4 |= address.getAddress() instanceof Inet4Address;
+                allowIPv6 |= address.getAddress() instanceof Inet6Address;
+            }
         }
-        if (hasDefaultRoute) {
-            mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
-        } else {
-            mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+
+        if (mConfig.routes != null) {
+            for (RouteInfo route : mConfig.routes) {
+                lp.addRoute(route);
+                InetAddress address = route.getDestination().getAddress();
+                allowIPv4 |= address instanceof Inet4Address;
+                allowIPv6 |= address instanceof Inet6Address;
+            }
         }
 
         if (mConfig.dnsServers != null) {
             for (String dnsServer : mConfig.dnsServers) {
                 InetAddress address = InetAddress.parseNumericAddress(dnsServer);
                 lp.addDnsServer(address);
-                if (address instanceof Inet4Address) {
-                    mAllowIPv4 = true;
-                } else {
-                    mAllowIPv6 = true;
-                }
+                allowIPv4 |= address instanceof Inet4Address;
+                allowIPv6 |= address instanceof Inet6Address;
             }
         }
 
+        if (!allowIPv4) {
+            lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
+        }
+        if (!allowIPv6) {
+            lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
+        }
+
         // Concatenate search domains into a string.
         StringBuilder buffer = new StringBuilder();
         if (mConfig.searchDomains != null) {
@@ -378,6 +393,20 @@
         }
         lp.setDomains(buffer.toString().trim());
 
+        // TODO: Stop setting the MTU in jniCreate and set it here.
+
+        return lp;
+    }
+
+    private void agentConnect() {
+        LinkProperties lp = makeLinkProperties();
+
+        if (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute()) {
+            mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        } else {
+            mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        }
+
         mNetworkInfo.setIsAvailable(true);
         mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null);
 
@@ -397,13 +426,6 @@
             Binder.restoreCallingIdentity(token);
         }
 
-        if (!mAllowIPv4) {
-            mNetworkAgent.blockAddressFamily(AF_INET);
-        }
-        if (!mAllowIPv6) {
-            mNetworkAgent.blockAddressFamily(AF_INET6);
-        }
-
         addVpnUserLocked(mUserHandle);
         // If we are owner assign all Restricted Users to this VPN
         if (mUserHandle == UserHandle.USER_OWNER) {
@@ -489,8 +511,6 @@
         NetworkAgent oldNetworkAgent = mNetworkAgent;
         mNetworkAgent = null;
         List<UidRange> oldUsers = mVpnUsers;
-        boolean oldAllowIPv4 = mAllowIPv4;
-        boolean oldAllowIPv6 = mAllowIPv6;
 
         // Configure the interface. Abort if any of these steps fails.
         ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
@@ -523,8 +543,6 @@
 
             // Set up forwarding and DNS rules.
             mVpnUsers = new ArrayList<UidRange>();
-            mAllowIPv4 = mConfig.allowIPv4;
-            mAllowIPv6 = mConfig.allowIPv6;
 
             agentConnect();
 
@@ -554,8 +572,6 @@
             mVpnUsers = oldUsers;
             mNetworkAgent = oldNetworkAgent;
             mInterface = oldInterface;
-            mAllowIPv4 = oldAllowIPv4;
-            mAllowIPv6 = oldAllowIPv6;
             throw e;
         }
         Log.i(TAG, "Established by " + config.user + " on " + mInterface);
@@ -778,25 +794,9 @@
             return false;
         }
         boolean success = jniAddAddress(mInterface, address, prefixLength);
-        if (success && (!mAllowIPv4 || !mAllowIPv6)) {
-            try {
-                InetAddress inetAddress = InetAddress.parseNumericAddress(address);
-                if ((inetAddress instanceof Inet4Address) && !mAllowIPv4) {
-                    mAllowIPv4 = true;
-                    mNetworkAgent.unblockAddressFamily(AF_INET);
-                } else if ((inetAddress instanceof Inet6Address) && !mAllowIPv6) {
-                    mAllowIPv6 = true;
-                    mNetworkAgent.unblockAddressFamily(AF_INET6);
-                }
-            } catch (IllegalArgumentException e) {
-                // ignore
-            }
+        if (mNetworkAgent != null) {
+            mNetworkAgent.sendLinkProperties(makeLinkProperties());
         }
-        // Ideally, we'd call mNetworkAgent.sendLinkProperties() here to notify ConnectivityService
-        // that the LinkAddress has changed. But we don't do so for two reasons: (1) We don't set
-        // LinkAddresses on the LinkProperties we establish in the first place (see agentConnect())
-        // and (2) CS doesn't do anything with LinkAddresses anyway (see updateLinkProperties()).
-        // TODO: Maybe fix this.
         return success;
     }
 
@@ -805,11 +805,9 @@
             return false;
         }
         boolean success = jniDelAddress(mInterface, address, prefixLength);
-        // Ideally, we'd call mNetworkAgent.sendLinkProperties() here to notify ConnectivityService
-        // that the LinkAddress has changed. But we don't do so for two reasons: (1) We don't set
-        // LinkAddresses on the LinkProperties we establish in the first place (see agentConnect())
-        // and (2) CS doesn't do anything with LinkAddresses anyway (see updateLinkProperties()).
-        // TODO: Maybe fix this.
+        if (mNetworkAgent != null) {
+            mNetworkAgent.sendLinkProperties(makeLinkProperties());
+        }
         return success;
     }
 
@@ -1220,7 +1218,7 @@
 
                 // Now we are connected. Read and parse the new state.
                 String[] parameters = FileUtils.readTextFile(state, 0, null).split("\n", -1);
-                if (parameters.length != 6) {
+                if (parameters.length != 7) {
                     throw new IllegalStateException("Cannot parse the state");
                 }
 
@@ -1249,6 +1247,23 @@
                     }
                 }
 
+                // Add a throw route for the VPN server endpoint, if one was specified.
+                String endpoint = parameters[5];
+                if (!endpoint.isEmpty()) {
+                    try {
+                        InetAddress addr = InetAddress.parseNumericAddress(endpoint);
+                        if (addr instanceof Inet4Address) {
+                            mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 32), RTN_THROW));
+                        } else if (addr instanceof Inet6Address) {
+                            mConfig.routes.add(new RouteInfo(new IpPrefix(addr, 128), RTN_THROW));
+                        } else {
+                            Log.e(TAG, "Unknown IP address family for VPN endpoint: " + endpoint);
+                        }
+                    } catch (IllegalArgumentException e) {
+                        Log.e(TAG, "Exception constructing throw route to " + endpoint + ": " + e);
+                    }
+                }
+
                 // Here is the last step and it must be done synchronously.
                 synchronized (Vpn.this) {
                     // Set the start time
@@ -1265,8 +1280,6 @@
                     // Now INetworkManagementEventObserver is watching our back.
                     mInterface = mConfig.interfaze;
                     mVpnUsers = new ArrayList<UidRange>();
-                    mAllowIPv4 = mConfig.allowIPv4;
-                    mAllowIPv6 = mConfig.allowIPv6;
 
                     agentConnect();
 
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 16554d3..683212a 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -108,8 +108,12 @@
 
     /**
      * Sets the display state, if supported.
+     *
+     * @return A runnable containing work to be deferred until after we have
+     * exited the critical section, or null if none.
      */
-    public void requestDisplayStateLocked(int state) {
+    public Runnable requestDisplayStateLocked(int state) {
+        return null;
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index e609701..43c01cd 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -63,6 +63,7 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
@@ -214,6 +215,11 @@
     private final DisplayViewport mTempDefaultViewport = new DisplayViewport();
     private final DisplayViewport mTempExternalTouchViewport = new DisplayViewport();
 
+    // Temporary list of deferred work to perform when setting the display state.
+    // Only used by requestDisplayState.  The field is self-synchronized and only
+    // intended for use inside of the requestGlobalDisplayStateInternal function.
+    private final ArrayList<Runnable> mTempDisplayStateWorkQueue = new ArrayList<Runnable>();
+
     public DisplayManagerService(Context context) {
         super(context);
         mContext = context;
@@ -318,11 +324,26 @@
     }
 
     private void requestGlobalDisplayStateInternal(int state) {
-        synchronized (mSyncRoot) {
-            if (mGlobalDisplayState != state) {
-                mGlobalDisplayState = state;
-                updateGlobalDisplayStateLocked();
-                scheduleTraversalLocked(false);
+        synchronized (mTempDisplayStateWorkQueue) {
+            try {
+                // Update the display state within the lock.
+                synchronized (mSyncRoot) {
+                    if (mGlobalDisplayState != state) {
+                        mGlobalDisplayState = state;
+                        updateGlobalDisplayStateLocked(mTempDisplayStateWorkQueue);
+                        scheduleTraversalLocked(false);
+                    }
+                }
+
+                // Setting the display power state can take hundreds of milliseconds
+                // to complete so we defer the most expensive part of the work until
+                // after we have exited the critical section to avoid blocking other
+                // threads for a long time.
+                for (int i = 0; i < mTempDisplayStateWorkQueue.size(); i++) {
+                    mTempDisplayStateWorkQueue.get(i).run();
+                }
+            } finally {
+                mTempDisplayStateWorkQueue.clear();
             }
         }
     }
@@ -669,21 +690,25 @@
         scheduleTraversalLocked(false);
     }
 
-    private void updateGlobalDisplayStateLocked() {
+    private void updateGlobalDisplayStateLocked(List<Runnable> workQueue) {
         final int count = mDisplayDevices.size();
         for (int i = 0; i < count; i++) {
             DisplayDevice device = mDisplayDevices.get(i);
-            updateDisplayStateLocked(device);
+            Runnable runnable = updateDisplayStateLocked(device);
+            if (runnable != null) {
+                workQueue.add(runnable);
+            }
         }
     }
 
-    private void updateDisplayStateLocked(DisplayDevice device) {
+    private Runnable updateDisplayStateLocked(DisplayDevice device) {
         // Blank or unblank the display immediately to match the state requested
         // by the display power controller (if known).
         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
-            device.requestDisplayStateLocked(mGlobalDisplayState);
+            return device.requestDisplayStateLocked(mGlobalDisplayState);
         }
+        return null;
     }
 
     // Adds a new logical display based on the given display device.
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 67d9776..e2a548a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -43,6 +43,7 @@
 import android.util.Spline;
 import android.util.TimeUtils;
 import android.view.Display;
+import android.view.WindowManagerPolicy;
 
 import java.io.PrintWriter;
 
@@ -65,7 +66,7 @@
  * does not need to worry about holding a suspend blocker unless it happens
  * independently of the display ready signal.
    *
- * For debugging, you can make the electron beam and brightness animations run
+ * For debugging, you can make the color fade and brightness animations run
  * slower by changing the "animator duration scale" option in Development Settings.
  */
 final class DisplayPowerController implements AutomaticBrightnessController.Callbacks {
@@ -76,13 +77,12 @@
 
     private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
 
-    // If true, uses the electron beam on animation.
+    // If true, uses the color fade on animation.
     // We might want to turn this off if we cannot get a guarantee that the screen
     // actually turns on and starts showing new content after the call to set the
     // screen state returns.  Playing the animation can also be somewhat slow.
     private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
 
-
     // The minimum reduction in brightness when dimmed.
     private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
 
@@ -91,6 +91,7 @@
 
     private static final int MSG_UPDATE_POWER_STATE = 1;
     private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
+    private static final int MSG_SCREEN_ON_UNBLOCKED = 3;
 
     private static final int PROXIMITY_UNKNOWN = -1;
     private static final int PROXIMITY_NEGATIVE = 0;
@@ -127,6 +128,9 @@
     // The sensor manager.
     private final SensorManager mSensorManager;
 
+    // The window manager policy.
+    private final WindowManagerPolicy mWindowManagerPolicy;
+
     // The display blanker.
     private final DisplayBlanker mBlanker;
 
@@ -152,7 +156,7 @@
     private boolean mUseSoftwareAutoBrightnessConfig;
 
     // True if we should fade the screen while turning it off, false if we should play
-    // a stylish electron beam animation instead.
+    // a stylish color fade animation instead.
     private boolean mColorFadeFadesConfig;
 
     // The pending power request.
@@ -214,8 +218,14 @@
     // When the screen turns on again, we report user activity to the power manager.
     private boolean mScreenOffBecauseOfProximity;
 
-    // True if the screen on is being blocked.
-    private boolean mScreenOnWasBlocked;
+    // The currently active screen on unblocker.  This field is non-null whenever
+    // we are waiting for a callback to release it and unblock the screen.
+    private ScreenOnUnblocker mPendingScreenOnUnblocker;
+
+    // True if we were in the process of turning off the screen.
+    // This allows us to recover more gracefully from situations where we abort
+    // turning off the screen.
+    private boolean mPendingScreenOff;
 
     // The elapsed real time when the screen on was blocked.
     private long mScreenOnBlockStartRealTime;
@@ -246,6 +256,7 @@
         mBatteryStats = BatteryStatsService.getService();
         mLights = LocalServices.getService(LightsManager.class);
         mSensorManager = sensorManager;
+        mWindowManagerPolicy = LocalServices.getService(WindowManagerPolicy.class);
         mBlanker = blanker;
         mContext = context;
 
@@ -633,7 +644,7 @@
 
         // Report whether the display is ready for use and all changes have been applied.
         if (mustNotify
-                && !mScreenOnWasBlocked
+                && mPendingScreenOnUnblocker == null
                 && !mColorFadeOnAnimator.isStarted()
                 && !mColorFadeOffAnimator.isStarted()
                 && !mScreenBrightnessRampAnimator.isAnimating()
@@ -657,32 +668,53 @@
     }
 
     private void blockScreenOn() {
-        if (!mScreenOnWasBlocked) {
+        if (mPendingScreenOnUnblocker == null) {
             Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
-            mScreenOnWasBlocked = true;
+            mPendingScreenOnUnblocker = new ScreenOnUnblocker();
             mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
             Slog.i(TAG, "Blocking screen on until initial contents have been drawn.");
         }
     }
 
     private void unblockScreenOn() {
-        if (mScreenOnWasBlocked) {
-            mScreenOnWasBlocked = false;
+        if (mPendingScreenOnUnblocker != null) {
+            mPendingScreenOnUnblocker = null;
             long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
             Slog.i(TAG, "Unblocked screen on after " + delay + " ms");
             Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, SCREEN_ON_BLOCKED_TRACE_NAME, 0);
         }
     }
 
-    private void setScreenState(int state) {
+    private boolean setScreenState(int state) {
         if (mPowerState.getScreenState() != state) {
+            final boolean wasOn = (mPowerState.getScreenState() != Display.STATE_OFF);
             mPowerState.setScreenState(state);
+
+            // Tell battery stats about the transition.
             try {
                 mBatteryStats.noteScreenState(state);
             } catch (RemoteException ex) {
                 // same process
             }
+
+            // Tell the window manager what's happening.
+            // Temporarily block turning the screen on until the window manager is ready
+            // by leaving a black surface covering the screen.  This surface is essentially
+            // the final state of the color fade animation.
+            boolean isOn = (state != Display.STATE_OFF);
+            if (wasOn && !isOn) {
+                unblockScreenOn();
+                mWindowManagerPolicy.screenTurnedOff();
+            } else if (!wasOn && isOn) {
+                if (mPowerState.getColorFadeLevel() == 0.0f) {
+                    blockScreenOn();
+                } else {
+                    unblockScreenOn();
+                }
+                mWindowManagerPolicy.screenTurningOn(mPendingScreenOnUnblocker);
+            }
         }
+        return mPendingScreenOnUnblocker == null;
     }
 
     private int clampScreenBrightness(int value) {
@@ -707,21 +739,21 @@
             return;
         }
 
-        // Temporarily block turning the screen on if requested and there is already a
-        // black surface covering the screen.
-        if (mPowerRequest.blockScreenOn
-                && mPowerState.getColorFadeLevel() == 0.0f
-                && target != Display.STATE_OFF) {
-            blockScreenOn();
-            return;
+        // If we were in the process of turning off the screen but didn't quite
+        // finish.  Then finish up now to prevent a jarring transition back
+        // to screen on if we skipped blocking screen on as usual.
+        if (mPendingScreenOff && target != Display.STATE_OFF) {
+            setScreenState(Display.STATE_OFF);
+            mPendingScreenOff = false;
         }
 
         if (target == Display.STATE_ON) {
             // Want screen on.  The contents of the screen may not yet
-            // be visible if the electron beam has not been dismissed because
+            // be visible if the color fade has not been dismissed because
             // its last frame of animation is solid black.
-            unblockScreenOn();
-            setScreenState(Display.STATE_ON);
+            if (!setScreenState(Display.STATE_ON)) {
+                return; // screen on blocked
+            }
             if (USE_COLOR_FADE_ON_ANIMATION && mPowerRequest.isBrightOrDim()) {
                 // Perform screen on animation.
                 if (mPowerState.getColorFadeLevel() == 1.0f) {
@@ -749,9 +781,12 @@
                 return;
             }
 
-            // Set screen state and dismiss the black surface without fanfare.
-            unblockScreenOn();
-            setScreenState(Display.STATE_DOZE);
+            // Set screen state.
+            if (!setScreenState(Display.STATE_DOZE)) {
+                return; // screen on blocked
+            }
+
+            // Dismiss the black surface without fanfare.
             mPowerState.setColorFadeLevel(1.0f);
             mPowerState.dismissColorFade();
         } else if (target == Display.STATE_DOZE_SUSPEND) {
@@ -763,18 +798,26 @@
                 return;
             }
 
-            // Set screen state and dismiss the black surface without fanfare.
-            unblockScreenOn();
-            setScreenState(Display.STATE_DOZE_SUSPEND);
+            // If not already suspending, temporarily set the state to doze until the
+            // screen on is unblocked, then suspend.
+            if (mPowerState.getScreenState() != Display.STATE_DOZE_SUSPEND) {
+                if (!setScreenState(Display.STATE_DOZE)) {
+                    return; // screen on blocked
+                }
+                setScreenState(Display.STATE_DOZE_SUSPEND); // already on so can't block
+            }
+
+            // Dismiss the black surface without fanfare.
             mPowerState.setColorFadeLevel(1.0f);
             mPowerState.dismissColorFade();
         } else {
             // Want screen off.
-            unblockScreenOn();
+            mPendingScreenOff = true;
             if (mPowerState.getColorFadeLevel() == 0.0f) {
                 // Turn the screen off.
                 // A black surface is already hiding the contents of the screen.
                 setScreenState(Display.STATE_OFF);
+                mPendingScreenOff = false;
             } else if (performScreenOffTransition
                     && mPowerState.prepareColorFade(mContext,
                             mColorFadeFadesConfig ?
@@ -968,6 +1011,8 @@
         pw.println("  mAppliedAutoBrightness=" + mAppliedAutoBrightness);
         pw.println("  mAppliedDimming=" + mAppliedDimming);
         pw.println("  mAppliedLowPower=" + mAppliedLowPower);
+        pw.println("  mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
+        pw.println("  mPendingScreenOff=" + mPendingScreenOff);
 
         pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
                 mScreenBrightnessRampAnimator.isAnimating());
@@ -1052,6 +1097,13 @@
                 case MSG_PROXIMITY_SENSOR_DEBOUNCED:
                     debounceProximitySensor();
                     break;
+
+                case MSG_SCREEN_ON_UNBLOCKED:
+                    if (mPendingScreenOnUnblocker == msg.obj) {
+                        unblockScreenOn();
+                        updatePowerState();
+                    }
+                    break;
             }
         }
     }
@@ -1072,4 +1124,13 @@
             // Not used.
         }
     };
+
+    private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
+        @Override
+        public void onScreenOn() {
+            Message msg = mHandler.obtainMessage(MSG_SCREEN_ON_UNBLOCKED, this);
+            msg.setAsynchronous(true);
+            mHandler.sendMessage(msg);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 9c91ab5..24cf423 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -222,19 +222,31 @@
         }
 
         @Override
-        public void requestDisplayStateLocked(int state) {
+        public Runnable requestDisplayStateLocked(final int state) {
             if (mState != state) {
+                final int displayId = mBuiltInDisplayId;
+                final IBinder token = getDisplayTokenLocked();
                 final int mode = getPowerModeForState(state);
-                Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestDisplayState("
-                        + Display.stateToString(state) + ", id=" + mBuiltInDisplayId + ")");
-                try {
-                    SurfaceControl.setDisplayPowerMode(getDisplayTokenLocked(), mode);
-                } finally {
-                    Trace.traceEnd(Trace.TRACE_TAG_POWER);
-                }
                 mState = state;
                 updateDeviceInfoLocked();
+
+                // Defer actually setting the display power mode until we have exited
+                // the critical section since it can take hundreds of milliseconds
+                // to complete.
+                return new Runnable() {
+                    @Override
+                    public void run() {
+                        Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestDisplayState("
+                                + Display.stateToString(state) + ", id=" + displayId + ")");
+                        try {
+                            SurfaceControl.setDisplayPowerMode(token, mode);
+                        } finally {
+                            Trace.traceEnd(Trace.TRACE_TAG_POWER);
+                        }
+                    }
+                };
             }
+            return null;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index a6a9a89..c2b4478 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -188,7 +188,7 @@
         }
 
         @Override
-        public void requestDisplayStateLocked(int state) {
+        public Runnable requestDisplayStateLocked(int state) {
             if (state != mDisplayState) {
                 mDisplayState = state;
                 if (state == Display.STATE_OFF) {
@@ -197,6 +197,7 @@
                     mCallback.dispatchDisplayResumed();
                 }
             }
+            return null;
         }
 
         @Override
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index 9d008b9..a17d731 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -16,18 +16,13 @@
 
 package com.android.server.display;
 
-import com.android.internal.R;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.res.Resources;
 import android.hardware.display.DisplayManager;
 import android.hardware.display.WifiDisplay;
 import android.hardware.display.WifiDisplaySessionInfo;
@@ -38,7 +33,6 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.util.Slog;
 import android.view.Display;
 import android.view.Surface;
@@ -71,17 +65,12 @@
     private static final boolean DEBUG = false;
 
     private static final int MSG_SEND_STATUS_CHANGE_BROADCAST = 1;
-    private static final int MSG_UPDATE_NOTIFICATION = 2;
 
     private static final String ACTION_DISCONNECT = "android.server.display.wfd.DISCONNECT";
 
     private final WifiDisplayHandler mHandler;
     private final PersistentDataStore mPersistentDataStore;
     private final boolean mSupportsProtectedBuffers;
-    private final NotificationManager mNotificationManager;
-
-    private PendingIntent mSettingsPendingIntent;
-    private PendingIntent mDisconnectPendingIntent;
 
     private WifiDisplayController mDisplayController;
     private WifiDisplayDevice mDisplayDevice;
@@ -97,7 +86,6 @@
     private WifiDisplaySessionInfo mSessionInfo;
 
     private boolean mPendingStatusChangeBroadcast;
-    private boolean mPendingNotificationUpdate;
 
     // Called with SyncRoot lock held.
     public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
@@ -108,8 +96,6 @@
         mPersistentDataStore = persistentDataStore;
         mSupportsProtectedBuffers = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
-        mNotificationManager = (NotificationManager)context.getSystemService(
-                Context.NOTIFICATION_SERVICE);
     }
 
     @Override
@@ -125,7 +111,6 @@
         pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
         pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
         pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
-        pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate);
         pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers);
 
         // Try to dump the controller state.
@@ -421,13 +406,6 @@
         }
     }
 
-    private void scheduleUpdateNotificationLocked() {
-        if (!mPendingNotificationUpdate) {
-            mPendingNotificationUpdate = true;
-            mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATION);
-        }
-    }
-
     // Runs on the handler.
     private void handleSendStatusChangeBroadcast() {
         final Intent intent;
@@ -447,87 +425,6 @@
         getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
-    // Runs on the handler.
-    private void handleUpdateNotification() {
-        final int state;
-        final WifiDisplay display;
-        synchronized (getSyncRoot()) {
-            if (!mPendingNotificationUpdate) {
-                return;
-            }
-
-            mPendingNotificationUpdate = false;
-            state = mActiveDisplayState;
-            display = mActiveDisplay;
-        }
-
-        // Cancel the old notification if there is one.
-        mNotificationManager.cancelAsUser(null,
-                R.string.wifi_display_notification_disconnect, UserHandle.ALL);
-
-        if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING
-                || state == WifiDisplayStatus.DISPLAY_STATE_CONNECTED) {
-            Context context = getContext();
-
-            // Initialize pending intents for the notification outside of the lock because
-            // creating a pending intent requires a call into the activity manager.
-            if (mSettingsPendingIntent == null) {
-                Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
-                settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
-                        | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-                mSettingsPendingIntent = PendingIntent.getActivityAsUser(
-                        context, 0, settingsIntent, 0, null, UserHandle.CURRENT);
-            }
-
-            if (mDisconnectPendingIntent == null) {
-                Intent disconnectIntent = new Intent(ACTION_DISCONNECT);
-                mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser(
-                        context, 0, disconnectIntent, 0, UserHandle.CURRENT);
-            }
-
-            // Post the notification.
-            Resources r = context.getResources();
-            Notification notification;
-            if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING) {
-                notification = new Notification.Builder(context)
-                        .setContentTitle(r.getString(
-                                R.string.wifi_display_notification_connecting_title))
-                        .setContentText(r.getString(
-                                R.string.wifi_display_notification_connecting_message,
-                                display.getFriendlyDisplayName()))
-                        .setContentIntent(mSettingsPendingIntent)
-                        .setSmallIcon(R.drawable.ic_notification_cast_connecting)
-                        .setOngoing(true)
-                        .addAction(android.R.drawable.ic_menu_close_clear_cancel,
-                                r.getString(R.string.wifi_display_notification_disconnect),
-                                mDisconnectPendingIntent)
-                        .setColor(r.getColor(
-                                com.android.internal.R.color.system_notification_accent_color))
-                        .build();
-            } else {
-                notification = new Notification.Builder(context)
-                        .setContentTitle(r.getString(
-                                R.string.wifi_display_notification_connected_title))
-                        .setContentText(r.getString(
-                                R.string.wifi_display_notification_connected_message,
-                                display.getFriendlyDisplayName()))
-                        .setContentIntent(mSettingsPendingIntent)
-                        .setSmallIcon(R.drawable.ic_notification_cast_on)
-                        .setOngoing(true)
-                        .addAction(android.R.drawable.ic_menu_close_clear_cancel,
-                                r.getString(R.string.wifi_display_notification_disconnect),
-                                mDisconnectPendingIntent)
-                        .setColor(r.getColor(
-                                com.android.internal.R.color.system_notification_accent_color))
-                        .build();
-            }
-            mNotificationManager.notifyAsUser(null,
-                    R.string.wifi_display_notification_disconnect,
-                    notification, UserHandle.ALL);
-        }
-    }
-
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -605,7 +502,6 @@
                     mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING;
                     mActiveDisplay = display;
                     scheduleStatusChangedBroadcastLocked();
-                    scheduleUpdateNotificationLocked();
                 }
             }
         }
@@ -618,7 +514,6 @@
                     mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
                     mActiveDisplay = null;
                     scheduleStatusChangedBroadcastLocked();
-                    scheduleUpdateNotificationLocked();
                 }
             }
         }
@@ -636,7 +531,6 @@
                     mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED;
                     mActiveDisplay = display;
                     scheduleStatusChangedBroadcastLocked();
-                    scheduleUpdateNotificationLocked();
                 }
             }
         }
@@ -659,7 +553,6 @@
                     mActiveDisplay = display;
                     renameDisplayDeviceLocked(display.getFriendlyDisplayName());
                     scheduleStatusChangedBroadcastLocked();
-                    scheduleUpdateNotificationLocked();
                 }
             }
         }
@@ -675,7 +568,6 @@
                     mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
                     mActiveDisplay = null;
                     scheduleStatusChangedBroadcastLocked();
-                    scheduleUpdateNotificationLocked();
                 }
             }
         }
@@ -755,10 +647,6 @@
                 case MSG_SEND_STATUS_CHANGE_BROADCAST:
                     handleSendStatusChangeBroadcast();
                     break;
-
-                case MSG_UPDATE_NOTIFICATION:
-                    handleUpdateNotification();
-                    break;
             }
         }
     }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 30154d7..f456bcd 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -195,12 +195,13 @@
     }
 
     private void cancelJobsForUser(int userHandle) {
+        List<JobStatus> jobsForUser;
         synchronized (mJobs) {
-            List<JobStatus> jobsForUser = mJobs.getJobsByUser(userHandle);
-            for (int i=0; i<jobsForUser.size(); i++) {
-                JobStatus toRemove = jobsForUser.get(i);
-                cancelJobLocked(toRemove);
-            }
+            jobsForUser = mJobs.getJobsByUser(userHandle);
+        }
+        for (int i=0; i<jobsForUser.size(); i++) {
+            JobStatus toRemove = jobsForUser.get(i);
+            cancelJobImpl(toRemove);
         }
     }
 
@@ -208,16 +209,16 @@
      * Entry point from client to cancel all jobs originating from their uid.
      * This will remove the job from the master list, and cancel the job if it was staged for
      * execution or being executed.
-     * @param uid To check against for removal of a job.
+     * @param uid Uid to check against for removal of a job.
      */
     public void cancelJobsForUid(int uid) {
-        // Remove from master list.
+        List<JobStatus> jobsForUid;
         synchronized (mJobs) {
-            List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
-            for (int i=0; i<jobsForUid.size(); i++) {
-                JobStatus toRemove = jobsForUid.get(i);
-                cancelJobLocked(toRemove);
-            }
+            jobsForUid = mJobs.getJobsByUid(uid);
+        }
+        for (int i=0; i<jobsForUid.size(); i++) {
+            JobStatus toRemove = jobsForUid.get(i);
+            cancelJobImpl(toRemove);
         }
     }
 
@@ -232,22 +233,23 @@
         JobStatus toCancel;
         synchronized (mJobs) {
             toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
-            if (toCancel != null) {
-                cancelJobLocked(toCancel);
-            }
+        }
+        if (toCancel != null) {
+            cancelJobImpl(toCancel);
         }
     }
 
-    private void cancelJobLocked(JobStatus cancelled) {
+    private void cancelJobImpl(JobStatus cancelled) {
         if (DEBUG) {
             Slog.d(TAG, "Cancelling: " + cancelled);
         }
-        // Remove from store.
         stopTrackingJob(cancelled);
-        // Remove from pending queue.
-        mPendingJobs.remove(cancelled);
-        // Cancel if running.
-        stopJobOnServiceContextLocked(cancelled);
+        synchronized (mJobs) {
+            // Remove from pending queue.
+            mPendingJobs.remove(cancelled);
+            // Cancel if running.
+            stopJobOnServiceContextLocked(cancelled);
+        }
     }
 
     /**
@@ -482,21 +484,13 @@
     // StateChangedListener implementations.
 
     /**
-     * Off-board work to our handler thread as quickly as possible, b/c this call is probably being
-     * made on the main thread.
-     * For now this takes the job and if it's ready to run it will run it. In future we might not
-     * provide the job, so that the StateChangedListener has to run through its list of jobs to
-     * see which are ready. This will further decouple the controllers from the execution logic.
+     * Posts a message to the {@link com.android.server.job.JobSchedulerService.JobHandler} that
+     * some controller's state has changed, so as to run through the list of jobs and start/stop
+     * any that are eligible.
      */
     @Override
     public void onControllerStateChanged() {
-        synchronized (mJobs) {
-            if (mReadyToRock) {
-                // Post a message to to run through the list of jobs and start/stop any that
-                // are eligible.
-                mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
-            }
-        }
+        mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
     }
 
     @Override
@@ -512,21 +506,29 @@
 
         @Override
         public void handleMessage(Message message) {
+            synchronized (mJobs) {
+                if (!mReadyToRock) {
+                    return;
+                }
+            }
             switch (message.what) {
                 case MSG_JOB_EXPIRED:
                     synchronized (mJobs) {
                         JobStatus runNow = (JobStatus) message.obj;
                         // runNow can be null, which is a controller's way of indicating that its
                         // state is such that all ready jobs should be run immediately.
-                        if (runNow != null && !mPendingJobs.contains(runNow)) {
+                        if (runNow != null && !mPendingJobs.contains(runNow)
+                                && mJobs.containsJob(runNow)) {
                             mPendingJobs.add(runNow);
                         }
+                        queueReadyJobsForExecutionLockedH();
                     }
-                    queueReadyJobsForExecutionH();
                     break;
                 case MSG_CHECK_JOB:
-                    // Check the list of jobs and run some of them if we feel inclined.
-                    maybeQueueReadyJobsForExecutionH();
+                    synchronized (mJobs) {
+                        // Check the list of jobs and run some of them if we feel inclined.
+                        maybeQueueReadyJobsForExecutionLockedH();
+                    }
                     break;
             }
             maybeRunPendingJobsH();
@@ -538,30 +540,28 @@
          * Run through list of jobs and execute all possible - at least one is expired so we do
          * as many as we can.
          */
-        private void queueReadyJobsForExecutionH() {
-            synchronized (mJobs) {
-                ArraySet<JobStatus> jobs = mJobs.getJobs();
-                if (DEBUG) {
-                    Slog.d(TAG, "queuing all ready jobs for execution:");
-                }
-                for (int i=0; i<jobs.size(); i++) {
-                    JobStatus job = jobs.valueAt(i);
-                    if (isReadyToBeExecutedLocked(job)) {
-                        if (DEBUG) {
-                            Slog.d(TAG, "    queued " + job.toShortString());
-                        }
-                        mPendingJobs.add(job);
-                    } else if (isReadyToBeCancelledLocked(job)) {
-                        stopJobOnServiceContextLocked(job);
+        private void queueReadyJobsForExecutionLockedH() {
+            ArraySet<JobStatus> jobs = mJobs.getJobs();
+            if (DEBUG) {
+                Slog.d(TAG, "queuing all ready jobs for execution:");
+            }
+            for (int i=0; i<jobs.size(); i++) {
+                JobStatus job = jobs.valueAt(i);
+                if (isReadyToBeExecutedLocked(job)) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "    queued " + job.toShortString());
                     }
+                    mPendingJobs.add(job);
+                } else if (isReadyToBeCancelledLocked(job)) {
+                    stopJobOnServiceContextLocked(job);
                 }
-                if (DEBUG) {
-                    final int queuedJobs = mPendingJobs.size();
-                    if (queuedJobs == 0) {
-                        Slog.d(TAG, "No jobs pending.");
-                    } else {
-                        Slog.d(TAG, queuedJobs + " jobs queued.");
-                    }
+            }
+            if (DEBUG) {
+                final int queuedJobs = mPendingJobs.size();
+                if (queuedJobs == 0) {
+                    Slog.d(TAG, "No jobs pending.");
+                } else {
+                    Slog.d(TAG, queuedJobs + " jobs queued.");
                 }
             }
         }
@@ -575,55 +575,53 @@
          * If more than 4 jobs total are ready we send them all off.
          * TODO: It would be nice to consolidate these sort of high-level policies somewhere.
          */
-        private void maybeQueueReadyJobsForExecutionH() {
-            synchronized (mJobs) {
-                int chargingCount = 0;
-                int idleCount =  0;
-                int backoffCount = 0;
-                int connectivityCount = 0;
-                List<JobStatus> runnableJobs = new ArrayList<JobStatus>();
-                ArraySet<JobStatus> jobs = mJobs.getJobs();
-                for (int i=0; i<jobs.size(); i++) {
-                    JobStatus job = jobs.valueAt(i);
-                    if (isReadyToBeExecutedLocked(job)) {
-                        if (job.getNumFailures() > 0) {
-                            backoffCount++;
-                        }
-                        if (job.hasIdleConstraint()) {
-                            idleCount++;
-                        }
-                        if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()) {
-                            connectivityCount++;
-                        }
-                        if (job.hasChargingConstraint()) {
-                            chargingCount++;
-                        }
-                        runnableJobs.add(job);
-                    } else if (isReadyToBeCancelledLocked(job)) {
-                        stopJobOnServiceContextLocked(job);
+        private void maybeQueueReadyJobsForExecutionLockedH() {
+            int chargingCount = 0;
+            int idleCount =  0;
+            int backoffCount = 0;
+            int connectivityCount = 0;
+            List<JobStatus> runnableJobs = new ArrayList<JobStatus>();
+            ArraySet<JobStatus> jobs = mJobs.getJobs();
+            for (int i=0; i<jobs.size(); i++) {
+                JobStatus job = jobs.valueAt(i);
+                if (isReadyToBeExecutedLocked(job)) {
+                    if (job.getNumFailures() > 0) {
+                        backoffCount++;
                     }
+                    if (job.hasIdleConstraint()) {
+                        idleCount++;
+                    }
+                    if (job.hasConnectivityConstraint() || job.hasUnmeteredConstraint()) {
+                        connectivityCount++;
+                    }
+                    if (job.hasChargingConstraint()) {
+                        chargingCount++;
+                    }
+                    runnableJobs.add(job);
+                } else if (isReadyToBeCancelledLocked(job)) {
+                    stopJobOnServiceContextLocked(job);
                 }
-                if (backoffCount > 0 ||
-                        idleCount >= MIN_IDLE_COUNT ||
-                        connectivityCount >= MIN_CONNECTIVITY_COUNT ||
-                        chargingCount >= MIN_CHARGING_COUNT ||
-                        runnableJobs.size() >= MIN_READY_JOBS_COUNT) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "maybeQueueReadyJobsForExecutionH: Running jobs.");
-                    }
-                    for (int i=0; i<runnableJobs.size(); i++) {
-                        mPendingJobs.add(runnableJobs.get(i));
-                    }
-                } else {
-                    if (DEBUG) {
-                        Slog.d(TAG, "maybeQueueReadyJobsForExecutionH: Not running anything.");
-                    }
-                }
+            }
+            if (backoffCount > 0 ||
+                    idleCount >= MIN_IDLE_COUNT ||
+                    connectivityCount >= MIN_CONNECTIVITY_COUNT ||
+                    chargingCount >= MIN_CHARGING_COUNT ||
+                    runnableJobs.size() >= MIN_READY_JOBS_COUNT) {
                 if (DEBUG) {
-                    Slog.d(TAG, "idle=" + idleCount + " connectivity=" +
-                    connectivityCount + " charging=" + chargingCount + " tot=" +
-                            runnableJobs.size());
+                    Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Running jobs.");
                 }
+                for (int i=0; i<runnableJobs.size(); i++) {
+                    mPendingJobs.add(runnableJobs.get(i));
+                }
+            } else {
+                if (DEBUG) {
+                    Slog.d(TAG, "maybeQueueReadyJobsForExecutionLockedH: Not running anything.");
+                }
+            }
+            if (DEBUG) {
+                Slog.d(TAG, "idle=" + idleCount + " connectivity=" +
+                connectivityCount + " charging=" + chargingCount + " tot=" +
+                        runnableJobs.size());
             }
         }
 
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index df12e1a..b64c677 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -50,15 +50,9 @@
 import org.xmlpull.v1.XmlSerializer;
 
 /**
- * Maintain a list of classes, and accessor methods/logic for these jobs.
- * This class offers the following functionality:
- *     - When a job is added, it will determine if the job requirements have changed (update) and
- *       whether the controllers need to be updated.
- *     - Persists JobInfos, figures out when to to rewrite the JobInfo to disk.
- *     - Handles rescheduling of jobs.
- *       - When a periodic job is executed and must be re-added.
- *       - When a job fails and the client requests that it be retried with backoff.
- *       - This class <strong>is not</strong> thread-safe.
+ * Maintains the master list of jobs that the job scheduler is tracking. These jobs are compared by
+ * reference, so none of the functions in this class should make a copy.
+ * Also handles read/write of persisted jobs.
  *
  * Note on locking:
  *      All callers to this class must <strong>lock on the class object they are calling</strong>.
@@ -152,6 +146,10 @@
         return false;
     }
 
+    boolean containsJob(JobStatus jobStatus) {
+        return mJobSet.contains(jobStatus);
+    }
+
     public int size() {
         return mJobSet.size();
     }
@@ -180,6 +178,10 @@
         maybeWriteStatusToDiskAsync();
     }
 
+    /**
+     * @param userHandle User for whom we are querying the list of jobs.
+     * @return A list of all the jobs scheduled by the provided user. Never null.
+     */
     public List<JobStatus> getJobsByUser(int userHandle) {
         List<JobStatus> matchingJobs = new ArrayList<JobStatus>();
         Iterator<JobStatus> it = mJobSet.iterator();
@@ -194,7 +196,7 @@
 
     /**
      * @param uid Uid of the requesting app.
-     * @return All JobStatus objects for a given uid from the master list.
+     * @return All JobStatus objects for a given uid from the master list. Never null.
      */
     public List<JobStatus> getJobsByUid(int uid) {
         List<JobStatus> matchingJobs = new ArrayList<JobStatus>();
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index f1c5a6c..0198e46 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -25,6 +25,7 @@
 import com.android.internal.R;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
 
 import android.app.AlarmManager;
 import android.app.AppOpsManager;
@@ -227,6 +228,11 @@
     private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
     private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
 
+    // TCP/IP constants.
+    // Valid TCP/UDP port range is (0, 65535].
+    private static final int TCP_MIN_PORT = 0;
+    private static final int TCP_MAX_PORT = 0xffff;
+
     // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
     private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
     // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
@@ -332,7 +338,7 @@
     // properties loaded from PROPERTIES_FILE
     private Properties mProperties;
     private String mSuplServerHost;
-    private int mSuplServerPort;
+    private int mSuplServerPort = TCP_MIN_PORT;
     private String mC2KServerHost;
     private int mC2KServerPort;
     private boolean mSuplEsEnabled = false;
@@ -487,7 +493,10 @@
                     || Intent.ACTION_SCREEN_OFF.equals(action)
                     || Intent.ACTION_SCREEN_ON.equals(action)) {
                 updateLowPowerMode();
-            } else if (action.equals(SIM_STATE_CHANGED)) {
+            } else if (action.equals(SIM_STATE_CHANGED)
+                    || action.equals(TelephonyIntents.ACTION_SUBINFO_CONTENT_CHANGE)
+                    || action.equals(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED)) {
+                Log.d(TAG, "received SIM realted action: " + action);
                 TelephonyManager phone = (TelephonyManager)
                         mContext.getSystemService(Context.TELEPHONY_SERVICE);
                 String mccMnc = phone.getSimOperator();
@@ -497,6 +506,8 @@
                         reloadGpsProperties(context, mProperties);
                         mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
                     }
+                } else {
+                    Log.d(TAG, "SIM MCC/MNC is still not available");
                 }
             }
         }
@@ -709,6 +720,10 @@
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
         intentFilter.addAction(SIM_STATE_CHANGED);
+        // TODO: remove the use TelephonyIntents. We are using it because SIM_STATE_CHANGED
+        // is not reliable at the moment.
+        intentFilter.addAction(TelephonyIntents.ACTION_SUBINFO_CONTENT_CHANGE);
+        intentFilter.addAction(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED);
         mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
     }
 
@@ -921,6 +936,11 @@
                 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
             }
         }
+        if (mSuplServerHost != null
+                && mSuplServerPort > TCP_MIN_PORT
+                && mSuplServerPort <= TCP_MAX_PORT) {
+            native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
+        }
     }
 
     /**
@@ -963,6 +983,8 @@
 
         if (enabled) {
             mSupportsXtra = native_supports_xtra();
+
+            // TODO: remove the following native calls if we can make sure they are redundant.
             if (mSuplServerHost != null) {
                 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
             }
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 8a1f3ad..cdfb656 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.hardware.display.DisplayManager;
+import android.media.MediaRouter;
 import android.media.projection.IMediaProjectionManager;
 import android.media.projection.IMediaProjection;
 import android.media.projection.IMediaProjectionCallback;
@@ -68,6 +69,10 @@
     private final Context mContext;
     private final AppOpsManager mAppOps;
 
+    private final MediaRouter mMediaRouter;
+    private final MediaRouterCallback mMediaRouterCallback;
+    private MediaRouter.RouteInfo mMediaRouteInfo;
+
     private IBinder mProjectionToken;
     private MediaProjection mProjectionGrant;
 
@@ -77,6 +82,8 @@
         mDeathEaters = new ArrayMap<IBinder, IBinder.DeathRecipient>();
         mCallbackDelegate = new CallbackDelegate();
         mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+        mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
+        mMediaRouterCallback = new MediaRouterCallback();
         Watchdog.getInstance().addMonitor(this);
     }
 
@@ -84,6 +91,12 @@
     public void onStart() {
         publishBinderService(Context.MEDIA_PROJECTION_SERVICE, new BinderService(),
                 false /*allowIsolated*/);
+        mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY, mMediaRouterCallback);
+    }
+
+    @Override
+    public void onSwitchUser(int userId) {
+        mMediaRouter.rebindAsUser(userId);
     }
 
     @Override
@@ -95,6 +108,9 @@
         if (mProjectionGrant != null) {
             mProjectionGrant.stop();
         }
+        if (mMediaRouteInfo != null) {
+            mMediaRouter.getDefaultRoute().select();
+        }
         mProjectionToken = projection.asBinder();
         mProjectionGrant = projection;
         dispatchStart(projection);
@@ -448,6 +464,27 @@
         }
     }
 
+    private class MediaRouterCallback extends MediaRouter.SimpleCallback {
+        @Override
+        public void onRouteSelected(MediaRouter router, int type, MediaRouter.RouteInfo info) {
+            synchronized (mLock) {
+                if ((type & MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY) != 0) {
+                    mMediaRouteInfo = info;
+                    if (mProjectionGrant != null) {
+                        mProjectionGrant.stop();
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void onRouteUnselected(MediaRouter route, int type, MediaRouter.RouteInfo info) {
+            if (mMediaRouteInfo == info) {
+                mMediaRouteInfo = null;
+            }
+        }
+    }
+
 
     private static class CallbackDelegate {
         private Map<IBinder, IMediaProjectionCallback> mClientCallbacks;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 479af89..5038d03 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -182,6 +182,12 @@
                 }
                 return shouldInterceptAudience(record);
             }
+            if (isEvent(record)) {
+                if (!mConfig.allowEvents) {
+                    ZenLog.traceIntercepted(record, "!allowEvents");
+                    return true;
+                }
+            }
             ZenLog.traceIntercepted(record, "!allowed");
             return true;
         }
@@ -328,17 +334,20 @@
         }
     }
 
-    private boolean isSystem(NotificationRecord record) {
+    private static boolean isSystem(NotificationRecord record) {
         return record.isCategory(Notification.CATEGORY_SYSTEM);
     }
 
-    private boolean isAlarm(NotificationRecord record) {
+    private static boolean isAlarm(NotificationRecord record) {
         return record.isCategory(Notification.CATEGORY_ALARM)
-                || record.isCategory(Notification.CATEGORY_EVENT)
                 || record.isAudioStream(AudioManager.STREAM_ALARM)
                 || record.isAudioAttributesUsage(AudioAttributes.USAGE_ALARM);
     }
 
+    private static boolean isEvent(NotificationRecord record) {
+        return record.isCategory(Notification.CATEGORY_EVENT);
+    }
+
     private boolean isCall(NotificationRecord record) {
         return isDefaultPhoneApp(record.sbn.getPackageName())
                 || record.isCategory(Notification.CATEGORY_CALL);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5a94f23..a61d621 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5589,9 +5589,11 @@
         // update the package settings accordingly.
         pkg.cpuAbiOverride = cpuAbiOverride;
 
-        Slog.d(TAG, "Resolved nativeLibraryRoot for " + pkg.applicationInfo.packageName
-                + " to root=" + pkg.applicationInfo.nativeLibraryRootDir + ", isa="
-                + pkg.applicationInfo.nativeLibraryRootRequiresIsa);
+        if (DEBUG_ABI_SELECTION) {
+            Slog.d(TAG, "Resolved nativeLibraryRoot for " + pkg.applicationInfo.packageName
+                    + " to root=" + pkg.applicationInfo.nativeLibraryRootDir + ", isa="
+                    + pkg.applicationInfo.nativeLibraryRootRequiresIsa);
+        }
 
         // Push the derived path down into PackageSettings so we know what to
         // clean up at uninstall time.
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 0dadee7..4e33ca8 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -2285,7 +2285,7 @@
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setData(builder.build());
                 applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                        scheme, ssp, null, null, null, userId);
+                        scheme, ssp, null, null, userId);
                 doScheme = false;
             }
             for (int iauth=0; iauth<tmpPa.countDataAuthorities(); iauth++) {
@@ -2302,7 +2302,7 @@
                     Intent finalIntent = new Intent(intent);
                     finalIntent.setData(builder.build());
                     applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                            scheme, null, auth, path, null, userId);
+                            scheme, null, auth, path, userId);
                     doAuth = doScheme = false;
                 }
                 if (doAuth) {
@@ -2314,7 +2314,7 @@
                     Intent finalIntent = new Intent(intent);
                     finalIntent.setData(builder.build());
                     applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                            scheme, null, auth, null, null, userId);
+                            scheme, null, auth, null, userId);
                     doScheme = false;
                 }
             }
@@ -2324,7 +2324,7 @@
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setData(builder.build());
                 applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                        scheme, null, null, null, null, userId);
+                        scheme, null, null, null, userId);
             }
             doNonData = false;
         }
@@ -2340,28 +2340,27 @@
                         builder.scheme(scheme);
                         finalIntent.setDataAndType(builder.build(), mimeType);
                         applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                                scheme, null, null, null, mimeType, userId);
+                                scheme, null, null, null, userId);
                     }
                 }
             } else {
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setType(mimeType);
                 applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
-                        null, null, null, null, mimeType, userId);
+                        null, null, null, null, userId);
             }
             doNonData = false;
         }
 
         if (doNonData) {
             applyDefaultPreferredActivityLPw(service, intent, flags, cn,
-                    null, null, null, null, null, userId);
+                    null, null, null, null, userId);
         }
     }
 
     private void applyDefaultPreferredActivityLPw(PackageManagerService service,
             Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp,
-            IntentFilter.AuthorityEntry auth, PatternMatcher path, String mimeType,
-            int userId) {
+            IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
         List<ResolveInfo> ri = service.mActivities.queryIntent(intent,
                 intent.getType(), flags, 0);
         if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent
@@ -2369,19 +2368,24 @@
         int match = 0;
         if (ri != null && ri.size() > 1) {
             boolean haveAct = false;
-            boolean haveNonSys = false;
+            ComponentName haveNonSys = null;
             ComponentName[] set = new ComponentName[ri.size()];
             for (int i=0; i<ri.size(); i++) {
                 ActivityInfo ai = ri.get(i).activityInfo;
                 set[i] = new ComponentName(ai.packageName, ai.name);
                 if ((ai.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
-                    // If any of the matches are not system apps, then
-                    // there is a third party app that is now an option...
-                    // so don't set a default since we don't want to hide it.
-                    if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
-                            + ai.packageName + "/" + ai.name + ": non-system!");
-                    haveNonSys = true;
-                    break;
+                    if (ri.get(i).match >= match) {
+                        // If any of the matches are not system apps, then
+                        // there is a third party app that is now an option...
+                        // so don't set a default since we don't want to hide it.
+                        // Only do this if the match of this one is at least as good
+                        // as what we have found as the built-in app; if it isn't
+                        // as good, the user won't want it anyway, right?
+                        if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
+                                + ai.packageName + "/" + ai.name + ": non-system!");
+                        haveNonSys = set[i];
+                        break;
+                    }
                 } else if (cn.getPackageName().equals(ai.packageName)
                         && cn.getClassName().equals(ai.name)) {
                     if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
@@ -2393,7 +2397,7 @@
                             + ai.packageName + "/" + ai.name + ": skipped");
                 }
             }
-            if (haveAct && !haveNonSys) {
+            if (haveAct && haveNonSys == null) {
                 IntentFilter filter = new IntentFilter();
                 if (intent.getAction() != null) {
                     filter.addAction(intent.getAction());
@@ -2427,9 +2431,25 @@
                 }
                 PreferredActivity pa = new PreferredActivity(filter, match, set, cn, true);
                 editPreferredActivitiesLPw(userId).addFilter(pa);
-            } else if (!haveNonSys) {
-                Slog.w(TAG, "No component found for default preferred activity " + cn);
+            } else if (haveNonSys == null) {
+                StringBuilder sb = new StringBuilder();
+                sb.append("No component ");
+                sb.append(cn.flattenToShortString());
+                sb.append(" found setting preferred ");
+                sb.append(intent);
+                sb.append("; possible matches are ");
+                for (int i=0; i<set.length; i++) {
+                    if (i > 0) sb.append(", ");
+                    sb.append(set[i].flattenToShortString());
+                }
+                Slog.w(TAG, sb.toString());
+            } else {
+                Slog.i(TAG, "Not setting preferred " + intent + "; found third party match "
+                        + haveNonSys.flattenToShortString());
             }
+        } else {
+            Slog.w(TAG, "No potential matches found for " + intent + " while setting preferred "
+                    + cn.flattenToShortString());
         }
     }
 
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index c720668..94a628d 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -84,7 +84,6 @@
     private final IBatteryStats mBatteryStats;
     private final IAppOpsService mAppOps;
     private final SuspendBlocker mSuspendBlocker;
-    private final ScreenOnBlocker mScreenOnBlocker;
     private final WindowManagerPolicy mPolicy;
     private final ActivityManagerInternal mActivityManagerInternal;
     private final InputManagerInternal mInputManagerInternal;
@@ -110,18 +109,13 @@
     // True if a user activity message should be sent.
     private boolean mUserActivityPending;
 
-    // The currently active screen on listener. This field is non-null whenever the
-    // ScreenOnBlocker has been acquired and we are awaiting a callback to release it.
-    private ScreenOnUnblocker mPendingScreenOnUnblocker;
-
     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
-            IAppOpsService appOps, SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker,
+            IAppOpsService appOps, SuspendBlocker suspendBlocker,
             WindowManagerPolicy policy) {
         mContext = context;
         mBatteryStats = batteryStats;
         mAppOps = appOps;
         mSuspendBlocker = suspendBlocker;
-        mScreenOnBlocker = screenOnBlocker;
         mPolicy = policy;
         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
@@ -333,21 +327,6 @@
     }
 
     /**
-     * Notifies that screen is about to be turned on (any state other than off).
-     */
-    public void onScreenTurningOn() {
-        synchronized (mLock) {
-            final ScreenOnUnblocker unblocker = blockScreenOnLocked();
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mPolicy.screenTurningOn(unblocker);
-                }
-            });
-        }
-    }
-
-    /**
      * Called when there has been user activity.
      */
     public void onUserActivity(int event, int uid) {
@@ -470,26 +449,6 @@
         }
     }
 
-    private ScreenOnUnblocker blockScreenOnLocked() {
-        if (mPendingScreenOnUnblocker == null) {
-            mScreenOnBlocker.acquire();
-        }
-        mPendingScreenOnUnblocker = new ScreenOnUnblocker();
-        return mPendingScreenOnUnblocker;
-    }
-
-    private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
-        @Override
-        public void onScreenOn() {
-            synchronized (mLock) {
-                if (mPendingScreenOnUnblocker == this) {
-                    mPendingScreenOnUnblocker = null;
-                    mScreenOnBlocker.release();
-                }
-            }
-        }
-    }
-
     private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 71e059a..4f41bee 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -88,8 +88,6 @@
     private static final int MSG_USER_ACTIVITY_TIMEOUT = 1;
     // Message: Sent when the device enters or exits a dreaming or dozing state.
     private static final int MSG_SANDMAN = 2;
-    // Message: Sent when the screen on blocker is released.
-    private static final int MSG_SCREEN_ON_BLOCKER_RELEASED = 3;
 
     // Dirty bit: mWakeLocks changed
     private static final int DIRTY_WAKE_LOCKS = 1 << 0;
@@ -111,10 +109,8 @@
     private static final int DIRTY_BATTERY_STATE = 1 << 8;
     // Dirty bit: proximity state changed
     private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9;
-    // Dirty bit: screen on blocker state became held or unheld
-    private static final int DIRTY_SCREEN_ON_BLOCKER_RELEASED = 1 << 10;
     // Dirty bit: dock state changed
-    private static final int DIRTY_DOCK_STATE = 1 << 11;
+    private static final int DIRTY_DOCK_STATE = 1 << 10;
 
     // Wakefulness: The device is asleep and can only be awoken by a call to wakeUp().
     // The screen should be off or in the process of being turned off by the display controller.
@@ -244,10 +240,6 @@
     // True if the display suspend blocker has been acquired.
     private boolean mHoldingDisplaySuspendBlocker;
 
-    // The screen on blocker used to keep the screen from turning on while the lock
-    // screen is coming up.
-    private final ScreenOnBlockerImpl mScreenOnBlocker;
-
     // True if systemReady() has been called.
     private boolean mSystemReady;
 
@@ -451,7 +443,6 @@
             mHalAutoSuspendModeEnabled = false;
             mHalInteractiveModeEnabled = true;
 
-            mScreenOnBlocker = new ScreenOnBlockerImpl();
             mWakefulness = WAKEFULNESS_AWAKE;
             mInteractive = true;
 
@@ -505,7 +496,7 @@
             mBatteryStats = BatteryStatsService.getService();
             mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
                     mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
-                    mScreenOnBlocker, mPolicy);
+                    mPolicy);
 
             mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
                     createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
@@ -1745,13 +1736,6 @@
         return true;
     }
 
-    private void handleScreenOnBlockerReleased() {
-        synchronized (mLock) {
-            mDirty |= DIRTY_SCREEN_ON_BLOCKER_RELEASED;
-            updatePowerStateLocked();
-        }
-    }
-
     /**
      * Updates the display power state asynchronously.
      * When the update is finished, mDisplayReady will be set to true.  The display
@@ -1766,8 +1750,7 @@
         final boolean oldDisplayReady = mDisplayReady;
         if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
                 | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
-                | DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
-            boolean wasBlockerNeeded = isScreenOnBlockerNeededLocked(mDisplayPowerRequest);
+                | DIRTY_SETTINGS)) != 0) {
             mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
 
             int screenBrightness = mScreenBrightnessSettingDefault;
@@ -1815,12 +1798,6 @@
                 mDisplayPowerRequest.dozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
             }
 
-            if (!wasBlockerNeeded && isScreenOnBlockerNeededLocked(mDisplayPowerRequest)
-                    && !mScreenOnBlocker.isHeld()) {
-                mNotifier.onScreenTurningOn();
-            }
-            mDisplayPowerRequest.blockScreenOn = mScreenOnBlocker.isHeld();
-
             mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
                     mRequestWaitForNegativeProximity);
             mRequestWaitForNegativeProximity = false;
@@ -1837,17 +1814,6 @@
         return mDisplayReady && !oldDisplayReady;
     }
 
-    private static boolean isScreenOnBlockerNeededLocked(DisplayPowerRequest req) {
-        switch (req.policy) {
-            case DisplayPowerRequest.POLICY_OFF:
-                return false;
-            case DisplayPowerRequest.POLICY_DOZE:
-                return req.dozeScreenState != Display.STATE_OFF;
-            default:
-                return true;
-        }
-    }
-
     private static boolean isValidBrightness(int value) {
         return value >= 0 && value <= 255;
     }
@@ -2420,9 +2386,6 @@
             }
 
             pw.println();
-            pw.println("Screen On Blocker: " + mScreenOnBlocker);
-
-            pw.println();
             pw.println("Display Power: " + mDisplayPowerCallbacks);
 
             wcd = mWirelessChargerDetector;
@@ -2530,9 +2493,6 @@
                 case MSG_SANDMAN:
                     handleSandman();
                     break;
-                case MSG_SCREEN_ON_BLOCKER_RELEASED:
-                    handleScreenOnBlockerReleased();
-                    break;
             }
         }
     }
@@ -2709,56 +2669,6 @@
         }
     }
 
-    private final class ScreenOnBlockerImpl implements ScreenOnBlocker {
-        private static final String TRACE_NAME = "ScreenOnBlocker";
-
-        private int mNestCount;
-
-        public boolean isHeld() {
-            synchronized (this) {
-                return mNestCount != 0;
-            }
-        }
-
-        @Override
-        public void acquire() {
-            synchronized (this) {
-                mNestCount += 1;
-                if (DEBUG || true) {
-                    Slog.d(TAG, "Screen on blocked: mNestCount=" + mNestCount);
-                }
-                if (mNestCount == 1) {
-                    Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_NAME, 0);
-                }
-            }
-        }
-
-        @Override
-        public void release() {
-            synchronized (this) {
-                mNestCount -= 1;
-                if (mNestCount == 0) {
-                    if (DEBUG || true) {
-                        Slog.d(TAG, "Screen on unblocked: mNestCount=" + mNestCount);
-                    }
-                    mHandler.sendEmptyMessage(MSG_SCREEN_ON_BLOCKER_RELEASED);
-                    Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_NAME, 0);
-                } else if (mNestCount < 0) {
-                    Slog.wtf(TAG, "Screen on blocker was released without being acquired!",
-                            new Throwable());
-                    mNestCount = 0;
-                }
-            }
-        }
-
-        @Override
-        public String toString() {
-            synchronized (this) {
-                return "held=" + (mNestCount != 0) + ", mNestCount=" + mNestCount;
-            }
-        }
-    }
-
     private final class BinderService extends IPowerManager.Stub {
         @Override // Binder call
         public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index a4edc86..999649b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3474,7 +3474,7 @@
     }
 
     boolean okToDisplay() {
-        return !mDisplayFrozen && mDisplayEnabled && mPolicy.isAwake();
+        return !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn();
     }
 
     AppWindowToken findAppWindowToken(IBinder token) {
@@ -10397,7 +10397,7 @@
             return;
         }
 
-        if (!mDisplayReady || !mPolicy.isAwake()) {
+        if (!mDisplayReady || !mPolicy.isScreenOn()) {
             // No need to freeze the screen before the system is ready or if
             // the screen is off.
             return;
@@ -11423,6 +11423,7 @@
                 createDisplayContentLocked(display);
                 displayReady(displayId);
             }
+            requestTraversalLocked();
         }
     }
 
@@ -11445,6 +11446,7 @@
             }
         }
         mAnimator.removeDisplayLocked(displayId);
+        requestTraversalLocked();
     }
 
     public void onDisplayChanged(int displayId) {
@@ -11456,6 +11458,7 @@
         if (displayContent != null) {
             displayContent.updateDisplayInfo();
         }
+        requestTraversalLocked();
     }
 
     @Override
@@ -11576,7 +11579,7 @@
                 final WindowList windows = getDefaultWindowListLocked();
                 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
                     final WindowState win = windows.get(winNdx);
-                    if (win.mHasSurface
+                    if (win.isVisibleLw()
                             && (win.mAppToken != null || mPolicy.isForceHiding(win.mAttrs))) {
                         win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
                         // Force add to mResizingWindows.
diff --git a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index 402f0dd..bd64392 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -67,6 +67,7 @@
         assertEquals("Didn't get expected number of persisted tasks.", 1, jobStatusSet.size());
         final JobStatus loadedTaskStatus = jobStatusSet.iterator().next();
         assertTasksEqual(task, loadedTaskStatus.getJob());
+        assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(ts));
         assertEquals("Different uids.", SOME_UID, loadedTaskStatus.getUid());
         compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
                 ts.getEarliestRunTime(), loadedTaskStatus.getEarliestRunTime());
@@ -103,7 +104,8 @@
         JobStatus loaded2 = it.next();
         assertTasksEqual(task1, loaded1.getJob());
         assertTasksEqual(task2, loaded2.getJob());
-
+        assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus1));
+        assertTrue("JobStore#contains invalid.", mTaskStoreUnderTest.containsJob(taskStatus2));
         // Check that the loaded task has the correct runtimes.
         compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
                 taskStatus1.getEarliestRunTime(), loaded1.getEarliestRunTime());
diff --git a/telecomm/java/android/telecom/AudioState.java b/telecomm/java/android/telecom/AudioState.java
index d0e2860..fc2fff4 100644
--- a/telecomm/java/android/telecom/AudioState.java
+++ b/telecomm/java/android/telecom/AudioState.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -23,7 +24,9 @@
 
 /**
  *  Encapsulates all audio states during a call.
+ *  @hide
  */
+@SystemApi
 public final class AudioState implements Parcelable {
     /** Direct the audio stream through the device's earpiece. */
     public static final int ROUTE_EARPIECE      = 0x00000001;
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 9b350c1..e47d9d1 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -16,6 +16,8 @@
 
 package android.telecom;
 
+import android.annotation.SystemApi;
+
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
@@ -24,7 +26,9 @@
 
 /**
  * Represents a conference call which can contain any number of {@link Connection} objects.
+ * @hide
  */
+@SystemApi
 public abstract class Conference {
 
     /** @hide */
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 7979e44..13acc59 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -19,6 +19,7 @@
 import com.android.internal.telecom.IVideoCallback;
 import com.android.internal.telecom.IVideoProvider;
 
+import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
@@ -43,7 +44,9 @@
  * Implementations are then responsible for updating the state of the {@code Connection}, and
  * must call {@link #destroy()} to signal to the framework that the {@code Connection} is no
  * longer used and associated resources may be recovered.
+ * @hide
  */
+@SystemApi
 public abstract class Connection {
 
     public static final int STATE_INITIALIZING = 0;
@@ -873,7 +876,7 @@
         return mUnmodifiableConferenceableConnections;
     }
 
-    /*
+    /**
      * @hide
      */
     public final void setConnectionService(ConnectionService connectionService) {
diff --git a/telecomm/java/android/telecom/ConnectionRequest.java b/telecomm/java/android/telecom/ConnectionRequest.java
index 71b481b..f691c17 100644
--- a/telecomm/java/android/telecom/ConnectionRequest.java
+++ b/telecomm/java/android/telecom/ConnectionRequest.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcel;
@@ -24,7 +25,9 @@
 /**
  * Simple data container encapsulating a request to some entity to
  * create a new {@link Connection}.
+ * @hide
  */
+@SystemApi
 public final class ConnectionRequest implements Parcelable {
 
     // TODO: Token to limit recursive invocations
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 3e18bac..ed9251b7 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.SystemApi;
 import android.annotation.SdkConstant;
 import android.app.Service;
 import android.content.ComponentName;
@@ -34,15 +35,17 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * A {@link android.app.Service} that provides telephone connections to processes running on an
  * Android device.
+ * @hide
  */
+@SystemApi
 public abstract class ConnectionService extends Service {
     /**
      * The {@link Intent} that must be declared as handled by the service.
@@ -74,10 +77,10 @@
 
     private static Connection sNullConnection;
 
-    private final Map<String, Connection> mConnectionById = new HashMap<>();
-    private final Map<Connection, String> mIdByConnection = new HashMap<>();
-    private final Map<String, Conference> mConferenceById = new HashMap<>();
-    private final Map<Conference, String> mIdByConference = new HashMap<>();
+    private final Map<String, Connection> mConnectionById = new ConcurrentHashMap<>();
+    private final Map<Connection, String> mIdByConnection = new ConcurrentHashMap<>();
+    private final Map<String, Conference> mConferenceById = new ConcurrentHashMap<>();
+    private final Map<Conference, String> mIdByConference = new ConcurrentHashMap<>();
     private final RemoteConnectionManager mRemoteConnectionManager =
             new RemoteConnectionManager(this);
     private final List<Runnable> mPreInitializationConnectionRequests = new ArrayList<>();
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 9be0138..52c1284 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.media.ToneGenerator;
@@ -28,7 +29,9 @@
  * cause of the disconnect. Optionally, it may include a localized label and/or localized description
  * to display to the user which is provided by the {@link ConnectionService}. It also may contain a
  * reason for the the disconnect, which is intended for logging and not for display to the user.
+ * @hide
  */
+@SystemApi
 public final class DisconnectCause implements Parcelable {
 
     /** Disconnected because of an unknown or unspecified reason. */
diff --git a/telecomm/java/android/telecom/GatewayInfo.java b/telecomm/java/android/telecom/GatewayInfo.java
index 583c3e2..3efab0f 100644
--- a/telecomm/java/android/telecom/GatewayInfo.java
+++ b/telecomm/java/android/telecom/GatewayInfo.java
@@ -30,7 +30,9 @@
  * <li> Call the appropriate routing number
  * <li> Display information about how the call is being routed to the user
  * </ol>
+ * @hide
  */
+@SystemApi
 public class GatewayInfo implements Parcelable {
 
     private final String mGatewayProviderPackageName;
diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java
index fa12756..11da0f2 100644
--- a/telecomm/java/android/telecom/InCallService.java
+++ b/telecomm/java/android/telecom/InCallService.java
@@ -59,6 +59,10 @@
     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
         @Override
         public void handleMessage(Message msg) {
+            if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) {
+                return;
+            }
+
             switch (msg.what) {
                 case MSG_SET_IN_CALL_ADAPTER:
                     mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 4b059b2..ffe787a 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Resources.NotFoundException;
@@ -34,7 +35,9 @@
 /**
  * Describes a distinct account, line of service or call placement method that the system
  * can use to place phone calls.
+ * @hide
  */
+@SystemApi
 public class PhoneAccount implements Parcelable {
 
     /**
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index e13df76..652befe5 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.SystemApi;
 import android.content.ComponentName;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -24,7 +25,9 @@
 
 /**
  * The unique identifier for a {@link PhoneAccount}.
+ * @hide
  */
+@SystemApi
 public class PhoneAccountHandle implements Parcelable {
     private ComponentName mComponentName;
     private String mId;
diff --git a/telecomm/java/android/telecom/PhoneCapabilities.java b/telecomm/java/android/telecom/PhoneCapabilities.java
index e73dfe2..de2abcb 100644
--- a/telecomm/java/android/telecom/PhoneCapabilities.java
+++ b/telecomm/java/android/telecom/PhoneCapabilities.java
@@ -16,10 +16,14 @@
 
 package android.telecom;
 
+import android.annotation.SystemApi;
+
 /**
  * Defines capabilities a phone call can support, such as conference calling and video telephony.
  * Also defines properties of a phone call, such as whether it is using VoLTE technology.
+ * @hide
  */
+@SystemApi
 public final class PhoneCapabilities {
     /** Call can currently be put on hold or unheld. */
     public static final int HOLD               = 0x00000001;
diff --git a/telecomm/java/android/telecom/RemoteConference.java b/telecomm/java/android/telecom/RemoteConference.java
index f931bc5..796725b 100644
--- a/telecomm/java/android/telecom/RemoteConference.java
+++ b/telecomm/java/android/telecom/RemoteConference.java
@@ -18,6 +18,7 @@
 
 import com.android.internal.telecom.IConnectionService;
 
+import android.annotation.SystemApi;
 import android.os.RemoteException;
 
 import java.util.Collections;
@@ -28,7 +29,9 @@
 
 /**
  * Represents a conference call which can contain any number of {@link Connection} objects.
+ * @hide
  */
+@SystemApi
 public final class RemoteConference {
 
     public abstract static class Callback {
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 9a094df..4a89692 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -20,6 +20,7 @@
 import com.android.internal.telecom.IVideoCallback;
 import com.android.internal.telecom.IVideoProvider;
 
+import android.annotation.SystemApi;
 import android.net.Uri;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -37,7 +38,9 @@
  *
  * @see ConnectionService#createRemoteOutgoingConnection(PhoneAccountHandle, ConnectionRequest)
  * @see ConnectionService#createRemoteIncomingConnection(PhoneAccountHandle, ConnectionRequest)
+ * @hide
  */
+@SystemApi
 public final class RemoteConnection {
 
     public static abstract class Callback {
diff --git a/telecomm/java/android/telecom/StatusHints.java b/telecomm/java/android/telecom/StatusHints.java
index a32eae7..dd3a639 100644
--- a/telecomm/java/android/telecom/StatusHints.java
+++ b/telecomm/java/android/telecom/StatusHints.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.SystemApi;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -29,7 +30,9 @@
 
 /**
  * Contains status label and icon displayed in the in-call UI.
+ * @hide
  */
+@SystemApi
 public final class StatusHints implements Parcelable {
 
     private final ComponentName mPackageName;
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 481e483..89d2dc0 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -53,6 +53,7 @@
     /**
      * The {@link android.content.Intent} action used to configure a
      * {@link android.telecom.ConnectionService}.
+     * @hide
      */
     public static final String ACTION_CONNECTION_SERVICE_CONFIGURE =
             "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
@@ -66,6 +67,7 @@
     /**
      * The {@link android.content.Intent} action used to show the settings page used to configure
      * {@link PhoneAccount} preferences.
+     * @hide
      */
     public static final String ACTION_CHANGE_PHONE_ACCOUNTS =
             "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
@@ -96,6 +98,7 @@
      * {@link PhoneAccountHandle} to use when making the call.
      * <p class="note">
      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
+     * @hide
      */
     public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
             "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
@@ -138,6 +141,7 @@
     /**
      * Optional extra for {@link android.telephony.TelephonyManager#ACTION_PHONE_STATE_CHANGED}
      * containing the component name of the associated connection service.
+     * @hide
      */
     public static final String EXTRA_CONNECTION_SERVICE =
             "android.telecom.extra.CONNECTION_SERVICE";
@@ -173,6 +177,7 @@
      * {@link ConnectionService}s which interact with {@link RemoteConnection}s should only populate
      * this if the {@link android.telephony.TelephonyManager#getLine1Number()} value, as that is the
      * user's expected caller ID.
+     * @hide
      */
     public static final String EXTRA_CALL_BACK_NUMBER = "android.telecom.extra.CALL_BACK_NUMBER";
 
@@ -419,6 +424,7 @@
      * {@code PhoneAccount}.
      *
      * @return The phone account handle of the current connection manager.
+     * @hide
      */
     public PhoneAccountHandle getConnectionManager() {
         return getSimCallManager();
@@ -476,6 +482,7 @@
      *
      * @return {@code true} if the device has more than one account registered and {@code false}
      * otherwise.
+     * @hide
      */
     public boolean hasMultipleCallCapableAccounts() {
         return getCallCapablePhoneAccounts().size() > 1;
@@ -485,6 +492,7 @@
      *  Returns a list of all {@link PhoneAccount}s registered for the calling package.
      *
      * @return A list of {@code PhoneAccountHandle} objects.
+     * @hide
      */
     public List<PhoneAccountHandle> getPhoneAccountsForPackage() {
         try {
@@ -503,6 +511,7 @@
      *
      * @param account The {@link PhoneAccountHandle}.
      * @return The {@link PhoneAccount} object.
+     * @hide
      */
     public PhoneAccount getPhoneAccount(PhoneAccountHandle account) {
         try {
@@ -573,6 +582,7 @@
      * Register a {@link PhoneAccount} for use by the system.
      *
      * @param account The complete {@link PhoneAccount}.
+     * @hide
      */
     public void registerPhoneAccount(PhoneAccount account) {
         try {
@@ -588,6 +598,7 @@
      * Remove a {@link PhoneAccount} registration from the system.
      *
      * @param accountHandle A {@link PhoneAccountHandle} for the {@link PhoneAccount} to unregister.
+     * @hide
      */
     public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
         try {
@@ -601,6 +612,7 @@
 
     /**
      * Remove all Accounts that belong to the calling package from the system.
+     * @hide
      */
     @SystemApi
     public void clearAccounts() {
@@ -786,6 +798,7 @@
      *            {@link #registerPhoneAccount}.
      * @param extras A bundle that will be passed through to
      *            {@link ConnectionService#onCreateIncomingConnection}.
+     * @hide
      */
     public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) {
         try {
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index d776833..ea5fa27 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -34,12 +34,10 @@
             boolean notifyNow);
     void notifyCallState(int state, String incomingNumber);
     void notifyCallStateForSubscriber(in long subId, int state, String incomingNumber);
-    void notifyServiceState(in ServiceState state);
-    void notifyServiceStateForSubscriber(in long subId, in ServiceState state);
+    void notifyServiceStateForPhoneId(in int phoneId, in long subId, in ServiceState state);
     void notifySignalStrength(in SignalStrength signalStrength);
     void notifySignalStrengthForSubscriber(in long subId, in SignalStrength signalStrength);
-    void notifyMessageWaitingChanged(boolean mwi);
-    void notifyMessageWaitingChangedForSubscriber(in long subId, boolean mwi);
+    void notifyMessageWaitingChangedForPhoneId(in int phoneId, in long subId, in boolean mwi);
     void notifyCallForwardingChanged(boolean cfi);
     void notifyCallForwardingChangedForSubscriber(in long subId, boolean cfi);
     void notifyDataActivity(int state);
diff --git a/test-runner/src/android/test/TouchUtils.java b/test-runner/src/android/test/TouchUtils.java
index acbde0b..67a0bc2 100644
--- a/test-runner/src/android/test/TouchUtils.java
+++ b/test-runner/src/android/test/TouchUtils.java
@@ -120,19 +120,13 @@
      */
     public static void scrollToBottom(InstrumentationTestCase test, Activity activity,
             ViewGroup v) {
-        View firstChild;
-        int firstId = Integer.MIN_VALUE;
-        int firstTop = Integer.MIN_VALUE; 
-        int prevId;
-        int prevTop; 
+        ViewStateSnapshot prev;
+        ViewStateSnapshot next = new ViewStateSnapshot(v);
         do {
-            prevId = firstId;
-            prevTop = firstTop;
+            prev = next;
             TouchUtils.dragQuarterScreenUp(test, activity);
-            firstChild = v.getChildAt(0);
-            firstId = firstChild.getId();
-            firstTop = firstChild.getTop(); 
-        } while ((prevId != firstId) || (prevTop != firstTop));
+            next = new ViewStateSnapshot(v);
+        } while (!prev.equals(next));
     }
 
     /**
@@ -160,19 +154,13 @@
      * @param v The ViewGroup that should be dragged
      */
     public static void scrollToTop(InstrumentationTestCase test, Activity activity, ViewGroup v) {
-        View firstChild;
-        int firstId = Integer.MIN_VALUE;
-        int firstTop = Integer.MIN_VALUE; 
-        int prevId;
-        int prevTop; 
+        ViewStateSnapshot prev;
+        ViewStateSnapshot next = new ViewStateSnapshot(v);
         do {
-            prevId = firstId;
-            prevTop = firstTop;
+            prev = next;
             TouchUtils.dragQuarterScreenDown(test, activity);
-            firstChild = v.getChildAt(0);
-            firstId = firstChild.getId();
-            firstTop = firstChild.getTop(); 
-        } while ((prevId != firstId) || (prevTop != firstTop));
+            next = new ViewStateSnapshot(v);
+        } while (!prev.equals(next));
     }
     
     /**
@@ -776,15 +764,12 @@
         MotionEvent event = MotionEvent.obtain(downTime, eventTime,
                 MotionEvent.ACTION_DOWN, x, y, 0);
         inst.sendPointerSync(event);
-        inst.waitForIdleSync();
-
         for (int i = 0; i < stepCount; ++i) {
             y += yStep;
             x += xStep;
             eventTime = SystemClock.uptimeMillis();
             event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0);
             inst.sendPointerSync(event);
-            inst.waitForIdleSync();
         }
 
         eventTime = SystemClock.uptimeMillis();
@@ -792,4 +777,51 @@
         inst.sendPointerSync(event);
         inst.waitForIdleSync();
     }
+
+    private static class ViewStateSnapshot {
+        final View mFirst;
+        final View mLast;
+        final int mFirstTop;
+        final int mLastBottom;
+        final int mChildCount;
+        private ViewStateSnapshot(ViewGroup viewGroup) {
+            mChildCount = viewGroup.getChildCount();
+            if (mChildCount == 0) {
+                mFirst = mLast = null;
+                mFirstTop = mLastBottom = Integer.MIN_VALUE;
+            } else {
+                mFirst = viewGroup.getChildAt(0);
+                mLast = viewGroup.getChildAt(mChildCount - 1);
+                mFirstTop = mFirst.getTop();
+                mLastBottom = mLast.getBottom();
+            }
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+
+            final ViewStateSnapshot that = (ViewStateSnapshot) o;
+            return mFirstTop == that.mFirstTop &&
+                    mLastBottom == that.mLastBottom &&
+                    mFirst == that.mFirst &&
+                    mLast == that.mLast &&
+                    mChildCount == that.mChildCount;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = mFirst != null ? mFirst.hashCode() : 0;
+            result = 31 * result + (mLast != null ? mLast.hashCode() : 0);
+            result = 31 * result + mFirstTop;
+            result = 31 * result + mLastBottom;
+            result = 31 * result + mChildCount;
+            return result;
+        }
+    }
 }
diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml
index 3fb547d..f31f4f2 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -30,6 +30,20 @@
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="http" android:host="www.angryredplanet.com"
+                        android:pathPrefix="" />
+            </intent-filter>
+            <preferred>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.BROWSABLE" />
+                <data android:scheme="http" android:host="www.angryredplanet.com"
+                        android:pathPrefix="" />
+            </preferred>
         </activity>
         <activity android:name="SpamActivity" android:label="Spam!"
                 android:documentLaunchMode="always">
diff --git a/tests/VectorDrawableTest/res/anim/animation_favorite.xml b/tests/VectorDrawableTest/res/anim/animation_favorite.xml
index c81ba40..2e2d9bb 100644
--- a/tests/VectorDrawableTest/res/anim/animation_favorite.xml
+++ b/tests/VectorDrawableTest/res/anim/animation_favorite.xml
@@ -25,5 +25,35 @@
         android:valueFrom="@string/round_box"
         android:valueTo="@string/heart"
         android:valueType="pathType" />
+    <objectAnimator
+        android:duration="8000"
+        android:propertyName="fillAlpha"
+        android:repeatCount="-1"
+        android:valueFrom="1.0"
+        android:valueTo="0.0" />
+    <objectAnimator
+        android:duration="8000"
+        android:propertyName="strokeAlpha"
+        android:repeatCount="-1"
+        android:valueFrom="1.0"
+        android:valueTo="0.0" />
+    <objectAnimator
+        android:duration="8000"
+        android:propertyName="strokeColor"
+        android:repeatCount="-1"
+        android:valueFrom="#FF0000FF"
+        android:valueTo="#FF00FF00" />
+    <objectAnimator
+        android:duration="8000"
+        android:propertyName="strokeWidth"
+        android:repeatCount="-1"
+        android:valueFrom="5"
+        android:valueTo="20" />
+    <objectAnimator
+        android:duration="8000"
+        android:propertyName="fillColor"
+        android:repeatCount="-1"
+        android:valueFrom="#FFFF0000"
+        android:valueTo="#FF00FF00" />
 
 </set>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/anim/trim_path_animation02.xml b/tests/VectorDrawableTest/res/anim/trim_path_animation02.xml
index 3bf2865..5d688cf 100644
--- a/tests/VectorDrawableTest/res/anim/trim_path_animation02.xml
+++ b/tests/VectorDrawableTest/res/anim/trim_path_animation02.xml
@@ -19,7 +19,7 @@
 
     <objectAnimator
         android:duration="5000"
-        android:propertyName="fill"
+        android:propertyName="fillColor"
         android:valueFrom="#FF000000"
         android:valueTo="#FFFF0000"/>
 
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 3fc9f81..d809c5b 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -104,6 +104,9 @@
 struct AaptGroupEntry
 {
 public:
+    AaptGroupEntry() {}
+    AaptGroupEntry(const ConfigDescription& config) : mParams(config) {}
+
     bool initFromDirName(const char* dir, String8* resType);
 
     inline const ConfigDescription& toParams() const { return mParams; }
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index 137c85c..56d1650 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -1483,7 +1483,7 @@
     return NO_ERROR;
 }
 
-status_t postProcessImage(const sp<AaptAssets>& assets,
+status_t postProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets,
                           ResourceTable* table, const sp<AaptFile>& file)
 {
     String8 ext(file->getPath().getPathExtension());
@@ -1491,7 +1491,8 @@
     // At this point, now that we have all the resource data, all we need to
     // do is compile XML files.
     if (strcmp(ext.string(), ".xml") == 0) {
-        return compileXmlFile(assets, file, table);
+        String16 resourceName(parseResourceName(file->getPath().getPathLeaf()));
+        return compileXmlFile(bundle, assets, resourceName, file, table);
     }
 
     return NO_ERROR;
diff --git a/tools/aapt/Images.h b/tools/aapt/Images.h
index 91b6554..a0a94f8 100644
--- a/tools/aapt/Images.h
+++ b/tools/aapt/Images.h
@@ -20,7 +20,7 @@
 
 status_t preProcessImageToCache(const Bundle* bundle, const String8& source, const String8& dest);
 
-status_t postProcessImage(const sp<AaptAssets>& assets,
+status_t postProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets,
                           ResourceTable* table, const sp<AaptFile>& file);
 
 #endif
diff --git a/tools/aapt/Main.h b/tools/aapt/Main.h
index f24a023b..089dde5 100644
--- a/tools/aapt/Main.h
+++ b/tools/aapt/Main.h
@@ -62,4 +62,7 @@
 
 status_t writeDependencyPreReqs(Bundle* bundle, const sp<AaptAssets>& assets,
                                 FILE* fp, bool includeRaw);
+
+android::String8 parseResourceName(const String8& pathLeaf);
+
 #endif // __MAIN_H
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index d605202..a4c9dab 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -50,7 +50,7 @@
 // ==========================================================================
 // ==========================================================================
 
-static String8 parseResourceName(const String8& leaf)
+String8 parseResourceName(const String8& leaf)
 {
     const char* firstDot = strchr(leaf.string(), '.');
     const char* str = leaf.string();
@@ -1088,7 +1088,7 @@
     manifest->addChild(app);
     root->addChild(manifest);
 
-    int err = compileXmlFile(assets, root, outFile, table);
+    int err = compileXmlFile(bundle, assets, String16(), root, outFile, table);
     if (err < NO_ERROR) {
         return err;
     }
@@ -1336,7 +1336,8 @@
         ResourceDirIterator it(layouts, String8("layout"));
         while ((err=it.next()) == NO_ERROR) {
             String8 src = it.getFile()->getPrintableSource();
-            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            err = compileXmlFile(bundle, assets, String16(it.getBaseName()),
+                    it.getFile(), &table, xmlFlags);
             if (err == NO_ERROR) {
                 ResXMLTree block;
                 block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true);
@@ -1355,7 +1356,8 @@
     if (anims != NULL) {
         ResourceDirIterator it(anims, String8("anim"));
         while ((err=it.next()) == NO_ERROR) {
-            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            err = compileXmlFile(bundle, assets, String16(it.getBaseName()),
+                    it.getFile(), &table, xmlFlags);
             if (err != NO_ERROR) {
                 hasErrors = true;
             }
@@ -1370,7 +1372,8 @@
     if (animators != NULL) {
         ResourceDirIterator it(animators, String8("animator"));
         while ((err=it.next()) == NO_ERROR) {
-            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            err = compileXmlFile(bundle, assets, String16(it.getBaseName()),
+                    it.getFile(), &table, xmlFlags);
             if (err != NO_ERROR) {
                 hasErrors = true;
             }
@@ -1385,7 +1388,8 @@
     if (interpolators != NULL) {
         ResourceDirIterator it(interpolators, String8("interpolator"));
         while ((err=it.next()) == NO_ERROR) {
-            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            err = compileXmlFile(bundle, assets, String16(it.getBaseName()),
+                    it.getFile(), &table, xmlFlags);
             if (err != NO_ERROR) {
                 hasErrors = true;
             }
@@ -1400,7 +1404,8 @@
     if (transitions != NULL) {
         ResourceDirIterator it(transitions, String8("transition"));
         while ((err=it.next()) == NO_ERROR) {
-            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            err = compileXmlFile(bundle, assets, String16(it.getBaseName()),
+                    it.getFile(), &table, xmlFlags);
             if (err != NO_ERROR) {
                 hasErrors = true;
             }
@@ -1415,7 +1420,8 @@
     if (xmls != NULL) {
         ResourceDirIterator it(xmls, String8("xml"));
         while ((err=it.next()) == NO_ERROR) {
-            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            err = compileXmlFile(bundle, assets, String16(it.getBaseName()),
+                    it.getFile(), &table, xmlFlags);
             if (err != NO_ERROR) {
                 hasErrors = true;
             }
@@ -1430,7 +1436,7 @@
     if (drawables != NULL) {
         ResourceDirIterator it(drawables, String8("drawable"));
         while ((err=it.next()) == NO_ERROR) {
-            err = postProcessImage(assets, &table, it.getFile());
+            err = postProcessImage(bundle, assets, &table, it.getFile());
             if (err != NO_ERROR) {
                 hasErrors = true;
             }
@@ -1445,7 +1451,8 @@
     if (colors != NULL) {
         ResourceDirIterator it(colors, String8("color"));
         while ((err=it.next()) == NO_ERROR) {
-            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            err = compileXmlFile(bundle, assets, String16(it.getBaseName()),
+                    it.getFile(), &table, xmlFlags);
             if (err != NO_ERROR) {
                 hasErrors = true;
             }
@@ -1461,7 +1468,8 @@
         ResourceDirIterator it(menus, String8("menu"));
         while ((err=it.next()) == NO_ERROR) {
             String8 src = it.getFile()->getPrintableSource();
-            err = compileXmlFile(assets, it.getFile(), &table, xmlFlags);
+            err = compileXmlFile(bundle, assets, String16(it.getBaseName()),
+                    it.getFile(), &table, xmlFlags);
             if (err == NO_ERROR) {
                 ResXMLTree block;
                 block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true);
@@ -1477,6 +1485,22 @@
         err = NO_ERROR;
     }
 
+    // Now compile any generated resources.
+    std::queue<CompileResourceWorkItem>& workQueue = table.getWorkQueue();
+    while (!workQueue.empty()) {
+        CompileResourceWorkItem& workItem = workQueue.front();
+        err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.file, &table, xmlFlags);
+        if (err == NO_ERROR) {
+            assets->addResource(workItem.resPath.getPathLeaf(),
+                    workItem.resPath,
+                    workItem.file,
+                    workItem.file->getResourceType());
+        } else {
+            hasErrors = true;
+        }
+        workQueue.pop();
+    }
+
     if (table.validateLocalizations()) {
         hasErrors = true;
     }
@@ -1509,7 +1533,7 @@
     if (err < NO_ERROR) {
         return err;
     }
-    err = compileXmlFile(assets, manifestTree, manifestFile, &table);
+    err = compileXmlFile(bundle, assets, String16(), manifestTree, manifestFile, &table);
     if (err < NO_ERROR) {
         return err;
     }
@@ -1599,7 +1623,7 @@
     sp<AaptFile> outManifestFile = new AaptFile(manifestFile->getSourceFile(),
             manifestFile->getGroupEntry(),
             manifestFile->getResourceType());
-    err = compileXmlFile(assets, manifestFile,
+    err = compileXmlFile(bundle, assets, String16(), manifestFile,
             outManifestFile, &table,
             XML_COMPILE_ASSIGN_ATTRIBUTE_IDS
             | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES);
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 8c9efc9..b8c3454 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -17,7 +17,9 @@
 
 #define NOISY(x) //x
 
-status_t compileXmlFile(const sp<AaptAssets>& assets,
+status_t compileXmlFile(const Bundle* bundle,
+                        const sp<AaptAssets>& assets,
+                        const String16& resourceName,
                         const sp<AaptFile>& target,
                         ResourceTable* table,
                         int options)
@@ -27,10 +29,12 @@
         return UNKNOWN_ERROR;
     }
 
-    return compileXmlFile(assets, root, target, table, options);
+    return compileXmlFile(bundle, assets, resourceName, root, target, table, options);
 }
 
-status_t compileXmlFile(const sp<AaptAssets>& assets,
+status_t compileXmlFile(const Bundle* bundle,
+                        const sp<AaptAssets>& assets,
+                        const String16& resourceName,
                         const sp<AaptFile>& target,
                         const sp<AaptFile>& outTarget,
                         ResourceTable* table,
@@ -41,10 +45,12 @@
         return UNKNOWN_ERROR;
     }
     
-    return compileXmlFile(assets, root, outTarget, table, options);
+    return compileXmlFile(bundle, assets, resourceName, root, outTarget, table, options);
 }
 
-status_t compileXmlFile(const sp<AaptAssets>& assets,
+status_t compileXmlFile(const Bundle* bundle,
+                        const sp<AaptAssets>& assets,
+                        const String16& resourceName,
                         const sp<XMLNode>& root,
                         const sp<AaptFile>& target,
                         ResourceTable* table,
@@ -77,6 +83,10 @@
     if (hasErrors) {
         return UNKNOWN_ERROR;
     }
+
+    if (table->modifyForCompat(bundle, resourceName, target, root) != NO_ERROR) {
+        return UNKNOWN_ERROR;
+    }
     
     NOISY(printf("Input XML Resource:\n"));
     NOISY(root->print());
@@ -4028,6 +4038,39 @@
     return t->getEntry(name, sourcePos, config, doSetIndex, overlay, mBundle->getAutoAddOverlay());
 }
 
+sp<ResourceTable::ConfigList> ResourceTable::getConfigList(const String16& package,
+        const String16& type, const String16& name) const
+{
+    const size_t packageCount = mOrderedPackages.size();
+    for (size_t pi = 0; pi < packageCount; pi++) {
+        const sp<Package>& p = mOrderedPackages[pi];
+        if (p == NULL || p->getName() != package) {
+            continue;
+        }
+
+        const Vector<sp<Type> >& types = p->getOrderedTypes();
+        const size_t typeCount = types.size();
+        for (size_t ti = 0; ti < typeCount; ti++) {
+            const sp<Type>& t = types[ti];
+            if (t == NULL || t->getName() != type) {
+                continue;
+            }
+
+            const Vector<sp<ConfigList> >& configs = t->getOrderedConfigs();
+            const size_t configCount = configs.size();
+            for (size_t ci = 0; ci < configCount; ci++) {
+                const sp<ConfigList>& cl = configs[ci];
+                if (cl == NULL || cl->getName() != name) {
+                    continue;
+                }
+
+                return cl;
+            }
+        }
+    }
+    return NULL;
+}
+
 sp<const ResourceTable::Entry> ResourceTable::getEntry(uint32_t resID,
                                                        const ResTable_config* config) const
 {
@@ -4157,6 +4200,22 @@
         (attrId & 0x0000ffff) >= (baseAttrId & 0x0000ffff);
 }
 
+static bool isMinSdkVersionLOrAbove(const Bundle* bundle) {
+    if (bundle->getMinSdkVersion() != NULL && strlen(bundle->getMinSdkVersion()) > 0) {
+        const char firstChar = bundle->getMinSdkVersion()[0];
+        if (firstChar >= 'L' && firstChar <= 'Z') {
+            // L is the code-name for the v21 release.
+            return true;
+        }
+
+        const int minSdk = atoi(bundle->getMinSdkVersion());
+        if (minSdk >= SDK_L) {
+            return true;
+        }
+    }
+    return false;
+}
+
 /**
  * Modifies the entries in the resource table to account for compatibility
  * issues with older versions of Android.
@@ -4200,19 +4259,10 @@
  * attribute will be respected.
  */
 status_t ResourceTable::modifyForCompat(const Bundle* bundle) {
-    if (bundle->getMinSdkVersion() != NULL) {
+    if (isMinSdkVersionLOrAbove(bundle)) {
         // If this app will only ever run on L+ devices,
         // we don't need to do any compatibility work.
-
-        if (String8("L") == bundle->getMinSdkVersion()) {
-            // Code-name for the v21 release.
-            return NO_ERROR;
-        }
-
-        const int minSdk = atoi(bundle->getMinSdkVersion());
-        if (minSdk >= SDK_L) {
-            return NO_ERROR;
-        }
+        return NO_ERROR;
     }
 
     const String16 attr16("attr");
@@ -4309,3 +4359,104 @@
     }
     return NO_ERROR;
 }
+
+status_t ResourceTable::modifyForCompat(const Bundle* bundle,
+                                        const String16& resourceName,
+                                        const sp<AaptFile>& target,
+                                        const sp<XMLNode>& root) {
+    if (isMinSdkVersionLOrAbove(bundle)) {
+        return NO_ERROR;
+    }
+
+    if (target->getResourceType() == "" || target->getGroupEntry().toParams().sdkVersion >= SDK_L) {
+        // Skip resources that have no type (AndroidManifest.xml) or are already version qualified with v21
+        // or higher.
+        return NO_ERROR;
+    }
+
+    Vector<key_value_pair_t<sp<XMLNode>, size_t> > attrsToRemove;
+
+    Vector<sp<XMLNode> > nodesToVisit;
+    nodesToVisit.push(root);
+    while (!nodesToVisit.isEmpty()) {
+        sp<XMLNode> node = nodesToVisit.top();
+        nodesToVisit.pop();
+
+        const Vector<XMLNode::attribute_entry>& attrs = node->getAttributes();
+        const size_t attrCount = attrs.size();
+        for (size_t i = 0; i < attrCount; i++) {
+            const XMLNode::attribute_entry& attr = attrs[i];
+            if (isAttributeFromL(attr.nameResId)) {
+                attrsToRemove.add(key_value_pair_t<sp<XMLNode>, size_t>(node, i));
+            }
+        }
+
+        // Schedule a visit to the children.
+        const Vector<sp<XMLNode> >& children = node->getChildren();
+        const size_t childCount = children.size();
+        for (size_t i = 0; i < childCount; i++) {
+            nodesToVisit.push(children[i]);
+        }
+    }
+
+    if (attrsToRemove.isEmpty()) {
+        return NO_ERROR;
+    }
+
+    ConfigDescription newConfig(target->getGroupEntry().toParams());
+    newConfig.sdkVersion = SDK_L;
+
+    // Look to see if we already have an overriding v21 configuration.
+    sp<ConfigList> cl = getConfigList(String16(mAssets->getPackage()),
+            String16(target->getResourceType()), resourceName);
+    if (cl->getEntries().indexOfKey(newConfig) < 0) {
+        // We don't have an overriding entry for v21, so we must duplicate this one.
+        sp<XMLNode> newRoot = root->clone();
+        sp<AaptFile> newFile = new AaptFile(target->getSourceFile(),
+                AaptGroupEntry(newConfig), target->getResourceType());
+        String8 resPath = String8::format("res/%s/%s",
+                newFile->getGroupEntry().toDirName(target->getResourceType()).string(),
+                target->getPath().getPathLeaf().string());
+        resPath.convertToResPath();
+
+        // Add a resource table entry.
+        SourcePos(target->getSourceFile(), -1).printf(
+                "using v%d attributes; synthesizing resource %s:%s/%s for configuration %s.",
+                SDK_L,
+                mAssets->getPackage().string(),
+                newFile->getResourceType().string(),
+                String8(resourceName).string(),
+                newConfig.toString().string());
+
+        addEntry(SourcePos(),
+                String16(mAssets->getPackage()),
+                String16(target->getResourceType()),
+                resourceName,
+                String16(resPath),
+                NULL,
+                &newConfig);
+
+        // Schedule this to be compiled.
+        CompileResourceWorkItem item;
+        item.resourceName = resourceName;
+        item.resPath = resPath;
+        item.file = newFile;
+        mWorkQueue.push(item);
+    }
+
+    const size_t removeCount = attrsToRemove.size();
+    for (size_t i = 0; i < removeCount; i++) {
+        sp<XMLNode> node = attrsToRemove[i].key;
+        size_t attrIndex = attrsToRemove[i].value;
+        const XMLNode::attribute_entry& ae = node->getAttributes()[attrIndex];
+        SourcePos(node->getFilename(), node->getStartLineNumber()).printf(
+                "removing attribute %s%s%s from <%s>",
+                String8(ae.ns).string(),
+                (ae.ns.size() == 0 ? "" : ":"),
+                String8(ae.name).string(),
+                String8(node->getElementName()).string());
+        node->removeAttribute(attrIndex);
+    }
+
+    return NO_ERROR;
+}
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index 025a868..c548a85 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -12,8 +12,9 @@
 #include "SourcePos.h"
 #include "ResourceFilter.h"
 
-#include <set>
 #include <map>
+#include <queue>
+#include <set>
 
 using namespace std;
 
@@ -33,18 +34,24 @@
             | XML_COMPILE_STRIP_WHITESPACE | XML_COMPILE_STRIP_RAW_VALUES
 };
 
-status_t compileXmlFile(const sp<AaptAssets>& assets,
+status_t compileXmlFile(const Bundle* bundle,
+                        const sp<AaptAssets>& assets,
+                        const String16& resourceName,
                         const sp<AaptFile>& target,
                         ResourceTable* table,
                         int options = XML_COMPILE_STANDARD_RESOURCE);
 
-status_t compileXmlFile(const sp<AaptAssets>& assets,
+status_t compileXmlFile(const Bundle* bundle,
+                        const sp<AaptAssets>& assets,
+                        const String16& resourceName,
                         const sp<AaptFile>& target,
                         const sp<AaptFile>& outTarget,
                         ResourceTable* table,
                         int options = XML_COMPILE_STANDARD_RESOURCE);
 
-status_t compileXmlFile(const sp<AaptAssets>& assets,
+status_t compileXmlFile(const Bundle* bundle,
+                        const sp<AaptAssets>& assets,
+                        const String16& resourceName,
                         const sp<XMLNode>& xmlTree,
                         const sp<AaptFile>& target,
                         ResourceTable* table,
@@ -71,6 +78,14 @@
     }
 };
 
+// Holds the necessary information to compile the
+// resource.
+struct CompileResourceWorkItem {
+    String16 resourceName;
+    String8 resPath;
+    sp<AaptFile> file;
+};
+
 class ResourceTable : public ResTable::Accessor
 {
 public:
@@ -92,6 +107,18 @@
         return mAssetsPackage;
     }
 
+    /**
+     * Returns the queue of resources that need to be compiled.
+     * This is only used for resources that have been generated
+     * during the compilation phase. If they were just added
+     * to the AaptAssets, then they may be skipped over
+     * and would mess up iteration order for the existing
+     * resources.
+     */
+    queue<CompileResourceWorkItem>& getWorkQueue() {
+        return mWorkQueue;
+    }
+
     status_t addIncludedResources(Bundle* bundle, const sp<AaptAssets>& assets);
 
     status_t addPublic(const SourcePos& pos,
@@ -166,6 +193,10 @@
     bool hasResources() const;
 
     status_t modifyForCompat(const Bundle* bundle);
+    status_t modifyForCompat(const Bundle* bundle,
+                             const String16& resourceName,
+                             const sp<AaptFile>& file,
+                             const sp<XMLNode>& root);
 
     sp<AaptFile> flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
             const bool isBase);
@@ -527,6 +558,9 @@
                        bool doSetIndex = false);
     sp<const Entry> getEntry(uint32_t resID,
                              const ResTable_config* config = NULL) const;
+    sp<ConfigList> getConfigList(const String16& package,
+                                 const String16& type,
+                                 const String16& name) const;
     const Item* getItem(uint32_t resID, uint32_t attrID) const;
     bool getItemValue(uint32_t resID, uint32_t attrID,
                       Res_value* outValue);
@@ -545,6 +579,7 @@
     
     // key = string resource name, value = set of locales in which that name is defined
     map<String16, map<String8, SourcePos> > mLocalizations;
+    queue<CompileResourceWorkItem> mWorkQueue;
 };
 
 #endif
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index 607d419..51a4154 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -621,6 +621,12 @@
     return state.root;
 }
 
+XMLNode::XMLNode()
+    : mNextAttributeIndex(0x80000000)
+    , mStartLineNumber(0)
+    , mEndLineNumber(0)
+    , mUTF8(false) {}
+
 XMLNode::XMLNode(const String8& filename, const String16& s1, const String16& s2, bool isNamespace)
     : mNextAttributeIndex(0x80000000)
     , mFilename(filename)
@@ -810,6 +816,32 @@
     return NO_ERROR;
 }
 
+status_t XMLNode::removeAttribute(size_t index)
+{
+    if (getType() == TYPE_CDATA) {
+        return UNKNOWN_ERROR;
+    }
+
+    if (index >= mAttributes.size()) {
+        return UNKNOWN_ERROR;
+    }
+
+    const attribute_entry& e = mAttributes[index];
+    const uint32_t key = e.nameResId ? e.nameResId : e.index;
+    mAttributeOrder.removeItem(key);
+    mAttributes.removeAt(index);
+
+    // Shift all the indices.
+    const size_t attrCount = mAttributeOrder.size();
+    for (size_t i = 0; i < attrCount; i++) {
+        size_t attrIdx = mAttributeOrder[i];
+        if (attrIdx > index) {
+            mAttributeOrder.replaceValueAt(i, attrIdx - 1);
+        }
+    }
+    return NO_ERROR;
+}
+
 void XMLNode::setAttributeResID(size_t attrIdx, uint32_t resId)
 {
     attribute_entry& e = mAttributes.editItemAt(attrIdx);
@@ -999,6 +1031,30 @@
     return hasErrors ? UNKNOWN_ERROR : NO_ERROR;
 }
 
+sp<XMLNode> XMLNode::clone() const {
+    sp<XMLNode> copy = new XMLNode();
+    copy->mNamespacePrefix = mNamespacePrefix;
+    copy->mNamespaceUri = mNamespaceUri;
+    copy->mElementName = mElementName;
+
+    const size_t childCount = mChildren.size();
+    for (size_t i = 0; i < childCount; i++) {
+        copy->mChildren.add(mChildren[i]->clone());
+    }
+
+    copy->mAttributes = mAttributes;
+    copy->mAttributeOrder = mAttributeOrder;
+    copy->mNextAttributeIndex = mNextAttributeIndex;
+    copy->mChars = mChars;
+    memcpy(&copy->mCharsValue, &mCharsValue, sizeof(mCharsValue));
+    copy->mComment = mComment;
+    copy->mFilename = mFilename;
+    copy->mStartLineNumber = mStartLineNumber;
+    copy->mEndLineNumber = mEndLineNumber;
+    copy->mUTF8 = mUTF8;
+    return copy;
+}
+
 status_t XMLNode::flatten(const sp<AaptFile>& dest,
         bool stripComments, bool stripRawValues) const
 {
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index ccbf9f4..3161f65 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -116,6 +116,8 @@
     status_t addAttribute(const String16& ns, const String16& name,
                           const String16& value);
 
+    status_t removeAttribute(size_t index);
+
     void setAttributeResID(size_t attrIdx, uint32_t resId);
 
     status_t appendChars(const String16& chars);
@@ -137,6 +139,8 @@
     status_t flatten(const sp<AaptFile>& dest, bool stripComments,
             bool stripRawValues) const;
 
+    sp<XMLNode> clone() const;
+
     void print(int indent=0);
 
 private:
@@ -163,6 +167,9 @@
     static void XMLCALL
     commentData(void *userData, const char *comment);
     
+    // For cloning
+    XMLNode();
+
     // Creating an element node.
     XMLNode(const String8& filename, const String16& s1, const String16& s2, bool isNamespace);
     
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index e80a8f4..29656c9 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -59,7 +59,7 @@
     public int frequency;
 
     /**
-     * Time Synchronization Function (tsf) timestamp in microseconds when
+     * timestamp in microseconds (since boot) when
      * this result was last seen.
      */
     public long timestamp;
@@ -107,6 +107,12 @@
     public int autoJoinStatus;
 
     /**
+     * num IP configuration failures
+     * @hide
+     */
+    public int numIpConfigFailures;
+
+    /**
      * @hide
      * Last time we blacklisted the ScanResult
      */
@@ -256,6 +262,7 @@
             untrusted = source.untrusted;
             numConnection = source.numConnection;
             numUsage = source.numUsage;
+            numIpConfigFailures = source.numIpConfigFailures;
         }
     }
 
@@ -320,6 +327,7 @@
         dest.writeInt(untrusted ? 1 : 0);
         dest.writeInt(numConnection);
         dest.writeInt(numUsage);
+        dest.writeInt(numIpConfigFailures);
         if (informationElements != null) {
             dest.writeInt(informationElements.length);
             for (int i = 0; i < informationElements.length; i++) {
@@ -355,6 +363,7 @@
                 sr.untrusted = in.readInt() != 0;
                 sr.numConnection = in.readInt();
                 sr.numUsage = in.readInt();
+                sr.numIpConfigFailures = in.readInt();
                 int n = in.readInt();
                 if (n != 0) {
                     sr.informationElements = new InformationElement[n];
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index d27c2f7..4f5f31a 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -203,6 +203,12 @@
     public int status;
 
     /**
+     * The configuration needs to be written to networkHistory.txt
+     * @hide
+     */
+    public boolean dirty;
+
+    /**
      * The code referring to a reason for disabling the network
      * Valid when {@link #status} == Status.DISABLED
      * @hide
@@ -621,6 +627,18 @@
 
     /**
      * @hide
+     * Number of IP config failures
+     */
+    public int numIpConfigFailures;
+
+    /**
+     * @hide
+     * Number of Auth failures
+     */
+    public int numAuthFailures;
+
+    /**
+     * @hide
      * Last time we blacklisted the configuration
      */
     public long blackListTimestamp;
@@ -884,7 +902,10 @@
         }  else if (status > autoJoinStatus) {
             blackListTimestamp = System.currentTimeMillis();
         }
-        autoJoinStatus = status;
+        if (status != autoJoinStatus) {
+            autoJoinStatus = status;
+            dirty = true;
+        }
     }
 
     @Override
@@ -893,7 +914,7 @@
         if (this.status == WifiConfiguration.Status.CURRENT) {
             sbuf.append("* ");
         } else if (this.status == WifiConfiguration.Status.DISABLED) {
-            sbuf.append("- DSBLE: ").append(this.disableReason).append(" ");
+            sbuf.append("- DSBLE");
         }
         sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
                 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN).
@@ -902,8 +923,20 @@
         if (this.numConnectionFailures > 0) {
             sbuf.append(" numConnectFailures ").append(this.numConnectionFailures).append("\n");
         }
+        if (this.numIpConfigFailures > 0) {
+            sbuf.append(" numIpConfigFailures ").append(this.numIpConfigFailures).append("\n");
+        }
+        if (this.numAuthFailures > 0) {
+            sbuf.append(" numAuthFailures ").append(this.numAuthFailures).append("\n");
+        }
         if (this.autoJoinStatus > 0) {
-            sbuf.append(" autoJoinStatus ").append(this.numConnectionFailures).append("\n");
+            sbuf.append(" autoJoinStatus ").append(this.autoJoinStatus).append("\n");
+        }
+        if (this.disableReason > 0) {
+            sbuf.append(" disableReason ").append(this.disableReason).append("\n");
+        }
+        if (this.numAssociation > 0) {
+            sbuf.append(" numAssociation ").append(this.numAssociation).append("\n");
         }
         if (this.didSelfAdd) sbuf.append(" didSelfAdd");
         if (this.selfAdded) sbuf.append(" selfAdded");
@@ -1028,10 +1061,17 @@
             }
         }
         if (this.scanResultCache != null) {
-            sbuf.append("scan cache:  ");
+            sbuf.append("Scan Cache:  ");
             for(ScanResult result : this.scanResultCache.values()) {
                 sbuf.append("{").append(result.BSSID).append(",").append(result.frequency);
-                sbuf.append(",").append(result.level).append(",st=");
+                sbuf.append(",").append(result.level);
+                if (result.autoJoinStatus > 0) {
+                    sbuf.append(",st=").append(result.autoJoinStatus);
+                }
+                if (result.numIpConfigFailures > 0) {
+                    sbuf.append(",ipfail=");
+                    sbuf.append(result.numIpConfigFailures);
+                }
                 sbuf.append(result.autoJoinStatus).append("} ");
             }
             sbuf.append('\n');
@@ -1356,6 +1396,8 @@
             lastDisconnected = source.lastDisconnected;
             lastConnectionFailure = source.lastConnectionFailure;
             numConnectionFailures = source.numConnectionFailures;
+            numIpConfigFailures = source.numIpConfigFailures;
+            numAuthFailures = source.numAuthFailures;
             numScorerOverride = source.numScorerOverride;
             numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork;
             numAssociation = source.numAssociation;
@@ -1370,6 +1412,7 @@
             autoJoinUseAggressiveJoinAttemptThreshold
                     = source.autoJoinUseAggressiveJoinAttemptThreshold;
             autoJoinBailedDueToLowRssi = source.autoJoinBailedDueToLowRssi;
+            dirty = source.dirty;
         }
     }
 
@@ -1420,6 +1463,8 @@
         dest.writeLong(blackListTimestamp);
         dest.writeLong(lastConnectionFailure);
         dest.writeInt(numConnectionFailures);
+        dest.writeInt(numIpConfigFailures);
+        dest.writeInt(numAuthFailures);
         dest.writeInt(numScorerOverride);
         dest.writeInt(numScorerOverrideAndSwitchedNetwork);
         dest.writeInt(numAssociation);
@@ -1478,6 +1523,8 @@
                 config.blackListTimestamp = in.readLong();
                 config.lastConnectionFailure = in.readLong();
                 config.numConnectionFailures = in.readInt();
+                config.numIpConfigFailures = in.readInt();
+                config.numAuthFailures = in.readInt();
                 config.numScorerOverride = in.readInt();
                 config.numScorerOverrideAndSwitchedNetwork = in.readInt();
                 config.numAssociation = in.readInt();