Merge "Remove activitystrings.xml from localized resource directories"
diff --git a/api/current.txt b/api/current.txt
index 2eea8ac..7ebabe4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -382,6 +382,7 @@
     field public static final int codes = 16843330; // 0x1010242
     field public static final int collapseColumns = 16843083; // 0x101014b
     field public static final int color = 16843173; // 0x10101a5
+    field public static final int colorAccent = 16843842; // 0x1010442
     field public static final int colorActivatedHighlight = 16843664; // 0x1010390
     field public static final int colorBackground = 16842801; // 0x1010031
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
@@ -397,6 +398,9 @@
     field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
     field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
     field public static final int colorPressedHighlight = 16843661; // 0x101038d
+    field public static final int colorPrimary = 16843840; // 0x1010440
+    field public static final int colorPrimaryDark = 16843841; // 0x1010441
+    field public static final int colorPrimaryLight = 16843839; // 0x101043f
     field public static final int columnCount = 16843639; // 0x1010377
     field public static final int columnDelay = 16843215; // 0x10101cf
     field public static final int columnOrderPreserved = 16843640; // 0x1010378
@@ -1650,7 +1654,10 @@
     field public static final int decelerate_cubic = 17563651; // 0x10c0003
     field public static final int decelerate_quad = 17563649; // 0x10c0001
     field public static final int decelerate_quint = 17563653; // 0x10c0005
+    field public static final int fast_out_linear_in = 17563663; // 0x10c000f
+    field public static final int fast_out_slow_in = 17563661; // 0x10c000d
     field public static final int linear = 17563659; // 0x10c000b
+    field public static final int linear_out_slow_in = 17563662; // 0x10c000e
     field public static final int overshoot = 17563656; // 0x10c0008
   }
 
@@ -6464,6 +6471,7 @@
     field public static final java.lang.String ALARM_SERVICE = "alarm";
     field public static final java.lang.String APP_OPS_SERVICE = "appops";
     field public static final java.lang.String AUDIO_SERVICE = "audio";
+    field public static final java.lang.String BATTERY_SERVICE = "batterymanager";
     field public static final int BIND_ABOVE_CLIENT = 8; // 0x8
     field public static final int BIND_ADJUST_WITH_ACTIVITY = 128; // 0x80
     field public static final int BIND_ALLOW_OOM_MANAGEMENT = 16; // 0x10
@@ -15808,10 +15816,13 @@
   public final class NsdServiceInfo implements android.os.Parcelable {
     ctor public NsdServiceInfo();
     method public int describeContents();
+    method public java.util.Map<java.lang.String, byte[]> getAttributes();
     method public java.net.InetAddress getHost();
     method public int getPort();
     method public java.lang.String getServiceName();
     method public java.lang.String getServiceType();
+    method public void removeAttribute(java.lang.String);
+    method public void setAttribute(java.lang.String, java.lang.String);
     method public void setHost(java.net.InetAddress);
     method public void setPort(int);
     method public void setServiceName(java.lang.String);
@@ -18971,6 +18982,7 @@
 
   public class BatteryManager {
     ctor public BatteryManager();
+    method public android.os.BatteryProperty getProperty(int) throws android.os.RemoteException;
     field public static final int BATTERY_HEALTH_COLD = 7; // 0x7
     field public static final int BATTERY_HEALTH_DEAD = 4; // 0x4
     field public static final int BATTERY_HEALTH_GOOD = 2; // 0x2
@@ -18998,6 +19010,18 @@
     field public static final java.lang.String EXTRA_VOLTAGE = "voltage";
   }
 
+  public class BatteryProperty implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getInt();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CAPACITY = 4; // 0x4
+    field public static final int CHARGE_COUNTER = 1; // 0x1
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int CURRENT_AVERAGE = 3; // 0x3
+    field public static final int CURRENT_NOW = 2; // 0x2
+  }
+
   public class Binder implements android.os.IBinder {
     ctor public Binder();
     method public void attachInterface(android.os.IInterface, java.lang.String);
@@ -23352,6 +23376,67 @@
     field public static final java.lang.String TYPE = "type";
   }
 
+  public final class TvContract {
+    method public static final android.net.Uri buildChannelUri(long);
+    method public static final android.net.Uri buildProgramUri(long);
+    field public static final java.lang.String AUTHORITY = "com.android.tv";
+  }
+
+  public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
+    field public static final java.lang.String PACKAGE_NAME = "package_name";
+  }
+
+  public static final class TvContract.Channels implements android.provider.TvContract.BaseTvColumns {
+    field public static final java.lang.String BROWSABLE = "browsable";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.android.tv.channels";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.android.tv.channels";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATA = "data";
+    field public static final java.lang.String DESCRIPTION = "description";
+    field public static final java.lang.String DISPLAY_NAME = "display_name";
+    field public static final java.lang.String DISPLAY_NUMBER = "display_number";
+    field public static final java.lang.String SERVICE_NAME = "service_name";
+    field public static final java.lang.String TRANSPORT_STREAM_ID = "transport_stream_id";
+    field public static final java.lang.String TYPE = "type";
+    field public static final int TYPE_1SEG = 263168; // 0x40400
+    field public static final int TYPE_ATSC = 196608; // 0x30000
+    field public static final int TYPE_ATSC_2_0 = 196609; // 0x30001
+    field public static final int TYPE_ATSC_M_H = 196864; // 0x30100
+    field public static final int TYPE_CMMB = 327936; // 0x50100
+    field public static final int TYPE_DTMB = 327680; // 0x50000
+    field public static final int TYPE_DVB_C = 131584; // 0x20200
+    field public static final int TYPE_DVB_C2 = 131585; // 0x20201
+    field public static final int TYPE_DVB_H = 131840; // 0x20300
+    field public static final int TYPE_DVB_S = 131328; // 0x20100
+    field public static final int TYPE_DVB_S2 = 131329; // 0x20101
+    field public static final int TYPE_DVB_SH = 132096; // 0x20400
+    field public static final int TYPE_DVB_T = 131072; // 0x20000
+    field public static final int TYPE_DVB_T2 = 131073; // 0x20001
+    field public static final int TYPE_ISDB_C = 262912; // 0x40300
+    field public static final int TYPE_ISDB_S = 262656; // 0x40200
+    field public static final int TYPE_ISDB_T = 262144; // 0x40000
+    field public static final int TYPE_ISDB_TB = 262400; // 0x40100
+    field public static final int TYPE_OTHER = 0; // 0x0
+    field public static final int TYPE_PASSTHROUGH = 65536; // 0x10000
+    field public static final int TYPE_S_DMB = 393472; // 0x60100
+    field public static final int TYPE_T_DMB = 393216; // 0x60000
+    field public static final java.lang.String VERSION_NUMBER = "version_number";
+  }
+
+  public static final class TvContract.Programs implements android.provider.TvContract.BaseTvColumns {
+    field public static final java.lang.String CHANNEL_ID = "channel_id";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.android.tv.programs";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.android.tv.programs";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATA = "data";
+    field public static final java.lang.String DESCRIPTION = "description";
+    field public static final java.lang.String END_TIME_UTC_MILLIS = "end_time_utc_millis";
+    field public static final java.lang.String LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String TITLE = "title";
+    field public static final java.lang.String VERSION_NUMBER = "version_number";
+  }
+
   public class UserDictionary {
     ctor public UserDictionary();
     field public static final java.lang.String AUTHORITY = "user_dictionary";
@@ -27750,14 +27835,6 @@
     method public abstract boolean onTune(android.net.Uri);
   }
 
-  public abstract class TvInputSession {
-    ctor public TvInputSession();
-    method public void release();
-    method public void setSurface(android.view.Surface);
-    method public void setVolume(float);
-    method public void tune(android.net.Uri);
-  }
-
 }
 
 package android.util {
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index c520b58..859d83b 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -97,7 +97,7 @@
 
     virtual void onExit(int code)
     {
-        if (mClassName == NULL) {
+        if (mClassName.isEmpty()) {
             // if zygote
             IPCThreadState::self()->stopProcess();
         }
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 466dcd4..948c9a2 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -26,9 +26,17 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 import android.text.TextUtils;
 
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import libcore.io.IoUtils;
+
 /**
  * This class is a command line utility for manipulating content. A client
  * can insert, update, and remove records in a content provider. For example,
@@ -109,6 +117,12 @@
         + "  <METHOD> is the name of a provider-defined method\n"
         + "  <ARG> is an optional string argument\n"
         + "  <BINDING> is like --bind above, typed data of the form <KEY>:{b,s,i,l,f,d}:<VAL>\n"
+        + "\n"
+        + "usage: adb shell content read --uri <URI> [--user <USER_ID>]\n"
+        + "  Example:\n"
+        + "  # cat default ringtone to a file, then pull to host\n"
+        + "  adb shell 'content read --uri content://settings/system/ringtone >"
+                + " /mnt/sdcard/tmp.ogg' && adb pull /mnt/sdcard/tmp.ogg\n"
         + "\n";
 
     private static class Parser {
@@ -117,6 +131,7 @@
         private static final String ARGUMENT_UPDATE = "update";
         private static final String ARGUMENT_QUERY = "query";
         private static final String ARGUMENT_CALL = "call";
+        private static final String ARGUMENT_READ = "read";
         private static final String ARGUMENT_WHERE = "--where";
         private static final String ARGUMENT_BIND = "--bind";
         private static final String ARGUMENT_URI = "--uri";
@@ -154,6 +169,8 @@
                     return parseQueryCommand();
                 } else if (ARGUMENT_CALL.equals(operation)) {
                     return parseCallCommand();
+                } else if (ARGUMENT_READ.equals(operation)) {
+                    return parseReadCommand();
                 } else {
                     throw new IllegalArgumentException("Unsupported operation: " + operation);
                 }
@@ -273,6 +290,25 @@
             return new CallCommand(uri, userId, method, arg, values);
         }
 
+        private ReadCommand parseReadCommand() {
+            Uri uri = null;
+            int userId = UserHandle.USER_OWNER;
+            for (String argument; (argument = mTokenizer.nextArg())!= null;) {
+                if (ARGUMENT_URI.equals(argument)) {
+                    uri = Uri.parse(argumentValueRequired(argument));
+                } else if (ARGUMENT_USER.equals(argument)) {
+                    userId = Integer.parseInt(argumentValueRequired(argument));
+                } else {
+                    throw new IllegalArgumentException("Unsupported argument: " + argument);
+                }
+            }
+            if (uri == null) {
+                throw new IllegalArgumentException("Content provider URI not specified."
+                        + " Did you specify --uri argument?");
+            }
+            return new ReadCommand(uri, userId);
+        }
+
         public QueryCommand parseQueryCommand() {
             Uri uri = null;
             int userId = UserHandle.USER_OWNER;
@@ -458,6 +494,31 @@
         }
     }
 
+    private static class ReadCommand extends Command {
+        public ReadCommand(Uri uri, int userId) {
+            super(uri, userId);
+        }
+
+        @Override
+        public void onExecute(IContentProvider provider) throws Exception {
+            final ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null);
+            copy(new FileInputStream(fd.getFileDescriptor()), System.out);
+        }
+
+        private static void copy(InputStream is, OutputStream os) throws IOException {
+            final byte[] buffer = new byte[8 * 1024];
+            int read;
+            try {
+                while ((read = is.read(buffer)) > -1) {
+                    os.write(buffer, 0, read);
+                }
+            } finally {
+                IoUtils.closeQuietly(is);
+                IoUtils.closeQuietly(os);
+            }
+        }
+    }
+
     private static class QueryCommand extends DeleteCommand {
         final String[] mProjection;
         final String mSortOrder;
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 34b0f3a..9818c33 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -1239,6 +1239,8 @@
 
         public LayoutParams(int width, int height, int gravity) {
             super(width, height);
+
+            this.gravity = gravity;
         }
 
         public LayoutParams(int gravity) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1c02102..77b5485 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -72,6 +72,7 @@
 import android.net.IConnectivityManager;
 import android.net.INetworkPolicyManager;
 import android.net.NetworkPolicyManager;
+import android.net.NetworkScoreManager;
 import android.net.Uri;
 import android.net.nsd.INsdManager;
 import android.net.nsd.NsdManager;
@@ -82,6 +83,7 @@
 import android.net.wifi.p2p.IWifiP2pManager;
 import android.net.wifi.p2p.WifiP2pManager;
 import android.nfc.NfcManager;
+import android.os.BatteryManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
@@ -404,6 +406,11 @@
                     return new DownloadManager(ctx.getContentResolver(), ctx.getPackageName());
                 }});
 
+        registerService(BATTERY_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                    return new BatteryManager();
+                }});
+
         registerService(NFC_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     return new NfcManager(ctx);
@@ -648,6 +655,12 @@
                 ITvInputManager service = ITvInputManager.Stub.asInterface(iBinder);
                 return new TvInputManager(service, UserHandle.myUserId());
             }});
+
+        registerService(NETWORK_SCORE_SERVICE, new ServiceFetcher() {
+            public Object createService(ContextImpl ctx) {
+                return new NetworkScoreManager(ctx);
+            }
+        });
     }
 
     static ContextImpl getImpl(Context context) {
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 9911467..bb6eeda 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -31,7 +31,7 @@
 
     void enqueueToast(String pkg, ITransientNotification callback, int duration);
     void cancelToast(String pkg, ITransientNotification callback);
-    void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id,
+    void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
             in Notification notification, inout int[] idReceived, int userId);
     void cancelNotificationWithTag(String pkg, String tag, int id, int userId);
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ed0cc23..ff92d82 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2009,6 +2009,7 @@
             CAMERA_SERVICE,
             PRINT_SERVICE,
             MEDIA_SESSION_SERVICE,
+            BATTERY_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -2060,6 +2061,8 @@
      * <dd> An {@link android.app.UiModeManager} for controlling UI modes.
      * <dt> {@link #DOWNLOAD_SERVICE} ("download")
      * <dd> A {@link android.app.DownloadManager} for requesting HTTP downloads
+     * <dt> {@link #BATTERY_SERVICE} ("batterymanager")
+     * <dd> A {@link android.os.BatteryManager} for managing battery state
      * </dl>
      *
      * <p>Note:  System services obtained via this API may be closely associated with
@@ -2113,6 +2116,8 @@
      * @see android.app.UiModeManager
      * @see #DOWNLOAD_SERVICE
      * @see android.app.DownloadManager
+     * @see #BATTERY_SERVICE
+     * @see android.os.BatteryManager
      */
     public abstract Object getSystemService(@ServiceName @NonNull String name);
 
@@ -2481,6 +2486,14 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.os.BatteryManager} for managing battery state.
+     *
+     * @see #getSystemService
+     */
+    public static final String BATTERY_SERVICE = "batterymanager";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.nfc.NfcManager} for using NFC.
      *
      * @see #getSystemService
@@ -2630,6 +2643,14 @@
     public static final String TV_INPUT_SERVICE = "tv_input";
 
     /**
+     * {@link android.net.NetworkScoreManager} for managing network scoring.
+     * @see #getSystemService
+     * @see android.net.NetworkScoreManager
+     * @hide
+     */
+    public static final String NETWORK_SCORE_SERVICE = "network_score";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4b5616f..8d8d220 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3292,19 +3292,23 @@
         if (packageName == null || packageName.length() == 0) {
             Slog.i(TAG, "verifier package name was null; skipping");
             return null;
-        } else if (encodedPublicKey == null) {
-            Slog.i(TAG, "verifier " + packageName + " public key was null; skipping");
         }
 
-        PublicKey publicKey = parsePublicKey(encodedPublicKey);
-        if (publicKey != null) {
-            return new VerifierInfo(packageName, publicKey);
+        final PublicKey publicKey = parsePublicKey(encodedPublicKey);
+        if (publicKey == null) {
+            Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
+            return null;
         }
 
-        return null;
+        return new VerifierInfo(packageName, publicKey);
     }
 
-    public static final PublicKey parsePublicKey(String encodedPublicKey) {
+    public static final PublicKey parsePublicKey(final String encodedPublicKey) {
+        if (encodedPublicKey == null) {
+            Slog.i(TAG, "Could not parse null public key");
+            return null;
+        }
+
         EncodedKeySpec keySpec;
         try {
             final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 0c0dfe9..b5efa8e 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -857,7 +857,7 @@
          * @hide
          */
         @Override
-        public void vibrate(int owningUid, String owningPackage, long milliseconds,
+        public void vibrate(int uid, String opPkg, long milliseconds,
                 int streamHint) {
             vibrate(new long[] { 0, milliseconds}, -1);
         }
@@ -866,7 +866,7 @@
          * @hide
          */
         @Override
-        public void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat,
+        public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
                 int streamHint) {
             if (repeat >= pattern.length) {
                 throw new ArrayIndexOutOfBoundsException();
diff --git a/core/java/android/net/NetworkKey.aidl b/core/java/android/net/NetworkKey.aidl
new file mode 100644
index 0000000..637075f
--- /dev/null
+++ b/core/java/android/net/NetworkKey.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.net;
+
+parcelable NetworkKey;
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
new file mode 100644
index 0000000..cc3ad3e
--- /dev/null
+++ b/core/java/android/net/NetworkKey.java
@@ -0,0 +1,105 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Information which identifies a specific network.
+ *
+ * @hide
+ */
+public class NetworkKey implements Parcelable {
+
+    /** A wifi network, for which {@link #wifiKey} will be populated. */
+    public static final int TYPE_WIFI = 1;
+
+    /**
+     * The type of this network.
+     * @see #TYPE_WIFI
+     */
+    public final int type;
+
+    /**
+     * Information identifying a Wi-Fi network. Only set when {@link #type} equals
+     * {@link #TYPE_WIFI}.
+     */
+    public final WifiKey wifiKey;
+
+    /**
+     * Construct a new {@link NetworkKey} for a Wi-Fi network.
+     * @param wifiKey the {@link WifiKey} identifying this Wi-Fi network.
+     */
+    public NetworkKey(WifiKey wifiKey) {
+        this.type = TYPE_WIFI;
+        this.wifiKey = wifiKey;
+    }
+
+    private NetworkKey(Parcel in) {
+        type = in.readInt();
+        switch (type) {
+            case TYPE_WIFI:
+                wifiKey = WifiKey.CREATOR.createFromParcel(in);
+                break;
+            default:
+                throw new IllegalArgumentException("Parcel has unknown type: " + type);
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(type);
+        switch (type) {
+            case TYPE_WIFI:
+                wifiKey.writeToParcel(out, flags);
+                break;
+            default:
+                throw new IllegalStateException("NetworkKey has unknown type " + type);
+        }
+    }
+
+    @Override
+    public String toString() {
+        switch (type) {
+            case TYPE_WIFI:
+                return wifiKey.toString();
+            default:
+                // Don't throw an exception here in case someone is logging this object in a catch
+                // block for debugging purposes.
+                return "InvalidKey";
+        }
+    }
+
+    public static final Parcelable.Creator<NetworkKey> CREATOR =
+            new Parcelable.Creator<NetworkKey>() {
+                @Override
+                public NetworkKey createFromParcel(Parcel in) {
+                    return new NetworkKey(in);
+                }
+
+                @Override
+                public NetworkKey[] newArray(int size) {
+                    return new NetworkKey[size];
+                }
+            };
+}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
new file mode 100644
index 0000000..3430547
--- /dev/null
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -0,0 +1,118 @@
+/*
+ * 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.net;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+
+/**
+ * Class that manages communication between network subsystems and a network scorer.
+ *
+ * <p>You can get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(String)}:
+ *
+ * <pre>NetworkScoreManager manager =
+ *     (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE)</pre>
+ *
+ * <p>A network scorer is any application which:
+ * <ul>
+ * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
+ * <li>Includes a receiver for {@link #ACTION_SCORE_NETWORKS} guarded by the
+ *     {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission which scores networks
+ *     and (eventually) calls {@link #updateScores} with the results.
+ * </ul>
+ *
+ * <p>The system keeps track of a default scorer application; at any time, only this application
+ * will receive {@link #ACTION_SCORE_NETWORKS} broadcasts and will be permitted to call
+ * {@link #updateScores}. Applications may determine the current default scorer with
+ * {@link #getDefaultScorerPackage()} and request to change the default scorer by sending an
+ * {@link #ACTION_CHANGE_DEFAULT} broadcast with another scorer.
+ *
+ * @hide
+ */
+public class NetworkScoreManager {
+    /**
+     * Activity action: ask the user to change the default network scorer. This will show a dialog
+     * that asks the user whether they want to replace the current default scorer with the one
+     * specified in {@link #EXTRA_PACKAGE_NAME}. The activity will finish with RESULT_OK if the
+     * default was changed or RESULT_CANCELED if it failed for any reason.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_CHANGE_DEFAULT = "android.net.scoring.CHANGE_DEFAULT";
+
+    /**
+     * Extra used with {@link #ACTION_CHANGE_DEFAULT} to specify the new scorer package. Set with
+     * {@link android.content.Intent#putExtra(String, String)}.
+     */
+    public static final String EXTRA_PACKAGE_NAME = "packageName";
+
+    /**
+     * Broadcast action: new network scores are being requested. This intent will only be delivered
+     * to the current default scorer app. That app is responsible for scoring the networks and
+     * calling {@link #updateScores} when complete. The networks to score are specified in
+     * {@link #EXTRA_NETWORKS_TO_SCORE}, and will generally consist of all networks which have been
+     * configured by the user as well as any open networks.
+     *
+     * <p class="note">This is a protected intent that can only be sent by the system.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
+
+    /**
+     * Extra used with {@link #ACTION_SCORE_NETWORKS} to specify the networks to be scored, as an
+     * array of {@link NetworkKey}s. Can be obtained with
+     * {@link android.content.Intent#getParcelableArrayExtra(String)}}.
+     */
+    public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
+
+    private final Context mContext;
+
+    /** @hide */
+    public NetworkScoreManager(Context context) {
+        mContext = context;
+    }
+
+    /**
+     * Obtain the package name of the current default network scorer.
+     *
+     * At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS}
+     * broadcasts and be allowed to call {@link #updateScores}. Applications may use this method to
+     * determine the current scorer and offer the user the ability to select a different scorer via
+     * the {@link #ACTION_CHANGE_DEFAULT} intent.
+     * @return the full package name of the current default scorer, or null if there is no active
+     *     scorer.
+     */
+    public String getDefaultScorerPackage() {
+        // TODO: Implement.
+        return null;
+    }
+
+    /**
+     * Update network scores.
+     *
+     * This may be called at any time to re-score active networks. Scores will generally be updated
+     * quickly, but if this method is called too frequently, the scores may be held and applied at
+     * a later time.
+     *
+     * @param networks the networks which have been scored by the scorer.
+     * @throws SecurityException if the caller is not the default scorer.
+     */
+    public void updateScores(ScoredNetwork[] networks) throws SecurityException {
+        // TODO: Implement.
+    }
+}
diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java
new file mode 100644
index 0000000..7af7998
--- /dev/null
+++ b/core/java/android/net/RssiCurve.java
@@ -0,0 +1,129 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A curve defining the network score over a range of RSSI values.
+ *
+ * <p>For each RSSI bucket, the score may be any byte. Scores have no absolute meaning and are only
+ * considered relative to other scores assigned by the same scorer. Networks with no score are all
+ * considered equivalent and ranked below any network with a score.
+ *
+ * <p>For example, consider a curve starting at -110 dBm with a bucket width of 10 and the
+ * following buckets: {@code [-20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]}.
+ * This represents a linear curve between -110 dBm and 30 dBm. It scores progressively higher at
+ * stronger signal strengths.
+ *
+ * <p>A network can be assigned a fixed score independent of RSSI by setting
+ * {@link #rssiBuckets} to a one-byte array whose element is the fixed score. {@link #start}
+ * should be set to the lowest RSSI value at which this fixed score should apply, and
+ * {@link #bucketWidth} should be set such that {@code start + bucketWidth} is equal to the
+ * highest RSSI value at which this fixed score should apply.
+ *
+ * <p>Note that RSSI values below -110 dBm or above 30 dBm are unlikely to cause any difference
+ * in connectivity behavior from those endpoints. That is, the connectivity framework will treat
+ * a network with a -120 dBm signal exactly as it would treat one with a -110 dBm signal.
+ * Therefore, graphs which specify scores outside this range may be truncated to this range by
+ * the system.
+ *
+ * @see ScoredNetwork
+ * @hide
+ */
+public class RssiCurve implements Parcelable {
+
+    /** The starting dBm of the curve. */
+    public final int start;
+
+    /** The width of each RSSI bucket, in dBm. */
+    public final int bucketWidth;
+
+    /** The score for each RSSI bucket. */
+    public final byte[] rssiBuckets;
+
+    /**
+     * Construct a new {@link RssiCurve}.
+     *
+     * @param start the starting dBm of the curve.
+     * @param bucketWidth the width of each RSSI bucket, in dBm.
+     * @param rssiBuckets the score for each RSSI bucket.
+     */
+    public RssiCurve(int start, int bucketWidth, byte[] rssiBuckets) {
+        this.start = start;
+        this.bucketWidth = bucketWidth;
+        if (rssiBuckets == null || rssiBuckets.length == 0) {
+            throw new IllegalArgumentException("rssiBuckets must be at least one element large.");
+        }
+        this.rssiBuckets = rssiBuckets;
+    }
+
+    private RssiCurve(Parcel in) {
+        start = in.readInt();
+        bucketWidth = in.readInt();
+        int bucketCount = in.readInt();
+        rssiBuckets = new byte[bucketCount];
+        in.readByteArray(rssiBuckets);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(start);
+        out.writeInt(bucketWidth);
+        out.writeInt(rssiBuckets.length);
+        out.writeByteArray(rssiBuckets);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("RssiCurve[start=")
+                .append(start)
+                .append(",bucketWidth=")
+                .append(bucketWidth);
+
+        sb.append(",buckets=");
+        for (int i = 0; i < rssiBuckets.length; i++) {
+            sb.append(rssiBuckets[i]);
+            if (i < rssiBuckets.length - 1) {
+                sb.append(",");
+            }
+        }
+        sb.append("]");
+
+        return sb.toString();
+    }
+
+    public static final Creator<RssiCurve> CREATOR =
+            new Creator<RssiCurve>() {
+                @Override
+                public RssiCurve createFromParcel(Parcel in) {
+                    return new RssiCurve(in);
+                }
+
+                @Override
+                public RssiCurve[] newArray(int size) {
+                    return new RssiCurve[size];
+                }
+            };
+}
diff --git a/core/java/android/net/ScoredNetwork.aidl b/core/java/android/net/ScoredNetwork.aidl
new file mode 100644
index 0000000..f83db11
--- /dev/null
+++ b/core/java/android/net/ScoredNetwork.aidl
@@ -0,0 +1,19 @@
+/**
+ * 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.net;
+
+parcelable ScoredNetwork;
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
new file mode 100644
index 0000000..8af3c3c
--- /dev/null
+++ b/core/java/android/net/ScoredNetwork.java
@@ -0,0 +1,99 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A network identifier along with a score for the quality of that network.
+ *
+ * @hide
+ */
+public class ScoredNetwork implements Parcelable {
+
+    /** A {@link NetworkKey} uniquely identifying this network. */
+    public final NetworkKey networkKey;
+
+    /**
+     * The {@link RssiCurve} representing the scores for this network based on the RSSI.
+     *
+     * <p>This field is optional and may be set to null to indicate that no score is available for
+     * this network at this time. Such networks, along with networks for which the scorer has not
+     * responded, are always prioritized below scored networks, regardless of the score.
+     */
+    public final RssiCurve rssiCurve;
+
+    /**
+     * Construct a new {@link ScoredNetwork}.
+     *
+     * @param networkKey the {@link NetworkKey} uniquely identifying this network.
+     * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
+     *     RSSI. This field is optional, and may be skipped to represent a network which the scorer
+     *     has opted not to score at this time. Passing a null value here is strongly preferred to
+     *     not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
+     *     indicates to the system not to request scores for this network in the future, although
+     *     the scorer may choose to issue an out-of-band update at any time.
+     */
+    public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve) {
+        this.networkKey = networkKey;
+        this.rssiCurve = rssiCurve;
+    }
+
+    private ScoredNetwork(Parcel in) {
+        networkKey = NetworkKey.CREATOR.createFromParcel(in);
+        if (in.readByte() == 1) {
+            rssiCurve = RssiCurve.CREATOR.createFromParcel(in);
+        } else {
+            rssiCurve = null;
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        networkKey.writeToParcel(out, flags);
+        if (rssiCurve != null) {
+            out.writeByte((byte) 1);
+            rssiCurve.writeToParcel(out, flags);
+        } else {
+            out.writeByte((byte) 0);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve + "]";
+    }
+
+    public static final Parcelable.Creator<ScoredNetwork> CREATOR =
+            new Parcelable.Creator<ScoredNetwork>() {
+                @Override
+                public ScoredNetwork createFromParcel(Parcel in) {
+                    return new ScoredNetwork(in);
+                }
+
+                @Override
+                public ScoredNetwork[] newArray(int size) {
+                    return new ScoredNetwork[size];
+                }
+            };
+}
diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java
new file mode 100644
index 0000000..ffcd85a
--- /dev/null
+++ b/core/java/android/net/WifiKey.java
@@ -0,0 +1,106 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.regex.Pattern;
+
+/**
+ * Information identifying a Wi-Fi network.
+ * @see NetworkKey
+ *
+ * @hide
+ */
+public class WifiKey implements Parcelable {
+
+    // Patterns used for validation.
+    private static final Pattern SSID_PATTERN = Pattern.compile("(\".*\")|(0x[\\p{XDigit}]+)");
+    private static final Pattern BSSID_PATTERN =
+            Pattern.compile("([\\p{XDigit}]{2}:){5}[\\p{XDigit}]{2}");
+
+    /**
+     * The service set identifier (SSID) of an 802.11 network. If the SSID can be decoded as
+     * UTF-8, it will be surrounded by double quotation marks. Otherwise, it will be a string of
+     * hex digits starting with 0x.
+     */
+    public final String ssid;
+
+    /**
+     * The basic service set identifier (BSSID) of an access point for this network. This will
+     * be in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX}, where each X is a
+     * hexadecimal digit.
+     */
+    public final String bssid;
+
+    /**
+     * Construct a new {@link WifiKey} for the given Wi-Fi SSID/BSSID pair.
+     *
+     * @param ssid the service set identifier (SSID) of an 802.11 network. If the SSID can be
+     *         decoded as UTF-8, it should be surrounded by double quotation marks. Otherwise,
+     *         it should be a string of hex digits starting with 0x.
+     * @param bssid the basic service set identifier (BSSID) of this network's access point.
+     *         This should be in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX},
+     *         where each X is a hexadecimal digit.
+     * @throws IllegalArgumentException if either the SSID or BSSID is invalid.
+     */
+    public WifiKey(String ssid, String bssid) {
+        if (!SSID_PATTERN.matcher(ssid).matches()) {
+            throw new IllegalArgumentException("Invalid ssid: " + ssid);
+        }
+        if (!BSSID_PATTERN.matcher(bssid).matches()) {
+            throw new IllegalArgumentException("Invalid bssid: " + bssid);
+        }
+        this.ssid = ssid;
+        this.bssid = bssid;
+    }
+
+    private WifiKey(Parcel in) {
+        ssid = in.readString();
+        bssid = in.readString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(ssid);
+        out.writeString(bssid);
+    }
+
+    @Override
+    public String toString() {
+        return "WifiKey[SSID=" + ssid + ",BSSID=" + bssid + "]";
+    }
+
+    public static final Creator<WifiKey> CREATOR =
+            new Creator<WifiKey>() {
+                @Override
+                public WifiKey createFromParcel(Parcel in) {
+                    return new WifiKey(in);
+                }
+
+                @Override
+                public WifiKey[] newArray(int size) {
+                    return new WifiKey[size];
+                }
+            };
+}
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index 205a21d..6fdb0d0 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -18,8 +18,15 @@
 
 import android.os.Parcelable;
 import android.os.Parcel;
+import android.util.Log;
+import android.util.ArrayMap;
 
+import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Map;
+
 
 /**
  * A class representing service information for network service discovery
@@ -27,11 +34,13 @@
  */
 public final class NsdServiceInfo implements Parcelable {
 
+    private static final String TAG = "NsdServiceInfo";
+
     private String mServiceName;
 
     private String mServiceType;
 
-    private DnsSdTxtRecord mTxtRecord;
+    private final ArrayMap<String, byte[]> mTxtRecord = new ArrayMap<String, byte[]>();
 
     private InetAddress mHost;
 
@@ -41,10 +50,9 @@
     }
 
     /** @hide */
-    public NsdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) {
+    public NsdServiceInfo(String sn, String rt) {
         mServiceName = sn;
         mServiceType = rt;
-        mTxtRecord = tr;
     }
 
     /** Get the service name */
@@ -67,16 +75,6 @@
         mServiceType = s;
     }
 
-    /** @hide */
-    public DnsSdTxtRecord getTxtRecord() {
-        return mTxtRecord;
-    }
-
-    /** @hide */
-    public void setTxtRecord(DnsSdTxtRecord t) {
-        mTxtRecord = new DnsSdTxtRecord(t);
-    }
-
     /** Get the host address. The host address is valid for a resolved service. */
     public InetAddress getHost() {
         return mHost;
@@ -97,14 +95,134 @@
         mPort = p;
     }
 
+    /** @hide */
+    public void setAttribute(String key, byte[] value) {
+        // Key must be printable US-ASCII, excluding =.
+        for (int i = 0; i < key.length(); ++i) {
+            char character = key.charAt(i);
+            if (character < 0x20 || character > 0x7E) {
+                throw new IllegalArgumentException("Key strings must be printable US-ASCII");
+            } else if (character == 0x3D) {
+                throw new IllegalArgumentException("Key strings must not include '='");
+            }
+        }
+
+        // Key length + value length must be < 255.
+        if (key.length() + (value == null ? 0 : value.length) >= 255) {
+            throw new IllegalArgumentException("Key length + value length must be < 255 bytes");
+        }
+
+        // Warn if key is > 9 characters, as recommended by RFC 6763 section 6.4.
+        if (key.length() > 9) {
+            Log.w(TAG, "Key lengths > 9 are discouraged: " + key);
+        }
+
+        // Check against total TXT record size limits.
+        // Arbitrary 400 / 1300 byte limits taken from RFC 6763 section 6.2.
+        int txtRecordSize = getTxtRecordSize();
+        int futureSize = txtRecordSize + key.length() + (value == null ? 0 : value.length) + 2;
+        if (futureSize > 1300) {
+            throw new IllegalArgumentException("Total length of attributes must be < 1300 bytes");
+        } else if (futureSize > 400) {
+            Log.w(TAG, "Total length of all attributes exceeds 400 bytes; truncation may occur");
+        }
+
+        mTxtRecord.put(key, value);
+    }
+
+    /**
+     * Add a service attribute as a key/value pair.
+     *
+     * <p> Service attributes are included as DNS-SD TXT record pairs.
+     *
+     * <p> The key must be US-ASCII printable characters, excluding the '=' character.  Values may
+     * be UTF-8 strings or null.  The total length of key + value must be less than 255 bytes.
+     *
+     * <p> Keys should be short, ideally no more than 9 characters, and unique per instance of
+     * {@link NsdServiceInfo}.  Calling {@link #setAttribute} twice with the same key will overwrite
+     * first value.
+     */
+    public void setAttribute(String key, String value) {
+        try {
+            setAttribute(key, value == null ? (byte []) null : value.getBytes("UTF-8"));
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalArgumentException("Value must be UTF-8");
+        }
+    }
+
+    /** Remove an attribute by key */
+    public void removeAttribute(String key) {
+        mTxtRecord.remove(key);
+    }
+
+    /**
+     * Retrive attributes as a map of String keys to byte[] values.
+     *
+     * <p> The returned map is unmodifiable; changes must be made through {@link #setAttribute} and
+     * {@link #removeAttribute}.
+     */
+    public Map<String, byte[]> getAttributes() {
+        return Collections.unmodifiableMap(mTxtRecord);
+    }
+
+    private int getTxtRecordSize() {
+        int txtRecordSize = 0;
+        for (Map.Entry<String, byte[]> entry : mTxtRecord.entrySet()) {
+            txtRecordSize += 2;  // One for the length byte, one for the = between key and value.
+            txtRecordSize += entry.getKey().length();
+            byte[] value = entry.getValue();
+            txtRecordSize += value == null ? 0 : value.length;
+        }
+        return txtRecordSize;
+    }
+
+    /** @hide */
+    public byte[] getTxtRecord() {
+        int txtRecordSize = getTxtRecordSize();
+        if (txtRecordSize == 0) {
+            return null;
+        }
+
+        byte[] txtRecord = new byte[txtRecordSize];
+        int ptr = 0;
+        for (Map.Entry<String, byte[]> entry : mTxtRecord.entrySet()) {
+            String key = entry.getKey();
+            byte[] value = entry.getValue();
+
+            // One byte to record the length of this key/value pair.
+            txtRecord[ptr++] = (byte) (key.length() + (value == null ? 0 : value.length) + 1);
+
+            // The key, in US-ASCII.
+            // Note: use the StandardCharsets const here because it doesn't raise exceptions and we
+            // already know the key is ASCII at this point.
+            System.arraycopy(key.getBytes(StandardCharsets.US_ASCII), 0, txtRecord, ptr,
+                    key.length());
+            ptr += key.length();
+
+            // US-ASCII '=' character.
+            txtRecord[ptr++] = (byte)'=';
+
+            // The value, as any raw bytes.
+            if (value != null) {
+                System.arraycopy(value, 0, txtRecord, ptr, value.length);
+                ptr += value.length;
+            }
+        }
+        return txtRecord;
+    }
+
     public String toString() {
         StringBuffer sb = new StringBuffer();
 
-        sb.append("name: ").append(mServiceName).
-            append("type: ").append(mServiceType).
-            append("host: ").append(mHost).
-            append("port: ").append(mPort).
-            append("txtRecord: ").append(mTxtRecord);
+        sb.append("name: ").append(mServiceName)
+                .append(", type: ").append(mServiceType)
+                .append(", host: ").append(mHost)
+                .append(", port: ").append(mPort);
+
+        byte[] txtRecord = getTxtRecord();
+        if (txtRecord != null) {
+            sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8));
+        }
         return sb.toString();
     }
 
@@ -117,14 +235,27 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(mServiceName);
         dest.writeString(mServiceType);
-        dest.writeParcelable(mTxtRecord, flags);
         if (mHost != null) {
-            dest.writeByte((byte)1);
+            dest.writeInt(1);
             dest.writeByteArray(mHost.getAddress());
         } else {
-            dest.writeByte((byte)0);
+            dest.writeInt(0);
         }
         dest.writeInt(mPort);
+
+        // TXT record key/value pairs.
+        dest.writeInt(mTxtRecord.size());
+        for (String key : mTxtRecord.keySet()) {
+            byte[] value = mTxtRecord.get(key);
+            if (value != null) {
+                dest.writeInt(1);
+                dest.writeInt(value.length);
+                dest.writeByteArray(value);
+            } else {
+                dest.writeInt(0);
+            }
+            dest.writeString(key);
+        }
     }
 
     /** Implement the Parcelable interface */
@@ -134,15 +265,26 @@
                 NsdServiceInfo info = new NsdServiceInfo();
                 info.mServiceName = in.readString();
                 info.mServiceType = in.readString();
-                info.mTxtRecord = in.readParcelable(null);
 
-                if (in.readByte() == 1) {
+                if (in.readInt() == 1) {
                     try {
                         info.mHost = InetAddress.getByAddress(in.createByteArray());
                     } catch (java.net.UnknownHostException e) {}
                 }
 
                 info.mPort = in.readInt();
+
+                // TXT record key/value pairs.
+                int recordCount = in.readInt();
+                for (int i = 0; i < recordCount; ++i) {
+                    byte[] valueArray = null;
+                    if (in.readInt() == 1) {
+                        int valueLength = in.readInt();
+                        valueArray = new byte[valueLength];
+                        in.readByteArray(valueArray);
+                    }
+                    info.mTxtRecord.put(in.readString(), valueArray);
+                }
                 return info;
             }
 
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 2e38960..f339e52 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -16,9 +16,15 @@
 
 package android.os;
 
+import android.os.BatteryProperty;
+import android.os.IBatteryPropertiesRegistrar;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
 /**
  * The BatteryManager class contains strings and constants used for values
- * in the {@link android.content.Intent#ACTION_BATTERY_CHANGED} Intent.
+ * in the {@link android.content.Intent#ACTION_BATTERY_CHANGED} Intent, and
+ * provides a method for querying battery and charging properties.
  */
 public class BatteryManager {
     /**
@@ -121,4 +127,30 @@
     /** @hide */
     public static final int BATTERY_PLUGGED_ANY =
             BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
+
+    private IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
+
+    /**
+     * Return the requested battery property.
+     *
+     * @param id identifier from {@link BatteryProperty} of the requested property
+     * @return a {@link BatteryProperty} object that returns the property value, or null on error
+     */
+    public BatteryProperty getProperty(int id) throws RemoteException {
+        if (mBatteryPropertiesRegistrar == null) {
+            IBinder b = ServiceManager.getService("batteryproperties");
+            mBatteryPropertiesRegistrar =
+                IBatteryPropertiesRegistrar.Stub.asInterface(b);
+
+            if (mBatteryPropertiesRegistrar == null)
+                return null;
+        }
+
+        BatteryProperty prop = new BatteryProperty(Integer.MIN_VALUE);
+        if ((mBatteryPropertiesRegistrar.getProperty(id, prop) == 0) &&
+            (prop.getInt() != Integer.MIN_VALUE))
+            return prop;
+        else
+            return null;
+    }
 }
diff --git a/core/java/android/os/BatteryProperty.java b/core/java/android/os/BatteryProperty.java
index 76b0dc4..ec73952 100644
--- a/core/java/android/os/BatteryProperty.java
+++ b/core/java/android/os/BatteryProperty.java
@@ -19,22 +19,67 @@
 import android.os.Parcelable;
 
 /**
- * {@hide}
+ * Battery properties that may be queried using
+ * {@link BatteryManager#getProperty
+ * BatteryManager.getProperty()}
  */
 public class BatteryProperty implements Parcelable {
     /*
      * Battery property identifiers.  These must match the values in
      * frameworks/native/include/batteryservice/BatteryService.h
      */
-    public static final int BATTERY_PROP_CHARGE_COUNTER = 1;
-    public static final int BATTERY_PROP_CURRENT_NOW = 2;
-    public static final int BATTERY_PROP_CURRENT_AVG = 3;
-    public static final int BATTERY_PROP_CAPACITY = 4;
+    /** Battery capacity in microampere-hours, as an integer. */
+    public static final int CHARGE_COUNTER = 1;
 
-    public int valueInt;
+    /**
+     * Instantaneous battery current in microamperes, as an integer.  Positive
+     * values indicate net current entering the battery from a charge source,
+     * negative values indicate net current discharging from the battery.
+     */
+    public static final int CURRENT_NOW = 2;
 
+    /**
+     * Average battery current in microamperes, as an integer.  Positive
+     * values indicate net current entering the battery from a charge source,
+     * negative values indicate net current discharging from the battery.
+     * The time period over which the average is computed may depend on the
+     * fuel gauge hardware and its configuration.
+     */
+    public static final int CURRENT_AVERAGE = 3;
+
+    /**
+     * Remaining battery capacity as an integer percentage of total capacity
+     * (with no fractional part).
+     */
+    public static final int CAPACITY = 4;
+
+    private int mValueInt;
+
+    /**
+     * @hide
+     */
+    public BatteryProperty(int value) {
+        mValueInt = value;
+    }
+
+    /**
+     * @hide
+     */
     public BatteryProperty() {
-        valueInt = Integer.MIN_VALUE;
+        mValueInt = Integer.MIN_VALUE;
+    }
+
+    /**
+     * Return the value of a property of integer type previously queried
+     * via {@link BatteryManager#getProperty
+     * BatteryManager.getProperty()}.  If the platform does
+     * not provide the property queried, this value will be
+     * Integer.MIN_VALUE.
+     *
+     * @return The queried property value, or Integer.MIN_VALUE if not supported.
+     */
+    public int getInt() {
+        return mValueInt;
     }
 
     /*
@@ -47,11 +92,11 @@
     }
 
     public void readFromParcel(Parcel p) {
-        valueInt = p.readInt();
+        mValueInt = p.readInt();
     }
 
     public void writeToParcel(Parcel p, int flags) {
-        p.writeInt(valueInt);
+        p.writeInt(mValueInt);
     }
 
     public static final Parcelable.Creator<BatteryProperty> CREATOR
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 4854bc0..4d05e2d 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -20,8 +20,8 @@
 interface IVibratorService
 {
     boolean hasVibrator();
-    void vibrate(int uid, String packageName, long milliseconds, int streamHint, IBinder token);
-    void vibratePattern(int uid, String packageName, in long[] pattern, int repeat, int streamHint, IBinder token);
+    void vibrate(int uid, String opPkg, long milliseconds, int streamHint, IBinder token);
+    void vibratePattern(int uid, String opPkg, in long[] pattern, int repeat, int streamHint, IBinder token);
     void cancelVibrate(IBinder token);
 }
 
diff --git a/core/java/android/os/NullVibrator.java b/core/java/android/os/NullVibrator.java
index 536da32..7b870ac 100644
--- a/core/java/android/os/NullVibrator.java
+++ b/core/java/android/os/NullVibrator.java
@@ -40,7 +40,7 @@
      * @hide
      */
     @Override
-    public void vibrate(int owningUid, String owningPackage, long milliseconds, int streamHint) {
+    public void vibrate(int uid, String opPkg, long milliseconds, int streamHint) {
         vibrate(milliseconds);
     }
 
@@ -48,7 +48,7 @@
      * @hide
      */
     @Override
-    public void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat,
+    public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
             int streamHint) {
         if (repeat >= pattern.length) {
             throw new ArrayIndexOutOfBoundsException();
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 13bc4f6..8d9cf54 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -58,13 +58,13 @@
      * @hide
      */
     @Override
-    public void vibrate(int owningUid, String owningPackage, long milliseconds, int streamHint) {
+    public void vibrate(int uid, String opPkg, long milliseconds, int streamHint) {
         if (mService == null) {
             Log.w(TAG, "Failed to vibrate; no vibrator service.");
             return;
         }
         try {
-            mService.vibrate(owningUid, owningPackage, milliseconds, streamHint, mToken);
+            mService.vibrate(uid, opPkg, milliseconds, streamHint, mToken);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to vibrate.", e);
         }
@@ -74,7 +74,7 @@
      * @hide
      */
     @Override
-    public void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat,
+    public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
             int streamHint) {
         if (mService == null) {
             Log.w(TAG, "Failed to vibrate; no vibrator service.");
@@ -85,7 +85,7 @@
         // anyway
         if (repeat < pattern.length) {
             try {
-                mService.vibratePattern(owningUid, owningPackage, pattern, repeat, streamHint,
+                mService.vibratePattern(uid, opPkg, pattern, repeat, streamHint,
                         mToken);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed to vibrate.", e);
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 8845ba3..c1d4d4c 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -135,7 +135,7 @@
      * Like {@link #vibrate(long, int)}, but allowing the caller to specify that
      * the vibration is owned by someone else.
      */
-    public abstract void vibrate(int owningUid, String owningPackage,
+    public abstract void vibrate(int uid, String opPkg,
             long milliseconds, int streamHint);
 
     /**
@@ -143,7 +143,7 @@
      * Like {@link #vibrate(long[], int, int)}, but allowing the caller to specify that
      * the vibration is owned by someone else.
      */
-    public abstract void vibrate(int owningUid, String owningPackage,
+    public abstract void vibrate(int uid, String opPkg,
             long[] pattern, int repeat, int streamHint);
 
     /**
diff --git a/core/java/android/provider/SearchIndexablesContract.java b/core/java/android/provider/SearchIndexablesContract.java
index 307ac39..a8b4cfb0 100644
--- a/core/java/android/provider/SearchIndexablesContract.java
+++ b/core/java/android/provider/SearchIndexablesContract.java
@@ -35,7 +35,7 @@
     private static final String SETTINGS = "settings";
 
     /**
-     * Indexable references name.
+     * Indexable reference names.
      */
     public static final String INDEXABLES_XML_RES = "indexables_xml_res";
 
@@ -45,7 +45,7 @@
     public static final String INDEXABLES_XML_RES_PATH = SETTINGS + "/" + INDEXABLES_XML_RES;
 
     /**
-     * Indexable raw data name.
+     * Indexable raw data names.
      */
     public static final String INDEXABLES_RAW = "indexables_raw";
 
@@ -55,6 +55,16 @@
     public static final String INDEXABLES_RAW_PATH = SETTINGS + "/" + INDEXABLES_RAW;
 
     /**
+     * Non indexable data keys.
+     */
+    public static final String NON_INDEXABLES_KEYS = "non_indexables_key";
+
+    /**
+     * ContentProvider path for non indexable data keys.
+     */
+    public static final String NON_INDEXABLES_KEYS_PATH = SETTINGS + "/" + NON_INDEXABLES_KEYS;
+
+    /**
      * Indexable xml resources colums.
      */
     public static final String[] INDEXABLES_XML_RES_COLUMNS = new String[] {
@@ -114,6 +124,17 @@
     public static final int COLUMN_INDEX_RAW_INTENT_TARGET_CLASS = 11;
     public static final int COLUMN_INDEX_RAW_KEY = 12;
 
+    /**
+     * Indexable raw data colums.
+     */
+    public static final String[] NON_INDEXABLES_KEYS_COLUMNS = new String[] {
+            NonIndexableKey.COLUMN_KEY_VALUE      // 0
+    };
+
+    /**
+     * Non indexable data keys colums indices.
+     */
+    public static final int COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE = 0;
 
     /**
      * Constants related to a {@link SearchIndexableResource}.
@@ -186,6 +207,24 @@
     }
 
     /**
+     * Constants related to a {@link SearchIndexableResource} and {@link SearchIndexableData}.
+     *
+     * This is a description of a data (thru its unique key) that cannot be indexed.
+     */
+    public static final class NonIndexableKey extends BaseColumns {
+        private NonIndexableKey() {
+        }
+
+        public static final String MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE +
+                "/" + NON_INDEXABLES_KEYS;
+
+        /**
+         * Key for the non indexable data.
+         */
+        public static final String COLUMN_KEY_VALUE = "key";
+    }
+
+    /**
      * The base columns.
      */
     private static class BaseColumns {
diff --git a/core/java/android/provider/SearchIndexablesProvider.java b/core/java/android/provider/SearchIndexablesProvider.java
index 2e358e4..9c8f6d0 100644
--- a/core/java/android/provider/SearchIndexablesProvider.java
+++ b/core/java/android/provider/SearchIndexablesProvider.java
@@ -69,6 +69,7 @@
 
     private static final int MATCH_RES_CODE = 1;
     private static final int MATCH_RAW_CODE = 2;
+    private static final int MATCH_NON_INDEXABLE_KEYS_CODE = 3;
 
     /**
      * Implementation is provided by the parent class.
@@ -82,6 +83,8 @@
                 MATCH_RES_CODE);
         mMatcher.addURI(mAuthority, SearchIndexablesContract.INDEXABLES_RAW_PATH,
                 MATCH_RAW_CODE);
+        mMatcher.addURI(mAuthority, SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH,
+                MATCH_NON_INDEXABLE_KEYS_CODE);
 
         // Sanity check our setup
         if (!info.exported) {
@@ -105,6 +108,8 @@
                 return queryXmlResources(null);
             case MATCH_RAW_CODE:
                 return queryRawData(null);
+            case MATCH_NON_INDEXABLE_KEYS_CODE:
+                return queryNonIndexableKeys(null);
             default:
                 throw new UnsupportedOperationException("Unknown Uri " + uri);
         }
@@ -113,7 +118,7 @@
     /**
      * Returns all {@link android.provider.SearchIndexablesContract.XmlResource}.
      *
-     * Those are usually xml resource ID to some {@link android.preference.PreferenceScreen}.
+     * Those are Xml resource IDs to some {@link android.preference.PreferenceScreen}.
      *
      * @param projection list of {@link android.provider.SearchIndexablesContract.XmlResource}
      *                   columns to put into the cursor. If {@code null} all supported columns
@@ -124,7 +129,7 @@
     /**
      * Returns all {@link android.provider.SearchIndexablesContract.RawData}.
      *
-     * Those are raw indexable data.
+     * Those are the raw indexable data.
      *
      * @param projection list of {@link android.provider.SearchIndexablesContract.RawData} columns
      *                   to put into the cursor. If {@code null} all supported columns should be
@@ -132,6 +137,17 @@
      */
     public abstract Cursor queryRawData(String[] projection);
 
+    /**
+     * Returns all {@link android.provider.SearchIndexablesContract.NonIndexableKey}.
+     *
+     * Those are the non indexable data keys.
+     *
+     * @param projection list of {@link android.provider.SearchIndexablesContract.NonIndexableKey}
+     *                   columns to put into the cursor. If {@code null} all supported columns
+     *                   should be included.
+     */
+    public abstract Cursor queryNonIndexableKeys(String[] projection);
+
     @Override
     public String getType(Uri uri) {
         switch (mMatcher.match(uri)) {
@@ -139,14 +155,15 @@
                 return SearchIndexablesContract.XmlResource.MIME_TYPE;
             case MATCH_RAW_CODE:
                 return SearchIndexablesContract.RawData.MIME_TYPE;
+            case MATCH_NON_INDEXABLE_KEYS_CODE:
+                return SearchIndexablesContract.NonIndexableKey.MIME_TYPE;
             default:
                 throw new IllegalArgumentException("Unknown URI " + uri);
         }
     }
 
     /**
-     * Implementation is provided by the parent class. Throws by default, and
-     * cannot be overriden.
+     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
      */
     @Override
     public final Uri insert(Uri uri, ContentValues values) {
@@ -154,8 +171,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Throws by default, and
-     * cannot be overriden.
+     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
      */
     @Override
     public final int delete(Uri uri, String selection, String[] selectionArgs) {
@@ -163,8 +179,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Throws by default, and
-     * cannot be overriden.
+     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
      */
     @Override
     public final int update(
diff --git a/core/java/android/provider/TvContract.java b/core/java/android/provider/TvContract.java
new file mode 100644
index 0000000..233e0ca
--- /dev/null
+++ b/core/java/android/provider/TvContract.java
@@ -0,0 +1,449 @@
+/*
+ * 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.provider;
+
+import android.content.ContentUris;
+import android.net.Uri;
+
+/**
+ * <p>
+ * The contract between the TV provider and applications. Contains definitions for the supported
+ * URIs and columns.
+ * </p>
+ * <h3>Overview</h3>
+ * <p>
+ * TvContract defines a basic database of TV content metadata such as channel and program
+ * information. The information is stored in {@link Channels} and {@link Programs} tables.
+ * </p>
+ * <ul>
+ *     <li>A row in the {@link Channels} table represents information about a TV channel. The data
+ *         format can vary greatly from standard to standard or according to service provider, thus
+ *         the columns here are mostly comprised of basic entities that are usually seen to users
+ *         regardless of standard such as channel number and name.</li>
+ *     <li>A row in the {@link Programs} table represents a set of data describing a TV program such
+ *         as program title and start time.</li>
+ * </ul>
+ */
+public final class TvContract {
+    /** The authority for the TV provider. */
+    public static final String AUTHORITY = "com.android.tv";
+
+    /**
+     * Builds a URI that points to a specific channel.
+     *
+     * @param channelId The ID of the channel to point to.
+     */
+    public static final Uri buildChannelUri(long channelId) {
+        return ContentUris.withAppendedId(Channels.CONTENT_URI, channelId);
+    }
+
+    /**
+     * Builds a URI that points to a specific program.
+     *
+     * @param programId The ID of the program to point to.
+     */
+    public static final Uri buildProgramUri(long programId) {
+        return ContentUris.withAppendedId(Programs.CONTENT_URI, programId);
+    }
+
+    /**
+     * Builds a URI that points to a specific program the user watched.
+     *
+     * @param watchedProgramId The ID of the watched program to point to.
+     * @hide
+     */
+    public static final Uri buildWatchedProgramUri(long watchedProgramId) {
+        return ContentUris.withAppendedId(WatchedPrograms.CONTENT_URI, watchedProgramId);
+    }
+
+    private TvContract() {}
+
+    /**
+     * Common base for the tables of TV channels/programs.
+     */
+    public interface BaseTvColumns extends BaseColumns {
+        /**
+         * The name of the package that owns a row in each table.
+         * <p>
+         * The TV provider fills it in with the name of the package that provides the initial data
+         * of that row. If the package is later uninstalled, the rows it owns are automatically
+         * removed from the tables.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String PACKAGE_NAME = "package_name";
+    }
+
+    /** Column definitions for the TV channels table. */
+    public static final class Channels implements BaseTvColumns {
+
+        /** The content:// style URI for this table. */
+        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/channel");
+
+        /** The MIME type of a directory of TV channels. */
+        public static final String CONTENT_TYPE =
+                "vnd.android.cursor.dir/vnd.com.android.tv.channels";
+
+        /** The MIME type of a single TV channel. */
+        public static final String CONTENT_ITEM_TYPE =
+                "vnd.android.cursor.item/vnd.com.android.tv.channels";
+
+        /** A generic channel type. */
+        public static final int TYPE_OTHER = 0x0;
+
+        /** The special channel type used for pass-through inputs such as HDMI. */
+        public static final int TYPE_PASSTHROUGH = 0x00010000;
+
+        /** The channel type for DVB-T (terrestrial). */
+        public static final int TYPE_DVB_T = 0x00020000;
+
+        /** The channel type for DVB-T2 (terrestrial). */
+        public static final int TYPE_DVB_T2 = 0x00020001;
+
+        /** The channel type for DVB-S (satellite). */
+        public static final int TYPE_DVB_S = 0x00020100;
+
+        /** The channel type for DVB-S2 (satellite). */
+        public static final int TYPE_DVB_S2 = 0x00020101;
+
+        /** The channel type for DVB-C (cable). */
+        public static final int TYPE_DVB_C = 0x00020200;
+
+        /** The channel type for DVB-C2 (cable). */
+        public static final int TYPE_DVB_C2 = 0x00020201;
+
+        /** The channel type for DVB-H (handheld). */
+        public static final int TYPE_DVB_H = 0x00020300;
+
+        /** The channel type for DVB-SH (satellite). */
+        public static final int TYPE_DVB_SH = 0x00020400;
+
+        /** The channel type for ATSC (terrestrial/cable). */
+        public static final int TYPE_ATSC = 0x00030000;
+
+        /** The channel type for ATSC 2.0. */
+        public static final int TYPE_ATSC_2_0 = 0x00030001;
+
+        /** The channel type for ATSC-M/H (mobile/handheld). */
+        public static final int TYPE_ATSC_M_H = 0x00030100;
+
+        /** The channel type for ISDB-T (terrestrial). */
+        public static final int TYPE_ISDB_T = 0x00040000;
+
+        /** The channel type for ISDB-Tb (Brazil). */
+        public static final int TYPE_ISDB_TB = 0x00040100;
+
+        /** The channel type for ISDB-S (satellite). */
+        public static final int TYPE_ISDB_S = 0x00040200;
+
+        /** The channel type for ISDB-C (cable). */
+        public static final int TYPE_ISDB_C = 0x00040300;
+
+        /** The channel type for 1seg (handheld). */
+        public static final int TYPE_1SEG = 0x00040400;
+
+        /** The channel type for DTMB (terrestrial). */
+        public static final int TYPE_DTMB = 0x00050000;
+
+        /** The channel type for CMMB (handheld). */
+        public static final int TYPE_CMMB = 0x00050100;
+
+        /** The channel type for T-DMB (terrestrial). */
+        public static final int TYPE_T_DMB = 0x00060000;
+
+        /** The channel type for S-DMB (satellite). */
+        public static final int TYPE_S_DMB = 0x00060100;
+
+        /**
+         * The name of the TV input service that provides this TV channel.
+         * <p>
+         * This is a required field.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String SERVICE_NAME = "service_name";
+
+        /**
+         * The predefined type of this TV channel.
+         * <p>
+         * This is used to indicate which broadcast standard (e.g. ATSC, DVB or ISDB) the current
+         * channel conforms to.
+         * </p><p>
+         * This is a required field.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         */
+        public static final String TYPE = "type";
+
+        /**
+         * The transport stream ID as appeared in various broadcast standards.
+         * <p>
+         * This is not a required field but if provided, can significantly increase the accuracy of
+         * channel identification.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         */
+        public static final String TRANSPORT_STREAM_ID = "transport_stream_id";
+
+        /**
+         * The channel number that is displayed to the user.
+         * <p>
+         * The format can vary depending on broadcast standard and product specification.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         */
+        public static final String DISPLAY_NUMBER = "display_number";
+
+        /**
+         * The channel name that is displayed to the user.
+         * <p>
+         * A call sign is a good candidate to use for this purpose but any name that helps the user
+         * recognize the current channel will be enough. Can also be empty depending on broadcast
+         * standard.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String DISPLAY_NAME = "display_name";
+
+        /**
+         * The description of this TV channel.
+         * <p>
+         * Can be empty initially.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String DESCRIPTION = "description";
+
+        /**
+         * The flag indicating whether this TV channel is browsable or not.
+         * <p>
+         * A value of 1 indicates the channel is included in the channel list that applications use
+         * to browse channels, a value of 0 indicates the channel is not included in the list. If
+         * not specified, this value is set to 1 by default.
+         * </p><p>
+         * Type: INTEGER (boolean)
+         * </p>
+         */
+        public static final String BROWSABLE = "browsable";
+
+        /**
+         * Generic data used by individual TV input services.
+         * <p>
+         * Type: BLOB
+         * </p>
+         */
+        public static final String DATA = "data";
+
+
+        /**
+         * The version number of this row entry used by TV input services.
+         * <p>
+         * This is best used by sync adapters to identify the rows to update. The number can be
+         * defined by individual TV input services. One may assign the same value as
+         * {@code version_number} that appears in ETSI EN 300 468 or ATSC A/65, if the data are
+         * coming from a TV broadcast.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         */
+        public static final String VERSION_NUMBER = "version_number";
+
+        private Channels() {}
+    }
+
+    /** Column definitions for the TV programs table. */
+    public static final class Programs implements BaseTvColumns {
+
+        /** The content:// style URI for this table. */
+        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/program");
+
+        /** The MIME type of a directory of TV programs. */
+        public static final String CONTENT_TYPE =
+                "vnd.android.cursor.dir/vnd.com.android.tv.programs";
+
+        /** The MIME type of a single TV program. */
+        public static final String CONTENT_ITEM_TYPE =
+                "vnd.android.cursor.item/vnd.com.android.tv.programs";
+
+        /**
+         * The ID of the TV channel that contains this TV program.
+         * <p>
+         * This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
+         * </p><p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String CHANNEL_ID = "channel_id";
+
+        /**
+         * The title of this TV program.
+         * <p>
+         * Type: TEXT
+         * </p>
+         **/
+        public static final String TITLE = "title";
+
+        /**
+         * The start time of this TV program, in milliseconds since the epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String START_TIME_UTC_MILLIS = "start_time_utc_millis";
+
+        /**
+         * The end time of this TV program, in milliseconds since the epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String END_TIME_UTC_MILLIS = "end_time_utc_millis";
+
+        /**
+         * The description of this TV program that is displayed to the user by default.
+         * <p>
+         * The maximum length of this field is 256 characters.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String DESCRIPTION = "description";
+
+        /**
+         * The detailed, lengthy description of this TV program that is displayed only when the user
+         * wants to see more information.
+         * <p>
+         * TV input services should leave this field empty if they have no additional
+         * details beyond {@link #DESCRIPTION}.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String LONG_DESCRIPTION = "long_description";
+
+        /**
+         * Generic data used by TV input services.
+         * <p>
+         * Type: BLOB
+         * </p>
+         */
+        public static final String DATA = "data";
+
+        /**
+         * The version number of this row entry used by TV input services.
+         * <p>
+         * This is best used by sync adapters to identify the rows to update. The number can be
+         * defined by individual TV input services. One may assign the same value as
+         * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
+         * broadcast.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         */
+        public static final String VERSION_NUMBER = "version_number";
+
+        private Programs() {}
+    }
+
+    /**
+     * Column definitions for the TV programs that the user watched. Applications do not have access
+     * to this table.
+     *
+     * @hide
+     */
+    public static final class WatchedPrograms implements BaseColumns {
+
+        /** The content:// style URI for this table. */
+        public static final Uri CONTENT_URI =
+                Uri.parse("content://" + AUTHORITY + "/watched_program");
+
+        /** The MIME type of a directory of watched programs. */
+        public static final String CONTENT_TYPE =
+                "vnd.android.cursor.dir/vnd.com.android.tv.watched_programs";
+
+        /** The MIME type of a single item in this table. */
+        public static final String CONTENT_ITEM_TYPE =
+                "vnd.android.cursor.item/vnd.com.android.tv.watched_programs";
+
+        /**
+         * The UTC time that the user started watching this TV program, in milliseconds since the
+         * epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String WATCH_START_TIME_UTC_MILLIS = "watch_start_time_utc_millis";
+
+        /**
+         * The UTC time that the user stopped watching this TV program, in milliseconds since the
+         * epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String WATCH_END_TIME_UTC_MILLIS = "watch_end_time_utc_millis";
+
+        /**
+         * The channel ID that contains this TV program.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String CHANNEL_ID = "channel_id";
+
+        /**
+         * The title of this TV program.
+         * <p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String TITLE = "title";
+
+        /**
+         * The start time of this TV program, in milliseconds since the epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String START_TIME_UTC_MILLIS = "start_time_utc_millis";
+
+        /**
+         * The end time of this TV program, in milliseconds since the epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String END_TIME_UTC_MILLIS = "end_time_utc_millis";
+
+        /**
+         * The description of this TV program.
+         * <p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String DESCRIPTION = "description";
+
+        private WatchedPrograms() {}
+    }
+}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 0f74169..2c0b76d 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -32,7 +32,7 @@
     private final String key;
 
     private final int uid;
-    private final String basePkg;
+    private final String opPkg;
     private final int initialPid;
     private final Notification notification;
     private final UserHandle user;
@@ -41,26 +41,20 @@
     private final int score;
 
     /** @hide */
-    public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
-            Notification notification, UserHandle user) {
-        this(pkg, null, id, tag, uid, initialPid, score, notification, user);
-    }
-
-    /** @hide */
-    public StatusBarNotification(String pkg, String basePkg, int id, String tag, int uid,
+    public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
             int initialPid, int score, Notification notification, UserHandle user) {
-        this(pkg, basePkg, id, tag, uid, initialPid, score, notification, user,
+        this(pkg, opPkg, id, tag, uid, initialPid, score, notification, user,
                 System.currentTimeMillis());
     }
 
-    public StatusBarNotification(String pkg, String basePkg, int id, String tag, int uid,
+    public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
             int initialPid, int score, Notification notification, UserHandle user,
             long postTime) {
         if (pkg == null) throw new NullPointerException();
         if (notification == null) throw new NullPointerException();
 
         this.pkg = pkg;
-        this.basePkg = pkg;
+        this.opPkg = opPkg;
         this.id = id;
         this.tag = tag;
         this.uid = uid;
@@ -75,7 +69,7 @@
 
     public StatusBarNotification(Parcel in) {
         this.pkg = in.readString();
-        this.basePkg = in.readString();
+        this.opPkg = in.readString();
         this.id = in.readInt();
         if (in.readInt() != 0) {
             this.tag = in.readString();
@@ -93,12 +87,12 @@
     }
 
     private String key() {
-        return pkg + '|' + basePkg + '|' + id + '|' + tag + '|' + uid;
+        return pkg + '|' + opPkg + '|' + id + '|' + tag + '|' + uid;
     }
 
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(this.pkg);
-        out.writeString(this.basePkg);
+        out.writeString(this.opPkg);
         out.writeInt(this.id);
         if (this.tag != null) {
             out.writeInt(1);
@@ -139,14 +133,14 @@
     public StatusBarNotification cloneLight() {
         final Notification no = new Notification();
         this.notification.cloneInto(no, false); // light copy
-        return new StatusBarNotification(this.pkg, this.basePkg,
+        return new StatusBarNotification(this.pkg, this.opPkg,
                 this.id, this.tag, this.uid, this.initialPid,
                 this.score, no, this.user, this.postTime);
     }
 
     @Override
     public StatusBarNotification clone() {
-        return new StatusBarNotification(this.pkg, this.basePkg,
+        return new StatusBarNotification(this.pkg, this.opPkg,
                 this.id, this.tag, this.uid, this.initialPid,
                 this.score, this.notification.clone(), this.user, this.postTime);
     }
@@ -205,9 +199,9 @@
         return uid;
     }
 
-    /** The notifying app's base package. @hide */
-    public String getBasePkg() {
-        return basePkg;
+    /** The package used for AppOps tracking. @hide */
+    public String getOpPkg() {
+        return opPkg;
     }
 
     /** @hide */
diff --git a/core/java/android/tv/ITvInputSessionWrapper.java b/core/java/android/tv/ITvInputSessionWrapper.java
index fd4e1e3..66fe5e1 100644
--- a/core/java/android/tv/ITvInputSessionWrapper.java
+++ b/core/java/android/tv/ITvInputSessionWrapper.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.net.Uri;
 import android.os.Message;
+import android.tv.TvInputService.TvInputSessionImpl;
 import android.util.Log;
 import android.view.Surface;
 
@@ -38,10 +39,10 @@
     private static final int DO_SET_VOLUME = 3;
     private static final int DO_TUNE = 4;
 
-    private TvInputSession mTvInputSession;
+    private TvInputSessionImpl mTvInputSession;
     private final HandlerCaller mCaller;
 
-    public ITvInputSessionWrapper(Context context, TvInputSession session) {
+    public ITvInputSessionWrapper(Context context, TvInputSessionImpl session) {
         mCaller = new HandlerCaller(context, null, this, true /* asyncHandler */);
         mTvInputSession = session;
     }
diff --git a/core/java/android/tv/TvInputManager.java b/core/java/android/tv/TvInputManager.java
index 0b6ab64..4cf2b35 100644
--- a/core/java/android/tv/TvInputManager.java
+++ b/core/java/android/tv/TvInputManager.java
@@ -282,7 +282,7 @@
     }
 
     /**
-     * Creates a {@link TvInputSession} interface for a given TV input.
+     * Creates a {@link Session} for a given TV input.
      * <p>
      * The number of sessions that can be created at the same time is limited by the capability of
      * the given TV input.
diff --git a/core/java/android/tv/TvInputService.java b/core/java/android/tv/TvInputService.java
index e43cc95..d7f6c32 100644
--- a/core/java/android/tv/TvInputService.java
+++ b/core/java/android/tv/TvInputService.java
@@ -123,7 +123,7 @@
     public abstract TvInputSessionImpl onCreateSession();
 
     /**
-     * Base class for derived classes to implement to provide {@link TvInputSession}.
+     * Base class for derived classes to implement to provide {@link TvInputManager.Session}.
      */
     public abstract static class TvInputSessionImpl {
         /**
@@ -155,52 +155,35 @@
          * @return {@code true} the tuning was successful, {@code false} otherwise.
          */
         public abstract boolean onTune(Uri channelUri);
-    }
-
-    /**
-     * Internal implementation of {@link TvInputSession}. This takes care of basic maintenance of
-     * the TV input session but most behavior must be implemented in {@link TvInputSessionImpl}
-     * returned by {@link TvInputService#onCreateSession}.
-     */
-    private static class TvInputSessionImplInternal extends TvInputSession {
-        private final TvInputSessionImpl mSessionImpl;
-
-        public TvInputSessionImplInternal(TvInputSessionImpl sessionImpl) {
-            mSessionImpl = sessionImpl;
-        }
 
         /**
          * This method is called when the application would like to stop using the current input
          * session.
          */
-        @Override
-        public final void release() {
-            mSessionImpl.onRelease();
+        void release() {
+            onRelease();
         }
 
         /**
-         * Calls {@link TvInputSessionImpl#onSetSurface}.
+         * Calls {@link onSetSurface}.
          */
-        @Override
-        public final void setSurface(Surface surface) {
-            mSessionImpl.onSetSurface(surface);
+        void setSurface(Surface surface) {
+            onSetSurface(surface);
             // TODO: Handle failure.
         }
 
         /**
-         * Calls {@link TvInputSessionImpl#onSetVolume}.
+         * Calls {@link onSetVolume}.
          */
-        @Override
-        public final void setVolume(float volume) {
-            mSessionImpl.onSetVolume(volume);
+        void setVolume(float volume) {
+            onSetVolume(volume);
         }
 
         /**
-         * Calls {@link TvInputSessionImpl#onTune}.
+         * Calls {@link onTune}.
          */
-        @Override
-        public final void tune(Uri channelUri) {
-            mSessionImpl.onTune(channelUri);
+        void tune(Uri channelUri) {
+            onTune(channelUri);
             // TODO: Handle failure.
         }
     }
@@ -222,7 +205,7 @@
                             return;
                         }
                         ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this,
-                                new TvInputSessionImplInternal(sessionImpl));
+                                sessionImpl);
                         cb.onSessionCreated(stub);
                     } catch (RemoteException e) {
                         Log.e(TAG, "error in onSessionCreated");
diff --git a/core/java/android/tv/TvInputSession.java b/core/java/android/tv/TvInputSession.java
deleted file mode 100644
index cdd363b..0000000
--- a/core/java/android/tv/TvInputSession.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.tv;
-
-import android.net.Uri;
-import android.view.Surface;
-
-/**
- * The TvInputSession provides the per-session functionality of TvInputService.
- */
-public abstract class TvInputSession {
-    /**
-     * This method is called when the application would like to stop using the current input
-     * session.
-     */
-    public void release() { }
-
-    /**
-     * Sets the {@link Surface} for the current input session on which the TV input renders video.
-     *
-     * @param surface {@link Surface} to be used for the video playback of this session.
-     */
-    public void setSurface(Surface surface) { }
-
-    /**
-     * This method is called when the application needs to handle the change of audio focus by
-     * setting the relative volume of the current TV input service session.
-     *
-     * @param volume Volume scale from 0.0 to 1.0.
-     */
-    // TODO: Remove this once it becomes irrelevant for applications to handle audio focus. The plan
-    // is to introduce some new concepts that will solve a number of problems in audio policy today.
-    public void setVolume(float volume) { }
-
-    /**
-     * Tunes to a given channel.
-     *
-     * @param channelUri The URI of the channel.
-     */
-    public void tune(Uri channelUri) { }
-}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 80d5bf2..7d13399 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -236,6 +236,11 @@
     boolean isSafeModeEnabled();
 
     /**
+     * Enables the screen if all conditions are met.
+     */
+    void enableScreenIfNeeded();
+
+    /**
      * Clears the frame statistics for a given window.
      *
      * @param token The window token.
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index cbb98e1..1429837 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -67,7 +67,7 @@
     void destroy(boolean full) {
         mInitialized = false;
         updateEnabledState(null);
-        nDestroyCanvas(mNativeProxy);
+        nDestroyCanvasAndSurface(mNativeProxy);
     }
 
     private void updateEnabledState(Surface surface) {
@@ -300,7 +300,7 @@
     private static native void nDrawDisplayList(long nativeProxy, long displayList,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
     private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
-    private static native void nDestroyCanvas(long nativeProxy);
+    private static native void nDestroyCanvasAndSurface(long nativeProxy);
 
     private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
 
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index d5a7d33..032a82f 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -49,7 +49,7 @@
 public interface WindowManager extends ViewManager {
     /**
      * Exception that is thrown when trying to add view whose
-     * {@link WindowManager.LayoutParams} {@link WindowManager.LayoutParams#token}
+     * {@link LayoutParams} {@link LayoutParams#token}
      * is invalid.
      */
     public static class BadTokenException extends RuntimeException {
@@ -173,7 +173,6 @@
          * @see #TYPE_SEARCH_BAR
          * @see #TYPE_PHONE
          * @see #TYPE_SYSTEM_ALERT
-         * @see #TYPE_KEYGUARD
          * @see #TYPE_TOAST
          * @see #TYPE_SYSTEM_OVERLAY
          * @see #TYPE_PRIORITY_PHONE
@@ -197,7 +196,6 @@
             @ViewDebug.IntToString(from = TYPE_SEARCH_BAR, to = "TYPE_SEARCH_BAR"),
             @ViewDebug.IntToString(from = TYPE_PHONE, to = "TYPE_PHONE"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_ALERT, to = "TYPE_SYSTEM_ALERT"),
-            @ViewDebug.IntToString(from = TYPE_KEYGUARD, to = "TYPE_KEYGUARD"),
             @ViewDebug.IntToString(from = TYPE_TOAST, to = "TYPE_TOAST"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY, to = "TYPE_SYSTEM_OVERLAY"),
             @ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE, to = "TYPE_PRIORITY_PHONE"),
@@ -341,13 +339,13 @@
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;
-        
+
         /**
          * Window type: keyguard window.
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
-        
+
         /**
          * Window type: transient notifications.
          * In multiuser systems shows only on the owning user's window.
@@ -916,7 +914,6 @@
          */
         public static final int FLAG_NEEDS_MENU_KEY = 0x40000000;
 
-
         /**
          * Various behavioral options/flags.  Default is none.
          * 
@@ -1090,6 +1087,14 @@
         public static final int PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR = 0x00000200;
 
         /**
+         * Flag whether the current window is a keyguard window, meaning that it will hide all other
+         * windows behind it except for windows with flag {@link #FLAG_SHOW_WHEN_LOCKED} set.
+         * Further, this can only be set by {@link LayoutParams#TYPE_STATUS_BAR}.
+         * {@hide}
+         */
+        public static final int PRIVATE_FLAG_KEYGUARD = 0x00000400;
+
+        /**
          * Control flags that are private to the platform.
          * @hide
          */
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index e68d4c0..c9be54d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1005,6 +1005,14 @@
     public void dismissKeyguardLw();
 
     /**
+     * Ask the policy whether the Keyguard has drawn. If the Keyguard is disabled, this method
+     * returns true as soon as we know that Keyguard is disabled.
+     *
+     * @return true if the keyguard has drawn.
+     */
+    public boolean isKeyguardDrawnLw();
+
+    /**
      * Given an orientation constant, returns the appropriate surface rotation,
      * taking into account sensors, docking mode, rotation lock, and other factors.
      *
diff --git a/core/java/android/webkit/PermissionRequest.java b/core/java/android/webkit/PermissionRequest.java
new file mode 100644
index 0000000..2f8850b
--- /dev/null
+++ b/core/java/android/webkit/PermissionRequest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.webkit;
+
+import android.net.Uri;
+
+/**
+ * This class wraps a permission request, and is used to request permission for
+ * the web content to access the resources.
+ *
+ * Either {@link #grant(long) grant()} or {@link #deny()} must be called to response the
+ * request, otherwise, {@link WebChromeClient#onPermissionRequest(PermissionRequest)} will
+ * not be invoked again if there is other permission request in this WebView.
+ *
+ * @hide
+ */
+public interface PermissionRequest {
+    /**
+     * Resource belongs to geolocation service.
+     */
+    public final static long RESOURCE_GEOLOCATION = 1 << 0;
+    /**
+     * Resource belongs to video capture device, like camera.
+     */
+    public final static long RESOURCE_VIDEO_CAPTURE = 1 << 1;
+    /**
+     * Resource belongs to audio capture device, like microphone.
+     */
+    public final static long RESOURCE_AUDIO_CAPTURE = 1 << 2;
+
+    /**
+     * @return the origin of web content which attempt to access the restricted
+     *         resources.
+     */
+    public Uri getOrigin();
+
+    /**
+     * @return a bit mask of resources the web content wants to access.
+     */
+    public long getResources();
+
+    /**
+     * Call this method to grant origin the permission to access the given resources.
+     * The granted permission is only valid for this WebView.
+     *
+     * @param resources the resources granted to be accessed by origin, to grant
+     *        request, the requested resources returned by {@link #getResources()}
+     *        must be equals or a subset of granted resources.
+     *        This parameter is designed to avoid granting permission by accident
+     *        especially when new resources are requested by web content.
+     *        Calling grant(getResources()) has security issue, the new permission
+     *        will be granted without being noticed.
+     */
+    public void grant(long resources);
+
+    /**
+     * Call this method to deny the request.
+     */
+    public void deny();
+}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index aa57423..60cba86 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -296,6 +296,30 @@
     public void onGeolocationPermissionsHidePrompt() {}
 
     /**
+     * Notify the host application that web content is requesting permission to
+     * access the specified resources and the permission currently isn't granted
+     * or denied. The host application must invoke {@link PermissionRequest#grant(long)}
+     * or {@link PermissionRequest#deny()}.
+     *
+     * If this method isn't overridden, the permission is denied.
+     *
+     * @param request the PermissionRequest from current web content.
+     * @hide
+     */
+    public void onPermissionRequest(PermissionRequest request) {
+        request.deny();
+    }
+
+    /**
+     * Notify the host application that the given permission request
+     * has been canceled. Any related UI should therefore be hidden.
+     *
+     * @param request the PermissionRequest need be canceled.
+     * @hide
+     */
+    public void onPermissionRequestCanceled(PermissionRequest request) {}
+
+    /**
      * Tell the client that a JavaScript execution timeout has occured. And the
      * client may decide whether or not to interrupt the execution. If the
      * client returns true, the JavaScript will be interrupted. If the client
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 85168fd..62fbbc4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -25,6 +25,7 @@
 import android.graphics.Picture;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
 import android.net.http.SslCertificate;
 import android.os.Build;
 import android.os.Bundle;
@@ -1640,6 +1641,21 @@
     }
 
     /**
+     * Preauthorize the given origin to access resources.
+     * This authorization only valid for this WebView instance life cycle and
+     * will not retained.
+     *
+     * @param origin the origin authorized to access resources
+     * @param resources the resource authorized to be accessed by origin.
+     *
+     * @hide
+     */
+    public void preauthorizePermission(Uri origin, long resources) {
+        checkThread();
+        mProvider.preauthorizePermission(origin, resources);
+    }
+
+    /**
      * Sets the Picture listener. This is an interface used to receive
      * notifications of a new Picture.
      *
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 696aad4..9488cdd 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -23,6 +23,7 @@
 import android.graphics.Picture;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
 import android.net.http.SslCertificate;
 import android.os.Bundle;
 import android.os.Message;
@@ -245,6 +246,8 @@
 
     public View findHierarchyView(String className, int hashCode);
 
+    public void preauthorizePermission(Uri origin, long resources);
+
     //-------------------------------------------------------------------------
     // Provider internal methods
     //-------------------------------------------------------------------------
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 96a2ab5..301317e 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -7167,7 +7167,7 @@
 
             final int itemCount = getCount();
             final int clampedPosition = MathUtils.constrain(targetPosition, 0, itemCount - 1);
-            final int clampedBoundPosition = MathUtils.constrain(boundPosition, 0, itemCount - 1);
+            final int clampedBoundPosition = MathUtils.constrain(boundPosition, -1, itemCount - 1);
             final int firstPosition = getFirstVisiblePosition();
             final int lastPosition = firstPosition + getChildCount();
             final int targetRow = getRowForPosition(clampedPosition);
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 64a1574..cde8080 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -161,9 +161,11 @@
     @Override
     public View onCreateActionView() {
         // Create the view and set its data model.
-        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
         ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
-        activityChooserView.setActivityChooserModel(dataModel);
+        if (!activityChooserView.isInEditMode()) {
+            ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
+            activityChooserView.setActivityChooserModel(dataModel);
+        }
 
         // Lookup and set the expand action icon.
         TypedValue outTypedValue = new TypedValue();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5e4c143..a7278da 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -714,19 +714,19 @@
                     break;
 
                 case com.android.internal.R.styleable.TextAppearance_shadowColor:
-                    shadowcolor = a.getInt(attr, 0);
+                    shadowcolor = appearance.getInt(attr, 0);
                     break;
 
                 case com.android.internal.R.styleable.TextAppearance_shadowDx:
-                    dx = a.getFloat(attr, 0);
+                    dx = appearance.getFloat(attr, 0);
                     break;
 
                 case com.android.internal.R.styleable.TextAppearance_shadowDy:
-                    dy = a.getFloat(attr, 0);
+                    dy = appearance.getFloat(attr, 0);
                     break;
 
                 case com.android.internal.R.styleable.TextAppearance_shadowRadius:
-                    r = a.getFloat(attr, 0);
+                    r = appearance.getFloat(attr, 0);
                     break;
                 }
             }
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index c6afae0..fb93ddd 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -170,6 +170,15 @@
         init(dialog.getWindow().getDecorView());
     }
 
+    /**
+     * Only for edit mode.
+     * @hide
+     */
+    public WindowDecorActionBar(View layout) {
+        assert layout.isInEditMode();
+        init(layout);
+    }
+
     private void init(View decor) {
         mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
                 com.android.internal.R.id.action_bar_overlay_layout);
@@ -559,8 +568,8 @@
             return;
         }
 
-        final FragmentTransaction trans = mActivity.getFragmentManager().beginTransaction()
-                .disallowAddToBackStack();
+        final FragmentTransaction trans = mActionView.isInEditMode() ? null :
+                mActivity.getFragmentManager().beginTransaction().disallowAddToBackStack();
 
         if (mSelectedTab == tab) {
             if (mSelectedTab != null) {
@@ -578,7 +587,7 @@
             }
         }
 
-        if (!trans.isEmpty()) {
+        if (trans != null && !trans.isEmpty()) {
             trans.commit();
         }
     }
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 63ff5a0..b78c70f 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -25,12 +25,24 @@
 interface IKeyguardService {
     boolean isShowing();
     boolean isSecure();
-    boolean isShowingAndNotHidden();
+    boolean isShowingAndNotOccluded();
     boolean isInputRestricted();
     boolean isDismissable();
     oneway void verifyUnlock(IKeyguardExitCallback callback);
     oneway void keyguardDone(boolean authenticated, boolean wakeup);
-    oneway void setHidden(boolean isHidden);
+
+    /**
+     * Sets the Keyguard as occluded when a window dismisses the Keyguard with flag
+     * FLAG_SHOW_ON_LOCK_SCREEN.
+     *
+     * @param isOccluded Whether the Keyguard is occluded by another window.
+     * @return See IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_*. This is needed because
+     *         PhoneWindowManager needs to set these flags immediately and can't wait for the
+     *         Keyguard thread to pick it up. In the hidden case, PhoneWindowManager is solely
+     *         responsible to make sure that the flags are unset.
+     */
+    int setOccluded(boolean isOccluded);
+
     oneway void dismiss();
     oneway void onDreamingStarted();
     oneway void onDreamingStopped();
diff --git a/core/java/com/android/internal/policy/IKeyguardServiceConstants.java b/core/java/com/android/internal/policy/IKeyguardServiceConstants.java
new file mode 100644
index 0000000..b88174a
--- /dev/null
+++ b/core/java/com/android/internal/policy/IKeyguardServiceConstants.java
@@ -0,0 +1,41 @@
+/*
+ * 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 com.android.internal.policy;
+
+/**
+ * @hide
+ */
+public class IKeyguardServiceConstants {
+
+    /**
+     * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
+     * Don't change the keyguard window flags.
+     */
+    public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE = 0;
+
+    /**
+     * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
+     * Set the keyguard window flags to FLAG_SHOW_WALLPAPER and PRIVATE_FLAG_KEYGUARD.
+     */
+    public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS = 1;
+
+    /**
+     * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
+     * Unset the keyguard window flags to FLAG_SHOW_WALLPAPER and PRIVATE_FLAG_KEYGUARD.
+     */
+    public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS = 2;
+}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index dfdb9ae..6428e15 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -47,6 +47,8 @@
             int uid, int initialPid, String message, int userId);
     void onClearAllNotifications(int userId);
     void onNotificationClear(String pkg, String tag, int id, int userId);
+    void onNotificationVisibilityChanged(
+            in String[] newlyVisibleKeys, in String[] noLongerVisibleKeys);
     void setSystemUiVisibility(int vis, int mask);
     void setHardKeyboardEnabled(boolean enabled);
     void toggleRecentApps();
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 4504910..2882b54 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -788,13 +788,13 @@
      */
     public int getKeyguardStoredPasswordQuality() {
         int quality =
-                (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+                (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
         // If the user has chosen to use weak biometric sensor, then return the backup locking
         // method and treat biometric as a special case.
         if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
             quality =
                 (int) getLong(PASSWORD_TYPE_ALTERNATE_KEY,
-                        DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
         }
         return quality;
     }
@@ -804,7 +804,7 @@
      */
     public boolean usingBiometricWeak() {
         int quality =
-                (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+                (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
         return quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
     }
 
@@ -943,11 +943,12 @@
      */
     public boolean isLockPatternEnabled() {
         final boolean backupEnabled =
-                getLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
-                == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+                getLong(PASSWORD_TYPE_ALTERNATE_KEY,
+                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
+                                == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
 
         return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false)
-                && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
+                && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
                         == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING ||
                         (usingBiometricWeak() && backupEnabled));
     }
diff --git a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
index 961e471..5f3c5f9 100644
--- a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
+++ b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
@@ -107,8 +107,6 @@
         }
         if (background instanceof ColorDrawable) {
             mModestyPanel.setBackgroundDrawable(background);
-        } else {
-            mModestyPanel.setBackgroundColor(Color.BLACK);
         }
         SizeAdaptiveLayout.LayoutParams layout =
                 new SizeAdaptiveLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/core/jni/android_view_GLRenderer.cpp b/core/jni/android_view_GLRenderer.cpp
index 6ae6c8f..d0269a3 100644
--- a/core/jni/android_view_GLRenderer.cpp
+++ b/core/jni/android_view_GLRenderer.cpp
@@ -146,8 +146,8 @@
         jlong renderNodePtr) {
     using namespace android::uirenderer;
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
-    TreeInfo info = {0};
-    renderNode->prepareTree(info);
+    TreeInfo ignoredInfo;
+    renderNode->prepareTree(ignoredInfo);
 }
 
 static void android_view_GLRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 2eb0d78..b2f17de 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -127,8 +127,8 @@
 static jboolean android_view_HardwareLayer_flushChanges(JNIEnv* env, jobject clazz,
         jlong layerUpdaterPtr) {
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
-    bool ignoredHasFunctors;
-    return layer->apply(&ignoredHasFunctors);
+    TreeInfo ignoredInfo;
+    return layer->apply(ignoredInfo);
 }
 
 static jlong android_view_HardwareLayer_getLayer(JNIEnv* env, jobject clazz,
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 30d3e0c..b5f489d 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -121,10 +121,10 @@
     proxy->drawDisplayList(displayList, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
 }
 
-static void android_view_ThreadedRenderer_destroyCanvas(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
         jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->destroyCanvas();
+    proxy->destroyCanvasAndSurface();
 }
 
 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
@@ -194,7 +194,7 @@
     { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
     { "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup },
     { "nDrawDisplayList", "(JJIIII)V", (void*) android_view_ThreadedRenderer_drawDisplayList },
-    { "nDestroyCanvas", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvas },
+    { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
     { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
     { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
     { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b2709af..606a4b1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -234,6 +234,7 @@
     <protected-broadcast android:name="android.net.conn.NETWORK_CONDITIONS_MEASURED" />
     <protected-broadcast
             android:name="android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED" />
+    <protected-broadcast android:name="android.net.scoring.SCORE_NETWORKS" />
     <protected-broadcast android:name="android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE" />
     <protected-broadcast android:name="android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE" />
     <protected-broadcast android:name="android.intent.action.AIRPLANE_MODE" />
@@ -762,6 +763,13 @@
         android:description="@string/permdesc_changeWimaxState"
         android:label="@string/permlab_changeWimaxState" />
 
+    <!-- Allows applications to act as network scorers. @hide -->
+    <permission android:name="android.permission.SCORE_NETWORKS"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="normal"
+        android:description="@string/permdesc_scoreNetworks"
+        android:label="@string/permlab_scoreNetworks" />
+
     <!-- ======================================= -->
     <!-- Permissions for short range, peripheral networks -->
     <!-- ======================================= -->
@@ -2290,6 +2298,13 @@
         android:description="@string/permdesc_broadcastWapPush"
         android:protectionLevel="signature" />
 
+    <!-- Allows an application to broadcast a SCORE_NETWORKS request.
+         <p>Not for use by third-party applications. @hide -->
+    <permission android:name="android.permission.BROADCAST_SCORE_NETWORKS"
+        android:label="@string/permlab_broadcastScoreNetworks"
+        android:description="@string/permdesc_broadcastScoreNetworks"
+        android:protectionLevel="signature|system" />
+
     <!-- Not for use by third-party applications. -->
     <permission android:name="android.permission.MASTER_CLEAR"
         android:label="@string/permlab_masterClear"
diff --git a/core/res/res/drawable-hdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..3813563
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..47263ea
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..aa23c59
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..cac32b5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..25b8935
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..598b98c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..df2fdb8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..79fe7c5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..7bcebcd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..eb1d945
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..d43e4d1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..42ac8ca
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..b5f6176
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..9137fea
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..3f1eee3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..506a186
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..e54d32e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..fb0e926
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..ef4ebc0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..9ddbcf5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..ddacb59
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..c10a1b7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..bd80981
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..513ee8b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..c1c23d04
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..38b8e8b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..c1ca323
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..d6002a7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..1a2546f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..500ec33
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..21ed9144
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..fc1b8b4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..8e1ab5b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..81b13aa
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..d95f1d0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..93469a2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..5753d89
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..b3493e7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..cd5b00f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..5ee867c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_check_quantum_anim.xml b/core/res/res/drawable/btn_check_quantum_anim.xml
new file mode 100644
index 0000000..d68d512
--- /dev/null
+++ b/core/res/res/drawable/btn_check_quantum_anim.xml
@@ -0,0 +1,79 @@
+<!-- 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:trigger="state_checked"
+    android:versionCode="1" >
+
+    <size
+        android:height="32dp"
+        android:width="32dp" />
+
+    <viewport
+        android:viewportHeight="320"
+        android:viewportWidth="320" />
+
+    <group>
+        <path
+            android:name="check"
+            android:pathData="M 232.1,80.6 L 248.5,92.1 L 145.2,239.5 L 71.5,187.8 L 83,171.5 L 140.3,211.7 z"
+            android:fill="?attr/colorControlActivated" />
+    </group>
+    <group>
+        <path
+            android:name="box1"
+            android:pathData="M 160,216.5 L 143.5,240 L 120,223.5 L 136.5,200 L 160,216.5 L 160,216.5 z"
+            android:fill="?attr/colorControlActivated"
+            android:stroke="?attr/colorControlActivated"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
+    </group>
+    <group>
+        <path
+            android:name="box2"
+            android:pathData="M 160,216.5 L 143.5,240 L 120,223.5 L 136.5,200 L 160,216.5 L 160,216.5 z"
+            android:rotation="-35"
+            android:pivotX="140"
+            android:pivotY="220"
+            android:fill="?attr/colorControlNormal"
+            android:stroke="?attr/colorControlNormal"
+            android:strokeWidth="5"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
+    </group>
+    <group>
+        <path
+            android:name="box3"
+            android:pathData="M 160,200 L 160,240 L 120,240 L 120,200 L 160,200 L 160,200 z"
+            android:stroke="?attr/colorControlNormal"
+            android:strokeWidth="10"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
+    </group>
+    <group>
+        <path
+            android:name="box4"
+            android:pathData="M 240,80 L 240,240 L 80,240 L 80,80 L 240,80 L 240,80 z"
+            android:stroke="?attr/colorControlNormal"
+            android:strokeWidth="20"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
+    </group>
+
+    <animation
+        android:durations="300,100,0,300"
+        android:sequence="check,box1,box2,box3,box4" />
+
+</vector>
diff --git a/core/res/res/drawable/ic_clear_quantum.xml b/core/res/res/drawable/ic_clear_quantum.xml
new file mode 100644
index 0000000..02f0929
--- /dev/null
+++ b/core/res/res/drawable/ic_clear_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_clear_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_commit_search_api_quantum.xml b/core/res/res/drawable/ic_commit_search_api_quantum.xml
new file mode 100644
index 0000000..02d08b9
--- /dev/null
+++ b/core/res/res/drawable/ic_commit_search_api_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_commit_search_api_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_go_search_api_quantum.xml b/core/res/res/drawable/ic_go_search_api_quantum.xml
new file mode 100644
index 0000000..b5b5cfb
--- /dev/null
+++ b/core/res/res/drawable/ic_go_search_api_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_go_search_api_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_search_api_quantum.xml b/core/res/res/drawable/ic_search_api_quantum.xml
new file mode 100644
index 0000000..2bbc294
--- /dev/null
+++ b/core/res/res/drawable/ic_search_api_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_search_api_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/ic_voice_search_api_quantum.xml b/core/res/res/drawable/ic_voice_search_api_quantum.xml
new file mode 100644
index 0000000..ddb14ef
--- /dev/null
+++ b/core/res/res/drawable/ic_voice_search_api_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_voice_search_api_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_bg_dim.xml
similarity index 77%
rename from core/res/res/drawable/notification_quantum_background.xml
rename to core/res/res/drawable/notification_bg_dim.xml
index 7b508a9..ec20368 100644
--- a/core/res/res/drawable/notification_quantum_background.xml
+++ b/core/res/res/drawable/notification_bg_dim.xml
@@ -15,7 +15,9 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffffffff" />
-    <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
-</shape>
\ No newline at end of file
+<touch-feedback
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:tint="#ff444444"
+    >
+    <item android:drawable="@drawable/notification_bg_normal" />
+</touch-feedback>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_quantum_bg.xml b/core/res/res/drawable/notification_quantum_bg.xml
index 608115e..300a565 100644
--- a/core/res/res/drawable/notification_quantum_bg.xml
+++ b/core/res/res/drawable/notification_quantum_bg.xml
@@ -16,6 +16,16 @@
   -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true"  android:drawable="@drawable/notification_quantum_press" />
-    <item android:state_pressed="false" android:drawable="@drawable/notification_quantum_background" />
+    <item android:state_pressed="true">
+        <shape>
+            <solid android:color="#ffd0d0d0" />
+            <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <solid android:color="#fffafafa" />
+            <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
+        </shape>
+    </item>
 </selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_quantum_bg_dim.xml
similarity index 65%
copy from core/res/res/drawable/notification_quantum_background.xml
copy to core/res/res/drawable/notification_quantum_bg_dim.xml
index 7b508a9..ab0e049 100644
--- a/core/res/res/drawable/notification_quantum_background.xml
+++ b/core/res/res/drawable/notification_quantum_bg_dim.xml
@@ -15,7 +15,15 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffffffff" />
-    <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
-</shape>
\ No newline at end of file
+<touch-feedback
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:tint="#ffffffff"
+    android:tintMode="src_over"
+    >
+    <item>
+        <shape>
+            <solid android:color="#d4ffffff" />
+            <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
+        </shape>
+    </item>
+</touch-feedback>
\ No newline at end of file
diff --git a/core/res/res/drawable/text_select_handle_left_quantum.xml b/core/res/res/drawable/text_select_handle_left_quantum.xml
new file mode 100644
index 0000000..a0ad7cf
--- /dev/null
+++ b/core/res/res/drawable/text_select_handle_left_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/text_select_handle_left_qntm_alpha"
+    android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/text_select_handle_middle_quantum.xml b/core/res/res/drawable/text_select_handle_middle_quantum.xml
new file mode 100644
index 0000000..bff0b66
--- /dev/null
+++ b/core/res/res/drawable/text_select_handle_middle_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/text_select_handle_middle_qntm_alpha"
+    android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/text_select_handle_right_quantum.xml b/core/res/res/drawable/text_select_handle_right_quantum.xml
new file mode 100644
index 0000000..413661f
--- /dev/null
+++ b/core/res/res/drawable/text_select_handle_right_quantum.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/text_select_handle_right_qntm_alpha"
+    android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/textfield_search_quantum.xml b/core/res/res/drawable/textfield_search_quantum.xml
new file mode 100644
index 0000000..877de46
--- /dev/null
+++ b/core/res/res/drawable/textfield_search_quantum.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="false" android:state_enabled="true">
+        <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:state_window_focused="false" android:state_enabled="false">
+        <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:state_enabled="true" android:state_focused="true">
+        <nine-patch android:src="@drawable/textfield_search_activated_qntm_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+    <item android:state_enabled="true" android:state_activated="true">
+        <nine-patch android:src="@drawable/textfield_search_activated_qntm_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+    <item android:state_enabled="true">
+        <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/interpolator/fast_out_linear_in.xml
similarity index 77%
rename from core/res/res/drawable/notification_quantum_press.xml
rename to core/res/res/interpolator/fast_out_linear_in.xml
index 4999f55..19f95a6 100644
--- a/core/res/res/drawable/notification_quantum_press.xml
+++ b/core/res/res/interpolator/fast_out_linear_in.xml
@@ -15,7 +15,8 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffcccccc" />
-    <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.4"
+    android:controlY1="0"
+    android:controlX2="1"
+    android:controlY2="1"/>
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/interpolator/fast_out_slow_in.xml
similarity index 77%
copy from core/res/res/drawable/notification_quantum_press.xml
copy to core/res/res/interpolator/fast_out_slow_in.xml
index 4999f55..2d68dbb 100644
--- a/core/res/res/drawable/notification_quantum_press.xml
+++ b/core/res/res/interpolator/fast_out_slow_in.xml
@@ -15,7 +15,8 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffcccccc" />
-    <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.4"
+    android:controlY1="0"
+    android:controlX2="0.2"
+    android:controlY2="1"/>
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/interpolator/linear_out_slow_in.xml
similarity index 77%
copy from core/res/res/drawable/notification_quantum_press.xml
copy to core/res/res/interpolator/linear_out_slow_in.xml
index 4999f55..83fc223 100644
--- a/core/res/res/drawable/notification_quantum_press.xml
+++ b/core/res/res/interpolator/linear_out_slow_in.xml
@@ -15,7 +15,8 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffcccccc" />
-    <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0"
+    android:controlY1="0"
+    android:controlX2="0.2"
+    android:controlY2="1"/>
diff --git a/core/res/res/layout/action_bar_home_quantum.xml b/core/res/res/layout/action_bar_home_quantum.xml
new file mode 100644
index 0000000..9213458
--- /dev/null
+++ b/core/res/res/layout/action_bar_home_quantum.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.internal.widget.ActionBarView$HomeView"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_vertical|start">
+    <ImageView android:id="@android:id/up"
+        android:src="?android:attr/homeAsUpIndicator"
+        android:layout_gravity="center_vertical|start"
+        android:visibility="gone"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:scaleType="centerInside" />
+    <ImageView android:id="@android:id/home"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="8dip"
+        android:layout_marginTop="@android:dimen/action_bar_icon_vertical_padding"
+        android:layout_marginBottom="@android:dimen/action_bar_icon_vertical_padding"
+        android:adjustViewBounds="true"
+        android:scaleType="fitCenter" />
+</view>
diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml
index 8863cfa..8f3019d 100644
--- a/core/res/res/layout/notification_template_quantum_base.xml
+++ b/core/res/res/layout/notification_template_quantum_base.xml
@@ -17,7 +17,6 @@
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:background="@android:drawable/notification_quantum_bg"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="64dp"
diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml
index 63935bb..45e69b1 100644
--- a/core/res/res/layout/notification_template_quantum_big_base.xml
+++ b/core/res/res/layout/notification_template_quantum_big_base.xml
@@ -17,7 +17,6 @@
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:background="@android:drawable/notification_quantum_bg"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_quantum_big_picture.xml b/core/res/res/layout/notification_template_quantum_big_picture.xml
index e49c3bd..f68e414 100644
--- a/core/res/res/layout/notification_template_quantum_big_picture.xml
+++ b/core/res/res/layout/notification_template_quantum_big_picture.xml
@@ -17,7 +17,6 @@
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:background="@android:drawable/notification_quantum_bg"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/core/res/res/layout/notification_template_quantum_big_text.xml b/core/res/res/layout/notification_template_quantum_big_text.xml
index 516b0c4..f7769d7 100644
--- a/core/res/res/layout/notification_template_quantum_big_text.xml
+++ b/core/res/res/layout/notification_template_quantum_big_text.xml
@@ -16,7 +16,6 @@
   -->
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:background="@android:drawable/notification_quantum_bg"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml
index c6192be..04974c4 100644
--- a/core/res/res/layout/notification_template_quantum_inbox.xml
+++ b/core/res/res/layout/notification_template_quantum_inbox.xml
@@ -18,7 +18,6 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:internal="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/status_bar_latest_event_content"
-    android:background="@android:drawable/notification_quantum_bg"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     internal:layout_minHeight="65dp"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 88f5c54..f9b00a9 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n legstuk-diens te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"skakel met \'n toestel-admin"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Laat die houer toe om bedoelings na \'n toesteladministrateur te stuur. Dit moet nooit vir normale programme nodig wees nie."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"bind aan \'n TV-invoer"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Laat die houer toe om aan die topvlak-koppelvlak van \'n TV-invoer te bind. Behoort nooit vir gewone programme nodig te wees nie."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"voeg \'n toesteladministrateur by of verwyder een"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Laat die houer aktiewe toesteladministrateurs byvoeg of verwyder. Behoort nooit nodig te wees vir normale programme nie."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"verander skermoriëntasie"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 101c4dc..c6ff2da 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة الأداة. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"التفاعل مع مشرف الجهاز"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"للسماح للمالك بإرسال الأهداف إلى أحد مشرفي الجهاز. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"الالتزام بإدخال التلفزيون"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لإدخال التلفزيون. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"إضافة مشرف جهاز أو إزالته"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"للسماح بحامل البطاقة بإضافة مشرفي أجهزة نشطين أو إزالتهم. لا يلزم ذلك أبدًا للتطبيقات العادية."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"تغيير اتجاه الشاشة"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 1d063f6..618eba9 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de widget. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar amb un administrador del dispositiu"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet que el titular enviï intents a un administrador del sistema. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"Vinculació a una entrada de televisor"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permet que el titular es vinculi a la interfície de nivell superior d\'una entrada de televisor. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"afegeix un administrador al dispositiu o suprimeix-lo"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permet que el titular afegeixi administradors actius al dispositiu o en suprimeixi. No s\'hauria de necessitar per a les aplicacions normals."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"canviar l\'orientació de la pantalla"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 3c113f0..73913a2 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Tillader, at brugeren kan forpligte sig til en grænseflade for en widgettjeneste på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikere med en enhedsadministrator"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Tillader, at brugeren kan sende hensigter til en enhedsadministrator. Dette bør aldrig være nødvendigt for almindelige apps."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"knyt til en tv-indgang"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Giver indehaveren mulighed for at knytte sig til det øverste grænsefladeniveau for en tv-indgang. Dette bør ikke være nødvendigt i normale apps."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"tilføje eller fjerne en enhedsadministrator"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Tillader, at man tilføjer eller fjerner aktive enhedsadministratorer. Dette burde aldrig være nødvendigt til normale apps."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"skift skærmretning"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index e1e9106..456b56d 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας γραφικών στοιχείων. Δεν απαιτείται για κανονικές εφαρμογές."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"επικοινωνία με έναν διαχειριστή συσκευής"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Επιτρέπει στον κάτοχο την αποστολή στόχων σε έναν διαχειριστή συσκευής. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"σύνδεση σε μία είσοδο τηλεόρασης"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Επιτρέπει στον κάτοχο τη σύνδεση στη διεπαφή ανώτερου επιπέδου μιας εισόδου τηλεόρασης. Δεν απαιτείται ποτέ για τις συνηθισμένες εφαρμογές."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"προσθήκη ή κατάργηση ενός διαχειριστή συσκευής"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Επιτρέπει στον κάτοχο να προσθέτει ή να καταργεί ενεργούς διαχειριστές συσκευών. Δεν θα πρέπει να ζητείται ποτέ για κανονικές εφαρμογές."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"αλλαγή προσανατολισμού οθόνης"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 8da35f1..528c840 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Allows the holder to send intents to a device administrator. Should never be needed for normal apps."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"bind to a TV input"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Allows the holder to bind to the top-level interface of a TV input. Should never be needed for normal apps."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"add or remove a device admin"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Allows the holder to add or remove active device administrators. Should never be needed for normal apps."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"change screen orientation"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 8da35f1..528c840 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Allows the holder to send intents to a device administrator. Should never be needed for normal apps."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"bind to a TV input"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Allows the holder to bind to the top-level interface of a TV input. Should never be needed for normal apps."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"add or remove a device admin"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Allows the holder to add or remove active device administrators. Should never be needed for normal apps."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"change screen orientation"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index adb033f..38774d7 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lubab omanikul siduda vidina teenuse ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"seadme administraatoriga suhtlemine"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Võimaldab omanikul saata kavatsusi seadme administraatorile. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"sidumine TV-sisendiga"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Lubab omanikul siduda TV-sisendi ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"seadme administraatori lisamine või eemaldamine"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Võimaldab omanikul lisada või eemaldada aktiivseid seadme administraatoreid. Tavarakenduste puhul ei tohiks see kunagi vajalik olla."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"muuda ekraani paigutust"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1419bc4..4a1c409 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"धारक को किसी विजेट सेवा के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"किसी उपकरण व्‍यवस्‍थापक के साथ सहभागिता करें"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"धारक को किसी उपकरण व्‍यवस्‍थापक को उद्देश्य भेजने देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"टीवी इनपुट से आबद्ध करें"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"धारक को किसी टीवी इनपुट के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देती है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"उपकरण उपकरण सुचारू ढ़ंग से चलाने वाले को जोड़ें या निकालें"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"धारक को सक्रिय डिवाइस व्यवस्थापकों को जोड़ने या निकालने देता है. सामान्य ऐप्स  के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"स्‍क्रीन अभिविन्‍यास बदलें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index dde0a5b..10e4ac8 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge widgeta. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcija s administratorom uređaja"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Nositelju omogućuje slanje namjera administratoru uređaja. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"povezivanje s TV ulazom"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Nositelju omogućuje vezanje uz sučelje najviše razine TV ulaza. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"dodavanje ili uklanjanje administratora uređaja"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Omogućuje nositelju dodavanje ili uklanjanje administratora aktivnih uređaja. Nikada ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"promjena orijentacije zaslona"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 41a1fb9..fd3a887 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lehetővé teszi a használó számára, hogy csatlakozzon egy modulszolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"az eszközkezelő használata"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Lehetővé teszi a tulajdonos számára, hogy célokat küldjön egy eszközkezelőnek. A normál alkalmazásoknak erre soha nincs szüksége."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"csatlakozás tévébemenethez"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Lehetővé teszi, hogy a tulajdonos kapcsolódjon egy tévébemenet legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"eszközrendszergazda hozzáadása vagy eltávolítása"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Lehetővé teszi a tulajdonos számára, hogy aktív eszközrendszergazdákat adjon meg vagy távolítson el. A normál alkalmazásoknál erre soha nincs szükség."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"képernyő irányának módosítása"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index b1d94e6..eddb9c85 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan widget. Tidak pernah diperlukan oleh apl normal."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan admin perangkat"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Mengizinkan pemegang mengirimkan tujuan kepada administrator perangkat. Tidak pernah diperlukan oleh apl normal."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"mengikat ke masukan TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Memungkinkan pemegang mengikat ke antarmuka tingkat tinggi dari masukan TV. Tidak pernah diperlukan oleh aplikasi normal."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"menambah atau menghapus admin perangkat"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Memungkinkan pemegang menambahkan atau menghapus administrator perangkat aktif. Tidak pernah dibutuhkan oleh aplikasi normal."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ubah orientasi layar"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 222dfe3..43b94b7 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"‏מאפשר למשתמש לבצע איגוד לממשק הרמה העליונה של שירות Widget. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"קיים אינטראקציה עם מנהל המכשיר"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"מאפשר למשתמש לשלוח כוונות למנהל התקנים. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"איגוד לקלט טלוויזיה"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"הרשאה זו מאפשרת למחזיק בה לבצע איגוד לממשק הרמה העליונה של קלט טלוויזיה. הרשאה זו אף פעם אינה אמורה להיות נחוצה לאפליקציות רגילות."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"הוספה או הסרה של מנהלי מכשיר"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"מאפשרת לבעלים להוסיף או להסיר מנהלי מכשיר פעילים. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"שנה את כיוון המסך"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 8dbd6ac..cb4f257 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ធាតុ​ក្រាហ្វិក។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ទាក់ទង​ជា​មួយ​អ្នកគ្រប់គ្រង​ឧបករណ៍"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ឲ្យ​ម្ចាស់​ផ្ញើ​គោលបំណង​​ទៅ​អ្នក​គ្រប់គ្រង​ឧបករណ៍។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"ភ្ជាប់​ទៅ​ការ​បញ្ចូល​ទូរទស្សន៍"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុចប្រទាក់​កម្រិត​ខ្ពស់​នៃ​ការ​បញ្ចូល​ទូរទស្សន៍។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"បន្ថែម​ ឬ​លុប​កម្មវិធី​គ្រប់គ្រង​​​ឧបករណ៍"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"អនុញ្ញាត​​​ឲ្យ​ម្ចាស់​​​បន្ថែម​ ឬ​លុប​កម្មវិធី​គ្រប់គ្រង​ឧបករណ៍​សកម្ម​ចេញ​។ មិន​គួរ​ប្រើ​សម្រាប់​កម្មវិធី​​ធម្មតា​ទេ​។"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ប្ដូរ​ទិស​អេក្រង់"</string>
diff --git a/core/res/res/values-land/dimens_quantum.xml b/core/res/res/values-land/dimens_quantum.xml
new file mode 100644
index 0000000..7789219
--- /dev/null
+++ b/core/res/res/values-land/dimens_quantum.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+
+    <!-- Default height of an action bar. -->
+    <dimen name="action_bar_default_height_quantum">48dp</dimen>
+    <!-- Default padding of an action bar. -->
+    <dimen name="action_bar_default_padding_quantum">0dp</dimen>
+
+</resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 79b8a33..178176f 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບອິນເຕີເຟດລະດັບສູງສຸດ ຂອງບໍລິການວິເຈັດ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ຕິດຕໍ່ກັບຜູ່ເບິ່ງແຍງອຸປະກອນ"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສົ່ງເຈດຕະນາຫາຜູ່ເບິ່ງແຍງລະບົບອຸປະກອນ. ແອັບຯທົ່ວໄປບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"ຜູກ​ກັບ​ການ​ປ້ອນ​ຂໍ້​ມູນ​ເຂົ້າ​ໂທ​ລະ​ທັດ"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"​ອະ​ນຸ​ຍາດ​ໃຫ້​ຜູ່​ຖື​ຜູກ​ຕິດ​ກັບ​ສ່ວ​ນ​ຕິດ​ຕໍ່​ລະ​ດັບ​ສູງ​ສຸດ​ຂອງ​ການ​ປ້ອນ​ຂໍ້​ມູນ​ເຂົ້າ​ໂທ​ລະ​ທັດ. ແອັບຯ​ທົ່ວ​ໄປ​ບໍ່​ຄວນ​ຈຳ​ເປັນ​ຕ້ອງ​ໃຊ້."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ເພີ່ມ ຫຼືລຶບຜູ່ເບິ່ງແຍງລະບົບອຸປະກອນ"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສາມາດລຶບ ຫຼືລຶບຂໍ້ມູນອຸປະກອນທີ່ນຳໃຊ້ໄດ້. ແອັບຯທົ່ວໄປບໍ່ຈຳເປັນຕ້ອງໃຊ້."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ປ່ຽນລວງຂອງໜ້າຈໍ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 99184d2..69d2420 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Leidžiama savininkui susisaistyti su aukščiausio lygio valdiklio paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"sąveikauti su įrenginio administratoriumi"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Leidžiama savininkui siųsti tikslus įrenginio administratoriui. Įprastoms programoms to neturėtų prireikti."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"susisaistyti su TV įvestimi"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Leidžiama savininkui susisaistyti su aukščiausio lygio TV įvesties sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pridėti arba pašalinti įrenginio administratorių"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Savininkui leidžiama pridėti aktyvių įrenginio administratorių arba juos pašalinti. Neturėtų reikėti įprastoms programoms."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"keisti ekrano padėtį"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 433115c..965e3eb 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ļauj īpašniekam izveidot saiti ar logrīka pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"mijiedarboties ar ierīces administratoru"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ļauj īpašniekam nosūtīt informāciju par nodomiem ierīces administratoram. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"Izveidot saiti ar TV ieeju"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Ļauj īpašniekam izveidot saiti ar TV ieejas augšējā līmeņa saskarni. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pievienot vai noņemt ierīces administratoru"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Ļauj īpašniekam pievienot vai noņemt aktīvos ierīces administratorus. Nekad nav nepieciešama parastām lietotnēm."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"mainīt ekrāna orientāciju"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 442b856..1284d92 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Эзэмшигч нь виджет үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"төхөөрөмжийн админтай харилцан үйлчлэх"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Эзэмшигч нь төхөөрөмжийн админруу интент илгээх боломжтой. Энгийн апп-д шаардлагагүй."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"ТВ оролт холбох"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Эзэмшигч нь ТВ оролтын дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"төхөөрөмжийн админ нэмэх, хасах"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Эзэмшигч нь идэвхтэй төхөөрөмжийн администраторыг нэмэх, хасах боломжтой. Энгийн апп-д шаардлагагүй."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"дэлгэцний чиглэлийг солих"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 379e3dd..65595ab 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite que o titular vincule a interface de nível superior de um serviço de widget. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir com um administrador do dispositivo"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite ao titular enviar intenções para um administrador do aparelho. Nunca deverá ser necessário para aplicações normais."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"vincular a uma entrada de TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permite ao titular vincular à interface de nível superior de uma entrada de TV. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"adicionar ou remover um administrador de dispositivos"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite que o titular adicione ou remova administradores de dispositivos ativos. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"mudar orientação do ecrã"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index aa467bb..851addc 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby miniaplikácií. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"komunikovať so správcom zariadenia"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Umožňuje držiteľovi odosielať informácie správcovi zariadenia. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"viazanie na televízny vstup"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania televízneho vstupu. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pridanie alebo odstránenie správcu zariadenia"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Umožňuje držiteľovi pridať alebo odstrániť správcov aktívnych zariadení. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"zmena orientácie obrazovky"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 0fed1e3..10d5376 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозвољава власнику да се обавеже на интерфејс услуге виџета највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"интеракција са администратором уређаја"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Омогућава да власник шаље своје намере администратору уређаја. Уобичајене апликације никада не би требало да је користе."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"повезивање са ТВ улазом"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Дозвољава власнику да се повеже са интерфејсом ТВ улаза највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"додавање или уклањање администратора уређаја"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Дозвољава власнику да додаје или уклања активне администраторе уређаја. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"промена положаја екрана"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 5afc0cd..820764c 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en widget. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"arbeta med en enhetsadministratör"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Tillåter att innehavaren skickar avsikter till en enhetsadministratör. Vanliga appar behöver aldrig göra detta."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"binda till en tv-insignal"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en tv-insignal. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"lägga till eller ta bort en enhetsadministratör"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Innehavaren får lägga till eller ta bort aktiva enhetsadministratörer. Detta ska normalt inte behövas för vanliga appar."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ändra bildskärmens rikting"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index e31392e..6758319 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби віджетів. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"взаємодіяти з адмін. пристрою"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Дозволяє власнику надсилати задавані функції адміністратору пристрою. Ніколи не застосовується для звичайних програм."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"прив’язуватися до вводу телевізора"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня вводу телевізора. Ніколи не застосовується для звичайних додатків."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"додавати чи вилучати адміністраторів пристрою"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Дозволяє власнику додавати чи вилучати активних адміністраторів пристрою. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"змінювати орієнтацію екрана"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index fa499d9..45f1856 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允許應用程式繫結至小工具服務的頂層介面 (不建議一般應用程式使用)。"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允許應用程式將調用請求傳送至裝置管理員 (不建議一般應用程式使用)。"</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"繫結至電視訊號輸入裝置"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"允許應用程式繫結至電視訊號輸入裝置的頂層介面,但一般應用程式並不需要使用。"</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"新增或移除裝置管理員"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"允許應用程式新增或移除有效的裝置管理員 (不建議一般應用程式使用)。"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕瀏覽方向"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 1359dd9..ccaf14c 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -384,10 +384,8 @@
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lensizakalo yesinqunjwana. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"xhumana nomphathi wedivaysi"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ivumela ummeli ukuthumela okuqukethwe kumphathi wedivaysi. Akusoze kwadingeka kwizinhlelo zokusebenza ezivamile."</string>
-    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
-    <skip />
-    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
-    <skip />
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"bophezela kokokufaka kwe-TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Ivumela umbambi ukuthi abophezele uxhumano nomsebenzisi kwezinga eliphezulu lokokufaka kwe-TV. Akumele kudingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"engeza noma susa umlawuli wedivayisi"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Ivumela umnikazi ukuthi angeze noma asuse abalawuli bedivayisi esebenzayo. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"shintsha ukujikeleza kwesikrini"</string>
diff --git a/core/res/res/values/dimens_quantum.xml b/core/res/res/values/dimens_quantum.xml
index 3913752..02e61e2 100644
--- a/core/res/res/values/dimens_quantum.xml
+++ b/core/res/res/values/dimens_quantum.xml
@@ -17,6 +17,8 @@
 
     <!-- Default height of an action bar. -->
     <dimen name="action_bar_default_height_quantum">56dp</dimen>
+    <!-- Default padding of an action bar. -->
+    <dimen name="action_bar_default_padding_quantum">4dp</dimen>
     <!-- Vertical padding around action bar icons. -->
     <dimen name="action_bar_icon_vertical_padding_quantum">16dp</dimen>
     <!-- Text size for action bar titles -->
@@ -28,6 +30,10 @@
     <!-- Bottom margin for action bar subtitles -->
     <dimen name="action_bar_subtitle_bottom_margin_quantum">5dp</dimen>
 
+    <dimen name="action_button_min_width_quantum">48dp</dimen>
+    <dimen name="action_button_min_height_quantum">48dp</dimen>
+    <dimen name="action_overflow_min_width_quantum">36dp</dimen>
+
     <dimen name="text_size_display_4_quantum">112sp</dimen>
     <dimen name="text_size_display_3_quantum">56sp</dimen>
     <dimen name="text_size_display_2_quantum">45sp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index d3bee28..32b674e 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2149,6 +2149,10 @@
   <public type="attr" name="slideEdge" />
   <public type="attr" name="actionBarTheme" />
   <public type="attr" name="textAppearanceListItemSecondary" />
+  <public type="attr" name="colorPrimaryLight" />
+  <public type="attr" name="colorPrimary" />
+  <public type="attr" name="colorPrimaryDark" />
+  <public type="attr" name="colorAccent" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
@@ -2378,4 +2382,11 @@
   <public type="style" name="TextAppearance.Quantum.Button" />
 
   <public type="style" name="Widget.Holo.Light.Button.Borderless" />
+
+  <!-- An interpolator which accelerates fast but decelerates slowly. -->
+  <public type="interpolator" name="fast_out_slow_in" />
+  <!-- An interpolator which starts with a peak non-zero velocity and decelerates slowly. -->
+  <public type="interpolator" name="linear_out_slow_in" />
+  <!-- An interpolator which accelerates fast and keeps accelerating until the end. -->
+  <public type="interpolator" name="fast_out_linear_in" />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fde5e3f..b0e1150 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -278,6 +278,8 @@
     <!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. -->
     <string name="low_memory" product="tablet">Tablet storage is full. Delete some files to free space.</string>
     <!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. -->
+    <string name="low_memory" product="watch">Watch storage is full. Delete some files to free space.</string>
+    <!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. -->
     <string name="low_memory" product="default">Phone storage is full. Delete some files to free space.</string>
 
     <!-- SSL CA cert notification --> <skip />
@@ -324,6 +326,9 @@
     <!-- Shutdown Confirmation Dialog.  When the user chooses to power off the phone, there will
          be a confirmation dialog.  This is the message. -->
     <string name="shutdown_confirm" product="tablet">Your tablet will shut down.</string>
+    <!-- Shutdown Confirmation Dialog.  When the user chooses to power off the watch, there will
+         be a confirmation dialog.  This is the message. -->
+    <string name="shutdown_confirm" product="watch">Your watch will shut down.</string>
     <!-- Shutdown Confirmation Dialog.  When the user chooses to power off the phone, there will
          be a confirmation dialog.  This is the message. -->
     <string name="shutdown_confirm" product="default">Your phone will shut down.</string>
@@ -901,6 +906,14 @@
         silently replace the content of any webpage with malicious variants.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_broadcastScoreNetworks">send score networks broadcast</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_broadcastScoreNetworks">Allows the app
+        to broadcast a notification that networks need to be scored.
+        Never needed for normal apps.
+    </string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_setProcessLimit">limit number of running processes</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_setProcessLimit">Allows the app
@@ -1876,6 +1889,15 @@
       connect the phone to and disconnect the phone from WiMAX networks.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_scoreNetworks">score networks</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_scoreNetworks" product="tablet">Allows the app to
+      rank networks and influence which networks the tablet should prefer.</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_scoreNetworks" product="default">Allows the app to
+        rank networks and influence which networks the phone should prefer.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_bluetooth">pair with Bluetooth devices</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_bluetooth" product="tablet">Allows the app to view the
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 2720d61..e42703e 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -713,10 +713,9 @@
     <style name="Widget.Quantum.PopupMenu" parent="Widget.Quantum.ListPopupWindow"/>
 
     <style name="Widget.Quantum.ActionButton" parent="Widget.ActionButton">
-        <item name="minWidth">@dimen/action_button_min_width</item>
+        <item name="minWidth">@dimen/action_button_min_width_quantum</item>
+        <item name="minHeight">@dimen/action_button_min_height_quantum</item>
         <item name="gravity">center</item>
-        <item name="paddingStart">12dip</item>
-        <item name="paddingEnd">12dip</item>
         <item name="scaleType">center</item>
         <item name="maxLines">2</item>
     </style>
@@ -729,6 +728,9 @@
         <item name="src">@drawable/ic_menu_moreoverflow_quantum</item>
         <item name="background">?attr/actionBarItemBackground</item>
         <item name="contentDescription">@string/action_menu_overflow_description</item>
+        <item name="minWidth">@dimen/action_overflow_min_width_quantum</item>
+        <item name="minHeight">@dimen/action_button_min_height_quantum</item>
+        <item name="scaleType">center</item>
     </style>
 
     <style name="Widget.Quantum.ActionButton.TextButton" parent="Widget.Quantum.ButtonBar"/>
@@ -756,16 +758,19 @@
     </style>
 
     <style name="Widget.Quantum.ActionBar" parent="Widget.ActionBar">
-        <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
-        <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
         <item name="background">@null</item>
         <item name="backgroundStacked">@null</item>
         <item name="backgroundSplit">@null</item>
+        <item name="displayOptions">useLogo|showHome|showTitle</item>
         <item name="divider">?attr/dividerVertical</item>
+        <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
+        <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
         <item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
         <item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
         <item name="progressBarPadding">32dip</item>
         <item name="itemPadding">8dip</item>
+        <item name="homeLayout">@layout/action_bar_home_quantum</item>
+        <item name="gravity">center_vertical</item>
     </style>
 
     <style name="Widget.Quantum.ActionBar.Solid">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7a11ce8..ac708b8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1092,6 +1092,7 @@
   <java-symbol type="drawable" name="unlock_ring" />
   <java-symbol type="drawable" name="unlock_wave" />
   <java-symbol type="drawable" name="notification_bg" />
+  <java-symbol type="drawable" name="notification_bg_dim" />
   <java-symbol type="drawable" name="notification_bg_low" />
   <java-symbol type="drawable" name="notification_template_icon_bg" />
   <java-symbol type="drawable" name="notification_template_icon_low_bg" />
@@ -1641,6 +1642,8 @@
   <java-symbol type="layout" name="notification_template_quantum_inbox" />
   <java-symbol type="color" name="notification_action_legacy_color_filter" />
   <java-symbol type="drawable" name="notification_icon_legacy_bg_inset" />
+  <java-symbol type="drawable" name="notification_quantum_bg_dim" />
+  <java-symbol type="drawable" name="notification_quantum_bg" />
 
     <!-- From SystemUI -->
   <java-symbol type="anim" name="push_down_in" />
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index 9e235d6..a28496e 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -123,7 +123,7 @@
         <item name="listSeparatorTextViewStyle">@style/Widget.Quantum.TextView.ListSeparator</item>
 
         <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum</item>
-        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum</item>
+        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_anim</item>
 
         <item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_dark</item>
 
@@ -202,9 +202,9 @@
         <item name="scrollbarTrackVertical">@null</item>
 
         <!-- Text selection handle attributes -->
-        <item name="textSelectHandleLeft">@drawable/text_select_handle_left</item>
-        <item name="textSelectHandleRight">@drawable/text_select_handle_right</item>
-        <item name="textSelectHandle">@drawable/text_select_handle_middle</item>
+        <item name="textSelectHandleLeft">@drawable/text_select_handle_left_quantum</item>
+        <item name="textSelectHandleRight">@drawable/text_select_handle_right_quantum</item>
+        <item name="textSelectHandle">@drawable/text_select_handle_middle_quantum</item>
         <item name="textSelectHandleWindowStyle">@style/Widget.Quantum.TextSelectHandle</item>
         <item name="textSuggestionsWindowStyle">@style/Widget.Quantum.TextSuggestionsPopupWindow</item>
         <item name="textCursorDrawable">@drawable/text_cursor_quantum</item>
@@ -300,10 +300,10 @@
         <item name="actionModeStyle">@style/Widget.Quantum.ActionMode</item>
         <item name="actionModeCloseButtonStyle">@style/Widget.Quantum.ActionButton.CloseMode</item>
         <item name="actionBarStyle">@style/Widget.Quantum.ActionBar.Solid</item>
-        <item name="actionBarSize">@dimen/action_bar_default_height</item>
+        <item name="actionBarSize">@dimen/action_bar_default_height_quantum</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Quantum.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
-        <item name="actionBarTheme">@null</item>
+        <item name="actionBarTheme">@style/ThemeOverlay.Quantum.ActionBarWidget</item>
         <item name="actionBarItemBackground">@drawable/item_background_quantum</item>
 
         <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
@@ -321,7 +321,14 @@
         <item name="segmentedButtonStyle">@style/Widget.Quantum.SegmentedButton</item>
 
         <!-- SearchView attributes -->
-        <item name="searchDropdownBackground">@drawable/search_dropdown_dark</item>
+        <item name="searchDropdownBackground">?attr/colorBackground</item>
+        <item name="searchViewTextField">@drawable/textfield_search_quantum</item>
+        <item name="searchViewTextFieldRight">@drawable/textfield_search_quantum</item>
+        <item name="searchViewCloseIcon">@android:drawable/ic_clear_quantum</item>
+        <item name="searchViewSearchIcon">@android:drawable/ic_search_api_quantum</item>
+        <item name="searchViewGoIcon">@android:drawable/ic_go_search_api_quantum</item>
+        <item name="searchViewVoiceIcon">@android:drawable/ic_voice_search_api_quantum</item>
+        <item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_quantum</item>
 
         <item name="searchDialogTheme">@style/Theme.Quantum.SearchBar</item>
 
@@ -459,7 +466,7 @@
         <item name="listSeparatorTextViewStyle">@style/Widget.Quantum.Light.TextView.ListSeparator</item>
 
         <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum</item>
-        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum</item>
+        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_anim</item>
 
         <item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_light</item>
 
@@ -537,9 +544,9 @@
         <item name="scrollbarTrackVertical">@null</item>
 
         <!-- Text selection handle attributes -->
-        <item name="textSelectHandleLeft">@drawable/text_select_handle_left</item>
-        <item name="textSelectHandleRight">@drawable/text_select_handle_right</item>
-        <item name="textSelectHandle">@drawable/text_select_handle_middle</item>
+        <item name="textSelectHandleLeft">@drawable/text_select_handle_left_quantum</item>
+        <item name="textSelectHandleRight">@drawable/text_select_handle_right_quantum</item>
+        <item name="textSelectHandle">@drawable/text_select_handle_middle_quantum</item>
         <item name="textSelectHandleWindowStyle">@style/Widget.Quantum.TextSelectHandle</item>
         <item name="textSuggestionsWindowStyle">@style/Widget.Quantum.Light.TextSuggestionsPopupWindow</item>
         <item name="textCursorDrawable">@drawable/text_cursor_quantum</item>
@@ -638,10 +645,10 @@
         <item name="actionModeStyle">@style/Widget.Quantum.Light.ActionMode</item>
         <item name="actionModeCloseButtonStyle">@style/Widget.Quantum.Light.ActionButton.CloseMode</item>
         <item name="actionBarStyle">@style/Widget.Quantum.Light.ActionBar.Solid</item>
-        <item name="actionBarSize">@dimen/action_bar_default_height</item>
+        <item name="actionBarSize">@dimen/action_bar_default_height_quantum</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Quantum.Light.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
-        <item name="actionBarTheme">@null</item>
+        <item name="actionBarTheme">@style/ThemeOverlay.Quantum.Light.ActionBarWidget</item>
         <item name="actionBarItemBackground">@drawable/item_background_quantum</item>
 
         <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
@@ -659,7 +666,14 @@
         <item name="segmentedButtonStyle">@style/Widget.Quantum.Light.SegmentedButton</item>
 
         <!-- SearchView attributes -->
-        <item name="searchDropdownBackground">@drawable/search_dropdown_light</item>
+        <item name="searchDropdownBackground">?attr/colorBackground</item>
+        <item name="searchViewTextField">@drawable/textfield_search_quantum</item>
+        <item name="searchViewTextFieldRight">@drawable/textfield_search_quantum</item>
+        <item name="searchViewCloseIcon">@android:drawable/ic_clear_quantum</item>
+        <item name="searchViewSearchIcon">@android:drawable/ic_search_api_quantum</item>
+        <item name="searchViewGoIcon">@android:drawable/ic_go_search_api_quantum</item>
+        <item name="searchViewVoiceIcon">@android:drawable/ic_voice_search_api_quantum</item>
+        <item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_quantum</item>
 
         <item name="searchDialogTheme">@style/Theme.Quantum.Light.SearchBar</item>
 
@@ -708,12 +722,29 @@
         <item name="colorButtonPressedColored">?attr/colorPrimaryDark</item>
     </style>
 
+    <style name="ThemeOverlay" />
+    <style name="ThemeOverlay.Quantum" />
+    <style name="ThemeOverlay.Quantum.Light" />
+
+    <!-- Variant of the quantum theme that replaces the activated control color
+         (which by default is identical to the action bar background color) with
+         the normal control color . -->
+    <style name="ThemeOverlay.Quantum.ActionBarWidget">
+        <item name="colorControlActivated">?attr/colorControlNormal</item>
+    </style>
+
+    <!-- Variant of the quantum (light) theme that replaces the activated control
+         color (which by default is identical to the action bar background color)
+         with the normal control color . -->
+    <style name="ThemeOverlay.Quantum.Light.ActionBarWidget">
+        <item name="colorControlActivated">?attr/colorControlNormal</item>
+    </style>
+
     <!-- Variant of the quantum (light) theme that has a solid (opaque) action bar
          with an inverse color profile. The dark action bar sharply stands out against
          the light content. -->
     <style name="Theme.Quantum.Light.DarkActionBar">
-        <item name="actionBarWidgetTheme">@null</item>
-        <item name="actionBarTheme">@style/Theme.Quantum</item>
+        <!-- TODO -->
     </style>
 
     <!-- Variant of the quantum (dark) theme with no action bar. -->
diff --git a/core/tests/coretests/src/android/net/NetworkKeyTest.java b/core/tests/coretests/src/android/net/NetworkKeyTest.java
new file mode 100644
index 0000000..9005188
--- /dev/null
+++ b/core/tests/coretests/src/android/net/NetworkKeyTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+
+import junit.framework.TestCase;
+
+public class NetworkKeyTest extends TestCase {
+    public void testValidWifiKey_utf8() {
+        new WifiKey("\"quotedSsid\"", "AB:CD:01:EF:23:03");
+        new WifiKey("\"\"", "AB:CD:01:EF:23:03");
+    }
+
+    public void testValidWifiKey_hex() {
+        new WifiKey("0x1234abcd", "AB:CD:01:EF:23:03");
+    }
+
+    public void testInvalidWifiKey_empty() {
+        try {
+            new WifiKey("", "AB:CD:01:EF:23:03");
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected - empty SSID
+        }
+    }
+
+    public void testInvalidWifiKey_unquotedUtf8() {
+        try {
+            new WifiKey("unquotedSsid", "AB:CD:01:EF:23:03");
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected - empty SSID
+        }
+    }
+
+    public void testInvalidWifiKey_invalidHex() {
+        try {
+            new WifiKey("0x\"nothex\"", "AB:CD:01:EF:23:03");
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected - empty SSID
+        }
+    }
+
+    public void testInvalidWifiKey_shortBssid() {
+        try {
+            new WifiKey("\"quotedSsid\"", "AB:CD:01:EF:23");
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected - BSSID too short
+        }
+    }
+
+    public void testInvalidWifiKey_longBssid() {
+        try {
+            new WifiKey("\"quotedSsid\"", "AB:CD:01:EF:23:03:11");
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected - BSSID too long
+        }
+    }
+
+    public void testParceling() {
+        WifiKey wifiKey = new WifiKey("\"ssid\"", "00:00:00:00:00:00");
+        NetworkKey networkKey = new NetworkKey(wifiKey);
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            parcel.writeParcelable(networkKey, 0);
+            parcel.setDataPosition(0);
+            networkKey = parcel.readParcelable(getClass().getClassLoader());
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+            }
+        }
+
+        assertEquals(NetworkKey.TYPE_WIFI, networkKey.type);
+        assertEquals("\"ssid\"", networkKey.wifiKey.ssid);
+        assertEquals("00:00:00:00:00:00", networkKey.wifiKey.bssid);
+    }
+}
diff --git a/core/tests/coretests/src/android/net/ScoredNetworkTest.java b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
new file mode 100644
index 0000000..7ab69ad
--- /dev/null
+++ b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.net;
+
+import android.os.Parcel;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+public class ScoredNetworkTest extends TestCase {
+    private static final RssiCurve CURVE =
+            new RssiCurve(-110, 10, new byte[] {0, 1, 2, 3, 4, 5, 6, 7});
+
+    public void testInvalidCurve_nullBuckets() {
+        try {
+            new RssiCurve(-110, 10, null);
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void testInvalidCurve_emptyBuckets() {
+        try {
+            new RssiCurve(-110, 10, new byte[] {});
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void testParceling() {
+        NetworkKey key = new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00"));
+        ScoredNetwork network = new ScoredNetwork(key, CURVE);
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            parcel.writeParcelable(network, 0);
+            parcel.setDataPosition(0);
+            network = parcel.readParcelable(getClass().getClassLoader());
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+            }
+        }
+        assertEquals(CURVE.start, network.rssiCurve.start);
+        assertEquals(CURVE.bucketWidth, network.rssiCurve.bucketWidth);
+        assertTrue(Arrays.equals(CURVE.rssiBuckets, network.rssiCurve.rssiBuckets));
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
index efd06bf..18411b0 100644
--- a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
@@ -438,17 +438,6 @@
         assertEquals("ModestyPanel color should match the SizeAdaptiveLayout",
                      panelColor.getColor(), Color.RED);
     }
-
-    @SmallTest
-    public void testModestyPanelHasDefault() {
-        inflate(R.layout.size_adaptive);
-        View panel = mSizeAdaptiveLayout.getModestyPanel();
-        assertNull("SizeAdaptiveLayout should have no background for this test",
-                     mSizeAdaptiveLayout.getBackground());
-        assertTrue("ModestyPanel should have a ColorDrawable background",
-                   panel.getBackground() instanceof ColorDrawable);
-    }
-
     @SmallTest
     public void testOpenSmallEvenWhenLargeIsActuallySmall() {
         inflate(R.layout.size_adaptive_lies);
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index d2177ca..03addfd 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -8,7 +8,7 @@
 <h2>In this document</h2>
 
 <ol class="toc">
-  <li><a href="#usage">How to Use CCS</a>
+  <li><a href="#connecting">Establishing a Connection</a>
     <ol class="toc">
       <li><a href="#auth">Authentication</a></li>
       </ol>
@@ -46,19 +46,20 @@
 <p class="note"><strong>Note:</strong> To try out this feature, sign up using
 <a href="https://services.google.com/fb/forms/gcm/">this form</a>.</p>
 
-<p>The GCM Cloud Connection Server (CCS) is a connection server based on XMPP.
-CCS allows 3rd-party app servers (which you're
-responsible for implementing) to communicate
-with Android devices by  establishing a persistent TCP connection with Google
-servers using the XMPP protocol. This communication is asynchronous and bidirectional.</p>
+<p>The GCM Cloud Connection Server (CCS) is an XMPP endpoint that provides a
+persistent, asynchronous, bidirectional connection to Google servers. The
+connection can be used to send and receive messages between your server and
+your users' GCM-connected devices.</p>
+
 <p>You can continue to use the HTTP request mechanism to send messages to GCM
 servers, side-by-side with CCS which uses XMPP. Some of the benefits of CCS include:</p>
+
 <ul>
   <li>The asynchronous nature of XMPP allows you to send more messages with fewer
 resources.</li>
-  <li>Communication is bidirectional&mdash;not only can the server send messages
-to the device, but the device can send messages back to the server.</li>
-<li>You can send messages back using the same connection used for receiving,
+  <li>Communication is bidirectional&mdash;not only can your server send messages
+to the device, but the device can send messages back to your server.</li>
+  <li>The device can send messages back using the same connection used for receiving,
 thereby improving battery life.</li>
 </ul>
 
@@ -73,22 +74,34 @@
 <a href="server.html#params">Implementing GCM Server</a> for a list of all the message
 parameters and which connection server(s) supports them.</p>
 
+<h2 id="connecting">Establishing a Connection</h2>
 
-<h2 id="usage">How to Use CCS</h2>
+<p>CCS just uses XMPP as an authenticated transport layer, so you can use most
+XMPP libraries to manage the connection. For an example, see <a href="#smack">
+Java sample using the Smack library</a>.</p>
 
-<p>GCM Cloud Connection Server (CCS) is an XMPP endpoint, running on
-{@code http://gcm.googleapis.com} port 5235.</p>
+<p>The CCS XMPP endpoint runs at {@code gcm.googleapis.com:5235}. When testing
+functionality (with non-production users), you should instead connect to
+{@code gcm-staging.googleapis.com:5236} (note the different port). Testing on
+staging (a smaller environment where the latest CCS builds run) is beneficial
+both for isolating real users from test code, as well as for early detection of
+unexpected behavior changes.</p>
 
-<p>CCS requires a Transport Layer Security (TLS) connection. That means the  XMPP
-client must initiate a TLS connection.
-For example in Java, you would call {@code setSocketFactory(SSLSocketFactory)}.</p>
+<p>The connection has two important requirements:</p>
 
-<p>CCS requires a SASL PLAIN authentication mechanism using
-{@code &lt;your_GCM_Sender_Id&gt;&#64;gcm.googleapis.com} (GCM sender ID) and the
-API key as the password, where the sender ID and API key are the same as described
-in <a href="gs.html">Getting Started</a>.</p>
+<ul>
+  <li>You must initiate a Transport Layer Security (TLS) connection. Note that
+  CCS doesn't currently support the <a href="http://xmpp.org/rfcs/rfc3920.html"
+  class="external-link" target="_android">STARTTLS extension</a>.</li>
+  <li>CCS requires a SASL PLAIN authentication mechanism using
+  {@code &lt;your_GCM_Sender_Id&gt;&#64;gcm.googleapis.com} (GCM sender ID)
+  and the API key as the password, where the sender ID and API key are the same
+  as described in <a href="gs.html">Getting Started</a>.</li>
+</ul>
 
-<p> You can use most XMPP libraries to interact with CCS.</p>
+<p>If at any point the connection fails, you should immediately reconnect.
+There is no need to back off after a disconnect that happens after
+authentication.</p>
 
 <h3 id="auth">Authentication</h3>
 
@@ -100,11 +113,11 @@
 </pre>
 <h4>Server</h4>
 <pre>&lt;str:features xmlns:str=&quot;http://etherx.jabber.org/streams&quot;&gt;
- &lt;mechanisms xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;
-   &lt;mechanism&gt;X-OAUTH2&lt;/mechanism&gt;
-   &lt;mechanism&gt;X-GOOGLE-TOKEN&lt;/mechanism&gt;
-   &lt;mechanism&gt;PLAIN&lt;/mechanism&gt;
- &lt;/mechanisms&gt;
+ &lt;mechanisms xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;
+   &lt;mechanism&gt;X-OAUTH2&lt;/mechanism&gt;
+   &lt;mechanism&gt;X-GOOGLE-TOKEN&lt;/mechanism&gt;
+   &lt;mechanism&gt;PLAIN&lt;/mechanism&gt;
+ &lt;/mechanisms&gt;
 &lt;/str:features&gt;
 </pre>
 
@@ -118,16 +131,18 @@
 <pre>&lt;success xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;/&gt;</pre>
 
 <h2 id="format">Message Format</h2>
-<p>CCS uses normal XMPP <code>&lt;message&gt;</code> stanzas. The body of the message must be:
-</p>
+<p>Once the XMPP connection is established, CCS and your server use normal XMPP
+<code>&lt;message&gt;</code> stanzas to send JSON-encoded messages back and
+forth. The body of the <code>&lt;message&gt;</code> must be:</p>
 <pre>
 &lt;gcm xmlns:google:mobile:data&gt;
     <em>JSON payload</em>
 &lt;/gcm&gt;
 </pre>
 
-<p>The JSON payload for server-to-device is similar to what the GCM http endpoint
-uses, with these exceptions:</p>
+<p>The JSON payload for regular GCM messages is similar to
+<a href="http.html#request">what the GCM http endpoint uses</a>, with these
+exceptions:</p>
 <ul>
   <li>There is no support for multiple recipients.</li>
   <li>{@code to} is used instead of {@code registration_ids}.</li>
@@ -136,14 +151,13 @@
 {@code message_id} to identify a message sent from 3rd-party app servers to CCS.
 Therefore, it's important that this {@code message_id} not only be unique, but
 always present.</li>
-
-<li>For ACK/NACK messages that are special control messages, you also need to
-include a {@code message_type} field in the JSON message. The value can be either
-'ack' or 'nack'. For example:
-
-<pre>message_type = ('ack');</pre>
-  </li>
 </ul>
+
+<p>In addition to regular GCM messages, control messages are sent, indicated by
+the {@code message_type} field in the JSON object. The value can be either
+'ack' or 'nack', or 'control' (see formats below). Any GCM message with an
+unknown {@code message_type} can be ignored by your server.</p>
+
 <p>For each device message your app server receives from CCS, it needs to send
 an ACK message.
 It never needs to send a NACK message. If you don't send an ACK for a message,
@@ -251,7 +265,9 @@
 &lt;/message&gt;</pre>
 
 
-<p>The following table lists some of the more common NACK error codes.</p>
+<p>The following table lists NACK error codes. Unless otherwise
+indicated, a NACKed message should not be retried. Unexpected NACK error codes
+should be treated the same as {@code INTERNAL_SERVER_ERROR}.</p>
 
 <p class="table-caption" id="table1">
   <strong>Table 1.</strong> NACK error codes.</p>
@@ -262,8 +278,17 @@
 <th>Description</th>
 </tr>
 <tr>
+<td>{@code BAD_ACK}</td>
+<td>The ACK message is improperly formed.</td>
+</tr>
+<tr>
 <td>{@code BAD_REGISTRATION}</td>
-<td>The device has a registration ID, but it's invalid.</td>
+<td>The device has a registration ID, but it's invalid or expired.</td>
+</tr>
+<tr>
+<td>{@code CONNECTION_DRAINING}</td>
+<td>The message couldn't be processed because the connection is draining. The
+message should be immediately retried over another connection.</td>
 </tr>
 <tr>
 <td>{@code DEVICE_UNREGISTERED}</td>
@@ -274,25 +299,20 @@
 <td>The server encountered an error while trying to process the request.</td>
 </tr>
 <tr>
+<td>{@code INVALID_JSON}</td>
+<td>The JSON message payload was not valid.</td>
+</tr>
+<tr>
+<td>{@code QUOTA_EXCEEDED}</td>
+<td>The rate of messages to a particular registration ID (in other words, to a
+sender/device pair) is too high. If you want to retry the message, try using a slower
+rate.</td>
+</tr>
+<tr>
 <td>{@code SERVICE_UNAVAILABLE}</td>
-<td>The CCS connection server is temporarily unavailable, try again later
-(using exponential backoff, etc.).</td>
-</tr>
-<tr>
-<td>{@code BAD_ACK}</td>
-<td>The ACK message is improperly formed.</td>
-</tr>
-<tr>
-<td>{@code AUTHENTICATION_FAILED}</td>
-<td>This is a 401 error indicating that there was an error authenticating the sender account.</td>
-</tr>
-<tr>
-<td>{@code INVALID_TTL}</td>
-<td>There was an error in the supplied "time to live" value.</td>
-</tr>
-<tr>
-<td>{@code JSON_TYPE_ERROR}</td>
-<td>There was an error in the supplied JSON data type.</td>
+<td>CCS is not currently able to process the message. The
+message should be retried over the same connection using exponential backoff
+with an initial delay of 1 second.</td>
 </tr>
 </table>
 
@@ -319,6 +339,28 @@
 &lt;/message&gt;
 </pre>
 
+<h4 id="control">Control messages</h4>
+
+<p>Periodically, CCS needs to close down a connection to perform load balancing. Before it
+closes the connection, CCS sends a {@code CONNECTION_DRAINING} message to indicate that the connection is being drained
+and will be closed soon. "Draining" refers to shutting off the flow of messages coming into a
+connection, but allowing whatever is already in the pipeline to continue. When you receive
+a {@code CONNECTION_DRAINING} message, you should immediately begin sending messages to another CCS
+connection, opening a new connection if necessary. You should, however, keep the original
+connection open and continue receiving messages that may come over the connection (and
+ACKing them)&mdash;CCS will handle initiating a connection close when it is ready.</p>
+
+<p>The {@code CONNECTION_DRAINING} message looks like this:</p>
+<pre>&lt;message&gt;
+  &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
+  {
+    &quot;message_type&quot;:&quot;control&quot;
+    &quot;control_type&quot;:&quot;CONNECTION_DRAINING&quot;
+  }
+  &lt;/data:gcm&gt;
+&lt;/message&gt;</pre>
+
+<p>{@code CONNECTION_DRAINING} is currently the only {@code control_type} supported.</p>
 
 <h2 id="upstream">Upstream Messages</h2>
 
@@ -381,7 +423,7 @@
 
 <p>Every message sent to CCS receives either an ACK or a NACK response. Messages
 that haven't received one of these responses are considered pending. If the pending
-message count reaches 1000, the 3rd-party app server should stop sending new messages
+message count reaches 100, the 3rd-party app server should stop sending new messages
 and wait for CCS to acknowledge some of the existing pending messages as illustrated in
 figure 1:</p>
 
@@ -395,7 +437,7 @@
 if there are too many unacknowledged messages. Therefore, the 3rd-party app server
 should "ACK" upstream messages, received from the client application via CCS, as soon as possible
 to maintain a constant flow of incoming messages. The aforementioned pending message limit doesn't
-apply to these ACKs. Even if the pending message count reaches 1000, the 3rd-party app server
+apply to these ACKs. Even if the pending message count reaches 100, the 3rd-party app server
 should continue sending ACKs for messages received from CCS to avoid blocking delivery of new
 upstream messages.</p>
 
@@ -795,7 +837,7 @@
 PASSWORD = "API Key"
 REGISTRATION_ID = "Registration Id of the target device"
 
-unacked_messages_quota = 1000
+unacked_messages_quota = 100
 send_queue = []
 
 # Return a random alphanumerical id
diff --git a/docs/html/google/play-services/maps.jd b/docs/html/google/play-services/maps.jd
index c24cc74..c541b08 100644
--- a/docs/html/google/play-services/maps.jd
+++ b/docs/html/google/play-services/maps.jd
@@ -1,4 +1,4 @@
-page.title=Google Maps Android API
+page.title=Google Maps Android API v2
 page.tags=mapview,location
 header.hide=1
 
@@ -12,14 +12,14 @@
 </div>
 <div class="col-6">
 
-  <h1 itemprop="name" style="margin-bottom:0;">Google Maps Android API</h1>
+  <h1 itemprop="name" style="margin-bottom:0;">Google Maps Android API v2</h1>
   <p itemprop="description">Allow your users explore the world with rich maps provided by
   Google. Identify locations with <b>custom markers</b>, augment the map data
   with <b>image overlays</b>, embed <b>one or more maps</b> as fragments,
   and much more.</p>
   <p>Explore the <a
 href="{@docRoot}reference/com/google/android/gms/maps/package-summary.html"
->Google Maps Android API reference</a> or visit <a class="external-link"
+>Google Maps Android API v2 reference</a> or visit <a class="external-link"
 href="https://developers.google.com/maps/documentation/android/">developers.google.com/maps</a>
 for more information about adding maps to your app.</p>
 </div>
@@ -31,7 +31,7 @@
   <div class="col-6 normal-links">
     <h3 style="clear:left">Key Developer Features</h3>
     <h4>Add maps to your app</h4>
-    <p>With version 2 of the Google Maps Android API, you can embed maps into an activity
+    <p>With Google Maps Android API v2, you can embed maps into an activity
     as a fragment with a simple XML snippet. The new Maps offer exciting features such as 3D maps;
     indoor, satellite, terrain, and hybrid maps;
     vector-based tiles for efficient caching and drawing; animated transitions; and much more.
@@ -58,7 +58,7 @@
   <div class="col-6 normal-links">
     <h3 style="clear:left">Getting Started</h3>
     <h4>1. Get the Google Play services SDK</h4>
-    <p>The Google Maps Android APIs are part of the Google Play services platform.</p>
+    <p>Google Maps Android API v2 is part of the Google Play services platform.</p>
     <p>To use Google Maps, <a href="{@docRoot}google/play-services/setup.html">set up
       the Google Play services SDK</a>. Then see the <a class="external-link"
       href="https://developers.google.com/maps/documentation/android/start#installing_the_google_maps_android_v2_api">
@@ -69,7 +69,7 @@
     
     <p>Once you've installed the Google Play services package, the Google Maps sample is located in
       <code>&lt;android-sdk&gt;/extras/google-play-services/samples/maps</code> and shows you
-      how to use the major components of the Google Maps Android APIs.
+      how to use the major components of Google Maps Android API v2.
     </p>
     
     <h4>3. Read the documentation</h4>
@@ -79,9 +79,9 @@
     
     <p>For quick access while developing your Android apps, the
       <a href="{@docRoot}reference/com/google/android/gms/maps/package-summary.html">Google Maps
-      Android API reference</a> is available here on developer.android.com.</p>
+      Android API v2 reference</a> is available here on developer.android.com.</p>
 
-    <p>Detailed documentation for the Google Maps Android APIs is available with the rest of the
+    <p>Detailed documentation for Google Maps Android API v2 is available with the rest of the
     Google Maps developer documents at <a class="external-link"
     href="https://developers.google.com/maps/documentation/android/">developers.google.com/maps</a>.
     </p>
diff --git a/docs/html/google/play-services/setup.jd b/docs/html/google/play-services/setup.jd
index 3137890..5df2629 100644
--- a/docs/html/google/play-services/setup.jd
+++ b/docs/html/google/play-services/setup.jd
@@ -104,7 +104,7 @@
 
 dependencies {
     compile 'com.android.support:appcompat-v7:+'
-    <strong>compile 'com.google.android.gms:play-services:4.0.30'</strong>
+    <strong>compile 'com.google.android.gms:play-services:4.3.23'</strong>
 }
 </pre>
 <p>Be sure you update this version number each time Google Play services is updated.</p>
@@ -235,4 +235,4 @@
 
 
 <p>To then begin a connection to Google Play services, read <a
-href="{@docRoot}google/auth/api-client.html">Accessing Google Play Services APIs</a>.</p>
\ No newline at end of file
+href="{@docRoot}google/auth/api-client.html">Accessing Google Play Services APIs</a>.</p>
diff --git a/docs/html/images/gcm/CCS-ack.png b/docs/html/images/gcm/CCS-ack.png
index bce2ab2..4633157 100644
--- a/docs/html/images/gcm/CCS-ack.png
+++ b/docs/html/images/gcm/CCS-ack.png
Binary files differ
diff --git a/docs/image_sources/gcm/CCS-ack.graffle b/docs/image_sources/gcm/CCS-ack.graffle
new file mode 100644
index 0000000..addd456
--- /dev/null
+++ b/docs/image_sources/gcm/CCS-ack.graffle
@@ -0,0 +1,1580 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ActiveLayerIndex</key>
+	<integer>0</integer>
+	<key>ApplicationVersion</key>
+	<array>
+		<string>com.omnigroup.OmniGrafflePro</string>
+		<string>139.18.0.187838</string>
+	</array>
+	<key>AutoAdjust</key>
+	<true/>
+	<key>BackgroundGraphic</key>
+	<dict>
+		<key>Bounds</key>
+		<string>{{0, 0}, {576.00002479553223, 733}}</string>
+		<key>Class</key>
+		<string>SolidGraphic</string>
+		<key>FontInfo</key>
+		<dict>
+			<key>Font</key>
+			<string>Helvetica</string>
+			<key>Size</key>
+			<real>12</real>
+		</dict>
+		<key>ID</key>
+		<integer>2</integer>
+		<key>Style</key>
+		<dict>
+			<key>shadow</key>
+			<dict>
+				<key>Draws</key>
+				<string>NO</string>
+			</dict>
+			<key>stroke</key>
+			<dict>
+				<key>Draws</key>
+				<string>NO</string>
+			</dict>
+		</dict>
+	</dict>
+	<key>BaseZoom</key>
+	<integer>0</integer>
+	<key>CanvasOrigin</key>
+	<string>{0, 0}</string>
+	<key>ColumnAlign</key>
+	<integer>1</integer>
+	<key>ColumnSpacing</key>
+	<real>36</real>
+	<key>CreationDate</key>
+	<string>2013-08-08 01:54:22 +0000</string>
+	<key>Creator</key>
+	<string>Katie McCormick</string>
+	<key>DisplayScale</key>
+	<string>1 0/72 in = 1.0000 in</string>
+	<key>GraphDocumentVersion</key>
+	<integer>8</integer>
+	<key>GraphicsList</key>
+	<array>
+		<dict>
+			<key>Bounds</key>
+			<string>{{89, 329}, {169, 44}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>250</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 Now app server can send\
+message no. 101}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{102, 266}, {114, 44}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>249</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 App server waits\
+for ack 1}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{153, 154}, {98, 44}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>244</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 Average\
+response time}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>226</integer>
+				<key>Position</key>
+				<real>0.375</real>
+			</dict>
+			<key>ID</key>
+			<integer>242</integer>
+			<key>Points</key>
+			<array>
+				<string>{263.00000095367432, 314.5}</string>
+				<string>{261, 99}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.112257</string>
+						<key>g</key>
+						<string>0.107007</string>
+						<key>r</key>
+						<string>0.934433</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>227</integer>
+				<key>Position</key>
+				<real>0.34722220897674561</real>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>227</integer>
+				<key>Position</key>
+				<real>0.3541666567325592</real>
+			</dict>
+			<key>ID</key>
+			<integer>241</integer>
+			<key>Points</key>
+			<array>
+				<string>{261, 99}</string>
+				<string>{262.50000071525574, 314.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.112257</string>
+						<key>g</key>
+						<string>0.107007</string>
+						<key>r</key>
+						<string>0.934433</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>226</integer>
+				<key>Position</key>
+				<real>0.375</real>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>227</integer>
+			</dict>
+			<key>ID</key>
+			<integer>240</integer>
+			<key>Points</key>
+			<array>
+				<string>{257.5, 336.5}</string>
+				<string>{288, 314.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.112257</string>
+						<key>g</key>
+						<string>0.107007</string>
+						<key>r</key>
+						<string>0.934433</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>239</integer>
+			<key>Points</key>
+			<array>
+				<string>{231, 288.50000116229057}</string>
+				<string>{231, 251.25}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.112257</string>
+						<key>g</key>
+						<string>0.107007</string>
+						<key>r</key>
+						<string>0.934433</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>238</integer>
+				<key>Position</key>
+				<real>0.56800001859664917</real>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>238</integer>
+			<key>Points</key>
+			<array>
+				<string>{231, 253}</string>
+				<string>{231, 315.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.112257</string>
+						<key>g</key>
+						<string>0.107007</string>
+						<key>r</key>
+						<string>0.934433</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{476, 33}, {49, 32}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>18</real>
+			</dict>
+			<key>ID</key>
+			<integer>230</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs36 \cf0 CCS}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{243, 35}, {101, 32}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>18</real>
+			</dict>
+			<key>ID</key>
+			<integer>229</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs36 \cf0 App Server}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>228</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 252}</string>
+				<string>{216, 252}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>227</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 314.5}</string>
+				<string>{216, 314.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>226</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 99}</string>
+				<string>{216, 99}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{393.69128000000001, 348.37441999999999}, {57, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>223</integer>
+			<key>Rotation</key>
+			<real>23</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 101}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{290.12054000000001, 420.17102}, {60, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>14</real>
+			</dict>
+			<key>ID</key>
+			<integer>222</integer>
+			<key>Rotation</key>
+			<real>341</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack 100}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>220</integer>
+			<key>Points</key>
+			<array>
+				<string>{504, 351}</string>
+				<string>{288, 463}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{430.51697000000001, 279.19488999999999}, {44, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>14</real>
+			</dict>
+			<key>ID</key>
+			<integer>219</integer>
+			<key>Rotation</key>
+			<real>341</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack.. }</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{390.63733000000002, 258.42700000000002}, {44, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>14</real>
+			</dict>
+			<key>ID</key>
+			<integer>218</integer>
+			<key>Rotation</key>
+			<real>341</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack 2}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{290.74178999999998, 239.21059}, {57, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>217</integer>
+			<key>Rotation</key>
+			<real>23</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 100}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{342.63623000000001, 185.82861}, {38, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>216</integer>
+			<key>Rotation</key>
+			<real>18</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no...}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{361.60431, 234}, {44, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>14</real>
+			</dict>
+			<key>ID</key>
+			<integer>209</integer>
+			<key>Rotation</key>
+			<real>341</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack 1}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{351.16005999999999, 153.43960999999999}, {42, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>172</integer>
+			<key>Rotation</key>
+			<real>18</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 2}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{363, 117}, {42, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>171</integer>
+			<key>Rotation</key>
+			<real>18</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 1}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>169</integer>
+			<key>Points</key>
+			<array>
+				<string>{504, 200.62189000000001}</string>
+				<string>{288, 312.62189000000001}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>168</integer>
+			<key>Points</key>
+			<array>
+				<string>{504, 241.00763000000001}</string>
+				<string>{288, 353.00763000000001}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>167</integer>
+			<key>Points</key>
+			<array>
+				<string>{504, 279}</string>
+				<string>{288, 391}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>165</integer>
+			<key>Points</key>
+			<array>
+				<string>{289, 391}</string>
+				<string>{505, 492}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>164</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 353}</string>
+				<string>{504, 454}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>163</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 313}</string>
+				<string>{504, 414}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>162</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 180}</string>
+				<string>{504, 281}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>161</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 252}</string>
+				<string>{504, 353}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>160</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 139.5}</string>
+				<string>{504, 240.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>158</integer>
+				<key>Position</key>
+				<real>0.29398149251937866</real>
+			</dict>
+			<key>ID</key>
+			<integer>159</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 98.000000596046448}</string>
+				<string>{504, 199.00000476837158}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>157</integer>
+				<key>Position</key>
+				<real>0.060185186564922333</real>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>158</integer>
+			<key>Points</key>
+			<array>
+				<string>{504, 72}</string>
+				<string>{504, 504}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>157</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 72}</string>
+				<string>{288, 504}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+	</array>
+	<key>GridInfo</key>
+	<dict>
+		<key>ShowsGrid</key>
+		<string>YES</string>
+	</dict>
+	<key>GuidesLocked</key>
+	<string>NO</string>
+	<key>GuidesVisible</key>
+	<string>YES</string>
+	<key>HPages</key>
+	<integer>1</integer>
+	<key>ImageCounter</key>
+	<integer>1</integer>
+	<key>KeepToScale</key>
+	<false/>
+	<key>Layers</key>
+	<array>
+		<dict>
+			<key>Lock</key>
+			<string>NO</string>
+			<key>Name</key>
+			<string>Layer 1</string>
+			<key>Print</key>
+			<string>YES</string>
+			<key>View</key>
+			<string>YES</string>
+		</dict>
+	</array>
+	<key>LayoutInfo</key>
+	<dict>
+		<key>Animate</key>
+		<string>NO</string>
+		<key>circoMinDist</key>
+		<real>18</real>
+		<key>circoSeparation</key>
+		<real>0.0</real>
+		<key>layoutEngine</key>
+		<string>dot</string>
+		<key>neatoSeparation</key>
+		<real>0.0</real>
+		<key>twopiSeparation</key>
+		<real>0.0</real>
+	</dict>
+	<key>LinksVisible</key>
+	<string>NO</string>
+	<key>MagnetsVisible</key>
+	<string>NO</string>
+	<key>MasterSheets</key>
+	<array/>
+	<key>ModificationDate</key>
+	<string>2014-01-22 22:42:38 +0000</string>
+	<key>Modifier</key>
+	<string>Katie McCormick</string>
+	<key>NotesVisible</key>
+	<string>NO</string>
+	<key>Orientation</key>
+	<integer>2</integer>
+	<key>OriginVisible</key>
+	<string>NO</string>
+	<key>PageBreaks</key>
+	<string>YES</string>
+	<key>PrintInfo</key>
+	<dict>
+		<key>NSBottomMargin</key>
+		<array>
+			<string>float</string>
+			<string>41</string>
+		</array>
+		<key>NSHorizonalPagination</key>
+		<array>
+			<string>int</string>
+			<string>0</string>
+		</array>
+		<key>NSLeftMargin</key>
+		<array>
+			<string>float</string>
+			<string>18</string>
+		</array>
+		<key>NSPaperSize</key>
+		<array>
+			<string>size</string>
+			<string>{612.00002479553223, 792}</string>
+		</array>
+		<key>NSPrintReverseOrientation</key>
+		<array>
+			<string>int</string>
+			<string>0</string>
+		</array>
+		<key>NSRightMargin</key>
+		<array>
+			<string>float</string>
+			<string>18</string>
+		</array>
+		<key>NSTopMargin</key>
+		<array>
+			<string>float</string>
+			<string>18</string>
+		</array>
+	</dict>
+	<key>PrintOnePage</key>
+	<false/>
+	<key>ReadOnly</key>
+	<string>NO</string>
+	<key>RowAlign</key>
+	<integer>1</integer>
+	<key>RowSpacing</key>
+	<real>36</real>
+	<key>SheetTitle</key>
+	<string>Canvas 1</string>
+	<key>SmartAlignmentGuidesActive</key>
+	<string>YES</string>
+	<key>SmartDistanceGuidesActive</key>
+	<string>YES</string>
+	<key>UniqueID</key>
+	<integer>1</integer>
+	<key>UseEntirePage</key>
+	<false/>
+	<key>VPages</key>
+	<integer>1</integer>
+	<key>WindowInfo</key>
+	<dict>
+		<key>CurrentSheet</key>
+		<integer>0</integer>
+		<key>ExpandedCanvases</key>
+		<array>
+			<dict>
+				<key>name</key>
+				<string>Canvas 1</string>
+			</dict>
+		</array>
+		<key>Frame</key>
+		<string>{{170, 139}, {1218, 882}}</string>
+		<key>ListView</key>
+		<true/>
+		<key>OutlineWidth</key>
+		<integer>142</integer>
+		<key>RightSidebar</key>
+		<false/>
+		<key>ShowRuler</key>
+		<true/>
+		<key>Sidebar</key>
+		<true/>
+		<key>SidebarWidth</key>
+		<integer>120</integer>
+		<key>VisibleRegion</key>
+		<string>{{40.5, 0}, {534.5, 364}}</string>
+		<key>Zoom</key>
+		<real>2</real>
+		<key>ZoomValues</key>
+		<array>
+			<array>
+				<string>Canvas 1</string>
+				<real>2</real>
+				<real>1</real>
+			</array>
+		</array>
+	</dict>
+</dict>
+</plist>
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 493e276..8fe06b5 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -206,6 +206,11 @@
         return mVectorState;
     }
 
+    @Override
+    public void jumpToCurrentState() {
+        mVectorState.mBasicAnimator.end();
+    }
+
     /**
      * Starts the animation.
      */
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 8b23955..285c8c3 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -63,7 +63,7 @@
     }
 }
 
-bool DeferredLayerUpdater::apply(bool* hasFunctors) {
+bool DeferredLayerUpdater::apply(TreeInfo& info) {
     bool success = true;
     // These properties are applied the same to both layer types
     mLayer->setColorFilter(mColorFilter);
@@ -74,11 +74,7 @@
             success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight);
         }
         mLayer->setBlend(mBlend);
-        TreeInfo info = {0};
         mDisplayList->prepareTree(info);
-        if (info.hasFunctors) {
-            *hasFunctors = true;
-        }
         mLayer->updateDeferred(mDisplayList.get(),
                 mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
         mDirtyRect.setEmpty();
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 2cc9229..cc62caa 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -77,7 +77,7 @@
 
     ANDROID_API void setPaint(const SkPaint* paint);
 
-    ANDROID_API bool apply(bool* hasFunctors);
+    ANDROID_API bool apply(TreeInfo& info);
 
     ANDROID_API Layer* backingLayer() {
         return mLayer;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 06f675e..f19da9d 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -286,12 +286,6 @@
 
     int getFlags() const { return mFlags; }
 private:
-    SaveOp() {}
-    DisplayListOp* reinit(int flags) {
-        mFlags = flags;
-        return this;
-    }
-
     int mFlags;
 };
 
@@ -318,12 +312,6 @@
     virtual const char* name() { return "RestoreToCount"; }
 
 private:
-    RestoreToCountOp() {}
-    DisplayListOp* reinit(int count) {
-        mCount = count;
-        return this;
-    }
-
     int mCount;
 };
 
@@ -514,7 +502,6 @@
     }
 
 protected:
-    ClipOp() {}
     virtual bool isRect() { return false; }
 
     SkRegion::Op mOp;
@@ -539,13 +526,6 @@
     virtual bool isRect() { return true; }
 
 private:
-    ClipRectOp() {}
-    DisplayListOp* reinit(float left, float top, float right, float bottom, SkRegion::Op op) {
-        mOp = op;
-        mArea.set(left, top, right, bottom);
-        return this;
-    }
-
     Rect mArea;
 };
 
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index c55ebd6..cf21834 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -109,7 +109,7 @@
         mNeedsDisplayListDataSync = false;
         // Do a push pass on the old tree to handle freeing DisplayListData
         // that are no longer used
-        TreeInfo oldTreeInfo = {0};
+        TreeInfo oldTreeInfo;
         prepareSubTree(oldTreeInfo, mDisplayListData);
         // TODO: The damage for the old tree should be accounted for
         delete mDisplayListData;
@@ -120,8 +120,15 @@
 
 void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) {
     if (subtree) {
-        if (!info.hasFunctors) {
-            info.hasFunctors = subtree->functorCount;
+        TextureCache& cache = Caches::getInstance().textureCache;
+        info.hasFunctors |= subtree->functorCount;
+        // TODO: Fix ownedBitmapResources to not require disabling prepareTextures
+        // and thus falling out of async drawing path.
+        if (subtree->ownedBitmapResources.size()) {
+            info.prepareTextures = false;
+        }
+        for (size_t i = 0; info.prepareTextures && i < subtree->bitmapResources.size(); i++) {
+            info.prepareTextures = cache.prefetchAndMarkInUse(subtree->bitmapResources[i]);
         }
         for (size_t i = 0; i < subtree->children().size(); i++) {
             RenderNode* childNode = subtree->children()[i]->mDisplayList;
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index 9e6ee3f..6688952 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -66,7 +66,13 @@
 class DrawDisplayListOp;
 
 struct TreeInfo {
+    TreeInfo()
+            : hasFunctors(false)
+            , prepareTextures(false)
+    {}
+
     bool hasFunctors;
+    bool prepareTextures;
     // TODO: Damage calculations? Flag to skip staging pushes for RT animations?
 };
 
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index 7923ce7..e783905 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -25,14 +25,14 @@
 namespace uirenderer {
 
 Texture::Texture(): id(0), generation(0), blend(false), width(0), height(0),
-        cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL),
+        cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL), isInUse(false),
         mWrapS(GL_CLAMP_TO_EDGE), mWrapT(GL_CLAMP_TO_EDGE),
         mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST),
         mFirstFilter(true), mFirstWrap(true), mCaches(Caches::getInstance()) {
 }
 
 Texture::Texture(Caches& caches): id(0), generation(0), blend(false), width(0), height(0),
-        cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL),
+        cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL), isInUse(false),
         mWrapS(GL_CLAMP_TO_EDGE), mWrapT(GL_CLAMP_TO_EDGE),
         mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST),
         mFirstFilter(true), mFirstWrap(true), mCaches(caches) {
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index d48ec59..d5601f8 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -94,6 +94,12 @@
      */
     const UvMapper* uvMapper;
 
+    /**
+     * Whether or not the Texture is marked in use and thus not evictable for
+     * the current frame. This is reset at the start of a new frame.
+     */
+    bool isInUse;
+
 private:
     /**
      * Last wrap modes set on this texture. Defaults to GL_CLAMP_TO_EDGE.
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 01d72d1..34e2265 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -121,29 +121,49 @@
 // Caching
 ///////////////////////////////////////////////////////////////////////////////
 
-Texture* TextureCache::get(const SkBitmap* bitmap) {
+void TextureCache::resetMarkInUse() {
+    LruCache<const SkBitmap*, Texture*>::Iterator iter(mCache);
+    while (iter.next()) {
+        iter.value()->isInUse = false;
+    }
+}
+
+bool TextureCache::canMakeTextureFromBitmap(const SkBitmap* bitmap) {
+    if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
+        ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)",
+                bitmap->width(), bitmap->height(), mMaxTextureSize, mMaxTextureSize);
+        return false;
+    }
+    return true;
+}
+
+// Returns a prepared Texture* that either is already in the cache or can fit
+// in the cache (and is thus added to the cache)
+Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
     Texture* texture = mCache.get(bitmap);
 
     if (!texture) {
-        if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
-            ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)",
-                    bitmap->width(), bitmap->height(), mMaxTextureSize, mMaxTextureSize);
+        if (!canMakeTextureFromBitmap(bitmap)) {
             return NULL;
         }
 
         const uint32_t size = bitmap->rowBytes() * bitmap->height();
+        bool canCache = size < mMaxSize;
         // Don't even try to cache a bitmap that's bigger than the cache
-        if (size < mMaxSize) {
-            while (mSize + size > mMaxSize) {
+        while (canCache && mSize + size > mMaxSize) {
+            Texture* oldest = mCache.peekOldestValue();
+            if (oldest && !oldest->isInUse) {
                 mCache.removeOldest();
+            } else {
+                canCache = false;
             }
         }
 
-        texture = new Texture();
-        texture->bitmapSize = size;
-        generateTexture(bitmap, texture, false);
+        if (canCache) {
+            texture = new Texture();
+            texture->bitmapSize = size;
+            generateTexture(bitmap, texture, false);
 
-        if (size < mMaxSize) {
             mSize += size;
             TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d",
                      bitmap, texture->id, size, mSize);
@@ -151,16 +171,42 @@
                 ALOGD("Texture created, size = %d", size);
             }
             mCache.put(bitmap, texture);
-        } else {
-            texture->cleanup = true;
         }
-    } else if (bitmap->getGenerationID() != texture->generation) {
+    } else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) {
+        // Texture was in the cache but is dirty, re-upload
+        // TODO: Re-adjust the cache size if the bitmap's dimensions have changed
         generateTexture(bitmap, texture, true);
     }
 
     return texture;
 }
 
+bool TextureCache::prefetchAndMarkInUse(const SkBitmap* bitmap) {
+    Texture* texture = getCachedTexture(bitmap);
+    if (texture) {
+        texture->isInUse = true;
+    }
+    return texture;
+}
+
+Texture* TextureCache::get(const SkBitmap* bitmap) {
+    Texture* texture = getCachedTexture(bitmap);
+
+    if (!texture) {
+        if (!canMakeTextureFromBitmap(bitmap)) {
+            return NULL;
+        }
+
+        const uint32_t size = bitmap->rowBytes() * bitmap->height();
+        texture = new Texture();
+        texture->bitmapSize = size;
+        generateTexture(bitmap, texture, false);
+        texture->cleanup = true;
+    }
+
+    return texture;
+}
+
 Texture* TextureCache::getTransient(const SkBitmap* bitmap) {
     Texture* texture = new Texture();
     texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index e33c60d..48a10c2 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -62,6 +62,18 @@
     void operator()(const SkBitmap*& bitmap, Texture*& texture);
 
     /**
+     * Resets all Textures to not be marked as in use
+     */
+    void resetMarkInUse();
+
+    /**
+     * Attempts to precache the SkBitmap. Returns true if a Texture was successfully
+     * acquired for the bitmap, false otherwise. If a Texture was acquired it is
+     * marked as in use.
+     */
+    bool prefetchAndMarkInUse(const SkBitmap* bitmap);
+
+    /**
      * Returns the texture associated with the specified bitmap. If the texture
      * cannot be found in the cache, a new texture is generated.
      */
@@ -116,6 +128,11 @@
     void setFlushRate(float flushRate);
 
 private:
+
+    bool canMakeTextureFromBitmap(const SkBitmap* bitmap);
+
+    Texture* getCachedTexture(const SkBitmap* bitmap);
+
     /**
      * Generates the texture from a bitmap into the specified texture structure.
      *
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 3638184..16baf77 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -318,10 +318,10 @@
 }
 
 CanvasContext::~CanvasContext() {
-    destroyCanvas();
+    destroyCanvasAndSurface();
 }
 
-void CanvasContext::destroyCanvas() {
+void CanvasContext::destroyCanvasAndSurface() {
     if (mCanvas) {
         delete mCanvas;
         mCanvas = 0;
@@ -382,13 +382,18 @@
     mCanvas->setViewport(width, height);
 }
 
-void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
-        bool* hasFunctors) {
-    LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!");
+void CanvasContext::makeCurrent() {
     mGlobalContext->makeCurrent(mEglSurface);
+}
+
+void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
+        TreeInfo& info) {
+    LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!");
+    makeCurrent();
     for (size_t i = 0; i < layerUpdaters->size(); i++) {
         DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
-        LOG_ALWAYS_FATAL_IF(!update->apply(hasFunctors), "Failed to update layer!");
+        bool success = update->apply(info);
+        LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
         if (update->backingLayer()->deferredUpdateScheduled) {
             mCanvas->pushLayerUpdate(update->backingLayer());
         }
@@ -444,8 +449,8 @@
 
 bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
     requireGlContext();
-    bool hasFunctors;
-    layer->apply(&hasFunctors);
+    TreeInfo info;
+    layer->apply(info);
     return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
 }
 
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index dcb5957..a3fe591 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -23,6 +23,7 @@
 #include <utils/Functor.h>
 #include <utils/Vector.h>
 
+#include "../RenderNode.h"
 #include "RenderTask.h"
 
 #define FUNCTOR_PROCESS_DELAY 4
@@ -31,8 +32,6 @@
 namespace uirenderer {
 
 class DeferredLayerUpdater;
-class RenderNode;
-class DisplayListData;
 class OpenGLRenderer;
 class Rect;
 class Layer;
@@ -54,9 +53,10 @@
     void updateSurface(EGLNativeWindowType window);
     void pauseSurface(EGLNativeWindowType window);
     void setup(int width, int height);
-    void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, bool* hasFunctors);
+    void makeCurrent();
+    void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
     void drawDisplayList(RenderNode* displayList, Rect* dirty);
-    void destroyCanvas();
+    void destroyCanvasAndSurface();
 
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
 
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index cf6c8db..f542d43 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -85,7 +85,6 @@
 void DrawFrameTask::run() {
     ATRACE_NAME("DrawFrame");
 
-    // canUnblockUiThread is temporary until WebView has a solution for syncing frame state
     bool canUnblockUiThread = syncFrameState();
 
     // Grab a copy of everything we need
@@ -105,17 +104,20 @@
     }
 }
 
+static void prepareTreeInfo(TreeInfo& info) {
+    info.prepareTextures = true;
+}
+
 bool DrawFrameTask::syncFrameState() {
     ATRACE_CALL();
-
-    bool hasFunctors = false;
-    mContext->processLayerUpdates(&mLayers, &hasFunctors);
-
-    TreeInfo info = {0};
+    mContext->makeCurrent();
+    Caches::getInstance().textureCache.resetMarkInUse();
+    TreeInfo info;
+    prepareTreeInfo(info);
+    mContext->processLayerUpdates(&mLayers, info);
     mRenderNode->prepareTree(info);
-    hasFunctors |= info.hasFunctors;
-
-    return !hasFunctors;
+    // If prepareTextures is false, we ran out of texture cache space
+    return !info.hasFunctors && info.prepareTextures;
 }
 
 void DrawFrameTask::unblockUiThread() {
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index b233ae9..ce490f1 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -140,15 +140,18 @@
     mDrawFrameTask.drawFrame(&mRenderThread);
 }
 
-CREATE_BRIDGE1(destroyCanvas, CanvasContext* context) {
-    args->context->destroyCanvas();
+CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) {
+    args->context->destroyCanvasAndSurface();
     return NULL;
 }
 
-void RenderProxy::destroyCanvas() {
-    SETUP_TASK(destroyCanvas);
+void RenderProxy::destroyCanvasAndSurface() {
+    SETUP_TASK(destroyCanvasAndSurface);
     args->context = mContext;
-    post(task);
+    // destroyCanvasAndSurface() needs a fence as when it returns the
+    // underlying BufferQueue is going to be released from under
+    // the render thread.
+    postAndWait(task);
 }
 
 CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 3eb8ed8..a112493 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -65,7 +65,7 @@
     ANDROID_API void setup(int width, int height);
     ANDROID_API void drawDisplayList(RenderNode* displayList,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
-    ANDROID_API void destroyCanvas();
+    ANDROID_API void destroyCanvasAndSurface();
 
     ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);
 
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 058012b..c0f6a95 100644
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -24,7 +24,6 @@
 #include <VideoEditorJava.h>
 #include <VideoEditorOsal.h>
 #include <VideoEditorLogging.h>
-#include <marker.h>
 #include <VideoEditorClasses.h>
 #include <VideoEditorThumbnailMain.h>
 #include <M4OSA_Debug.h>
@@ -438,7 +437,7 @@
                                     M4VS, (M4OSA_Char*)"videoEdito JNI overlayFile");
             if (pContext->mOverlayFileName != NULL) {
                 strncpy (pContext->mOverlayFileName,
-                    (const char*)pContext->pEditSettings->\
+                    (const char*)pContext->pEditSettings->
                     Effects[overlayEffectIndex].xVSS.pFramingFilePath, overlayFileNameLen);
                 //Change the name to png file
                 extPos = strstr(pContext->mOverlayFileName, ".rgb");
@@ -1560,9 +1559,6 @@
     int *pOverlayIndex = M4OSA_NULL;
     M4OSA_Char* pTempChar = M4OSA_NULL;
 
-    // Add a code marker (the condition must always be true).
-    ADD_CODE_MARKER_FUN(NULL != pEnv)
-
     // Validate the settings parameter.
     videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
                                                 (NULL == settings),
@@ -2196,10 +2192,6 @@
     M4OSA_Context   mContext = M4OSA_NULL;
     jint*           m_dst32 = M4OSA_NULL;
 
-
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != env)
-
     const char *pString = env->GetStringUTFChars(path, NULL);
     if (pString == M4OSA_NULL) {
         if (env != NULL) {
@@ -2537,9 +2529,6 @@
 
     VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_init()");
 
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
     // Get the context.
     pContext = (ManualEditContext*)videoEditClasses_getContext(&initialized, pEnv, thiz);
 
@@ -2948,9 +2937,6 @@
 
     VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_loadSettings()");
 
-    // Add a code marker (the condition must always be true).
-    ADD_CODE_MARKER_FUN(NULL != pEnv)
-
     // Get the context.
     pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded,
                                                                 pEnv, thiz);
@@ -3123,9 +3109,6 @@
 
     VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_release()");
 
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
     // Get the context.
     pContext = (ManualEditContext*)videoEditClasses_getContext(&released, pEnv, thiz);
 
@@ -3633,15 +3616,9 @@
 
     VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "JNI_OnLoad()");
 
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != pVm)
-
     // Check the JNI version.
     if (pVm->GetEnv(&pEnv, JNI_VERSION_1_4) == JNI_OK)
     {
-        // Add a code marker (the condition must always be true).
-        ADD_CODE_MARKER_FUN(NULL != pEnv)
-
         // Register the manual edit JNI methods.
         if (videoEditor_registerManualEditMethods((JNIEnv*)pEnv) == 0)
         {
diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
index 2f8e357..ae1a80e 100644
--- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
@@ -26,7 +26,6 @@
 #include <VideoEditorOsal.h>
 #include <VideoEditorLogging.h>
 #include <VideoEditorOsal.h>
-#include <marker.h>
 
 extern "C" {
 #include <M4OSA_Clock.h>
@@ -107,9 +106,6 @@
             ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
             "videoEditProp_getProperties()");
 
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
     // Initialize the classes.
     videoEditPropClass_init(&initialized, (JNIEnv*)pEnv);
 
@@ -192,9 +188,6 @@
             // dereferencing of pClipProperties).
             if (gotten)
             {
-                // Add a code marker (the condition must always be true).
-                ADD_CODE_MARKER_FUN(NULL != pClipProperties)
-
                 // Log the API call.
                 VIDEOEDIT_LOG_API(
                         ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
@@ -316,9 +309,6 @@
     videoEditOsal_free(pFile);
     pFile = M4OSA_NULL;
 
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
     // Return the Properties object.
     return(properties);
 }
diff --git a/packages/BackupRestoreConfirmation/res/values-sk/strings.xml b/packages/BackupRestoreConfirmation/res/values-sk/strings.xml
index 12f562b..21e21b5 100644
--- a/packages/BackupRestoreConfirmation/res/values-sk/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values-sk/strings.xml
@@ -24,7 +24,7 @@
     <string name="restore_confirm_text" msgid="7499866728030461776">"Z pripojeného počítača bolo vyžiadané úplné obnovenie všetkých údajov. Chcete túto akciu povoliť?\n\nAk ste toto obnovenie nevyžiadali vy, túto operáciu nepovoľujte. Táto akcia nahradí všetky údaje v zariadení."</string>
     <string name="allow_restore_button_label" msgid="3081286752277127827">"Obnoviť údaje"</string>
     <string name="deny_restore_button_label" msgid="1724367334453104378">"Neobnoviť"</string>
-    <string name="current_password_text" msgid="8268189555578298067">"Zadajte svoje aktuálne heslo záloh nižšie:"</string>
+    <string name="current_password_text" msgid="8268189555578298067">"Zadajte svoje aktuálne heslo pre zálohu nižšie:"</string>
     <string name="device_encryption_restore_text" msgid="1570864916855208992">"Zadajte svoje heslo na šifrovanie zariadenia nižšie."</string>
     <string name="device_encryption_backup_text" msgid="5866590762672844664">"Zadajte svoje heslo na šifrovanie zariadenia nižšie. Bude tiež použité na šifrovanie archívu zálohy."</string>
     <string name="backup_enc_password_text" msgid="4981585714795233099">"Zadajte heslo, ktoré sa použije pri šifrovaní údajov úplnej zálohy. Ak pole ponecháte prázdne, použije sa vaše aktuálne heslo zálohy:"</string>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index baca387..28323b6 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -38,7 +38,7 @@
     <string name="save_error" msgid="6167009778003223664">"Impossibile salvare il documento"</string>
     <string name="create_error" msgid="3735649141335444215">"Impossibile creare la cartella"</string>
     <string name="query_error" msgid="1222448261663503501">"Impossibile chiedere documenti"</string>
-    <string name="root_recent" msgid="4470053704320518133">"Recenti"</string>
+    <string name="root_recent" msgid="4470053704320518133">"Recente"</string>
     <string name="root_available_bytes" msgid="8568452858617033281">"<xliff:g id="SIZE">%1$s</xliff:g> liberi"</string>
     <string name="root_type_service" msgid="2178854894416775409">"Servizi di archiviazione"</string>
     <string name="root_type_shortcut" msgid="3318760609471618093">"Scorciatoie"</string>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 42cec9c..f4e5582 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -44,8 +44,8 @@
     <string name="root_type_shortcut" msgid="3318760609471618093">"Skróty"</string>
     <string name="root_type_device" msgid="7121342474653483538">"Urządzenia"</string>
     <string name="root_type_apps" msgid="8838065367985945189">"Więcej aplikacji"</string>
-    <string name="pref_advanced_devices" msgid="903257239609301276">"Pokaż urządzenia zaawansowane"</string>
-    <string name="pref_file_size" msgid="2826879315743961459">"Pokaż rozmiar pliku"</string>
+    <string name="pref_advanced_devices" msgid="903257239609301276">"Wyświetl urządzenia zaawansowane"</string>
+    <string name="pref_file_size" msgid="2826879315743961459">"Wyświetl rozmiar pliku"</string>
     <string name="pref_device_size" msgid="3542106883278997222">"Wyświetl rozmiar urządzenia"</string>
     <string name="empty" msgid="7858882803708117596">"Brak elementów"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"Nie można otworzyć pliku"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index 269583a..75ecbcf 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="2783841764617238354">"文件"</string>
-    <string name="title_open" msgid="4353228937663917801">"開啟工具"</string>
+    <string name="title_open" msgid="4353228937663917801">"開啟檔案"</string>
     <string name="title_save" msgid="2433679664882857999">"儲存至"</string>
     <string name="menu_create_dir" msgid="5947289605844398389">"建立資料夾"</string>
     <string name="menu_grid" msgid="6878021334497835259">"格狀檢視"</string>
@@ -38,7 +38,7 @@
     <string name="save_error" msgid="6167009778003223664">"無法儲存文件"</string>
     <string name="create_error" msgid="3735649141335444215">"無法建立資料夾"</string>
     <string name="query_error" msgid="1222448261663503501">"無法查詢文件"</string>
-    <string name="root_recent" msgid="4470053704320518133">"最近使用過的項目"</string>
+    <string name="root_recent" msgid="4470053704320518133">"最近存取過"</string>
     <string name="root_available_bytes" msgid="8568452858617033281">"可用空間:<xliff:g id="SIZE">%1$s</xliff:g>"</string>
     <string name="root_type_service" msgid="2178854894416775409">"儲存空間服務"</string>
     <string name="root_type_shortcut" msgid="3318760609471618093">"捷徑"</string>
@@ -47,7 +47,7 @@
     <string name="pref_advanced_devices" msgid="903257239609301276">"顯示進階裝置"</string>
     <string name="pref_file_size" msgid="2826879315743961459">"顯示檔案大小"</string>
     <string name="pref_device_size" msgid="3542106883278997222">"顯示裝置大小"</string>
-    <string name="empty" msgid="7858882803708117596">"沒有項目"</string>
+    <string name="empty" msgid="7858882803708117596">"沒有任何項目"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"無法開啟檔案"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"無法刪除部分文件"</string>
     <string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
diff --git a/packages/FusedLocation/res/values-fr-rCA/strings.xml b/packages/FusedLocation/res/values-fr-rCA/strings.xml
index c7d33af..0d2cccc 100644
--- a/packages/FusedLocation/res/values-fr-rCA/strings.xml
+++ b/packages/FusedLocation/res/values-fr-rCA/strings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_label" msgid="5379477904423203699">"Tables de fusion"</string>
+    <string name="app_label" msgid="5379477904423203699">"Fused Location"</string>
 </resources>
diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk
index 5b08674..1be44f9 100644
--- a/packages/Keyguard/Android.mk
+++ b/packages/Keyguard/Android.mk
@@ -19,7 +19,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files) \
                    $(call all-proto-files-under,src)
 
-LOCAL_PACKAGE_NAME := Keyguard
+LOCAL_MODULE := Keyguard
 
 LOCAL_CERTIFICATE := platform
 
@@ -30,6 +30,8 @@
 LOCAL_PROTOC_OPTIMIZE_TYPE := nano
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
 
-include $(BUILD_PACKAGE)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
-#include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+#include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml
index b2d2ec5..352317d 100644
--- a/packages/Keyguard/AndroidManifest.xml
+++ b/packages/Keyguard/AndroidManifest.xml
@@ -46,8 +46,5 @@
         android:persistent="true"
         android:supportsRtl="true">
 
-        <service android:name=".KeyguardService"
-            android:exported="true" />
-
     </application>
 </manifest>
diff --git a/packages/Keyguard/res/layout-land/keyguard_host_view.xml b/packages/Keyguard/res/layout-land/keyguard_host_view.xml
index 9f1c1f0..1d596d3 100644
--- a/packages/Keyguard/res/layout-land/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-land/keyguard_host_view.xml
@@ -21,7 +21,7 @@
     and the security view. -->
 <com.android.keyguard.KeyguardHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_host_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml b/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
index ebd0a64..49b4212 100644
--- a/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
+++ b/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
@@ -21,7 +21,7 @@
     and the security view. -->
 <com.android.keyguard.KeyguardSimpleHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_host_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
diff --git a/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml b/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml
index da31065..50c2709 100644
--- a/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml
+++ b/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml
@@ -19,7 +19,7 @@
 
 <!-- This is the selector widget that allows the user to select an action. -->
 <com.android.keyguard.KeyguardWidgetCarousel
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:paddingLeft="25dp"
     android:paddingRight="25dp"
diff --git a/packages/Keyguard/res/layout-port/keyguard_host_view.xml b/packages/Keyguard/res/layout-port/keyguard_host_view.xml
index 136b296..8223db4 100644
--- a/packages/Keyguard/res/layout-port/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-port/keyguard_host_view.xml
@@ -21,7 +21,7 @@
     and the security view. -->
 <com.android.keyguard.KeyguardHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_host_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml b/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
index cba7667..ed600b0 100644
--- a/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
+++ b/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
@@ -21,7 +21,7 @@
     and the security view. -->
 <com.android.keyguard.KeyguardSimpleHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_host_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
diff --git a/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml b/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml
index d0a07ca..6d7d864 100644
--- a/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml
+++ b/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml
@@ -19,7 +19,7 @@
 
 <!-- This is the selector widget that allows the user to select an action. -->
 <com.android.keyguard.KeyguardWidgetPager
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/app_widget_container"
     android:paddingLeft="25dp"
diff --git a/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml b/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
index 85f6b6d..ba2f3a6 100644
--- a/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
@@ -21,7 +21,7 @@
     and the security view. -->
 <com.android.keyguard.KeyguardHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_host_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_account_view.xml b/packages/Keyguard/res/layout/keyguard_account_view.xml
index 766effa..bde2ec6 100644
--- a/packages/Keyguard/res/layout/keyguard_account_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_account_view.xml
@@ -18,7 +18,7 @@
 -->
 <com.android.keyguard.KeyguardAccountView
     xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+	xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_account_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_bouncer.xml b/packages/Keyguard/res/layout/keyguard_bouncer.xml
new file mode 100644
index 0000000..dedf427
--- /dev/null
+++ b/packages/Keyguard/res/layout/keyguard_bouncer.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <View android:id="@+id/bouncer_background"
+        android:background="#aa000000"
+        android:clickable="true"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+    <include layout="@layout/keyguard_simple_host_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+</FrameLayout>
+
diff --git a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
index 94c68a5..8c8ec7a 100644
--- a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
@@ -20,7 +20,7 @@
 <!-- This is the screen that allows the user to unlock by showing their face.  -->
 <com.android.keyguard.KeyguardFaceUnlockView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_face_unlock_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml b/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml
index c1d5326..83036ab 100644
--- a/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml
+++ b/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml
@@ -17,7 +17,7 @@
 */
 -->
 <com.android.keyguard.KeyguardMultiUserSelectorView
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     xmlns:android="http://schemas.android.com/apk/res/android"
     androidprv:layout_childType="userSwitcher"
     android:id="@+id/keyguard_user_selector"
diff --git a/packages/Keyguard/res/layout/keyguard_password_view.xml b/packages/Keyguard/res/layout/keyguard_password_view.xml
index d8012bf..ed3f0e0 100644
--- a/packages/Keyguard/res/layout/keyguard_password_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_password_view.xml
@@ -18,7 +18,7 @@
 -->
 <com.android.keyguard.KeyguardPasswordView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_password_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_pattern_view.xml b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
index 0c9380c..3d7820f 100644
--- a/packages/Keyguard/res/layout/keyguard_pattern_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
@@ -22,7 +22,7 @@
      is the portrait layout.  -->
 <com.android.keyguard.KeyguardPatternView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_pattern_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_pin_view.xml b/packages/Keyguard/res/layout/keyguard_pin_view.xml
index 00c6a21..a804c8c 100644
--- a/packages/Keyguard/res/layout/keyguard_pin_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pin_view.xml
@@ -19,7 +19,7 @@
 
 <com.android.keyguard.KeyguardPINView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_pin_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_presentation.xml b/packages/Keyguard/res/layout/keyguard_presentation.xml
index 7df0b70..ab676aa 100644
--- a/packages/Keyguard/res/layout/keyguard_presentation.xml
+++ b/packages/Keyguard/res/layout/keyguard_presentation.xml
@@ -20,7 +20,7 @@
 <!-- This is a view that shows general status information in Keyguard. -->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/presentation"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
diff --git a/packages/Keyguard/res/layout/keyguard_selector_view.xml b/packages/Keyguard/res/layout/keyguard_selector_view.xml
index 6cb5e67..d3064ed 100644
--- a/packages/Keyguard/res/layout/keyguard_selector_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_selector_view.xml
@@ -20,7 +20,7 @@
 <!-- This is the selector widget that allows the user to select an action. -->
 <com.android.keyguard.KeyguardSelectorView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_selector_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
index eccac19..e96220e 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
@@ -19,7 +19,7 @@
 <!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. -->
 <com.android.keyguard.KeyguardSimPinView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_sim_pin_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
index fe37203..bf15ba0 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
@@ -20,7 +20,7 @@
     carrier-provided PUK code and entering a new SIM PIN for it. -->
 <com.android.keyguard.KeyguardSimPukView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_sim_puk_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_status_area.xml b/packages/Keyguard/res/layout/keyguard_status_area.xml
index 98ba512..2730517 100644
--- a/packages/Keyguard/res/layout/keyguard_status_area.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_area.xml
@@ -20,7 +20,7 @@
 <!-- This is a view that shows general status information in Keyguard. -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="horizontal"
diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml
index a4d298a..3b3a069 100644
--- a/packages/Keyguard/res/layout/keyguard_status_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_view.xml
@@ -18,43 +18,38 @@
 -->
 
 <!-- This is a view that shows general status information in Keyguard. -->
-<com.android.keyguard.KeyguardWidgetFrame
+<com.android.keyguard.KeyguardStatusView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_status_view"
+    android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     androidprv:layout_maxWidth="@dimen/keyguard_security_width"
     androidprv:layout_maxHeight="@dimen/keyguard_security_height"
-    android:gravity="center">
-
-    <com.android.keyguard.KeyguardStatusView
-        android:id="@+id/keyguard_status_view_face_palm"
-        android:orientation="vertical"
+    android:gravity="center_horizontal|top"
+    android:layout_marginTop="32dp"
+    android:layout_marginBottom="32dp"
+    android:contentDescription="@string/keyguard_accessibility_status">
+    <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:gravity="center_horizontal|top"
-        android:contentDescription="@string/keyguard_accessibility_status">
-        <LinearLayout
-            android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal|top"
+        android:orientation="vertical"
+        android:focusable="true">
+        <TextClock
+            android:id="@+id/clock_view"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal|top"
-            android:orientation="vertical"
-            android:focusable="true">
-            <TextClock
-                android:id="@+id/clock_view"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal|top"
-                android:textColor="@color/clock_white"
-                android:singleLine="true"
-                style="@style/widget_big_thin"
-                android:format12Hour="@string/keyguard_widget_12_hours_format"
-                android:format24Hour="@string/keyguard_widget_24_hours_format"
-                android:baselineAligned="true"
-                android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
+            android:textColor="@color/clock_white"
+            android:singleLine="true"
+            style="@style/widget_big_thin"
+            android:format12Hour="@string/keyguard_widget_12_hours_format"
+            android:format24Hour="@string/keyguard_widget_24_hours_format"
+            android:baselineAligned="true"
+            android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
 
-            <include layout="@layout/keyguard_status_area" />
-        </LinearLayout>
-    </com.android.keyguard.KeyguardStatusView>
-</com.android.keyguard.KeyguardWidgetFrame>
+        <include layout="@layout/keyguard_status_area" />
+    </LinearLayout>
+</com.android.keyguard.KeyguardStatusView>
diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml
index 89ac293..cdf8ca9 100644
--- a/packages/Keyguard/res/values-sk/strings.xml
+++ b/packages/Keyguard/res/values-sk/strings.xml
@@ -35,7 +35,7 @@
     <string name="keyguard_low_battery" msgid="8143808018719173859">"Pripojte nabíjačku."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="1332288268600329841">"Telefón odomknete stlačením tlačidla Menu."</string>
     <string name="keyguard_network_locked_message" msgid="9169717779058037168">"Sieť je zablokovaná"</string>
-    <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"Nie je vložená karta SIM"</string>
+    <string name="keyguard_missing_sim_message_short" msgid="494980561304211931">"Nie je vložená karta SIM."</string>
     <string name="keyguard_missing_sim_message" product="tablet" msgid="1445849005909260039">"V tablete nie je žiadna karta SIM."</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="3481110395508637643">"V telefóne nie je žiadna karta SIM."</string>
     <string name="keyguard_missing_sim_instructions" msgid="5210891509995942250">"Vložte kartu SIM."</string>
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index c775467..19eb4c5 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -75,7 +75,7 @@
     <string name="keyguard_accessibility_transport_thumbs_down_description" msgid="8101433677192177861">"Bài hát được đánh dấu không thích"</string>
     <string name="keyguard_accessibility_transport_heart_description" msgid="2336943232474689887">"Trái tim"</string>
     <string name="keyguard_accessibility_show_bouncer" msgid="5425837272418176176">"Mở khóa để tiếp tục"</string>
-    <string name="keyguard_accessibility_hide_bouncer" msgid="7896992171878309358">"Quá trình chạy bị hủy"</string>
+    <string name="keyguard_accessibility_hide_bouncer" msgid="7896992171878309358">"Quá trình khởi chạy bị hủy"</string>
     <string name="keyguard_accessibility_delete_widget_start" msgid="4096550552634391451">"Thả <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> để xóa."</string>
     <string name="keyguard_accessibility_delete_widget_end" msgid="508833506780909393">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> sẽ không bị xóa."</string>
     <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml
index 71e9924..c05f834 100644
--- a/packages/Keyguard/res/values/dimens.xml
+++ b/packages/Keyguard/res/values/dimens.xml
@@ -158,7 +158,7 @@
     <dimen name="bottom_text_spacing_digital">-8dp</dimen>
     <dimen name="label_font_size">14dp</dimen>
     <dimen name="widget_label_font_size">14dp</dimen>
-    <dimen name="widget_big_font_size">80dp</dimen>
+    <dimen name="widget_big_font_size">60dp</dimen>
     <dimen name="big_font_size">120dp</dimen>
 
 </resources>
diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml
index 80fcf75..4a034aa 100644
--- a/packages/Keyguard/res/values/styles.xml
+++ b/packages/Keyguard/res/values/styles.xml
@@ -56,8 +56,7 @@
     <!-- Built-in clock widget stuff -->
     <style name="widget_label">
         <item name="android:textStyle">bold</item>
-        <item name="android:textAllCaps">true</item>
-        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="android:fontFamily">sans-serif-light</item>
         <item name="android:textSize">@dimen/widget_label_font_size</item>
     </style>
     <style name="big_thin">
diff --git a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
index 74e6f33..2bf74ea 100644
--- a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
+++ b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
@@ -38,7 +38,7 @@
 
 public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnClickListener {
     private static final String TAG = CameraWidgetFrame.class.getSimpleName();
-    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final int WIDGET_ANIMATION_DURATION = 250; // ms
     private static final int WIDGET_WAIT_DURATION = 400; // ms
     private static final int RECOVERY_DELAY = 1000; // ms
@@ -113,12 +113,14 @@
 
     private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
         private boolean mShowing;
-        void onKeyguardVisibilityChanged(boolean showing) {
+
+        @Override
+        public void onKeyguardVisibilityChanged(boolean showing) {
             if (mShowing == showing)
                 return;
             mShowing = showing;
             CameraWidgetFrame.this.onKeyguardVisibilityChanged(mShowing);
-        };
+        }
     };
 
     private static final class FixedSizeFrameLayout extends FrameLayout {
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index fd56613..4ed37d4 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -48,10 +48,11 @@
             updateEmergencyCallButton(simState, phoneState);
         }
 
-        void onPhoneStateChanged(int phoneState) {
+        @Override
+        public void onPhoneStateChanged(int phoneState) {
             State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
             updateEmergencyCallButton(simState, phoneState);
-        };
+        }
     };
     private LockPatternUtils mLockPatternUtils;
     private PowerManager mPowerManager;
diff --git a/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java b/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
index de839c6..2f14003 100644
--- a/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
+++ b/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
@@ -37,8 +37,9 @@
 
 public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
 
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "FULLockscreen";
+    private static final String FACE_LOCK_PACKAGE = "com.android.facelock";
 
     private final Context mContext;
     private final LockPatternUtils mLockPatternUtils;
@@ -128,7 +129,8 @@
         if (!mBoundToService) {
             Log.d(TAG, "Binding to Face Unlock service for user="
                     + mLockPatternUtils.getCurrentUser());
-            mContext.bindServiceAsUser(new Intent(IFaceLockInterface.class.getName()),
+            mContext.bindServiceAsUser(
+                    new Intent(IFaceLockInterface.class.getName()).setPackage(FACE_LOCK_PACKAGE),
                     mConnection,
                     Context.BIND_AUTO_CREATE,
                     new UserHandle(mLockPatternUtils.getCurrentUser()));
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 3950159..4b386b6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -231,7 +231,7 @@
     @Override
     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
         if (mCallback != null) {
-            mCallback.userActivity(KeyguardViewManager.DIGIT_PRESS_WAKE_MILLIS);
+            mCallback.userActivity(KeyguardConstants.DIGIT_PRESS_WAKE_MILLIS);
         }
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
index 0d5e477..25f3383 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
@@ -43,7 +43,7 @@
 
 public abstract class KeyguardActivityLauncher {
     private static final String TAG = KeyguardActivityLauncher.class.getSimpleName();
-    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout";
     private static final Intent SECURE_CAMERA_INTENT =
             new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java b/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java
new file mode 100644
index 0000000..bfa95f38
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java
@@ -0,0 +1,32 @@
+/*
+ * 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 com.android.keyguard;
+
+/**
+ * Defines constants for the Keyguard.
+ */
+public class KeyguardConstants {
+
+    /**
+     * Turns on debugging information for the whole Keyguard. This is very verbose and should only
+     * be used temporarily for debugging.
+     */
+    public static final boolean DEBUG = false;
+
+    /** Timeout used for key presses. */
+    public static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
index 6bcbd6c..55f965c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -30,18 +30,18 @@
 
 public class KeyguardDisplayManager {
     protected static final String TAG = "KeyguardDisplayManager";
-    private static boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static boolean DEBUG = KeyguardConstants.DEBUG;
     Presentation mPresentation;
     private MediaRouter mMediaRouter;
     private Context mContext;
     private boolean mShowing;
 
-    KeyguardDisplayManager(Context context) {
+    public KeyguardDisplayManager(Context context) {
         mContext = context;
         mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
     }
 
-    void show() {
+    public void show() {
         if (!mShowing) {
             if (DEBUG) Slog.v(TAG, "show");
             mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
@@ -51,7 +51,7 @@
         mShowing = true;
     }
 
-    void hide() {
+    public void hide() {
         if (mShowing) {
             if (DEBUG) Slog.v(TAG, "hide");
             mMediaRouter.removeCallback(mMediaRouterCallback);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
index c2cd32f..900d16e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
@@ -36,7 +36,7 @@
 public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {
 
     private static final String TAG = "FULKeyguardFaceUnlockView";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private KeyguardSecurityCallback mKeyguardSecurityCallback;
     private LockPatternUtils mLockPatternUtils;
     private BiometricSensorUnlock mBiometricUnlock;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 2e76f19..7cfd684 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -61,7 +61,7 @@
 
 public class KeyguardHostView extends KeyguardViewBase {
     private static final String TAG = "KeyguardHostView";
-    public static boolean DEBUG = KeyguardViewMediator.DEBUG;
+    public static boolean DEBUG = KeyguardConstants.DEBUG;
     public static boolean DEBUGXPORT = true; // debug music transport control
 
     // Transport control states.
@@ -118,7 +118,7 @@
         void userActivity();
     }
 
-    /*package*/ interface OnDismissAction {
+    public interface OnDismissAction {
         /* returns true if the dismiss should be deferred */
         boolean onDismiss();
     }
@@ -241,7 +241,7 @@
             }
         }
         @Override
-        void onMusicClientIdChanged(
+        public void onMusicClientIdChanged(
                 int clientGeneration, boolean clearing, android.app.PendingIntent intent) {
             // Set transport state to invisible until we know music is playing (below)
             if (DEBUGXPORT && (mClientGeneration != clientGeneration || clearing)) {
@@ -449,7 +449,7 @@
     }
 
     @Override
-    protected void setLockPatternUtils(LockPatternUtils utils) {
+    public void setLockPatternUtils(LockPatternUtils utils) {
         super.setLockPatternUtils(utils);
         getSecurityContainer().updateSecurityViews(mViewStateManager.isBouncing());
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java
index aa2ae0e..3aec55c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java
@@ -37,7 +37,7 @@
 
 class KeyguardMultiUserAvatar extends FrameLayout {
     private static final String TAG = KeyguardMultiUserAvatar.class.getSimpleName();
-    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
 
     private ImageView mUserImage;
     private TextView mUserName;
@@ -123,7 +123,7 @@
         mUserName = (TextView) findViewById(R.id.keyguard_user_name);
 
         mFramed = (KeyguardCircleFramedDrawable)
-                KeyguardViewMediator.getAvatarCache().get(user.id);
+                MultiUserAvatarCache.getInstance().get(user.id);
 
         // If we can't find it or the params don't match, create the drawable again
         if (mFramed == null
@@ -143,7 +143,7 @@
 
             mFramed = new KeyguardCircleFramedDrawable(icon, (int) mIconSize, mFrameColor, mStroke,
                     mFrameShadowColor, mShadowRadius, mHighlightColor);
-            KeyguardViewMediator.getAvatarCache().put(user.id, mFramed);
+            MultiUserAvatarCache.getInstance().put(user.id, mFramed);
         }
 
         mFramed.reset();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 14de6dd..b4308c6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -44,7 +44,7 @@
 public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView {
 
     private static final String TAG = "SecurityPatternView";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
 
     // how long before we clear the wrong pattern
     private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 0f62100..8425c48 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -30,7 +30,7 @@
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 
 public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {
-    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "KeyguardSecurityView";
     private KeyguardSecurityModel mSecurityModel;
     private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 70a0e44..07239d1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -38,7 +38,7 @@
  */
 public class KeyguardSecurityViewFlipper extends ViewFlipper implements KeyguardSecurityView {
     private static final String TAG = "KeyguardSecurityViewFlipper";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
 
     private Rect mTempRect = new Rect();
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
index 97aec68..03e7b07 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
@@ -36,7 +36,6 @@
 import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
 
 public class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
-    private static final boolean DEBUG = KeyguardHostView.DEBUG;
     private static final String TAG = "SecuritySelectorView";
     private static final String ASSIST_ICON_METADATA_NAME =
         "com.android.systemui.action_assist_icon";
@@ -57,12 +56,10 @@
         public void onTrigger(View v, int target) {
             final int resId = mGlowPadView.getResourceIdForTarget(target);
 
-            switch (resId) {
-                case R.drawable.ic_lockscreen_unlock_phantom:
-                case R.drawable.ic_lockscreen_unlock:
-                    mCallback.userActivity(0);
-                    mCallback.dismiss(false);
-                break;
+            if (resId == R.drawable.ic_lockscreen_unlock_phantom
+                    || resId == R.drawable.ic_lockscreen_unlock) {
+                mCallback.userActivity(0);
+                mCallback.dismiss(false);
             }
         }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index ae7ac97..d6a4f52 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -41,7 +41,7 @@
 public class KeyguardSimPinView extends KeyguardAbsKeyInputView
         implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
     private static final String LOG_TAG = "KeyguardSimPinView";
-    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     public static final String TAG = "KeyguardSimPinView";
 
     private ProgressDialog mSimUnlockProgressDialog = null;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index ca4f811..04cbde1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -42,7 +42,7 @@
 public class KeyguardSimPukView extends KeyguardAbsKeyInputView
         implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
     private static final String LOG_TAG = "KeyguardSimPukView";
-    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     public static final String TAG = "KeyguardSimPukView";
 
     private ProgressDialog mSimUnlockProgressDialog = null;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
index cf983cb..5d5168c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
@@ -38,11 +38,6 @@
     }
 
     @Override
-    public void verifyUnlock() {
-        // TODO Auto-generated method stub
-    }
-
-    @Override
     public void cleanUp() {
         // TODO Auto-generated method stub
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index 0bfee38..ae55c4a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -33,7 +33,7 @@
 import java.util.Locale;
 
 public class KeyguardStatusView extends GridLayout {
-    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "KeyguardStatusView";
 
     private LockPatternUtils mLockPatternUtils;
@@ -50,22 +50,22 @@
         }
 
         @Override
-        void onKeyguardVisibilityChanged(boolean showing) {
+        public void onKeyguardVisibilityChanged(boolean showing) {
             if (showing) {
                 if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
                 refresh();
             }
-        };
+        }
 
         @Override
         public void onScreenTurnedOn() {
             setEnableMarquee(true);
-        };
+        }
 
         @Override
         public void onScreenTurnedOff(int why) {
             setEnableMarquee(false);
-        };
+        }
     };
 
     public KeyguardStatusView(Context context) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
index a7cd909..0d472ae 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
@@ -60,7 +60,7 @@
 public class KeyguardTransportControlView extends FrameLayout {
 
     private static final int RESET_TO_METADATA_DELAY = 5000;
-    protected static final boolean DEBUG = false;
+    protected static final boolean DEBUG = KeyguardConstants.DEBUG;
     protected static final String TAG = "TransportControlView";
 
     private static final boolean ANIMATE_TRANSITIONS = true;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 88c78ab..73c2840 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -72,7 +72,7 @@
 public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
 
     private static final String TAG = "KeyguardUpdateMonitor";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final boolean DEBUG_SIM_STATES = DEBUG || false;
     private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
     private static final int LOW_BATTERY_THRESHOLD = 20;
@@ -679,7 +679,7 @@
      * broadcast and hence not handle the event. This method is ultimately called by
      * PhoneWindowManager in this case.
      */
-    protected void dispatchBootCompleted() {
+    public void dispatchBootCompleted() {
         mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 556711b..862931e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -20,7 +20,7 @@
 import android.graphics.Bitmap;
 import android.media.AudioManager;
 import android.os.SystemClock;
-import android.util.Log;
+import android.telephony.TelephonyManager;
 import android.view.WindowManagerPolicy;
 
 import com.android.internal.telephony.IccCardConstants;
@@ -28,7 +28,7 @@
 /**
  * Callback for general information relevant to lock screen.
  */
-class KeyguardUpdateMonitorCallback {
+public class KeyguardUpdateMonitorCallback {
 
     private static final long VISIBILITY_CHANGED_COLLAPSE_MS = 1000;
     private long mVisibilityChangedCalled;
@@ -40,12 +40,12 @@
      *
      * @param status current battery status
      */
-    void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { }
+    public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { }
 
     /**
      * Called once per minute or when the time changes.
      */
-    void onTimeChanged() { }
+    public void onTimeChanged() { }
 
     /**
      * Called when the carrier PLMN or SPN changes.
@@ -54,14 +54,14 @@
      *   be displayed.
      * @param spn The service provider name.  May be null if it shouldn't be displayed.
      */
-    void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { }
+    public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { }
 
     /**
      * Called when the ringer mode changes.
      * @param state the current ringer state, as defined in
      * {@link AudioManager#RINGER_MODE_CHANGED_ACTION}
      */
-    void onRingerModeChanged(int state) { }
+    public void onRingerModeChanged(int state) { }
 
     /**
      * Called when the phone state changes. String will be one of:
@@ -69,15 +69,15 @@
      * {@link TelephonyManager@EXTRA_STATE_RINGING}
      * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
      */
-    void onPhoneStateChanged(int phoneState) { }
+    public void onPhoneStateChanged(int phoneState) { }
 
     /**
      * Called when the visibility of the keyguard changes.
      * @param showing Indicates if the keyguard is now visible.
      */
-    void onKeyguardVisibilityChanged(boolean showing) { }
+    public void onKeyguardVisibilityChanged(boolean showing) { }
 
-    void onKeyguardVisibilityChangedRaw(boolean showing) {
+    public void onKeyguardVisibilityChangedRaw(boolean showing) {
         final long now = SystemClock.elapsedRealtime();
         if (showing == mShowing
                 && (now - mVisibilityChangedCalled) < VISIBILITY_CHANGED_COLLAPSE_MS) return;
@@ -90,44 +90,44 @@
      * Called when visibility of lockscreen clock changes, such as when
      * obscured by a widget.
      */
-    void onClockVisibilityChanged() { }
+    public void onClockVisibilityChanged() { }
 
     /**
      * Called when the device becomes provisioned
      */
-    void onDeviceProvisioned() { }
+    public void onDeviceProvisioned() { }
 
     /**
      * Called when the device policy changes.
      * See {@link DevicePolicyManager#ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED}
      */
-    void onDevicePolicyManagerStateChanged() { }
+    public void onDevicePolicyManagerStateChanged() { }
 
     /**
      * Called when the user change begins.
      */
-    void onUserSwitching(int userId) { }
+    public void onUserSwitching(int userId) { }
 
     /**
      * Called when the user change is complete.
      */
-    void onUserSwitchComplete(int userId) { }
+    public void onUserSwitchComplete(int userId) { }
 
     /**
      * Called when the SIM state changes.
      * @param simState
      */
-    void onSimStateChanged(IccCardConstants.State simState) { }
+    public void onSimStateChanged(IccCardConstants.State simState) { }
 
     /**
      * Called when a user is removed.
      */
-    void onUserRemoved(int userId) { }
+    public void onUserRemoved(int userId) { }
 
     /**
      * Called when the user's info changed.
      */
-    void onUserInfoChanged(int userId) { }
+    public void onUserInfoChanged(int userId) { }
 
     /**
      * Called when boot completed.
@@ -135,12 +135,12 @@
      * Note, this callback will only be received if boot complete occurs after registering with
      * KeyguardUpdateMonitor.
      */
-    void onBootCompleted() { }
+    public void onBootCompleted() { }
 
     /**
      * Called when audio client attaches or detaches from AudioManager.
      */
-    void onMusicClientIdChanged(int clientGeneration, boolean clearing, PendingIntent intent) { }
+    public void onMusicClientIdChanged(int clientGeneration, boolean clearing, PendingIntent intent) { }
 
     /**
      * Called when the audio playback state changes.
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
index 78f4506..bc0f364 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
@@ -60,7 +60,7 @@
 
     private AudioManager mAudioManager;
     private TelephonyManager mTelephonyManager = null;
-    protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
+    protected ViewMediatorCallback mViewMediatorCallback;
     protected LockPatternUtils mLockPatternUtils;
     private OnDismissAction mDismissAction;
 
@@ -68,7 +68,7 @@
     // they will be handled here for specific media types such as music, otherwise
     // the audio service will bring up the volume dialog.
     private static final boolean KEYGUARD_MANAGES_VOLUME = true;
-    private static final boolean DEBUG = false;
+    public static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "KeyguardViewBase";
 
     private KeyguardSecurityContainer mSecurityContainer;
@@ -107,7 +107,6 @@
         mSecurityContainer.setSecurityCallback(this);
         mSecurityContainer.showPrimarySecurityScreen(false);
         // mSecurityContainer.updateSecurityViews(false /* not bouncing */);
-        setBackButtonEnabled(false);
     }
 
     /**
@@ -120,15 +119,11 @@
 
     /**
      *  Dismisses the keyguard by going to the next screen or making it gone.
+     *
+     *  @return True if the keyguard is done.
      */
-    public void dismiss() {
-        dismiss(false);
-    }
-
-    private void setBackButtonEnabled(boolean enabled) {
-        setSystemUiVisibility(enabled ?
-                getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_BACK :
-                getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
+    public boolean dismiss() {
+        return dismiss(false);
     }
 
     protected void showBouncer(boolean show) {
@@ -141,8 +136,7 @@
 
     public boolean handleBackKey() {
         if (mSecurityContainer.getCurrentSecuritySelection() == SecurityMode.Account) {
-            // go back to primary screen and re-disable back
-            setBackButtonEnabled(false);
+            // go back to primary screen
             mSecurityContainer.showPrimarySecurityScreen(false /*turningOff*/);
             return true;
         }
@@ -205,12 +199,6 @@
 
     @Override
     public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
-        // Enable or disable the back button based on security mode
-        if (securityMode == SecurityMode.Account && !mLockPatternUtils.isPermanentlyLocked()) {
-            // we're showing account as a backup, provide a way to get back to primary
-            setBackButtonEnabled(true);
-        }
-
         if (mViewMediatorCallback != null) {
             mViewMediatorCallback.setNeedsInput(needsInput);
         }
@@ -231,7 +219,7 @@
     /**
      * Called when the screen turned off.
      */
-    protected void onScreenTurnedOff() {
+    public void onScreenTurnedOff() {
         if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
                 Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
         // Once the screen turns off, we no longer consider this to be first boot and we want the
@@ -245,7 +233,7 @@
     /**
      * Called when the screen turned on.
      */
-    protected void onScreenTurnedOn() {
+    public void onScreenTurnedOn() {
         if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
         mSecurityContainer.showPrimarySecurityScreen(false);
         mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
@@ -433,8 +421,7 @@
         return false;
     }
 
-    public void setViewMediatorCallback(
-            KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
+    public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
         mViewMediatorCallback = viewMediatorCallback;
         // Update ViewMediator with the current input method requirements
         mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput());
@@ -484,7 +471,7 @@
         mActivityLauncher.launchCamera(getHandler(), null);
     }
 
-    protected void setLockPatternUtils(LockPatternUtils utils) {
+    public void setLockPatternUtils(LockPatternUtils utils) {
         mLockPatternUtils = utils;
         mSecurityContainer.setLockPatternUtils(utils);
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
deleted file mode 100644
index 5b35ba88..0000000
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.keyguard;
-
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-
-import com.android.internal.policy.IKeyguardShowCallback;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.analytics.KeyguardAnalytics;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.app.ActivityManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewManager;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-
-/**
- * Manages creating, showing, hiding and resetting the keyguard.  Calls back
- * via {@link KeyguardViewMediator.ViewMediatorCallback} to poke
- * the wake lock and report that the keyguard is done, which is in turn,
- * reported to this class by the current {@link KeyguardViewBase}.
- */
-public class KeyguardViewManager {
-    private final static boolean DEBUG = KeyguardViewMediator.DEBUG;
-    private static String TAG = "KeyguardViewManager";
-    public final static String IS_SWITCHING_USER = "is_switching_user";
-
-    // Delay dismissing keyguard to allow animations to complete.
-    private static final int HIDE_KEYGUARD_DELAY = 500;
-
-    // Timeout used for keypresses
-    static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
-    private static final boolean ENABLE_SIMPLE_KEYGUARD = false;
-
-    private final Context mContext;
-    private final ViewManager mViewManager;
-    private final KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
-    private final KeyguardAnalytics.Callback mAnalyticsCallback;
-
-    private WindowManager.LayoutParams mWindowLayoutParams;
-    private boolean mNeedsInput = false;
-
-    private ViewManagerHost mKeyguardHost;
-    private KeyguardViewBase mKeyguardView;
-
-    private boolean mScreenOn = false;
-    private LockPatternUtils mLockPatternUtils;
-
-    private KeyguardUpdateMonitorCallback mBackgroundChanger = new KeyguardUpdateMonitorCallback() {
-        @Override
-        public void onSetBackground(Bitmap bmp) {
-            mKeyguardHost.setCustomBackground(bmp != null ?
-                    new BitmapDrawable(mContext.getResources(), bmp) : null);
-            updateShowWallpaper(bmp == null);
-        }
-    };
-
-    public interface ShowListener {
-        void onShown(IBinder windowToken);
-    };
-
-    /**
-     * @param context Used to create views.
-     * @param viewManager Keyguard will be attached to this.
-     * @param callback Used to notify of changes.
-     * @param lockPatternUtils
-     */
-    public KeyguardViewManager(Context context, ViewManager viewManager,
-            KeyguardViewMediator.ViewMediatorCallback callback,
-            LockPatternUtils lockPatternUtils, KeyguardAnalytics.Callback analyticsCallback) {
-        mContext = context;
-        mViewManager = viewManager;
-        mViewMediatorCallback = callback;
-        mLockPatternUtils = lockPatternUtils;
-        mAnalyticsCallback = analyticsCallback;
-    }
-
-    /**
-     * Show the keyguard.  Will handle creating and attaching to the view manager
-     * lazily.
-     */
-    public synchronized void show(Bundle options) {
-        if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
-        if (mAnalyticsCallback != null) {
-            mAnalyticsCallback.onShow();
-        }
-
-        boolean enableScreenRotation = shouldEnableScreenRotation();
-
-        maybeCreateKeyguardLocked(enableScreenRotation, false, options);
-        maybeEnableScreenRotation(enableScreenRotation);
-
-        // Disable common aspects of the system/status/navigation bars that are not appropriate or
-        // useful on any keyguard screen but can be re-shown by dialogs or SHOW_WHEN_LOCKED
-        // activities. Other disabled bits are handled by the KeyguardViewMediator talking
-        // directly to the status bar service.
-        int visFlags = View.STATUS_BAR_DISABLE_HOME;
-        if (shouldEnableTranslucentDecor()) {
-            mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
-                                       | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
-        }
-        if (DEBUG) Log.v(TAG, "show:setSystemUiVisibility(" + Integer.toHexString(visFlags)+")");
-        mKeyguardHost.setSystemUiVisibility(visFlags);
-
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-        mKeyguardHost.setVisibility(View.VISIBLE);
-        mKeyguardView.show();
-        mKeyguardView.requestFocus();
-    }
-
-    private boolean shouldEnableScreenRotation() {
-        Resources res = mContext.getResources();
-        return SystemProperties.getBoolean("lockscreen.rot_override",false)
-                || res.getBoolean(R.bool.config_enableLockScreenRotation);
-    }
-
-    private boolean shouldEnableTranslucentDecor() {
-        Resources res = mContext.getResources();
-        return res.getBoolean(R.bool.config_enableLockScreenTranslucentDecor);
-    }
-
-    class ViewManagerHost extends FrameLayout {
-        private static final int BACKGROUND_COLOR = 0x70000000;
-
-        private Drawable mCustomBackground;
-
-        // This is a faster way to draw the background on devices without hardware acceleration
-        private final Drawable mBackgroundDrawable = new Drawable() {
-            @Override
-            public void draw(Canvas canvas) {
-                if (mCustomBackground != null) {
-                    final Rect bounds = mCustomBackground.getBounds();
-                    final int vWidth = getWidth();
-                    final int vHeight = getHeight();
-
-                    final int restore = canvas.save();
-                    canvas.translate(-(bounds.width() - vWidth) / 2,
-                            -(bounds.height() - vHeight) / 2);
-                    mCustomBackground.draw(canvas);
-                    canvas.restoreToCount(restore);
-                } else {
-                    canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
-                }
-            }
-
-            @Override
-            public void setAlpha(int alpha) {
-            }
-
-            @Override
-            public void setColorFilter(ColorFilter cf) {
-            }
-
-            @Override
-            public int getOpacity() {
-                return PixelFormat.TRANSLUCENT;
-            }
-        };
-
-        public ViewManagerHost(Context context) {
-            super(context);
-            setBackground(mBackgroundDrawable);
-        }
-
-        public void setCustomBackground(Drawable d) {
-            mCustomBackground = d;
-            if (d != null) {
-                d.setColorFilter(BACKGROUND_COLOR, PorterDuff.Mode.SRC_OVER);
-            }
-            computeCustomBackgroundBounds();
-            invalidate();
-        }
-
-        private void computeCustomBackgroundBounds() {
-            if (mCustomBackground == null) return; // Nothing to do
-            if (!isLaidOut()) return; // We'll do this later
-
-            final int bgWidth = mCustomBackground.getIntrinsicWidth();
-            final int bgHeight = mCustomBackground.getIntrinsicHeight();
-            final int vWidth = getWidth();
-            final int vHeight = getHeight();
-
-            final float bgAspect = (float) bgWidth / bgHeight;
-            final float vAspect = (float) vWidth / vHeight;
-
-            if (bgAspect > vAspect) {
-                mCustomBackground.setBounds(0, 0, (int) (vHeight * bgAspect), vHeight);
-            } else {
-                mCustomBackground.setBounds(0, 0, vWidth, (int) (vWidth / bgAspect));
-            }
-        }
-
-        @Override
-        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-            super.onSizeChanged(w, h, oldw, oldh);
-            computeCustomBackgroundBounds();
-        }
-
-        @Override
-        protected void onConfigurationChanged(Configuration newConfig) {
-            super.onConfigurationChanged(newConfig);
-            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
-                // only propagate configuration messages if we're currently showing
-                maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, null);
-            } else {
-                if (DEBUG) Log.v(TAG, "onConfigurationChanged: view not visible");
-            }
-        }
-
-        @Override
-        public boolean dispatchKeyEvent(KeyEvent event) {
-            if (mKeyguardView != null) {
-                // Always process back and menu keys, regardless of focus
-                if (event.getAction() == KeyEvent.ACTION_DOWN) {
-                    int keyCode = event.getKeyCode();
-                    if (keyCode == KeyEvent.KEYCODE_BACK && mKeyguardView.handleBackKey()) {
-                        return true;
-                    } else if (keyCode == KeyEvent.KEYCODE_MENU && mKeyguardView.handleMenuKey()) {
-                        return true;
-                    }
-                }
-                // Always process media keys, regardless of focus
-                if (mKeyguardView.dispatchKeyEvent(event)) {
-                    return true;
-                }
-            }
-            return super.dispatchKeyEvent(event);
-        }
-
-        @Override
-        public boolean dispatchTouchEvent(MotionEvent ev) {
-            boolean result = false;
-            if (mAnalyticsCallback != null) {
-                result = mAnalyticsCallback.onTouchEvent(ev, getWidth(), getHeight()) || result;
-            }
-            return super.dispatchTouchEvent(ev) || result;
-        }
-    }
-
-    SparseArray<Parcelable> mStateContainer = new SparseArray<Parcelable>();
-    private int mCurrentLayout;
-
-    private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
-            Bundle options) {
-        if (mKeyguardHost != null) {
-            mKeyguardHost.saveHierarchyState(mStateContainer);
-        }
-
-        if (mKeyguardHost == null) {
-            if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
-
-            mKeyguardHost = new ViewManagerHost(mContext);
-
-            int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
-                    | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
-                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-
-            if (!mNeedsInput) {
-                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-            }
-
-            final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
-            final int type = WindowManager.LayoutParams.TYPE_KEYGUARD;
-            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                    stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
-            lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-            lp.windowAnimations = R.style.Animation_LockScreen;
-            lp.screenOrientation = enableScreenRotation ?
-                    ActivityInfo.SCREEN_ORIENTATION_USER : ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-
-            if (ActivityManager.isHighEndGfx()) {
-                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-                lp.privateFlags |=
-                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
-            }
-            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
-            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
-            lp.setTitle("Keyguard");
-            mWindowLayoutParams = lp;
-            mViewManager.addView(mKeyguardHost, lp);
-
-            KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mBackgroundChanger);
-        }
-
-        if (force || mKeyguardView == null) {
-            mKeyguardHost.setCustomBackground(null);
-            mKeyguardHost.removeAllViews();
-            int layout = (allowNotificationsOnSecureKeyguard() && ENABLE_SIMPLE_KEYGUARD)
-                    ? R.layout.keyguard_simple_host_view
-                    : R.layout.keyguard_host_view;
-            if (mCurrentLayout != layout) {
-                mStateContainer.clear(); // don't restore to the wrong view hierarchy
-                mCurrentLayout = layout;
-            }
-            mKeyguardView = inflateKeyguardView(options, layout);
-            mKeyguardView.requestFocus();
-        }
-        updateUserActivityTimeoutInWindowLayoutParams();
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-
-        mKeyguardHost.restoreHierarchyState(mStateContainer);
-    }
-
-    private boolean allowNotificationsOnSecureKeyguard() {
-        ContentResolver cr = mContext.getContentResolver();
-        return Settings.Global.getInt(cr, Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) == 1;
-    }
-
-    private KeyguardViewBase inflateKeyguardView(Bundle options, int layoutId) {
-        View v = mKeyguardHost.findViewById(R.id.keyguard_host_view);
-        if (v != null) {
-            mKeyguardHost.removeView(v);
-        }
-        final LayoutInflater inflater = LayoutInflater.from(mContext);
-        View view = inflater.inflate(layoutId, mKeyguardHost, true);
-        KeyguardViewBase keyguard = (KeyguardViewBase) view.findViewById(R.id.keyguard_host_view);
-        keyguard.setLockPatternUtils(mLockPatternUtils);
-        keyguard.setViewMediatorCallback(mViewMediatorCallback);
-        keyguard.onUserSwitching(options != null && options.getBoolean(IS_SWITCHING_USER));
-        keyguard.onCreateOptions(options);
-        return keyguard;
-    }
-
-    public void updateUserActivityTimeout() {
-        updateUserActivityTimeoutInWindowLayoutParams();
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-    }
-
-    private void updateUserActivityTimeoutInWindowLayoutParams() {
-        // Use the user activity timeout requested by the keyguard view, if any.
-        if (mKeyguardView != null) {
-            long timeout = mKeyguardView.getUserActivityTimeout();
-            if (timeout >= 0) {
-                mWindowLayoutParams.userActivityTimeout = timeout;
-                return;
-            }
-        }
-
-        // Otherwise, use the default timeout.
-        mWindowLayoutParams.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
-    }
-
-    private void maybeEnableScreenRotation(boolean enableScreenRotation) {
-        // TODO: move this outside
-        if (enableScreenRotation) {
-            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
-            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
-        } else {
-            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
-            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-        }
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-    }
-
-    void updateShowWallpaper(boolean show) {
-        if (show) {
-            mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-        } else {
-            mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-        }
-        mWindowLayoutParams.format = show ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
-
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-    }
-
-    public void setNeedsInput(boolean needsInput) {
-        mNeedsInput = needsInput;
-        if (mWindowLayoutParams != null) {
-            if (needsInput) {
-                mWindowLayoutParams.flags &=
-                    ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-            } else {
-                mWindowLayoutParams.flags |=
-                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-            }
-
-            try {
-                mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-            } catch (java.lang.IllegalArgumentException e) {
-                // TODO: Ensure this method isn't called on views that are changing...
-                Log.w(TAG,"Can't update input method on " + mKeyguardHost + " window not attached");
-            }
-        }
-    }
-
-    /**
-     * Reset the state of the view.
-     */
-    public synchronized void reset(Bundle options) {
-        if (DEBUG) Log.d(TAG, "reset()");
-        // User might have switched, check if we need to go back to keyguard
-        // TODO: It's preferable to stay and show the correct lockscreen or unlock if none
-        maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, options);
-    }
-
-    public synchronized void onScreenTurnedOff() {
-        if (DEBUG) Log.d(TAG, "onScreenTurnedOff()");
-        mScreenOn = false;
-        if (mKeyguardView != null) {
-            mKeyguardView.onScreenTurnedOff();
-        }
-    }
-
-    public synchronized void onScreenTurnedOn(final IKeyguardShowCallback callback) {
-        if (DEBUG) Log.d(TAG, "onScreenTurnedOn()");
-        mScreenOn = true;
-
-        // If keyguard is not showing, we need to inform PhoneWindowManager with a null
-        // token so it doesn't wait for us to draw...
-        final IBinder token = isShowing() ? mKeyguardHost.getWindowToken() : null;
-
-        if (DEBUG && token == null) Slog.v(TAG, "send wm null token: "
-                + (mKeyguardHost == null ? "host was null" : "not showing"));
-
-        if (mKeyguardView != null) {
-            mKeyguardView.onScreenTurnedOn();
-
-            // Caller should wait for this window to be shown before turning
-            // on the screen.
-            if (callback != null) {
-                if (mKeyguardHost.getVisibility() == View.VISIBLE) {
-                    // Keyguard may be in the process of being shown, but not yet
-                    // updated with the window manager...  give it a chance to do so.
-                    mKeyguardHost.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            try {
-                                callback.onShown(token);
-                            } catch (RemoteException e) {
-                                Slog.w(TAG, "Exception calling onShown():", e);
-                            }
-                        }
-                    });
-                } else {
-                    try {
-                        callback.onShown(token);
-                    } catch (RemoteException e) {
-                        Slog.w(TAG, "Exception calling onShown():", e);
-                    }
-                }
-            }
-        } else if (callback != null) {
-            try {
-                callback.onShown(token);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Exception calling onShown():", e);
-            }
-        }
-        if (mAnalyticsCallback != null) {
-            mAnalyticsCallback.onScreenOn();
-        }
-    }
-
-    public synchronized void verifyUnlock() {
-        if (DEBUG) Log.d(TAG, "verifyUnlock()");
-        show(null);
-        mKeyguardView.verifyUnlock();
-    }
-
-    /**
-     * Hides the keyguard view
-     */
-    public synchronized void hide() {
-        if (DEBUG) Log.d(TAG, "hide()");
-
-        if (mAnalyticsCallback != null) {
-            mAnalyticsCallback.onHide();
-        }
-
-        if (mKeyguardHost != null) {
-            mKeyguardHost.setVisibility(View.GONE);
-
-            // We really only want to preserve keyguard state for configuration changes. Hence
-            // we should clear state of widgets (e.g. Music) when we hide keyguard so it can
-            // start with a fresh state when we return.
-            mStateContainer.clear();
-
-            // Don't do this right away, so we can let the view continue to animate
-            // as it goes away.
-            if (mKeyguardView != null) {
-                final KeyguardViewBase lastView = mKeyguardView;
-                mKeyguardView = null;
-                mKeyguardHost.postDelayed(new Runnable() {
-                    @Override
-                    public void run() {
-                        synchronized (KeyguardViewManager.this) {
-                            lastView.cleanUp();
-                            // Let go of any large bitmaps.
-                            mKeyguardHost.setCustomBackground(null);
-                            updateShowWallpaper(true);
-                            mKeyguardHost.removeView(lastView);
-                            mViewMediatorCallback.keyguardGone();
-                        }
-                    }
-                }, HIDE_KEYGUARD_DELAY);
-            }
-        }
-    }
-
-    /**
-     * Dismisses the keyguard by going to the next screen or making it gone.
-     */
-    public synchronized void dismiss() {
-        if (mScreenOn) {
-            mKeyguardView.dismiss();
-        }
-    }
-
-    /**
-     * @return Whether the keyguard is showing
-     */
-    public synchronized boolean isShowing() {
-        return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
-    }
-
-    public void showAssistant() {
-        if (mKeyguardView != null) {
-            mKeyguardView.showAssistant();
-        }
-    }
-
-    public void dispatch(MotionEvent event) {
-        if (mKeyguardView != null) {
-            mKeyguardView.onExternalMotionEvent(event);
-        }
-    }
-
-    public void launchCamera() {
-        if (mKeyguardView != null) {
-            mKeyguardView.launchCamera();
-        }
-    }
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java b/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java
index 9930e72..7128211 100644
--- a/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java
+++ b/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java
@@ -22,12 +22,21 @@
 
 public class MultiUserAvatarCache {
 
+    private static MultiUserAvatarCache sInstance;
+
     private final HashMap<Integer, Drawable> mCache;
 
-    public MultiUserAvatarCache() {
+    private MultiUserAvatarCache() {
         mCache = new HashMap<Integer, Drawable>();
     }
 
+    public static MultiUserAvatarCache getInstance() {
+        if (sInstance == null) {
+            sInstance = new MultiUserAvatarCache();
+        }
+        return sInstance;
+    }
+
     public void clear(int userId) {
         mCache.remove(userId);
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/PagedView.java b/packages/Keyguard/src/com/android/keyguard/PagedView.java
index d233ee9..b42a085 100644
--- a/packages/Keyguard/src/com/android/keyguard/PagedView.java
+++ b/packages/Keyguard/src/com/android/keyguard/PagedView.java
@@ -56,7 +56,7 @@
 public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeListener {
     private static final int WARP_SNAP_DURATION = 160;
     private static final String TAG = "WidgetPagedView";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final boolean DEBUG_WARP = false;
     protected static final int INVALID_PAGE = -1;
     private static final int WARP_PEEK_ANIMATION_DURATION = 150;
diff --git a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
index 3d515ce..ab9286b 100644
--- a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
+++ b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
@@ -45,7 +45,7 @@
  */
 public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout {
     private static final String TAG = "SlidingChallengeLayout";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
 
     // The drag handle is measured in dp above & below the top edge of the
     // challenge view; these parameters change based on whether the challenge
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
new file mode 100644
index 0000000..1f23785
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -0,0 +1,71 @@
+/*
+ * 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 com.android.keyguard;
+
+/**
+ * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
+ * various things.
+ */
+public interface ViewMediatorCallback {
+    /**
+     * Reports user activity and requests that the screen stay on.
+     */
+    void userActivity();
+
+    /**
+     * Reports user activity and requests that the screen stay on for at least
+     * the specified amount of time.
+     * @param millis The amount of time in millis.  This value is currently ignored.
+     */
+    void userActivity(long millis);
+
+    /**
+     * Report that the keyguard is done.
+     * @param authenticated Whether the user securely got past the keyguard.
+     *   the only reason for this to be false is if the keyguard was instructed
+     *   to appear temporarily to verify the user is supposed to get past the
+     *   keyguard, and the user fails to do so.
+     */
+    void keyguardDone(boolean authenticated);
+
+    /**
+     * Report that the keyguard is done drawing.
+     */
+    void keyguardDoneDrawing();
+
+    /**
+     * Tell ViewMediator that the current view needs IME input
+     * @param needsInput
+     */
+    void setNeedsInput(boolean needsInput);
+
+    /**
+     * Tell view mediator that the keyguard view's desired user activity timeout
+     * has changed and needs to be reapplied to the window.
+     */
+    void onUserActivityTimeoutChanged();
+
+    /**
+     * Report that the keyguard is dismissable, pending the next keyguardDone call.
+     */
+    void keyguardDonePending();
+
+    /**
+     * Report when keyguard is actually gone
+     */
+    void keyguardGone();
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java b/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
index 55750cc..20af2f1 100644
--- a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
+++ b/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
@@ -80,7 +80,7 @@
         public void onScreenOn();
         public void onScreenOff();
         public boolean onTouchEvent(MotionEvent ev, int width, int height);
-        public void onSetHidden(boolean hidden);
+        public void onSetOccluded(boolean hidden);
     }
 
     public interface SessionTypeAdapter {
@@ -256,11 +256,11 @@
         }
 
         @Override
-        public void onSetHidden(boolean hidden) {
+        public void onSetOccluded(boolean hidden) {
             synchronized (KeyguardAnalytics.this) {
                 if (hidden != mHidden) {
                     if (DEBUG) {
-                        Log.d(TAG, "onSetHidden(" + hidden + ")");
+                        Log.d(TAG, "onSetOccluded(" + hidden + ")");
                     }
                     mHidden = hidden;
                     if (hidden) {
diff --git a/packages/PrintSpooler/res/values-da/strings.xml b/packages/PrintSpooler/res/values-da/strings.xml
index 1a871f8..74190b4 100644
--- a/packages/PrintSpooler/res/values-da/strings.xml
+++ b/packages/PrintSpooler/res/values-da/strings.xml
@@ -69,8 +69,8 @@
     <item msgid="2762241247228983754">"Farve"</item>
   </string-array>
   <string-array name="orientation_labels">
-    <item msgid="4061931020926489228">"Stående"</item>
-    <item msgid="3199660090246166812">"Liggende"</item>
+    <item msgid="4061931020926489228">"Portræt"</item>
+    <item msgid="3199660090246166812">"Landskab"</item>
   </string-array>
   <string-array name="page_options_labels">
     <item msgid="7421377442011699994">"Alle"</item>
diff --git a/packages/PrintSpooler/res/values-sl/strings.xml b/packages/PrintSpooler/res/values-sl/strings.xml
index e299508..5d4fe94 100644
--- a/packages/PrintSpooler/res/values-sl/strings.xml
+++ b/packages/PrintSpooler/res/values-sl/strings.xml
@@ -69,7 +69,7 @@
     <item msgid="2762241247228983754">"Barvno"</item>
   </string-array>
   <string-array name="orientation_labels">
-    <item msgid="4061931020926489228">"Pokončno"</item>
+    <item msgid="4061931020926489228">"Navpično"</item>
     <item msgid="3199660090246166812">"Ležeče"</item>
   </string-array>
   <string-array name="page_options_labels">
diff --git a/packages/PrintSpooler/res/values-sw/strings.xml b/packages/PrintSpooler/res/values-sw/strings.xml
index a84e9b3..55c8687 100644
--- a/packages/PrintSpooler/res/values-sw/strings.xml
+++ b/packages/PrintSpooler/res/values-sw/strings.xml
@@ -31,7 +31,7 @@
     <string name="install_for_print_preview" msgid="6366303997385509332">"Sakinisha kitazamaji cha PDF kwa onyesho la kuchungulia"</string>
     <string name="printing_app_crashed" msgid="854477616686566398">"Programu ya kuchapisha imeacha kufanya kazi"</string>
     <string name="page_count_unknown" msgid="6058852665954511124">"Kurasa"</string>
-    <string name="generating_print_job" msgid="3119608742651698916">"Inaleta kazi ya kuchapisha"</string>
+    <string name="generating_print_job" msgid="3119608742651698916">"Inazanzisha kazi ya kuchapisha"</string>
     <string name="save_as_pdf" msgid="5718454119847596853">"Hifadhi kama PDF"</string>
     <string name="all_printers" msgid="5018829726861876202">"Printa zote..."</string>
     <string name="print_dialog" msgid="32628687461331979">"Chapisha mazungumzo"</string>
@@ -63,7 +63,7 @@
     <string name="no_connection_to_printer" msgid="2159246915977282728">"Hakuna muunganisho kwa printa"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"haijulikani"</string>
     <string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> - haipatikani"</string>
-    <string name="print_error_default_message" msgid="8568506918983980567">"Haikuweza kuleta kazi ya kuchapisha"</string>
+    <string name="print_error_default_message" msgid="8568506918983980567">"Haikuweza kuunda kazi ya kuchapisha"</string>
   <string-array name="color_mode_labels">
     <item msgid="7602948745415174937">"Nyeusi na Nyeupe"</item>
     <item msgid="2762241247228983754">"Rangi"</item>
diff --git a/packages/Shell/res/values-sk/strings.xml b/packages/Shell/res/values-sk/strings.xml
index 59c3ccf..99f36f9 100644
--- a/packages/Shell/res/values-sk/strings.xml
+++ b/packages/Shell/res/values-sk/strings.xml
@@ -17,8 +17,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="3701846017049540910">"Prostredie"</string>
-    <string name="bugreport_finished_title" msgid="2293711546892863898">"Hlásenie o chybách bolo vytvorené"</string>
-    <string name="bugreport_finished_text" msgid="3559904746859400732">"Hlásenie o chybách môžete zdielať klepnutím"</string>
+    <string name="bugreport_finished_title" msgid="2293711546892863898">"Správa o chybách sa zaznamenala"</string>
+    <string name="bugreport_finished_text" msgid="3559904746859400732">"Dotykom môžete zdieľať správu o chybách"</string>
     <string name="bugreport_confirm" msgid="5130698467795669780">"Správy o chybách obsahujú údaje z rôznych súborov denníkov systému vrátane osobných a súkromných informácií. Zdieľajte ich iba s dôveryhodnými aplikáciami a ľuďmi."</string>
     <string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Zobraziť túto správu nabudúce"</string>
 </resources>
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index f8f064a..69c6159 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     src/com/android/systemui/EventLogTags.logtags
 
+LOCAL_STATIC_JAVA_LIBRARIES := Keyguard
 LOCAL_JAVA_LIBRARIES := telephony-common
 
 LOCAL_PACKAGE_NAME := SystemUI
@@ -14,6 +15,11 @@
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
+LOCAL_RESOURCE_DIR := \
+    frameworks/base/packages/Keyguard/res \
+    $(LOCAL_PATH)/res
+LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages com.android.keyguard
+
 include $(BUILD_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3424eed..d371d70 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -89,11 +89,20 @@
 
     <!-- Keyguard -->
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
+    <uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />
+    <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
+    <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
+    <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+    <uses-permission android:name="android.permission.TRUST_LISTENER" />
 
     <!-- Wifi Display -->
     <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
 
     <application
+        android:name=".SystemUIApplication"
         android:persistent="true"
         android:allowClearUserData="false"
         android:allowBackup="false"
@@ -101,7 +110,11 @@
         android:label="@string/app_label"
         android:icon="@*android:drawable/platlogo"
         android:process="com.android.systemui"
-        android:supportsRtl="true">
+        android:supportsRtl="true"
+        android:theme="@style/systemui_theme">
+        <!-- Keep theme in sync with SystemUIApplication.onCreate().
+             Setting the theme on the application does not affect views inflated by services.
+             The application theme is set again from onCreate to take effect for those views. -->
 
         <!-- Broadcast receiver that gets the broadcast at boot time and starts
              up everything else.
@@ -258,6 +271,10 @@
             </intent-filter>
         </service>
 
+        <service
+            android:name=".keyguard.KeyguardService"
+            android:exported="true" />
+
         <activity android:name=".Somnambulator"
             android:label="@string/start_dreams"
             android:icon="@mipmap/ic_launcher_dreams"
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 48d9722..da37803 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -6,7 +6,7 @@
   public void setGlowAlpha(float);
   public void setGlowScale(float);
 }
--keep class com.android.systemui.recents.views.TaskIconView {
+-keep class com.android.systemui.recents.views.TaskInfoView {
 	public void setCircularClipRadius(float);
 	public float getCircularClipRadius();
 }
diff --git a/packages/SystemUI/res/drawable/ic_notify_button_bg.xml b/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
index 85f1ea2..3a47261 100644
--- a/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
+++ b/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
@@ -15,6 +15,6 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true"  android:drawable="@*android:drawable/list_selector_pressed_holo_dark" />
-    <item                               android:drawable="@*android:drawable/list_selector_disabled_holo_dark" />
+    <item android:state_pressed="true"
+          android:drawable="@*android:drawable/list_selector_pressed_holo_dark" />
 </selector>
diff --git a/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml b/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
deleted file mode 100644
index 0947c6f..0000000
--- a/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, 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.
-*/
--->
-
-<!-- This is the combined status bar / notification panel window. -->
-<com.android.systemui.statusbar.phone.StatusBarWindowView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
-    android:focusable="true"
-    android:descendantFocusability="afterDescendants"
-    android:fitsSystemWindows="true"
-    >
-
-    <include layout="@layout/status_bar"
-        android:layout_width="match_parent"
-        android:layout_height="@*android:dimen/status_bar_height"
-        />
-
-
-    <com.android.systemui.statusbar.phone.PanelHolder
-        android:id="@+id/panel_holder"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginTop="@*android:dimen/status_bar_height"
-        >
-        <include layout="@layout/status_bar_expanded"
-            android:layout_width="@dimen/notification_panel_width"
-            android:layout_height="wrap_content"
-            android:layout_gravity="start|top"
-            />
-        <include layout="@layout/quick_settings"
-            android:layout_width="@dimen/notification_panel_width"
-            android:layout_height="wrap_content"
-            android:layout_gravity="end|top"
-            />
-    </com.android.systemui.statusbar.phone.PanelHolder>
-</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 5488a87..a6fb443 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -169,6 +169,7 @@
                 android:scaleType="center"
                 android:visibility="gone"
                 android:contentDescription="@string/accessibility_camera_button"
+                systemui:glowBackground="@drawable/ic_sysbar_highlight_land"
                 />
         </FrameLayout>
 
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 8297878..7f64032 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -21,6 +21,21 @@
         android:id="@+id/task_view_thumbnail"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
+    <com.android.systemui.recents.views.TaskInfoView
+    	android:id="@+id/task_view_info_pane"
+    	android:layout_width="match_parent"
+    	android:layout_height="match_parent"
+    	android:visibility="invisible"
+        android:background="#e6444444">
+        <Button
+        	android:id="@+id/task_view_app_info_button"
+        	android:layout_width="match_parent"
+        	android:layout_height="wrap_content"
+        	android:layout_marginStart="20dp"
+        	android:layout_marginEnd="20dp"
+    		android:layout_gravity="top|center_horizontal"
+        	android:text="@string/recents_app_info_button_label" />
+    </com.android.systemui.recents.views.TaskInfoView>
     <com.android.systemui.recents.views.TaskBarView
         android:id="@+id/task_view_bar"
         android:layout_width="match_parent"
@@ -31,15 +46,15 @@
             android:id="@+id/application_icon"
             android:layout_width="@dimen/recents_task_view_application_icon_size"
             android:layout_height="@dimen/recents_task_view_application_icon_size"
-            android:layout_gravity="center_vertical|left"
+            android:layout_gravity="center_vertical|start"
             android:padding="8dp" />
         <TextView
             android:id="@+id/activity_description"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical|left"
-            android:layout_marginLeft="@dimen/recents_task_view_application_icon_size"
-            android:layout_marginRight="@dimen/recents_task_view_activity_icon_size"
+            android:layout_marginStart="@dimen/recents_task_view_application_icon_size"
+            android:layout_marginEnd="@dimen/recents_task_view_activity_icon_size"
             android:textSize="24sp"
             android:textColor="#ffffffff"
             android:text="@string/recents_empty_message"
@@ -52,7 +67,7 @@
             android:id="@+id/activity_icon"
             android:layout_width="@dimen/recents_task_view_activity_icon_size"
             android:layout_height="@dimen/recents_task_view_activity_icon_size"
-            android:layout_gravity="center_vertical|right"
+            android:layout_gravity="center_vertical|end"
             android:padding="12dp"
             android:visibility="invisible" />
     </com.android.systemui.recents.views.TaskBarView>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index ea6be1b..1b35537 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -27,7 +27,6 @@
     android:orientation="vertical"
     android:focusable="true"
     android:descendantFocusability="afterDescendants"
-    android:fitsSystemWindows="true"
     >
 
     <ImageView
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index a7ec064..8f4417e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -36,6 +36,14 @@
         android:layout_gravity="bottom"
         />
 
+    <ViewStub android:id="@+id/keyguard_flip_stub"
+        android:layout="@layout/status_bar_flip_button"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
+        android:layout_gravity="right|top"
+        android:layout_marginTop="@*android:dimen/status_bar_height"
+        android:visibility="gone" />
+
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
@@ -49,6 +57,10 @@
             android:layout_height="@dimen/notification_panel_header_height"
             />
 
+        <include
+            layout="@layout/keyguard_status_view"
+            android:visibility="gone" />
+
         <TextView
             android:id="@+id/emergency_calls_only"
             android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 9aa7cfd..56523db 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -81,29 +81,10 @@
         android:src="@drawable/ic_notify_clear"
         android:background="@drawable/ic_notify_button_bg"
         android:contentDescription="@string/accessibility_clear_all"
-        />     
+        />
 
-    <FrameLayout android:id="@+id/settings_button_holder"
+    <include layout="@layout/status_bar_flip_button"
         android:layout_width="50dp"
         android:layout_height="50dp"
-        android:layout_marginStart="12dp"
-        >
-        <ImageView android:id="@+id/settings_button"
-            android:layout_width="50dp"
-            android:layout_height="50dp"
-            android:scaleType="center"
-            android:src="@drawable/ic_notify_settings"
-            android:background="@drawable/ic_notify_button_bg"
-            android:contentDescription="@string/accessibility_desc_quick_settings"
-            />
-        <ImageView android:id="@+id/notification_button"
-            android:layout_width="50dp"
-            android:layout_height="50dp"
-            android:scaleType="center"
-            android:src="@drawable/ic_notifications"
-            android:background="@drawable/ic_notify_button_bg"
-            android:visibility="gone"
-            android:contentDescription="@string/accessibility_notifications_button"
-            />
-    </FrameLayout>
+        android:layout_marginStart="12dp" />
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_flip_button.xml b/packages/SystemUI/res/layout/status_bar_flip_button.xml
new file mode 100644
index 0000000..db672ea
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_flip_button.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/settings_button_holder"
+        android:layout_width="50dp"
+        android:layout_height="50dp">
+    <ImageView android:id="@+id/settings_button"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
+        android:scaleType="center"
+        android:src="@drawable/ic_notify_settings"
+        android:background="@drawable/ic_notify_button_bg"
+        android:contentDescription="@string/accessibility_desc_quick_settings" />
+    <ImageView android:id="@+id/notification_button"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
+        android:scaleType="center"
+        android:src="@drawable/ic_notifications"
+        android:background="@drawable/ic_notify_button_bg"
+        android:visibility="gone"
+        android:contentDescription="@string/accessibility_notifications_button" />
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
new file mode 100644
index 0000000..5d2f330
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -0,0 +1,52 @@
+<!--
+  ~ 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
+  -->
+
+<!-- Extends FrameLayout -->
+<com.android.systemui.statusbar.NotificationOverflowContainer
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    >
+    <com.android.systemui.statusbar.LatestItemView
+        android:id="@+id/container"
+        android:layout_width="match_parent"
+        android:layout_height="40dp"
+        android:layout_marginTop="@dimen/notification_divider_height"
+        android:focusable="true"
+        android:clickable="true"
+        android:background="@*android:drawable/notification_quantum_bg_dim"
+        >
+        <TextView
+            android:id="@+id/more_text"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_vertical"
+            android:gravity="center_horizontal"
+            android:textColor="@color/keyguard_overflow_content_color"
+            android:textAllCaps="true"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            />
+        <com.android.systemui.statusbar.NotificationOverflowIconsView
+            android:id="@+id/overflow_icons_view"
+            android:layout_gravity="end|center_vertical"
+            android:gravity="end"
+            android:paddingLeft="8dp"
+            android:paddingRight="8dp"
+            android:layout_width="120dp"
+            android:layout_height="wrap_content"
+            />
+    </com.android.systemui.statusbar.LatestItemView>
+</com.android.systemui.statusbar.NotificationOverflowContainer>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index e74e568..d61d8b9 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -32,6 +32,7 @@
         android:layout_marginTop="@dimen/notification_divider_height"
         android:focusable="true"
         android:clickable="true"
+        android:background="@*android:drawable/notification_quantum_bg"
         >
 
         <com.android.internal.widget.SizeAdaptiveLayout android:id="@+id/expanded"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 2b56618..9176d24 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -20,32 +20,29 @@
 <!-- This is the combined status bar / notification panel window. -->
 <com.android.systemui.statusbar.phone.StatusBarWindowView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:focusable="true"
-    android:descendantFocusability="afterDescendants"
-    android:fitsSystemWindows="true"
-    android:background="@android:color/transparent"
-    >
+    android:descendantFocusability="afterDescendants">
 
     <include layout="@layout/status_bar"
         android:layout_width="match_parent"
-        android:layout_height="@*android:dimen/status_bar_height"
-        />
+        android:layout_height="@*android:dimen/status_bar_height" />
 
     <com.android.systemui.statusbar.phone.PanelHolder
         android:id="@+id/panel_holder"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        >
+        android:layout_marginTop="@dimen/panel_holder_padding_top"
+        android:layout_marginBottom="@*android:dimen/navigation_bar_height">
         <include layout="@layout/status_bar_expanded"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            />
+            android:layout_width="@dimen/notification_panel_width"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start|top" />
         <ViewStub android:id="@+id/quick_settings_stub"
             android:layout="@layout/quick_settings"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            />
+            android:layout_width="@dimen/notification_panel_width"
+            android:layout_height="match_parent" />
     </com.android.systemui.statusbar.phone.PanelHolder>
 
 </com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout/user_switcher_host.xml b/packages/SystemUI/res/layout/user_switcher_host.xml
new file mode 100644
index 0000000..bc56cf6
--- /dev/null
+++ b/packages/SystemUI/res/layout/user_switcher_host.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ 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
+  -->
+
+<!-- FrameLayout -->
+<com.android.systemui.settings.UserSwitcherHostView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:tools="http://schemas.android.com/tools"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#dd000000">
+    <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@*android:dimen/volume_panel_top"
+            android:background="@*android:drawable/dialog_full_holo_dark">
+        <ListView android:id="@android:id/list"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                tools:listitem="@layout/user_switcher_item"/>
+    </FrameLayout>
+</com.android.systemui.settings.UserSwitcherHostView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/user_switcher_item.xml b/packages/SystemUI/res/layout/user_switcher_item.xml
new file mode 100644
index 0000000..43a85e7
--- /dev/null
+++ b/packages/SystemUI/res/layout/user_switcher_item.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:tools="http://schemas.android.com/tools"
+        android:layout_width="match_parent"
+        android:layout_height="64dp"
+        android:orientation="horizontal"
+        tools:context=".settings.UserSwitcherDialog">
+    <ImageView
+            android:layout_width="64dp"
+            android:layout_height="match_parent"
+            android:id="@+id/user_picture"
+            tools:src="@drawable/dessert_zombiegingerbread"/>
+    <TextView
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:id="@+id/user_name"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:padding="8dp"
+            android:gravity="center_vertical"
+            tools:text="Hiroshi Lockheimer"
+            />
+</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 98d132a..a3cabc2 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Soek"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Gly op vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Gly links vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Kennisgewing versteek"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d kennisgewings versteek"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Raak om te wys"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 2e116d0..5dbc618 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"ፍለጋ"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ላይ አንሸራትት።"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ግራ አንሸራትት።"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"ማሳወቂያ ተደብቋል"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d ማሳወቂያዎች ተደብቀዋል"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"ለማሳየት ነካ ያድርጉ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 596f612..715aadc 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"بحث"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"تمرير لأعلى لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"تمرير لليسار لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"تم إخفاء الإشعار"</item>
+    <item quantity="other" msgid="7388721375827338153">"‏تم إخفاء %d من الإشعارات"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"المس للعرض"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 335c33a..c9ca1f0 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Търсене"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Плъзнете нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Плъзнете наляво за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Известието е скрито"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d известия са скрити"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Докоснете за показване"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e79e094..62d4c72 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Cerca"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Fes lliscar el dit cap amunt per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Fes lliscar el dit cap a l\'esquerra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notificació oculta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notificacions ocultes"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toca per mostrar-ho."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 60bbe3b..e96f8cf 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Vyhledávání"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Přejeďte prstem nahoru: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Přejeďte prstem doleva: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Oznámení bylo skryto"</item>
+    <item quantity="other" msgid="7388721375827338153">"Skrytá oznámení: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Oznámení zobrazíte kliknutím"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 86c1eb96..5b4a41c 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Søgning"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Glid op for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Glid til venstre for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Underretningen er skjult"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d underretninger er skjult"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Tryk for at vise"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index c8cb0a4..9557897 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Suche"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach oben schieben"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach links schieben"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Benachrichtigung ausgeblendet"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d Benachrichtigungen ausgeblendet"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Zum Ansehen tippen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 79025b6..796b80d 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Αναζήτηση"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Κύλιση προς τα επάνω για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Κύλιση προς τα αριστερά για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Έγινε απόκρυψη της ειδοποίησης"</item>
+    <item quantity="other" msgid="7388721375827338153">"Έγινε απόκρυψη %d ειδοποιήσεων"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Αγγίξτε για εμφάνιση"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 338c8ac..77262d5 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Search"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notification hidden"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notifications hidden"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Touch to show"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 338c8ac..77262d5 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Search"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notification hidden"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notifications hidden"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Touch to show"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 89fe58b..f195f6a 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notificación oculta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notificaciones ocultas"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toca para mostrar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f2a9850..d6ddd63 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notification oculta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notificaciones ocultas"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toca para mostrar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index b734fa8..ab9b18e 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -209,4 +209,7 @@
     <string name="description_target_search" msgid="3091587249776033139">"Otsing"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Lohistage üles: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Lohistage vasakule: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for zen_mode_notification_title:other (7388721375827338153) -->
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Puudutage kuvamiseks"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 5780a57..bf295f2 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"جستجو"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"لغزاندن به بالا برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"لغزاندن به چپ برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"اعلان پنهان شده"</item>
+    <item quantity="other" msgid="7388721375827338153">"‏%d اعلان پنهان شده"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"برای نمایش لمس کنید"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4809741..0fa764e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Haku"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Liu\'uta ylös ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Liu\'uta vasemmalle ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Ilmoitus piilotettu"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d ilmoitusta piilotettu"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Näytä koskettamalla"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 36b54ce..2a2ed5e 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Recherche"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Faire glisser le doigt vers le haut : <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Faites glisser votre doigt vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notification masquée"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notifications masquées"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Touchez pour afficher la notification"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5b81975..278e580 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Rechercher"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Faites glisser vers le haut pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Faites glisser vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notification masquée"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notifications masquées"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Appuyer pour afficher"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 9be9550..139ae83 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"खोजें"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए ऊपर स्‍लाइड करें."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए बाएं स्‍लाइड करें."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"सूचना छिपी हुई है"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d सूचनाएं छिपी हुई हैं"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"दिखाने के लिए स्पर्श करें"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 21d6ef5..646c391 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Pretraživanje"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Kliznite prema gore za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Kliznite lijevo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Obavijest je skrivena"</item>
+    <item quantity="other" msgid="7388721375827338153">"Broj skrivenih obavijesti: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Dodirnite za prikaz"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8e6ee4f..ea1caec 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Keresés"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa felfelé."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa balra."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Értesítés elrejtve"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d értesítés elrejtve"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"A megtekintéshez érintse meg"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index a787983..ca185f6 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Որոնել"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Սահեցրեք վերև <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-ի համար:"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Սահեցրեք ձախ` <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-ի համար:"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Ծանուցումը թաքցված է"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d ծանուցում թաքցված է"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Հպեք՝ ցուցադրելու համար"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 13fc534..d6dacd6 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Telusuri"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Geser ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Geser ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Pemberitahuan disembunyikan"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d pemberitahuan disembunyikan"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Sentuh untuk menampilkan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 289d6c6..5a6d93b 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Ricerca"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Su per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"A sinistra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notifica nascosta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notifiche nascoste"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Tocca per visualizzare"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 798e8c3..3650bfe 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"חיפוש"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"הסט למעלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"הסט שמאלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"ההודעה הוסתרה"</item>
+    <item quantity="other" msgid="7388721375827338153">"‏%d הודעות הוסתרו"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"גע כדי להציג"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index c5070a8..97a3083 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"検索します"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"上にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"左にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"通知が非表示"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d件の通知が非表示"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"表示するにはタップします"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index bbdce19..d893f51 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"ძიება"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"გაასრიალეთ ზემოთ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-თვის."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"გაასრიალეთ მარცხნივ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-თვის."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"შეტყობინება დამალულია"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d შეტყობინება დამალულია"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"შეეხეთ საჩვენებლად"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 61ca77d..ed0b874 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"ស្វែងរក"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"រុញ​ឡើង​លើ​ដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"រុញ​ទៅ​ឆ្វេង​ដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"បាន​លាក់​ការ​ជូនដំណឹង"</item>
+    <item quantity="other" msgid="7388721375827338153">"បាន​លាក់ការ​ជូនដំណឹង %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"ប៉ះ​ដើម្បី​បង្ហាញ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 8108daa..56f0278 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"검색"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 위로 슬라이드"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 왼쪽으로 슬라이드"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"알림 숨김"</item>
+    <item quantity="other" msgid="7388721375827338153">"알림 %d개 숨김"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"표시하려면 터치"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index c2e5990..b0e4b15 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"ຊອກຫາ"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"ເລື່ອນຂຶ້ນເພື່ອ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"ເລື່ອນໄປທາງຊ້າຍເພື່ອ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"ເຊື່ອງ​ການ​ແຈ້ງ​ເຕ​ືອນ​ແລ້ວ"</item>
+    <item quantity="other" msgid="7388721375827338153">"ເຊື່ອງ %d ການ​ແຈ້ງ​ເຕືອນ​ແລ້ວ"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"​ແຕະ​ເພື່ອ​ສະ​ແດງ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 1d8b051..adbba12 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Paieška"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Slyskite aukštyn link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Slyskite į kairę link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Pranešimas paslėptas"</item>
+    <item quantity="other" msgid="7388721375827338153">"Paslėpta pranešimų: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Palieskite, kad būtų rodoma"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 603fa1a..42bdbc8 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Meklēt"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Velciet uz augšu, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Velciet pa kreisi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Paziņojums paslēpts"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d paziņojumi paslēpti"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Pieskarieties, lai rādītu"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 110cfd2..c56d51a 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Хайх"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-г гулсуулах."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> хийх зүүнлүү гулсуулах."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Мэдэгдлийг нуусан"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d мэдэгдлийг нуусан"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Харуулахын тулд хүрнэ үү"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 62c90ab..5ca5082 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Carian"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Luncurkan ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Luncurkan ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Pemberitahuan disembunyikan"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d pemberitahuan disembunyikan"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Sentuh untuk menunjukkan"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 0e914ea..7f4d0d1 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Søk"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Dra opp for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Dra til venstre for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Varselet er skjult"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d varsler er skjult"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Trykk for å vise"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 032fa34..4e1c811 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Zoeken"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Veeg omhoog voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Veeg naar links voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Melding verborgen"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d meldingen verborgen"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Raak aan om weer te geven"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index c21230c..5b360c9 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Szukaj"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Przesuń w górę: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Przesuń w lewo: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Powiadomienie ukryte"</item>
+    <item quantity="other" msgid="7388721375827338153">"Ukryte powiadomienia: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Dotknij, by zobaczyć"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 771daf2..5e182f6 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Deslize para cima para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Deslize para a esquerda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notificação oculta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notificações ocultas"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toque para mostrar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index b643bae..c88faf1 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para cima."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para a esquerda."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notificação oculta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notificações ocultas"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toque para mostrar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 33cb355..7f17a23 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -388,4 +388,8 @@
     <skip />
     <!-- no translation found for description_direction_left (7207478719805562165) -->
     <skip />
+    <!-- no translation found for zen_mode_notification_title:one (7809876956258040354) -->
+    <!-- no translation found for zen_mode_notification_title:other (7388721375827338153) -->
+    <!-- no translation found for zen_mode_notification_text (8336623711388065713) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 87f9c0c..c37fda5 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Căutaţi"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Glisaţi în sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Glisaţi spre stânga pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notificare ascunsă"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d de notificări ascunse"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Atingeți pentru a afișa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index e79a0dd..aff253c 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -213,4 +213,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Поиск"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Проведите вверх, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Проведите влево, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Оповещение скрыто"</item>
+    <item quantity="other" msgid="7388721375827338153">"Скрыто оповещений: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Нажмите, чтобы открыть"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index d39c8bd..5e5ae9b 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Vyhľadávanie"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Prejdite prstom nahor: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Prejdite prstom doľava: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Upozornenie bolo skryté"</item>
+    <item quantity="other" msgid="7388721375827338153">"Skryté upozornenia: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Upozornenie zobrazíte dotykom"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 9d57586..2d562da 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Iskanje"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Povlecite navzgor za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Povlecite v levo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Obvestilo je skrito"</item>
+    <item quantity="other" msgid="7388721375827338153">"Skritih je toliko obvestil: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Dotaknite se za prikaz"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 89bc3c5..97743ad 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Претрага"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Превуците нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Превуците улево за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Обавештење је сакривено"</item>
+    <item quantity="other" msgid="7388721375827338153">"Сакривена обавештења: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Додирните за приказ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 1b47be5..4ce20e9 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Sök"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Dra uppåt för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Dra åt vänster för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Aviseringen har dolts"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d aviseringar har dolts"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Tryck här om du vill visa aviseringar"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 3702196..5b9a4ad 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -207,4 +207,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Tafuta"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Sogeza juu kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Sogeza kushoto kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Arifa imefichwa"</item>
+    <item quantity="other" msgid="7388721375827338153">"Arifa %d zimefichwa"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Gusa ili zionekane"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index b77f1e0..440ead6 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -30,5 +30,5 @@
     <integer name="quick_settings_user_time_settings_tile_span">1</integer>
 
     <!-- Enable the "flip settings" panel -->
-    <bool name="config_hasFlipSettingsPanel">false</bool>
+    <bool name="config_hasFlipSettingsPanel">true</bool>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 45f6af3..b4fafec 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -24,8 +24,8 @@
     <dimen name="notification_panel_margin_left">16dp</dimen>
 
     <!-- Gravity for the notification & quick settings panels -->
-    <!-- 0x800033 = start|top ; 0x800035 = end|top -->
-    <integer name="notification_panel_layout_gravity">0x800033</integer>
+    <!-- 0x31 = top|center_horizontal ; 0x800035 = end|top -->
+    <integer name="notification_panel_layout_gravity">0x31</integer>
     <integer name="settings_panel_layout_gravity">0x800035</integer>
 
     <!-- Diameter of outer shape drawable shown in navbar search-->
@@ -41,9 +41,8 @@
     <dimen name="status_bar_recents_thumbnail_width">200dp</dimen>
     <dimen name="status_bar_recents_thumbnail_height">177dp</dimen>
 
-    <!-- On tablet-sized devices, we allocate the rightmost third(ish) of the draggable status bar
-         to quick settings. -->
-    <item type="dimen" name="settings_panel_dragzone_fraction">35%</item>
+    <!-- On tablets, panels drop from the statusbar instead of overlapping it. -->
+    <dimen name="panel_holder_padding_top">@*android:dimen/status_bar_height</dimen>
 
     <!-- Minimum fraction of the screen that should be taken up by the notification panel. -->
     <item type="dimen" name="notification_panel_min_height_frac">40%</item>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 0188563..74edb61 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"ค้นหา"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"เลื่อนขึ้นเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"เลื่อนไปทางซ้ายเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"ซ่อนการแจ้งเตือนแล้ว"</item>
+    <item quantity="other" msgid="7388721375827338153">"ซ่อน %d การแจ้งเตือนแล้ว"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"แตะเพื่อแสดง"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index d7502cb..3ac4cd5 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Maghanap"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Mag-slide pataas para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Mag-slide pakaliwa para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Nakatago ang notification"</item>
+    <item quantity="other" msgid="7388721375827338153">"Nakatago ang %d (na) notification"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Pindutin upang ipakita"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index f56293b..f38c86a 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Ara"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için yukarı kaydırın."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sola kaydırın."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Bildirim gizli"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d bildirim gizli"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Görüntülemek için dokunun"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index df94b26..54e7ca1 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Пошук"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Проведіть пальцем угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Проведіть пальцем ліворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Сповіщення сховано"</item>
+    <item quantity="other" msgid="7388721375827338153">"Сховано сповіщень: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Торкніться, щоб показати"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 471cbd3..ade5fe1 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Tìm kiếm"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Trượt lên để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Trượt sang trái để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Thông báo ẩn"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d thông báo ẩn"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Chạm để hiển thị"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7fb5868..cbb1496 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"搜索"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"向上滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"向左滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"已隐藏通知"</item>
+    <item quantity="other" msgid="7388721375827338153">"已隐藏%d条通知"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"触摸即可显示"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index d4defa4..b6d438c 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"已隱藏通知"</item>
+    <item quantity="other" msgid="7388721375827338153">"已隱藏 %d 則通知"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"輕觸即可顯示"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 163ef2a..1c4cb4a 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -211,4 +211,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"已隱藏通知"</item>
+    <item quantity="other" msgid="7388721375827338153">"已隱藏 %d 則通知"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"輕觸即可顯示"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 92e3382..cbb6c09 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -209,4 +209,9 @@
     <string name="description_target_search" msgid="3091587249776033139">"Sesha"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Shelelisela ngenhla ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Shelelisela ngakwesokunxele ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Isaziso sifihliwe"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d izaziso zifihliwe"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Thinta ukuze ubonise"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 5cf0453..59e8360 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -31,7 +31,8 @@
     <drawable name="notification_item_background_legacy_color">#ffaaaaaa</drawable>
     <drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
     <drawable name="notification_header_bg">#FF000000</drawable>
-    <color name="notification_panel_scrim_color">#B0000000</color>
+    <color name="notification_panel_scrim_color">#A0000000</color>
+    <color name="notification_panel_scrim_color_keyguard">#80000000</color>
     <color name="batterymeter_frame_color">#66FFFFFF</color><!-- 40% white -->
     <color name="batterymeter_charge_color">#FFFFFFFF</color>
     <color name="batterymeter_bolt_color">#FFFFFFFF</color>
@@ -45,4 +46,7 @@
 
     <!-- Tint color for active Quick Settings icons. -->
     <color name="ic_qs_on">#ffffffff</color>
+
+    <!-- Tint color for the content on the notification overflow card. -->
+    <color name="keyguard_overflow_content_color">#ff666666</color>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 672c1d0..73e3e05 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -114,5 +114,13 @@
     <integer name="recents_filter_animate_new_views_min_duration">125</integer>
     <!-- The min animation duration for animating views that are newly visible. -->
     <integer name="recents_animate_task_bar_enter_duration">200</integer>
+    <!-- The animation duration for animating in the info pane. -->
+    <integer name="recents_animate_task_view_info_pane_duration">150</integer>
+    <!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
+    <integer name="recents_max_task_stack_view_dim">96</integer>
+
+    <!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
+     card. -->
+    <integer name="keyguard_max_notification_count">4</integer>
 </resources>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2c8f9a1..e7959ab 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -83,7 +83,7 @@
     <dimen name="notification_mid_height">128dp</dimen>
 
     <!-- Height of a small notification in the status bar plus glow, padding, etc -->
-    <dimen name="notification_row_min_height">70dp</dimen>
+    <dimen name="notification_row_min_height">68dp</dimen>
 
     <!-- Height of a large notification in the status bar plus glow, padding, etc -->
     <dimen name="notification_row_max_height">260dp</dimen>
@@ -98,7 +98,7 @@
     <dimen name="status_bar_icon_padding">0dp</dimen>
 
     <!-- half the distance between notifications in the panel -->
-    <dimen name="notification_divider_height">3dp</dimen>
+    <dimen name="notification_divider_height">2dp</dimen>
 
     <!-- Notification drawer tuning parameters (phone UI) -->
     <!-- Initial velocity of the shade when expanding on its own -->
@@ -167,6 +167,9 @@
     <!-- Extra space above the clock in the panel -->
     <dimen name="notification_panel_header_padding_top">0dp</dimen>
 
+    <!-- Extra space above the panel holder -->
+    <dimen name="panel_holder_padding_top">0dp</dimen>
+
     <!-- Layout parameters for the notification panel -->
     <dimen name="notification_panel_margin_bottom">0dp</dimen>
     <dimen name="notification_panel_margin_left">0dp</dimen>
@@ -236,6 +239,12 @@
     <!-- The size of the activity icon in the recents task view. -->
     <dimen name="recents_task_view_activity_icon_size">60dp</dimen>
 
+    <!-- The radius of the rounded corners on a task view. -->
+    <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
+
+    <!-- The amount of space a user has to scroll to dismiss any info panes. -->
+    <dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen>
+
     <!-- Used to calculate the translation animation duration, the expected amount of movement 
          in dps over one second of time. -->
     <dimen name="recents_animation_movement_in_dps_per_second">800dp</dimen>
@@ -257,4 +266,7 @@
 
     <!-- Width of the zen mode interstitial dialog. -->
     <dimen name="zen_mode_dialog_width">320dp</dimen>
+
+    <!-- Camera affordance drag distance -->
+    <dimen name="camera_drag_distance">100dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ad10545..73e5e19 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -509,6 +509,8 @@
 
     <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
     <string name="recents_empty_message">RECENTS</string>
+    <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] -->
+    <string name="recents_app_info_button_label">Application Info</string>
 
 
     <!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
@@ -534,4 +536,9 @@
     </plurals>
     <!-- Zen mode: Summary notification content text. [CHAR LIMIT=NONE] -->
     <string name="zen_mode_notification_text">Touch to show</string>
+
+    <!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=12] -->
+    <plurals name="keyguard_more_overflow_text">
+        <item quantity="other">%d more</item>
+    </plurals>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 0ece8e0..8ab646d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -168,5 +168,7 @@
         <!-- Note: must be dp to fit in status bar -->
         <item name="android:textSize">14dp</item>
     </style>
-    
+
+    <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault" />
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
new file mode 100644
index 0000000..0f55683
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -0,0 +1,111 @@
+/*
+ * 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 com.android.systemui;
+
+import android.app.Application;
+import android.content.res.Configuration;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Application class for SystemUI.
+ */
+public class SystemUIApplication extends Application {
+
+    private static final String TAG = "SystemUIService";
+    private static final boolean DEBUG = false;
+
+    /**
+     * The classes of the stuff to start.
+     */
+    private final Class<?>[] SERVICES = new Class[] {
+            com.android.systemui.keyguard.KeyguardViewMediator.class,
+            com.android.systemui.recent.Recents.class,
+            com.android.systemui.statusbar.SystemBars.class,
+            com.android.systemui.usb.StorageNotification.class,
+            com.android.systemui.power.PowerUI.class,
+            com.android.systemui.media.RingtonePlayer.class,
+            com.android.systemui.settings.SettingsUI.class,
+    };
+
+    /**
+     * Hold a reference on the stuff we start.
+     */
+    private final SystemUI[] mServices = new SystemUI[SERVICES.length];
+    private boolean mServicesStarted;
+    private final Map<Class<?>, Object> mComponents = new HashMap<Class<?>, Object>();
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        // Set the application theme that is inherited by all services. Note that setting the
+        // application theme in the manifest does only work for activities. Keep this in sync with
+        // the theme set there.
+        setTheme(R.style.systemui_theme);
+    }
+
+    /**
+     * Makes sure that all the SystemUI services are running. If they are already running, this is a
+     * no-op. This is needed to conditinally start all the services, as we only need to have it in
+     * the main process.
+     *
+     * <p>This method must only be called from the main thread.</p>
+     */
+    public void startServicesIfNeeded() {
+        if (mServicesStarted) {
+            return;
+        }
+        final int N = SERVICES.length;
+        for (int i=0; i<N; i++) {
+            Class<?> cl = SERVICES[i];
+            if (DEBUG) Log.d(TAG, "loading: " + cl);
+            try {
+                mServices[i] = (SystemUI)cl.newInstance();
+            } catch (IllegalAccessException ex) {
+                throw new RuntimeException(ex);
+            } catch (InstantiationException ex) {
+                throw new RuntimeException(ex);
+            }
+            mServices[i].mContext = this;
+            mServices[i].mComponents = mComponents;
+            if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
+            mServices[i].start();
+        }
+        mServicesStarted = true;
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        if (mServicesStarted) {
+            int len = mServices.length;
+            for (int i = 0; i < len; i++) {
+                mServices[i].onConfigurationChanged(newConfig);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T getComponent(Class<T> interfaceType) {
+        return (T) mComponents.get(interfaceType);
+    }
+
+    public SystemUI[] getServices() {
+        return mServices;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index ca5f7d1..05e5f6b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -18,80 +18,35 @@
 
 import android.app.Service;
 import android.content.Intent;
-import android.content.res.Configuration;
 import android.os.IBinder;
-import android.util.Log;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.HashMap;
 
 public class SystemUIService extends Service {
-    private static final String TAG = "SystemUIService";
-
-    /**
-     * The classes of the stuff to start.
-     */
-    private final Class<?>[] SERVICES = new Class[] {
-            com.android.systemui.recent.Recents.class,
-            com.android.systemui.statusbar.SystemBars.class,
-            com.android.systemui.usb.StorageNotification.class,
-            com.android.systemui.power.PowerUI.class,
-            com.android.systemui.media.RingtonePlayer.class,
-            com.android.systemui.settings.SettingsUI.class,
-        };
-
-    /**
-     * Hold a reference on the stuff we start.
-     */
-    private final SystemUI[] mServices = new SystemUI[SERVICES.length];
 
     @Override
     public void onCreate() {
-        HashMap<Class<?>, Object> components = new HashMap<Class<?>, Object>();
-        final int N = SERVICES.length;
-        for (int i=0; i<N; i++) {
-            Class<?> cl = SERVICES[i];
-            Log.d(TAG, "loading: " + cl);
-            try {
-                mServices[i] = (SystemUI)cl.newInstance();
-            } catch (IllegalAccessException ex) {
-                throw new RuntimeException(ex);
-            } catch (InstantiationException ex) {
-                throw new RuntimeException(ex);
-            }
-            mServices[i].mContext = this;
-            mServices[i].mComponents = components;
-            Log.d(TAG, "running: " + mServices[i]);
-            mServices[i].start();
-        }
+        super.onCreate();
+        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
     }
 
     @Override
-    public void onConfigurationChanged(Configuration newConfig) {
-        for (SystemUI ui: mServices) {
-            ui.onConfigurationChanged(newConfig);
-        }
-    }
-
-    /**
-     * Nobody binds to us.
-     */
-    @Override
     public IBinder onBind(Intent intent) {
         return null;
     }
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
         if (args == null || args.length == 0) {
-            for (SystemUI ui: mServices) {
+            for (SystemUI ui: services) {
                 pw.println("dumping service: " + ui.getClass().getName());
                 ui.dump(fd, pw, args);
             }
         } else {
             String svc = args[0];
-            for (SystemUI ui: mServices) {
+            for (SystemUI ui: services) {
                 String name = ui.getClass().getName();
                 if (name.endsWith(svc)) {
                     ui.dump(fd, pw, args);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
similarity index 65%
rename from packages/Keyguard/src/com/android/keyguard/KeyguardService.java
rename to packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 36b2446..41c0e78 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -11,18 +11,13 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.keyguard;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
+package com.android.systemui.keyguard;
 
 import android.app.Service;
 import android.content.Intent;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
@@ -30,23 +25,25 @@
 import android.util.Log;
 import android.view.MotionEvent;
 
-import com.android.internal.policy.IKeyguardService;
 import com.android.internal.policy.IKeyguardExitCallback;
+import com.android.internal.policy.IKeyguardService;
+import com.android.internal.policy.IKeyguardServiceConstants;
 import com.android.internal.policy.IKeyguardShowCallback;
-import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.SystemUIApplication;
+
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 public class KeyguardService extends Service {
     static final String TAG = "KeyguardService";
     static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
+
     private KeyguardViewMediator mKeyguardViewMediator;
 
     @Override
     public void onCreate() {
-        if (mKeyguardViewMediator == null) {
-            mKeyguardViewMediator = new KeyguardViewMediator(
-                    KeyguardService.this, new LockPatternUtils(KeyguardService.this));
-        }
-        Log.v(TAG, "onCreate()");
+        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
+        mKeyguardViewMediator =
+                ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
     }
 
     @Override
@@ -54,11 +51,6 @@
         return mBinder;
     }
 
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        // TODO
-    }
-
     void checkPermission() {
         if (getBaseContext().checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
             Log.w(TAG, "Caller needs permission '" + PERMISSION + "' to call " + Debug.getCaller());
@@ -68,84 +60,148 @@
     }
 
     private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
+
+        private boolean mIsOccluded;
+
+        @Override
         public boolean isShowing() {
             return mKeyguardViewMediator.isShowing();
         }
+
+        @Override
         public boolean isSecure() {
             return mKeyguardViewMediator.isSecure();
         }
-        public boolean isShowingAndNotHidden() {
-            return mKeyguardViewMediator.isShowingAndNotHidden();
+
+        @Override
+        public boolean isShowingAndNotOccluded() {
+            return mKeyguardViewMediator.isShowingAndNotOccluded();
         }
+
+        @Override
         public boolean isInputRestricted() {
             return mKeyguardViewMediator.isInputRestricted();
         }
+
+        @Override
         public void verifyUnlock(IKeyguardExitCallback callback) {
+            checkPermission();
             mKeyguardViewMediator.verifyUnlock(callback);
         }
+
+        @Override
         public void keyguardDone(boolean authenticated, boolean wakeup) {
             checkPermission();
             mKeyguardViewMediator.keyguardDone(authenticated, wakeup);
         }
-        public void setHidden(boolean isHidden) {
+
+        @Override
+        public int setOccluded(boolean isOccluded) {
             checkPermission();
-            mKeyguardViewMediator.setHidden(isHidden);
+            synchronized (this) {
+                int result;
+                if (isOccluded && mKeyguardViewMediator.isShowing()
+                        && !mIsOccluded) {
+                    result = IKeyguardServiceConstants
+                            .KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS;
+                } else if (!isOccluded && mKeyguardViewMediator.isShowing()
+                        && mIsOccluded) {
+                    result = IKeyguardServiceConstants
+                            .KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS;
+                } else {
+                    result = IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE;
+                }
+                if (mIsOccluded != isOccluded) {
+                    mKeyguardViewMediator.setOccluded(isOccluded);
+
+                    // Cache the value so we always have a fresh view in whether Keyguard is occluded.
+                    // If we would just call mKeyguardViewMediator.isOccluded(), this might be stale
+                    // because that value gets updated in another thread.
+                    mIsOccluded = isOccluded;
+                }
+                return result;
+            }
         }
+
+        @Override
         public void dismiss() {
+            checkPermission();
             mKeyguardViewMediator.dismiss();
         }
+
+        @Override
         public void onDreamingStarted() {
             checkPermission();
             mKeyguardViewMediator.onDreamingStarted();
         }
+
+        @Override
         public void onDreamingStopped() {
             checkPermission();
             mKeyguardViewMediator.onDreamingStopped();
         }
+
+        @Override
         public void onScreenTurnedOff(int reason) {
             checkPermission();
             mKeyguardViewMediator.onScreenTurnedOff(reason);
         }
+
+        @Override
         public void onScreenTurnedOn(IKeyguardShowCallback callback) {
             checkPermission();
             mKeyguardViewMediator.onScreenTurnedOn(callback);
         }
+
+        @Override
         public void setKeyguardEnabled(boolean enabled) {
             checkPermission();
             mKeyguardViewMediator.setKeyguardEnabled(enabled);
         }
+
+        @Override
         public boolean isDismissable() {
             return mKeyguardViewMediator.isDismissable();
         }
+
+        @Override
         public void onSystemReady() {
             checkPermission();
             mKeyguardViewMediator.onSystemReady();
         }
+
+        @Override
         public void doKeyguardTimeout(Bundle options) {
             checkPermission();
             mKeyguardViewMediator.doKeyguardTimeout(options);
         }
+
+        @Override
         public void setCurrentUser(int userId) {
             checkPermission();
             mKeyguardViewMediator.setCurrentUser(userId);
         }
+
+        @Override
         public void showAssistant() {
             checkPermission();
-            mKeyguardViewMediator.showAssistant();
         }
+
+        @Override
         public void dispatch(MotionEvent event) {
             checkPermission();
-            mKeyguardViewMediator.dispatch(event);
         }
+
+        @Override
         public void launchCamera() {
             checkPermission();
-            mKeyguardViewMediator.launchCamera();
         }
+
+        @Override
         public void onBootCompleted() {
             checkPermission();
             mKeyguardViewMediator.onBootCompleted();
         }
     };
-
 }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
similarity index 85%
rename from packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
rename to packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 354d13f..bb39d36 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 The Android Open Source Project
+ * 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.
@@ -11,15 +11,10 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.keyguard;
-
-import com.android.internal.policy.IKeyguardExitCallback;
-import com.android.internal.policy.IKeyguardShowCallback;
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
+package com.android.systemui.keyguard;
 
 import android.app.Activity;
 import android.app.ActivityManagerNative;
@@ -50,17 +45,31 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
-import android.view.MotionEvent;
+import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 
+import com.android.internal.policy.IKeyguardExitCallback;
+import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.analytics.Session;
+import com.android.keyguard.KeyguardDisplayManager;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.MultiUserAvatarCache;
+import com.android.keyguard.ViewMediatorCallback;
 import com.android.keyguard.analytics.KeyguardAnalytics;
+import com.android.keyguard.analytics.Session;
+import com.android.systemui.SystemUI;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowManager;
 
 import java.io.File;
 
+import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
+
 
 /**
  * Mediates requests related to the keyguard.  This includes queries about the
@@ -95,15 +104,15 @@
  * false, this will override all other conditions for turning on the keyguard.
  *
  * Threading and synchronization:
- * This class is created by the initialization routine of the {@link WindowManagerPolicy},
+ * This class is created by the initialization routine of the {@link android.view.WindowManagerPolicy},
  * and runs on its thread.  The keyguard UI is created from that thread in the
  * constructor of this class.  The apis may be called from other threads, including the
  * {@link com.android.server.input.InputManagerService}'s and {@link android.view.WindowManager}'s.
  * Therefore, methods on this class are synchronized, and any action that is pointed
- * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI
+ * directly to the keyguard UI is posted to a {@link android.os.Handler} to ensure it is taken on the UI
  * thread of the keyguard.
  */
-public class KeyguardViewMediator {
+public class KeyguardViewMediator extends SystemUI {
     private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
     final static boolean DEBUG = false;
     private static final boolean ENABLE_ANALYTICS = Build.IS_DEBUGGABLE;
@@ -124,17 +133,14 @@
     private static final int KEYGUARD_DONE = 9;
     private static final int KEYGUARD_DONE_DRAWING = 10;
     private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
-    private static final int SET_HIDDEN = 12;
+    private static final int SET_OCCLUDED = 12;
     private static final int KEYGUARD_TIMEOUT = 13;
-    private static final int SHOW_ASSISTANT = 14;
-    private static final int DISPATCH_EVENT = 15;
-    private static final int LAUNCH_CAMERA = 16;
     private static final int DISMISS = 17;
 
     /**
      * The default amount of time we stay awake (used for all key input)
      */
-    protected static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
+    public static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
 
     /**
      * How long to wait after the screen turns off due to timeout before
@@ -158,13 +164,13 @@
 
     /**
      * Allow the user to expand the status bar when a SECURE keyguard is engaged
-     * and {@link Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS} is set
+     * and {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS} is set
      * (private notifications will be masked).
      */
     private static final boolean ENABLE_SECURE_STATUS_BAR_EXPAND = true;
 
     /**
-     * Default value of {@link Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
+     * Default value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
      */
     private static final boolean ALLOW_NOTIFICATIONS_DEFAULT = false;
 
@@ -176,7 +182,6 @@
     /** The stream type that the lock sounds are tied to. */
     private int mMasterStreamType;
 
-    private Context mContext;
     private AlarmManager mAlarmManager;
     private AudioManager mAudioManager;
     private StatusBarManager mStatusBarManager;
@@ -204,9 +209,9 @@
      */
     private PowerManager.WakeLock mShowKeyguardWakeLock;
 
-    private KeyguardViewManager mKeyguardViewManager;
+    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
-    private final KeyguardAnalytics mKeyguardAnalytics;
+    private KeyguardAnalytics mKeyguardAnalytics;
 
     // these are protected by synchronized (this)
 
@@ -227,7 +232,7 @@
     private boolean mShowing;
 
     // true if the keyguard is hidden by another window
-    private boolean mHidden = false;
+    private boolean mOccluded = false;
 
     /**
      * Helps remember whether the screen has turned on since the last time
@@ -272,79 +277,20 @@
     private int mLockSoundStreamId;
 
     /**
-     * Tracks value of {@link Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
+     * Tracks value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
      */
     private boolean mAllowNotificationsWhenSecure;
 
     /**
      * The volume applied to the lock/unlock sounds.
      */
-    private final float mLockSoundVolume;
+    private float mLockSoundVolume;
 
     /**
      * For managing external displays
      */
     private KeyguardDisplayManager mKeyguardDisplayManager;
 
-    /**
-     * Cache of avatar drawables, for use by KeyguardMultiUserAvatar.
-     */
-    private static MultiUserAvatarCache sMultiUserAvatarCache = new MultiUserAvatarCache();
-
-    /**
-     * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
-     * various things.
-     */
-    public interface ViewMediatorCallback {
-        /**
-         * Reports user activity and requests that the screen stay on.
-         */
-        void userActivity();
-
-        /**
-         * Reports user activity and requests that the screen stay on for at least
-         * the specified amount of time.
-         * @param millis The amount of time in millis.  This value is currently ignored.
-         */
-        void userActivity(long millis);
-
-        /**
-         * Report that the keyguard is done.
-         * @param authenticated Whether the user securely got past the keyguard.
-         *   the only reason for this to be false is if the keyguard was instructed
-         *   to appear temporarily to verify the user is supposed to get past the
-         *   keyguard, and the user fails to do so.
-         */
-        void keyguardDone(boolean authenticated);
-
-        /**
-         * Report that the keyguard is done drawing.
-         */
-        void keyguardDoneDrawing();
-
-        /**
-         * Tell ViewMediator that the current view needs IME input
-         * @param needsInput
-         */
-        void setNeedsInput(boolean needsInput);
-
-        /**
-         * Tell view mediator that the keyguard view's desired user activity timeout
-         * has changed and needs to be reapplied to the window.
-         */
-        void onUserActivityTimeoutChanged();
-
-        /**
-         * Report that the keyguard is dismissable, pending the next keyguardDone call.
-         */
-        void keyguardDonePending();
-
-        /**
-         * Report when keyguard is actually gone
-         */
-        void keyguardGone();
-    }
-
     KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
@@ -354,7 +300,7 @@
             // ActivityManagerService) will not reconstruct the keyguard if it is already showing.
             synchronized (KeyguardViewMediator.this) {
                 mSwitchingUser = true;
-                resetStateLocked(null);
+                resetStateLocked();
                 adjustStatusBarLocked();
                 // When we switch users we want to bring the new user to the biometric unlock even
                 // if the current user has gone to the backup.
@@ -370,16 +316,16 @@
         @Override
         public void onUserRemoved(int userId) {
             mLockPatternUtils.removeUser(userId);
-            sMultiUserAvatarCache.clear(userId);
+            MultiUserAvatarCache.getInstance().clear(userId);
         }
 
         @Override
         public void onUserInfoChanged(int userId) {
-            sMultiUserAvatarCache.clear(userId);
+            MultiUserAvatarCache.getInstance().clear(userId);
         }
 
         @Override
-        void onPhoneStateChanged(int phoneState) {
+        public void onPhoneStateChanged(int phoneState) {
             synchronized (KeyguardViewMediator.this) {
                 if (TelephonyManager.CALL_STATE_IDLE == phoneState  // call ending
                         && !mScreenOn                           // screen off
@@ -394,7 +340,7 @@
                     doKeyguardLocked(null);
                 }
             }
-        };
+        }
 
         @Override
         public void onClockVisibilityChanged() {
@@ -423,7 +369,7 @@
                                         + "device isn't provisioned yet.");
                                 doKeyguardLocked(null);
                             } else {
-                                resetStateLocked(null);
+                                resetStateLocked();
                             }
                         }
                     }
@@ -436,7 +382,7 @@
                                     + "showing; need to show keyguard so user can enter sim pin");
                             doKeyguardLocked(null);
                         } else {
-                            resetStateLocked(null);
+                            resetStateLocked();
                         }
                     }
                     break;
@@ -449,14 +395,14 @@
                         } else {
                             if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
                                   + "show permanently disabled message in lockscreen.");
-                            resetStateLocked(null);
+                            resetStateLocked();
                         }
                     }
                     break;
                 case READY:
                     synchronized (this) {
                         if (isShowing()) {
-                            resetStateLocked(null);
+                            resetStateLocked();
                         }
                     }
                     break;
@@ -466,6 +412,7 @@
     };
 
     ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
+
         public void userActivity() {
             KeyguardViewMediator.this.userActivity();
         }
@@ -484,12 +431,12 @@
 
         @Override
         public void setNeedsInput(boolean needsInput) {
-            mKeyguardViewManager.setNeedsInput(needsInput);
+            mStatusBarKeyguardViewManager.setNeedsInput(needsInput);
         }
 
         @Override
         public void onUserActivityTimeoutChanged() {
-            mKeyguardViewManager.updateUserActivityTimeout();
+            mStatusBarKeyguardViewManager.updateUserActivityTimeout();
         }
 
         @Override
@@ -513,40 +460,34 @@
         mPM.userActivity(SystemClock.uptimeMillis(), false);
     }
 
-    /**
-     * Construct a KeyguardViewMediator
-     * @param context
-     * @param lockPatternUtils optional mock interface for LockPatternUtils
-     */
-    public KeyguardViewMediator(Context context, LockPatternUtils lockPatternUtils) {
-        mContext = context;
-        mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+    private void setup() {
+        mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
         mShowKeyguardWakeLock.setReferenceCounted(false);
 
         mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
 
-        mKeyguardDisplayManager = new KeyguardDisplayManager(context);
+        mKeyguardDisplayManager = new KeyguardDisplayManager(mContext);
 
-        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
 
-        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
+        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
 
-        mLockPatternUtils = lockPatternUtils != null
-                ? lockPatternUtils : new LockPatternUtils(mContext);
+        mLockPatternUtils = new LockPatternUtils(mContext);
         mLockPatternUtils.setCurrentUser(UserHandle.USER_OWNER);
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure...
         mShowing = (mUpdateMonitor.isDeviceProvisioned() || mLockPatternUtils.isSecure())
                 && !mLockPatternUtils.isLockScreenDisabled();
 
-        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+        mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
+                mViewMediatorCallback, mLockPatternUtils);
         final ContentResolver cr = mContext.getContentResolver();
 
         if (ENABLE_ANALYTICS && !LockPatternUtils.isSafeModeEnabled() &&
                 Settings.Secure.getInt(cr, KEYGUARD_ANALYTICS_SETTING, 0) == 1) {
-            mKeyguardAnalytics = new KeyguardAnalytics(context, new SessionTypeAdapter() {
+            mKeyguardAnalytics = new KeyguardAnalytics(mContext, new SessionTypeAdapter() {
 
                 @Override
                 public int getSessionType() {
@@ -559,9 +500,6 @@
         } else {
             mKeyguardAnalytics = null;
         }
-        mKeyguardViewManager = new KeyguardViewManager(context, wm, mViewMediatorCallback,
-                mLockPatternUtils,
-                mKeyguardAnalytics != null ? mKeyguardAnalytics.getCallback() : null);
 
         mScreenOn = mPM.isScreenOn();
 
@@ -580,11 +518,17 @@
         if (soundPath == null || mUnlockSoundId == 0) {
             Log.w(TAG, "failed to load unlock sound from " + soundPath);
         }
-        int lockSoundDefaultAttenuation = context.getResources().getInteger(
+        int lockSoundDefaultAttenuation = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lockSoundVolumeDb);
         mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
     }
 
+    @Override
+    public void start() {
+        setup();
+        putComponent(KeyguardViewMediator.class, this);
+    }
+
     /**
      * Let us know that the system is ready after startup.
      */
@@ -621,9 +565,9 @@
 
     /**
      * Called to let us know the screen was turned off.
-     * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
-     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
-     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
+     * @param why either {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_USER},
+     *   {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
+     *   {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
      */
     public void onScreenTurnedOff(int why) {
         synchronized (this) {
@@ -651,7 +595,7 @@
                 }
             } else if (mShowing) {
                 notifyScreenOffLocked();
-                resetStateLocked(null);
+                resetStateLocked();
             } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
                    || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
                 doKeyguardLaterLocked();
@@ -768,7 +712,7 @@
     }
 
     /**
-     * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide
+     * Same semantics as {@link android.view.WindowManagerPolicy#enableKeyguard}; provide
      * a way for external stuff to override normal keyguard behavior.  For instance
      * the phone app disables the keyguard when it receives incoming calls.
      */
@@ -805,7 +749,7 @@
                         Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
                     }
                     mExitSecureCallback = null;
-                    resetStateLocked(null);
+                    resetStateLocked();
                 } else {
                     showLocked(null);
 
@@ -873,36 +817,41 @@
         return mShowing;
     }
 
-    /**
-     * Is the keyguard currently showing and not being force hidden?
-     */
-    public boolean isShowingAndNotHidden() {
-        return mShowing && !mHidden;
+    public boolean isOccluded() {
+        return mOccluded;
     }
 
     /**
-     * Notify us when the keyguard is hidden by another window
+     * Is the keyguard currently showing and not being force hidden?
      */
-    public void setHidden(boolean isHidden) {
-        if (DEBUG) Log.d(TAG, "setHidden " + isHidden);
-        mUpdateMonitor.sendKeyguardVisibilityChanged(!isHidden);
-        mHandler.removeMessages(SET_HIDDEN);
-        Message msg = mHandler.obtainMessage(SET_HIDDEN, (isHidden ? 1 : 0), 0);
+    public boolean isShowingAndNotOccluded() {
+        return mShowing && !mOccluded;
+    }
+
+    /**
+     * Notify us when the keyguard is occluded by another window
+     */
+    public void setOccluded(boolean isOccluded) {
+        if (DEBUG) Log.d(TAG, "setOccluded " + isOccluded);
+        mUpdateMonitor.sendKeyguardVisibilityChanged(!isOccluded);
+        mHandler.removeMessages(SET_OCCLUDED);
+        Message msg = mHandler.obtainMessage(SET_OCCLUDED, (isOccluded ? 1 : 0), 0);
         mHandler.sendMessage(msg);
     }
 
     /**
-     * Handles SET_HIDDEN message sent by setHidden()
+     * Handles SET_OCCLUDED message sent by setOccluded()
      */
-    private void handleSetHidden(boolean isHidden) {
+    private void handleSetOccluded(boolean isOccluded) {
         synchronized (KeyguardViewMediator.this) {
-            if (mHidden != isHidden) {
-                mHidden = isHidden;
+            if (mOccluded != isOccluded) {
+                mOccluded = isOccluded;
+                mStatusBarKeyguardViewManager.setOccluded(isOccluded);
                 updateActivityLockScreenState();
                 adjustStatusBarLocked();
             }
             if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
-                mKeyguardAnalytics.getCallback().onSetHidden(isHidden);
+                mKeyguardAnalytics.getCallback().onSetOccluded(isOccluded);
             }
         }
     }
@@ -954,7 +903,7 @@
                         ALLOW_NOTIFICATIONS_DEFAULT ? 1 : 0);
 
         // if the keyguard is already showing, don't bother
-        if (mKeyguardViewManager.isShowing()) {
+        if (mStatusBarKeyguardViewManager.isShowing()) {
             if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
             return;
         }
@@ -996,8 +945,8 @@
      * Dismiss the keyguard through the security layers.
      */
     public void handleDismiss() {
-        if (mShowing && !mHidden) {
-            mKeyguardViewManager.dismiss();
+        if (mShowing && !mOccluded) {
+            mStatusBarKeyguardViewManager.dismiss();
         }
     }
 
@@ -1007,12 +956,11 @@
 
     /**
      * Send message to keyguard telling it to reset its state.
-     * @param options options about how to show the keyguard
-     * @see #handleReset()
+     * @see #handleReset
      */
-    private void resetStateLocked(Bundle options) {
+    private void resetStateLocked() {
         if (DEBUG) Log.e(TAG, "resetStateLocked");
-        Message msg = mHandler.obtainMessage(RESET, options);
+        Message msg = mHandler.obtainMessage(RESET);
         mHandler.sendMessage(msg);
     }
 
@@ -1038,7 +986,7 @@
 
     /**
      * Send a message to keyguard telling it the screen just turned on.
-     * @see #onScreenTurnedOn()
+     * @see #onScreenTurnedOn
      * @see #handleNotifyScreenOn
      */
     private void notifyScreenOnLocked(IKeyguardShowCallback result) {
@@ -1049,7 +997,7 @@
 
     /**
      * Send message to keyguard telling it to show itself
-     * @see #handleShow()
+     * @see #handleShow
      */
     private void showLocked(Bundle options) {
         if (DEBUG) Log.d(TAG, "showLocked");
@@ -1130,7 +1078,7 @@
                     handleHide();
                     break;
                 case RESET:
-                    handleReset((Bundle) msg.obj);
+                    handleReset();
                     break;
                 case VERIFY_UNLOCK:
                     handleVerifyUnlock();
@@ -1150,23 +1098,14 @@
                 case KEYGUARD_DONE_AUTHENTICATING:
                     keyguardDone(true, true);
                     break;
-                case SET_HIDDEN:
-                    handleSetHidden(msg.arg1 != 0);
+                case SET_OCCLUDED:
+                    handleSetOccluded(msg.arg1 != 0);
                     break;
                 case KEYGUARD_TIMEOUT:
                     synchronized (KeyguardViewMediator.this) {
                         doKeyguardLocked((Bundle) msg.obj);
                     }
                     break;
-                case SHOW_ASSISTANT:
-                    handleShowAssistant();
-                    break;
-                case DISPATCH_EVENT:
-                    handleDispatchEvent((MotionEvent) msg.obj);
-                    break;
-                case LAUNCH_CAMERA:
-                    handleLaunchCamera();
-                    break;
                 case DISMISS:
                     handleDismiss();
                     break;
@@ -1206,21 +1145,13 @@
         sendUserPresentBroadcast();
     }
 
-    protected void handleLaunchCamera() {
-        mKeyguardViewManager.launchCamera();
-    }
-
-    protected void handleDispatchEvent(MotionEvent event) {
-        mKeyguardViewManager.dispatch(event);
-    }
-
     private void sendUserPresentBroadcast() {
         final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
         mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, currentUser);
     }
 
     /**
-     * @see #keyguardDoneDrawing
+     * @see #keyguardDone
      * @see #KEYGUARD_DONE_DRAWING
      */
     private void handleKeyguardDoneDrawing() {
@@ -1269,7 +1200,7 @@
 
     private void updateActivityLockScreenState() {
         try {
-            ActivityManagerNative.getDefault().setLockScreenShown(mShowing && !mHidden);
+            ActivityManagerNative.getDefault().setLockScreenShown(mShowing && !mOccluded);
         } catch (RemoteException e) {
         }
     }
@@ -1287,16 +1218,12 @@
                 if (DEBUG) Log.d(TAG, "handleShow");
             }
 
-            mKeyguardViewManager.show(options);
+            mStatusBarKeyguardViewManager.show(options);
             mShowing = true;
             mKeyguardDonePending = false;
             updateActivityLockScreenState();
             adjustStatusBarLocked();
             userActivity();
-            try {
-                ActivityManagerNative.getDefault().closeSystemDialogs("lock");
-            } catch (RemoteException e) {
-            }
 
             // Do this at the end to not slow down display of the keyguard.
             playSounds(true);
@@ -1320,7 +1247,7 @@
                 playSounds(false);
             }
 
-            mKeyguardViewManager.hide();
+            mStatusBarKeyguardViewManager.hide();
             mShowing = false;
             mKeyguardDonePending = false;
             updateActivityLockScreenState();
@@ -1360,7 +1287,7 @@
             }
 
             if (DEBUG) {
-                Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
+                Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mOccluded=" + mOccluded
                         + " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
             }
 
@@ -1371,17 +1298,13 @@
     }
 
     /**
-     * Handle message sent by {@link #resetStateLocked(Bundle)}
+     * Handle message sent by {@link #resetStateLocked}
      * @see #RESET
      */
-    private void handleReset(Bundle options) {
-        if (options == null) {
-            options = new Bundle();
-        }
-        options.putBoolean(KeyguardViewManager.IS_SWITCHING_USER, mSwitchingUser);
+    private void handleReset() {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleReset");
-            mKeyguardViewManager.reset(options);
+            mStatusBarKeyguardViewManager.reset();
         }
     }
 
@@ -1392,7 +1315,7 @@
     private void handleVerifyUnlock() {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
-            mKeyguardViewManager.verifyUnlock();
+            mStatusBarKeyguardViewManager.verifyUnlock();
             mShowing = true;
             updateActivityLockScreenState();
         }
@@ -1405,18 +1328,18 @@
     private void handleNotifyScreenOff() {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleNotifyScreenOff");
-            mKeyguardViewManager.onScreenTurnedOff();
+            mStatusBarKeyguardViewManager.onScreenTurnedOff();
         }
     }
 
     /**
-     * Handle message sent by {@link #notifyScreenOnLocked()}
+     * Handle message sent by {@link #notifyScreenOnLocked}
      * @see #NOTIFY_SCREEN_ON
      */
     private void handleNotifyScreenOn(IKeyguardShowCallback callback) {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
-            mKeyguardViewManager.onScreenTurnedOn(callback);
+            mStatusBarKeyguardViewManager.onScreenTurnedOn(callback);
         }
     }
 
@@ -1424,35 +1347,23 @@
         return mKeyguardDonePending || !isSecure();
     }
 
-    public void showAssistant() {
-        Message msg = mHandler.obtainMessage(SHOW_ASSISTANT);
-        mHandler.sendMessage(msg);
-    }
-
-    public void handleShowAssistant() {
-        mKeyguardViewManager.showAssistant();
-    }
-
     private boolean isAssistantAvailable() {
         return mSearchManager != null
                 && mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
     }
 
-    public static MultiUserAvatarCache getAvatarCache() {
-        return sMultiUserAvatarCache;
-    }
-
-    public void dispatch(MotionEvent event) {
-        Message msg = mHandler.obtainMessage(DISPATCH_EVENT, event);
-        mHandler.sendMessage(msg);
-    }
-
-    public void launchCamera() {
-        Message msg = mHandler.obtainMessage(LAUNCH_CAMERA);
-        mHandler.sendMessage(msg);
-    }
-
     public void onBootCompleted() {
         mUpdateMonitor.dispatchBootCompleted();
     }
+
+    public StatusBarKeyguardViewManager registerStatusBar(PhoneStatusBar phoneStatusBar,
+            ViewGroup container, StatusBarWindowManager statusBarWindowManager) {
+        mStatusBarKeyguardViewManager.registerStatusBar(phoneStatusBar, container,
+                statusBarWindowManager);
+        return mStatusBarKeyguardViewManager;
+    }
+
+    public ViewMediatorCallback getViewMediatorCallback() {
+        return mViewMediatorCallback;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index cde17f5e..64770a4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -28,8 +28,9 @@
         public static class App {
             public static final boolean EnableTaskFiltering = true;
             public static final boolean EnableTaskStackClipping = false;
-            public static final boolean EnableToggleNewRecentsActivity = false;
-            // This disables the bitmap and icon caches to
+            public static final boolean EnableInfoPane = true;
+
+            // This disables the bitmap and icon caches
             public static final boolean DisableBackgroundCache = false;
             // For debugging, this enables us to create mock recents tasks
             public static final boolean EnableSystemServicesProxy = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index f61c28c..71c45f2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -50,11 +50,7 @@
             String action = intent.getAction();
             Console.log(Constants.DebugFlags.App.SystemUIHandshake,
                     "[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
-            if (action.equals(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY)) {
-                if (Constants.DebugFlags.App.EnableToggleNewRecentsActivity) {
-                    finish();
-                }
-            } else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
+            if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
                 // Try and unfilter and filtered stacks
                 if (!mRecentsView.unfilterFilteredStacks()) {
                     // If there are no filtered stacks, dismiss recents and launch the first task
@@ -97,6 +93,12 @@
             getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
         } else {
             mEmptyView.setVisibility(View.GONE);
+
+            // Un-dim the background
+            WindowManager.LayoutParams wlp = getWindow().getAttributes();
+            wlp.dimAmount = 0f;
+            getWindow().setAttributes(wlp);
+            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
         }
     }
 
@@ -190,7 +192,6 @@
         // Register the broadcast receiver to handle messages from our service
         IntentFilter filter = new IntentFilter();
         filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
-        filter.addAction(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY);
         registerReceiver(mServiceBroadcastReceiver, filter);
 
         // Register the broadcast receiver to handle messages when the screen is turned off
@@ -224,11 +225,6 @@
                 Console.AnsiRed);
         super.onStop();
 
-        // Finish the current recents activity after we have launched a task
-        if (mTaskLaunched && Constants.DebugFlags.App.EnableToggleNewRecentsActivity) {
-            finish();
-        }
-
         mVisible = false;
         mTaskLaunched = false;
     }
@@ -250,8 +246,18 @@
 
     @Override
     public void onBackPressed() {
-        if (!mRecentsView.unfilterFilteredStacks()) {
-            super.onBackPressed();
+        boolean interceptedByInfoPanelClose = false;
+
+        // Try and return from any open info panes
+        if (Constants.DebugFlags.App.EnableInfoPane) {
+            interceptedByInfoPanelClose = mRecentsView.closeOpenInfoPanes();
+        }
+
+        // If we haven't been intercepted already, then unfilter any stacks
+        if (!interceptedByInfoPanelClose) {
+            if (!mRecentsView.unfilterFilteredStacks()) {
+                super.onBackPressed();
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 8949663..5e5b841 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -40,6 +40,10 @@
     public int filteringCurrentViewsMinAnimDuration;
     public int filteringNewViewsMinAnimDuration;
     public int taskBarEnterAnimDuration;
+    public int taskStackScrollDismissInfoPaneDistance;
+    public int taskStackMaxDim;
+    public int taskViewInfoPaneAnimDuration;
+    public int taskViewRoundedCornerRadiusPx;
 
     public boolean launchedWithThumbnailAnimation;
 
@@ -81,6 +85,13 @@
                 res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
         taskBarEnterAnimDuration =
                 res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
+        taskStackScrollDismissInfoPaneDistance = res.getDimensionPixelSize(
+                R.dimen.recents_task_stack_scroll_dismiss_info_pane_distance);
+        taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
+        taskViewInfoPaneAnimDuration =
+                res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
+        taskViewRoundedCornerRadiusPx =
+                res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
     }
 
     /** Updates the system insets */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index f78a999..06ca9e2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -112,7 +112,6 @@
 
 /* Service */
 public class RecentsService extends Service {
-    final static String ACTION_FINISH_RECENTS_ACTIVITY = "action_finish_recents_activity";
     final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
 
     Messenger mSystemUIMessenger = new Messenger(new SystemUIMessageHandler(this));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index ec28379..b054a22 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -17,13 +17,16 @@
 package com.android.systemui.recents.views;
 
 import android.app.ActivityOptions;
+import android.app.TaskStackBuilder;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.net.Uri;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.view.View;
 import android.widget.FrameLayout;
 import com.android.systemui.recents.Console;
@@ -179,6 +182,21 @@
         return true;
     }
 
+    /** Closes any open info panes */
+    public boolean closeOpenInfoPanes() {
+        if (mBSP != null) {
+            // Get the first stack view
+            int childCount = getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                TaskStackView stackView = (TaskStackView) getChildAt(i);
+                if (stackView.closeOpenInfoPanes()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     /** Unfilters any filtered stacks */
     public boolean unfilterFilteredStacks() {
         if (mBSP != null) {
@@ -206,6 +224,9 @@
             mCb.onTaskLaunching();
         }
 
+        // Close any open info panes
+        closeOpenInfoPanes();
+
         final Runnable launchRunnable = new Runnable() {
             @Override
             public void run() {
@@ -283,4 +304,15 @@
             tv.animateOnLeavingRecents(launchRunnable);
         }
     }
+
+    @Override
+    public void onTaskAppInfoLaunched(Task t) {
+        // Create a new task stack with the application info details activity
+        Intent baseIntent = t.key.baseIntent;
+        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+                Uri.fromParts("package", baseIntent.getComponent().getPackageName(), null));
+        intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
+        TaskStackBuilder.create(getContext())
+                .addNextIntentWithParentStack(intent).startActivities();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
new file mode 100644
index 0000000..233e38c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
@@ -0,0 +1,163 @@
+/*
+ * 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 com.android.systemui.recents.views;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import com.android.systemui.R;
+import com.android.systemui.recents.BakedBezierInterpolator;
+import com.android.systemui.recents.Utilities;
+
+
+/* The task info view */
+class TaskInfoView extends FrameLayout {
+
+    Button mAppInfoButton;
+
+    // Circular clip animation
+    boolean mCircularClipEnabled;
+    Path mClipPath = new Path();
+    float mClipRadius;
+    float mMaxClipRadius;
+    Point mClipOrigin = new Point();
+    ObjectAnimator mCircularClipAnimator;
+
+    public TaskInfoView(Context context) {
+        this(context, null);
+    }
+
+    public TaskInfoView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        // Initialize the buttons on the info panel
+        mAppInfoButton = (Button) findViewById(R.id.task_view_app_info_button);
+    }
+
+    /** Updates the positions of each of the items to fit in the rect specified */
+    void updateContents(Rect visibleRect) {
+        // Offset the app info button
+        LayoutParams lp = (LayoutParams) mAppInfoButton.getLayoutParams();
+        lp.topMargin = visibleRect.top +
+                (visibleRect.height() - mAppInfoButton.getMeasuredHeight()) / 2;
+        requestLayout();
+    }
+
+    /** Sets the circular clip radius on this panel */
+    public void setCircularClipRadius(float r) {
+        mClipRadius = r;
+        invalidate();
+    }
+
+    /** Gets the circular clip radius on this panel */
+    public float getCircularClipRadius() {
+        return mClipRadius;
+    }
+
+    /** Animates the circular clip radius on the icon */
+    void animateCircularClip(Point o, float fromRadius, float toRadius,
+                             final Runnable postRunnable, boolean animateInContent) {
+        if (mCircularClipAnimator != null) {
+            mCircularClipAnimator.cancel();
+        }
+
+        // Calculate the max clip radius to each of the corners
+        int w = getMeasuredWidth() - o.x;
+        int h = getMeasuredHeight() - o.y;
+        // origin to tl, tr, br, bl
+        mMaxClipRadius = (int) Math.ceil(Math.sqrt(o.x * o.x + o.y * o.y));
+        mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + o.y * o.y)));
+        mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + h * h)));
+        mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(o.x * o.x + h * h)));
+
+        mClipOrigin.set(o.x, o.y);
+        mClipRadius = fromRadius;
+        int duration = Utilities.calculateTranslationAnimationDuration((int) mMaxClipRadius);
+        mCircularClipAnimator = ObjectAnimator.ofFloat(this, "circularClipRadius", toRadius);
+        mCircularClipAnimator.setDuration(duration);
+        mCircularClipAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+        mCircularClipAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mCircularClipEnabled = false;
+                if (postRunnable != null) {
+                    postRunnable.run();
+                }
+            }
+        });
+        mCircularClipAnimator.start();
+        mCircularClipEnabled = true;
+
+        if (animateInContent) {
+            animateAppInfoButtonIn(duration);
+        }
+    }
+
+    /** Cancels the circular clip animation. */
+    void cancelCircularClipAnimation() {
+        if (mCircularClipAnimator != null) {
+            mCircularClipAnimator.cancel();
+        }
+    }
+
+    void animateAppInfoButtonIn(int duration) {
+        mAppInfoButton.setScaleX(0.75f);
+        mAppInfoButton.setScaleY(0.75f);
+        mAppInfoButton.animate()
+                .scaleX(1f)
+                .scaleY(1f)
+                .setDuration(duration)
+                .setInterpolator(BakedBezierInterpolator.INSTANCE)
+                .withLayer()
+                .start();
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        int saveCount = 0;
+        if (mCircularClipEnabled) {
+            saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
+            mClipPath.reset();
+            mClipPath.addCircle(mClipOrigin.x, mClipOrigin.y, mClipRadius * mMaxClipRadius,
+                    Path.Direction.CW);
+            canvas.clipPath(mClipPath);
+        }
+        super.draw(canvas);
+        if (mCircularClipEnabled) {
+            canvas.restoreToCount(saveCount);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 88fb972..ee92b16 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -52,11 +52,12 @@
 /* The visual representation of a task stack view */
 public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
         TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>,
-        View.OnClickListener {
+        View.OnClickListener, View.OnLongClickListener {
 
     /** The TaskView callbacks */
     interface TaskStackViewCallbacks {
         public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
+        public void onTaskAppInfoLaunched(Task t);
     }
 
     TaskStack mStack;
@@ -75,6 +76,7 @@
     int mMinScroll;
     int mMaxScroll;
     int mStashedScroll;
+    int mLastInfoPaneStackScroll;
     OverScroller mScroller;
     ObjectAnimator mScrollAnimator;
 
@@ -281,6 +283,17 @@
     public void setStackScroll(int value) {
         mStackScroll = value;
         requestSynchronizeStackViewsWithModel();
+
+        // Close any open info panes if the user has scrolled away from them
+        boolean isAnimatingScroll = (mScrollAnimator != null && mScrollAnimator.isRunning());
+        if (mLastInfoPaneStackScroll > -1 && !isAnimatingScroll) {
+            RecentsConfiguration config = RecentsConfiguration.getInstance();
+            if (Math.abs(mStackScroll - mLastInfoPaneStackScroll) >
+                    config.taskStackScrollDismissInfoPaneDistance) {
+                // Close any open info panes
+                closeOpenInfoPanes();
+            }
+        }
     }
     /** Sets the current stack scroll without synchronizing the stack view with the model */
     public void setStackScrollRaw(int value) {
@@ -300,19 +313,24 @@
             // Enable hw layers on the stack
             addHwLayersRefCount("animateBoundScroll");
 
-            // Abort any current animations
-            abortScroller();
-            abortBoundScrollAnimation();
-
             // Start a new scroll animation
-            animateScroll(curScroll, newScroll);
-            mScrollAnimator.start();
+            animateScroll(curScroll, newScroll, new Runnable() {
+                @Override
+                public void run() {
+                    // Disable hw layers on the stack
+                    decHwLayersRefCount("animateBoundScroll");
+                }
+            });
         }
         return mScrollAnimator;
     }
 
     /** Animates the stack scroll */
-    void animateScroll(int curScroll, int newScroll) {
+    void animateScroll(int curScroll, int newScroll, final Runnable postRunnable) {
+        // Abort any current animations
+        abortScroller();
+        abortBoundScrollAnimation();
+
         mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
         mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
                 curScroll, 250));
@@ -326,20 +344,23 @@
         mScrollAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                // Disable hw layers on the stack
-                decHwLayersRefCount("animateBoundScroll");
+                if (postRunnable != null) {
+                    postRunnable.run();
+                }
+                mScrollAnimator.removeAllListeners();
             }
         });
+        mScrollAnimator.start();
     }
 
     /** Aborts any current stack scrolls */
     void abortBoundScrollAnimation() {
         if (mScrollAnimator != null) {
             mScrollAnimator.cancel();
-            mScrollAnimator.removeAllListeners();
         }
     }
 
+    /** Aborts the scroller and any current fling */
     void abortScroller() {
         if (!mScroller.isFinished()) {
             // Abort the scroller
@@ -407,6 +428,21 @@
         }
     }
 
+    /** Closes any open info panes. */
+    boolean closeOpenInfoPanes() {
+        if (!Constants.DebugFlags.App.EnableInfoPane) return false;
+
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            TaskView tv = (TaskView) getChildAt(i);
+            if (tv.isInfoPaneVisible()) {
+                tv.hideInfoPane();
+                return true;
+            }
+        }
+        return false;
+    }
+
     /** Enables the hw layers and increments the hw layer requirement ref count */
     void addHwLayersRefCount(String reason) {
         Console.log(Constants.DebugFlags.UI.HwLayers,
@@ -528,8 +564,9 @@
         int minHeight = (int) (mStackRect.height() -
                 (Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height()));
         int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height()));
-        mTaskRect.set(mStackRect.left, mStackRectSansPeek.top,
-                mStackRect.right, mStackRectSansPeek.top + size);
+        int left = mStackRect.left + (mStackRect.width() - size) / 2;
+        mTaskRect.set(left, mStackRectSansPeek.top,
+                left + size, mStackRectSansPeek.top + size);
 
         // Update the scroll bounds
         updateMinMaxScroll(false);
@@ -644,7 +681,6 @@
         requestSynchronizeStackViewsWithModel(Utilities.calculateTranslationAnimationDuration(movement));
     }
 
-
     /**
      * Creates the animations for all the children views that need to be removed or to move views
      * to their un/filtered position when we are un/filtering a stack, and returns the duration
@@ -789,6 +825,9 @@
     @Override
     public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curTasks,
                                 Task filteredTask) {
+        // Close any open info panes
+        closeOpenInfoPanes();
+
         // Stash the scroll and filtered task for us to restore to when we unfilter
         mStashedScroll = getStackScroll();
 
@@ -813,6 +852,9 @@
 
     @Override
     public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curTasks) {
+        // Close any open info panes
+        closeOpenInfoPanes();
+
         // Calculate the current task transforms
         final ArrayList<TaskViewTransform> curTaskTransforms =
                 getStackTransforms(curTasks, getStackScroll(), null, true);
@@ -892,6 +934,9 @@
 
             // Set the callbacks and listeners for this new view
             tv.setOnClickListener(this);
+            if (Constants.DebugFlags.App.EnableInfoPane) {
+                tv.setOnLongClickListener(this);
+            }
             tv.setCallbacks(this);
         } else {
             attachViewToParent(tv, insertIndex, tv.getLayoutParams());
@@ -926,6 +971,24 @@
         }
     }
 
+    @Override
+    public void onTaskInfoPanelShown(TaskView tv) {
+        // Do nothing
+    }
+
+    @Override
+    public void onTaskInfoPanelHidden(TaskView tv) {
+        // Unset the saved scroll
+        mLastInfoPaneStackScroll = -1;
+    }
+
+    @Override
+    public void onTaskAppInfoClicked(TaskView tv) {
+        if (mCb != null) {
+            mCb.onTaskAppInfoLaunched(tv.getTask());
+        }
+    }
+
     /**** View.OnClickListener Implementation ****/
 
     @Override
@@ -935,10 +998,51 @@
         Console.log(Constants.DebugFlags.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
                 task + " cb: " + mCb);
 
+        // Close any open info panes if the user taps on another task
+        if (closeOpenInfoPanes()) {
+            return;
+        }
+
         if (mCb != null) {
             mCb.onTaskLaunched(this, tv, mStack, task);
         }
     }
+
+    @Override
+    public boolean onLongClick(View v) {
+        if (!Constants.DebugFlags.App.EnableInfoPane) return false;
+
+        TaskView tv = (TaskView) v;
+
+        // Close any other task info panels if we launch another info pane
+        closeOpenInfoPanes();
+
+        // Scroll the task view so that it is maximally visible
+        float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
+        int taskIndex = mStack.indexOfTask(tv.getTask());
+        int curScroll = getStackScroll();
+        int newScroll = (int) Math.max(mMinScroll, Math.min(mMaxScroll, taskIndex * overlapHeight));
+        TaskViewTransform transform = getStackTransform(taskIndex, curScroll);
+        Rect nonOverlapRect = new Rect(transform.rect);
+        if (taskIndex < (mStack.getTaskCount() - 1)) {
+            nonOverlapRect.bottom = nonOverlapRect.top + (int) overlapHeight;
+        }
+
+        // XXX: Use HW Layers
+        if (transform.t < 0f) {
+            animateScroll(curScroll, newScroll, null);
+        } else if (nonOverlapRect.bottom > mStackRectSansPeek.bottom) {
+            // Check if we are out of bounds, if so, just scroll it in such that the bottom of the
+            // task view is visible
+            newScroll = curScroll - (mStackRectSansPeek.bottom - nonOverlapRect.bottom);
+            animateScroll(curScroll, newScroll, null);
+        }
+        mLastInfoPaneStackScroll = newScroll;
+
+        // Show the info pane for this task view
+        tv.showInfoPane(new Rect(0, 0, 0, (int) overlapHeight));
+        return true;
+    }
 }
 
 /* Handles touch events */
@@ -1153,9 +1257,10 @@
                 int activePointerIndex = ev.findPointerIndex(mActivePointerId);
                 int x = (int) ev.getX(activePointerIndex);
                 int y = (int) ev.getY(activePointerIndex);
+                int yTotal = Math.abs(y - mInitialMotionY);
                 int deltaY = mLastMotionY - y;
                 if (!mIsScrolling) {
-                    if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
+                    if (yTotal > mScrollTouchSlop) {
                         mIsScrolling = true;
                         // Initialize the velocity tracker
                         initOrResetVelocityTracker();
@@ -1277,6 +1382,13 @@
         if (parent != null) {
             parent.requestDisallowInterceptTouchEvent(true);
         }
+        // If the info panel is currently showing on this view, then we need to dismiss it
+        if (Constants.DebugFlags.App.EnableInfoPane) {
+            TaskView tv = (TaskView) v;
+            if (tv.isInfoPaneVisible()) {
+                tv.hideInfoPane();
+            }
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index b4100127..d3b79d6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,31 +16,53 @@
 
 package com.android.systemui.recents.views;
 
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
 import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.Point;
 import android.graphics.Rect;
+import android.graphics.RectF;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.animation.AccelerateInterpolator;
 import android.widget.FrameLayout;
 import com.android.systemui.R;
 import com.android.systemui.recents.BakedBezierInterpolator;
+import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.Utilities;
 import com.android.systemui.recents.model.Task;
 
 
 /* A task view */
-public class TaskView extends FrameLayout implements View.OnClickListener, Task.TaskCallbacks {
+public class TaskView extends FrameLayout implements View.OnClickListener,
+        Task.TaskCallbacks {
     /** The TaskView callbacks */
     interface TaskViewCallbacks {
         public void onTaskIconClicked(TaskView tv);
+        public void onTaskInfoPanelShown(TaskView tv);
+        public void onTaskInfoPanelHidden(TaskView tv);
+        public void onTaskAppInfoClicked(TaskView tv);
+
         // public void onTaskViewReboundToTask(TaskView tv, Task t);
     }
 
+    int mDim;
+    int mMaxDim;
+    TimeInterpolator mDimInterpolator = new AccelerateInterpolator();
+
     Task mTask;
     boolean mTaskDataLoaded;
+    boolean mTaskInfoPaneVisible;
+    Point mLastTouchDown = new Point();
+    Path mRoundedRectClipPath = new Path();
 
     TaskThumbnailView mThumbnailView;
     TaskBarView mBarView;
+    TaskInfoView mInfoView;
     TaskViewCallbacks mCb;
 
 
@@ -58,19 +80,47 @@
 
     public TaskView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        setWillNotDraw(false);
     }
 
     @Override
     protected void onFinishInflate() {
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        mMaxDim = config.taskStackMaxDim;
+
         // Bind the views
         mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
         mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
-        mBarView.mApplicationIcon.setOnClickListener(this);
+        mInfoView = (TaskInfoView) findViewById(R.id.task_view_info_pane);
+
         if (mTaskDataLoaded) {
             onTaskDataLoaded(false);
         }
     }
 
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+        // Update the rounded rect clip path
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        float radius = config.taskViewRoundedCornerRadiusPx;
+        mRoundedRectClipPath.reset();
+        mRoundedRectClipPath.addRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()),
+                radius, radius, Path.Direction.CW);
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+            case MotionEvent.ACTION_MOVE:
+                mLastTouchDown.set((int) ev.getX(), (int) ev.getY());
+                break;
+        }
+        return super.onInterceptTouchEvent(ev);
+    }
+
     /** Set callback */
     void setCallbacks(TaskViewCallbacks cb) {
         mCb = cb;
@@ -98,6 +148,12 @@
                     .setDuration(duration)
                     .setInterpolator(BakedBezierInterpolator.INSTANCE)
                     .withLayer()
+                    .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                        @Override
+                        public void onAnimationUpdate(ValueAnimator animation) {
+                            updateDimOverlayFromScale();
+                        }
+                    })
                     .start();
         } else {
             setTranslationY(toTransform.translationY);
@@ -105,6 +161,8 @@
             setScaleY(toTransform.scale);
             setAlpha(toTransform.alpha);
         }
+        updateDimOverlayFromScale();
+        invalidate();
     }
 
     /** Resets this view's properties */
@@ -114,6 +172,7 @@
         setScaleX(1f);
         setScaleY(1f);
         setAlpha(1f);
+        invalidate();
     }
 
     /**
@@ -189,6 +248,63 @@
         return outRect;
     }
 
+    /** Returns whether this task has an info pane visible */
+    boolean isInfoPaneVisible() {
+        return mTaskInfoPaneVisible;
+    }
+
+    /** Shows the info pane if it is not visible. */
+    void showInfoPane(Rect taskVisibleRect) {
+        if (mTaskInfoPaneVisible) return;
+
+        // Remove the bar view from the visible rect and update the info pane contents
+        taskVisibleRect.top += mBarView.getMeasuredHeight();
+        mInfoView.updateContents(taskVisibleRect);
+
+        // Show the info pane and animate it into view
+        mInfoView.setVisibility(View.VISIBLE);
+        mInfoView.animateCircularClip(mLastTouchDown, 0f, 1f, null, true);
+        mInfoView.setOnClickListener(this);
+        mTaskInfoPaneVisible = true;
+
+        // Notify any callbacks
+        if (mCb != null) {
+            mCb.onTaskInfoPanelShown(this);
+        }
+    }
+
+    /** Hides the info pane if it is visible. */
+    void hideInfoPane() {
+        if (!mTaskInfoPaneVisible) return;
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+
+        // Cancel any circular clip animation
+        mInfoView.cancelCircularClipAnimation();
+
+        // Animate the info pane out
+        mInfoView.animate()
+                .alpha(0f)
+                .setDuration(config.taskViewInfoPaneAnimDuration)
+                .setInterpolator(BakedBezierInterpolator.INSTANCE)
+                .withLayer()
+                .withEndAction(new Runnable() {
+                    @Override
+                    public void run() {
+                        mInfoView.setVisibility(View.INVISIBLE);
+                        mInfoView.setOnClickListener(null);
+
+                        mInfoView.setAlpha(1f);
+                    }
+                })
+                .start();
+        mTaskInfoPaneVisible = false;
+
+        // Notify any callbacks
+        if (mCb != null) {
+            mCb.onTaskInfoPanelHidden(this);
+        }
+    }
+
     /** Enable the hw layers on this task view */
     void enableHwLayers() {
         mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
@@ -199,6 +315,29 @@
         mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, null);
     }
 
+    /** Update the dim as a function of the scale of this view. */
+    void updateDimOverlayFromScale() {
+        float minScale = Constants.Values.TaskStackView.StackPeekMinScale;
+        float scaleRange = 1f - minScale;
+        float dim = (1f - getScaleX()) / scaleRange;
+        dim = mDimInterpolator.getInterpolation(Math.min(dim, 1f));
+        mDim = Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
+        invalidate();
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        // Apply the rounded rect clip path on the whole view
+        canvas.clipPath(mRoundedRectClipPath);
+
+        super.draw(canvas);
+
+        // Apply the dim if necessary
+        if (mDim > 0) {
+            canvas.drawColor(mDim << 24);
+        }
+    }
+
     /**** TaskCallbacks Implementation ****/
 
     /** Binds this task view to the task */
@@ -209,27 +348,39 @@
 
     @Override
     public void onTaskDataLoaded(boolean reloadingTaskData) {
-        if (mThumbnailView != null && mBarView != null) {
+        if (mThumbnailView != null && mBarView != null && mInfoView != null) {
             // Bind each of the views to the new task data
             mThumbnailView.rebindToTask(mTask, reloadingTaskData);
             mBarView.rebindToTask(mTask, reloadingTaskData);
+            // Rebind any listeners
+            mBarView.mApplicationIcon.setOnClickListener(this);
+            mInfoView.mAppInfoButton.setOnClickListener(this);
         }
         mTaskDataLoaded = true;
     }
 
     @Override
     public void onTaskDataUnloaded() {
-        if (mThumbnailView != null && mBarView != null) {
+        if (mThumbnailView != null && mBarView != null && mInfoView != null) {
             // Unbind each of the views from the task data and remove the task callback
             mTask.setCallbacks(null);
             mThumbnailView.unbindFromTask();
             mBarView.unbindFromTask();
+            // Unbind any listeners
+            mBarView.mApplicationIcon.setOnClickListener(null);
+            mInfoView.mAppInfoButton.setOnClickListener(null);
         }
         mTaskDataLoaded = false;
     }
 
     @Override
     public void onClick(View v) {
-        mCb.onTaskIconClicked(this);
+        if (v == mInfoView) {
+            // Do nothing
+        } else if (v == mBarView.mApplicationIcon) {
+            mCb.onTaskIconClicked(this);
+        } else if (v == mInfoView.mAppInfoButton) {
+            mCb.onTaskAppInfoClicked(this);
+        }
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
new file mode 100644
index 0000000..87ebcc1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
@@ -0,0 +1,172 @@
+/*
+ * 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 com.android.systemui.settings;
+
+import com.android.systemui.R;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+/**
+ * A quick and dirty view to show a user switcher.
+ */
+public class UserSwitcherHostView extends FrameLayout implements ListView.OnItemClickListener {
+
+    private static final String TAG = "UserSwitcherDialog";
+
+    private ArrayList<UserInfo> mUserInfo = new ArrayList<UserInfo>();
+    private Adapter mAdapter = new Adapter();
+    private UserManager mUserManager;
+    private Runnable mFinishRunnable;
+    private ListView mListView;
+
+    public UserSwitcherHostView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        if (isInEditMode()) {
+            return;
+        }
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+    }
+
+    public UserSwitcherHostView(Context context, AttributeSet attrs) {
+        this(context, attrs, com.android.internal.R.attr.listViewStyle);
+    }
+
+    public UserSwitcherHostView(Context context) {
+        this(context, null);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mListView = (ListView) findViewById(android.R.id.list);
+        mListView.setAdapter(mAdapter);
+        mListView.setOnItemClickListener(this);
+    }
+
+    @Override
+    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
+        int userId = mAdapter.getItem(position).id;
+        try {
+            WindowManagerGlobal.getWindowManagerService().lockNow(null);
+            ActivityManagerNative.getDefault().switchUser(userId);
+            finish();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Couldn't switch user.", e);
+        }
+    }
+
+    private void finish() {
+        if (mFinishRunnable != null) {
+            mFinishRunnable.run();
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (event.getAction() == MotionEvent.ACTION_UP) {
+            finish();
+        }
+        return true;
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+        // A gross hack to get rid of the switcher when the shade is collapsed.
+        if (visibility != VISIBLE) {
+            finish();
+        }
+    }
+
+    public void setFinishRunnable(Runnable finishRunnable) {
+        mFinishRunnable = finishRunnable;
+    }
+
+    public void refreshUsers() {
+        mUserInfo.clear();
+        mUserInfo.addAll(mUserManager.getUsers(true));
+        mAdapter.notifyDataSetChanged();
+    }
+
+    private class Adapter extends BaseAdapter {
+
+        @Override
+        public int getCount() {
+            return mUserInfo.size();
+        }
+
+        @Override
+        public UserInfo getItem(int position) {
+            return mUserInfo.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return getItem(position).serialNumber;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null || (!(convertView.getTag() instanceof ViewHolder))) {
+                convertView = createView(parent);
+            }
+            ViewHolder h = (ViewHolder) convertView.getTag();
+            bindView(h, getItem(position));
+            return convertView;
+        }
+
+        private View createView(ViewGroup parent) {
+            View v = LayoutInflater.from(getContext()).inflate(
+                    R.layout.user_switcher_item, parent, false);
+            ViewHolder h = new ViewHolder();
+            h.name = (TextView) v.findViewById(R.id.user_name);
+            h.picture = (ImageView) v.findViewById(R.id.user_picture);
+            v.setTag(h);
+            return v;
+        }
+
+        private void bindView(ViewHolder h, UserInfo item) {
+            h.name.setText(item.name);
+            h.picture.setImageBitmap(mUserManager.getUserIcon(item.id));
+        }
+
+        class ViewHolder {
+            TextView name;
+            ImageView picture;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 2f135ec..2ea5add 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -83,7 +83,7 @@
 import java.util.Locale;
 
 public abstract class BaseStatusBar extends SystemUI implements
-        CommandQueue.Callbacks {
+        CommandQueue.Callbacks, LatestItemView.OnActivatedListener {
     public static final String TAG = "StatusBar";
     public static final boolean DEBUG = false;
     public static final boolean MULTIUSER_DEBUG = false;
@@ -168,9 +168,8 @@
 
     protected int mZenMode;
 
-    public IStatusBarService getStatusBarService() {
-        return mBarService;
-    }
+    protected boolean mOnKeyguard;
+    protected NotificationOverflowContainer mKeyguardIconOverflowContainer;
 
     public boolean isDeviceProvisioned() {
         return mDeviceProvisioned;
@@ -423,9 +422,9 @@
     }
 
 
-    protected void applyLegacyRowBackground(StatusBarNotification sbn, View content) {
-        if (sbn.getNotification().contentView.getLayoutId() !=
-                com.android.internal.R.layout.notification_template_base) {
+    protected void applyLegacyRowBackground(StatusBarNotification sbn,
+            NotificationData.Entry entry) {
+        if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) {
             int version = 0;
             try {
                 ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.getPackageName(), 0);
@@ -434,9 +433,11 @@
                 Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
             }
             if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
-                content.setBackgroundResource(R.drawable.notification_row_legacy_bg);
-            } else {
-                content.setBackgroundResource(com.android.internal.R.drawable.notification_bg);
+                entry.row.setBackgroundResource(R.drawable.notification_row_legacy_bg);
+            } else if (version < Build.VERSION_CODES.L) {
+                entry.row.setBackgroundResourceIds(
+                        com.android.internal.R.drawable.notification_bg,
+                        com.android.internal.R.drawable.notification_bg_dim);
             }
         }
     }
@@ -871,8 +872,6 @@
 
         row.setDrawingCacheEnabled(true);
 
-        applyLegacyRowBackground(sbn, content);
-
         if (MULTIUSER_DEBUG) {
             TextView debug = (TextView) row.findViewById(R.id.debug_info);
             if (debug != null) {
@@ -882,11 +881,14 @@
         }
         entry.row = row;
         entry.row.setHeightRange(mRowMinHeight, mRowMaxHeight);
+        entry.row.setOnActivatedListener(this);
         entry.content = content;
         entry.expanded = contentViewLocal;
         entry.expandedPublic = publicViewLocal;
         entry.setBigContentView(bigContentViewLocal);
 
+        applyLegacyRowBackground(sbn, entry);
+
         return true;
     }
 
@@ -1004,7 +1006,7 @@
         // Remove the expanded view.
         ViewGroup rowParent = (ViewGroup)entry.row.getParent();
         if (rowParent != null) rowParent.removeView(entry.row);
-        updateExpansionStates();
+        updateRowStates();
         updateNotificationIcons();
 
         return entry.notification;
@@ -1047,7 +1049,7 @@
         if (DEBUG) {
             Log.d(TAG, "addNotificationViews: added at " + pos);
         }
-        updateExpansionStates();
+        updateRowStates();
         updateNotificationIcons();
     }
 
@@ -1055,28 +1057,89 @@
         addNotificationViews(createNotificationViews(key, notification));
     }
 
-    protected void updateExpansionStates() {
+    /**
+     * @return The number of notifications we show on Keyguard.
+     */
+    protected abstract int getMaxKeyguardNotifications();
 
-        // TODO: Handle user expansion better
-        int N = mNotificationData.size();
-        for (int i = 0; i < N; i++) {
+    /**
+     * Updates expanded, dimmed and locked states of notification rows.
+     */
+    protected void updateRowStates() {
+        int maxKeyguardNotifications = getMaxKeyguardNotifications();
+        mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
+        int n = mNotificationData.size();
+        int visibleNotifications = 0;
+        for (int i = n-1; i >= 0; i--) {
             NotificationData.Entry entry = mNotificationData.get(i);
-            if (!entry.row.isUserLocked()) {
-                if (i == (N-1)) {
-                    if (DEBUG) Log.d(TAG, "expanding top notification at " + i);
-                    entry.row.setSystemExpanded(true);
-                } else {
-                    if (!entry.row.isUserExpanded()) {
-                        if (DEBUG) Log.d(TAG, "collapsing notification at " + i);
-                        entry.row.setSystemExpanded(false);
-                    } else {
-                        if (DEBUG) Log.d(TAG, "ignoring user-modified notification at " + i);
-                    }
+            if (mOnKeyguard) {
+                entry.row.setSystemExpanded(false);
+            } else {
+                if (!entry.row.isUserLocked()) {
+                    boolean top = (i == n-1);
+                    entry.row.setSystemExpanded(top || entry.row.isUserExpanded());
+                }
+            }
+            entry.row.setDimmed(mOnKeyguard);
+            entry.row.setLocked(mOnKeyguard);
+            boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
+            if (mOnKeyguard && (visibleNotifications >= maxKeyguardNotifications
+                    || !showOnKeyguard)) {
+                entry.row.setVisibility(View.GONE);
+                if (showOnKeyguard) {
+                    mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
                 }
             } else {
-                if (DEBUG) Log.d(TAG, "ignoring notification being held by user at " + i);
+                entry.row.setVisibility(View.VISIBLE);
+                visibleNotifications++;
             }
         }
+
+        if (mOnKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) {
+            mKeyguardIconOverflowContainer.setVisibility(View.VISIBLE);
+        } else {
+            mKeyguardIconOverflowContainer.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public void onActivated(View view) {
+        int n = mNotificationData.size();
+        for (int i = 0; i < n; i++) {
+            NotificationData.Entry entry = mNotificationData.get(i);
+            if (entry.row.getVisibility() != View.GONE) {
+                if (view == entry.row) {
+                    entry.row.getActivator().activate();
+                } else {
+                    entry.row.getActivator().activateInverse();
+                }
+            }
+        }
+        if (mKeyguardIconOverflowContainer.getVisibility() != View.GONE) {
+            if (view == mKeyguardIconOverflowContainer) {
+                mKeyguardIconOverflowContainer.getActivator().activate();
+            } else {
+                mKeyguardIconOverflowContainer.getActivator().activateInverse();
+            }
+        }
+    }
+
+    @Override
+    public void onReset(View view) {
+        int n = mNotificationData.size();
+        for (int i = 0; i < n; i++) {
+            NotificationData.Entry entry = mNotificationData.get(i);
+            if (entry.row.getVisibility() != View.GONE) {
+                entry.row.getActivator().reset();
+            }
+        }
+        if (mKeyguardIconOverflowContainer.getVisibility() != View.GONE) {
+            mKeyguardIconOverflowContainer.getActivator().reset();
+        }
+    }
+
+    private boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
+        return sbn.getNotification().priority >= Notification.PRIORITY_LOW;
     }
 
     protected void setZenMode(int mode) {
@@ -1208,7 +1271,7 @@
                     handleNotificationError(key, notification, "Couldn't update icon: " + ic);
                     return;
                 }
-                updateExpansionStates();
+                updateRowStates();
             }
             catch (RuntimeException e) {
                 // It failed to add cleanly.  Log, and remove the view from the panel.
@@ -1315,7 +1378,7 @@
         boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
                 && isAllowed
                 && mPowerManager.isScreenOn()
-                && !keyguard.isShowingAndNotHidden()
+                && !keyguard.isShowingAndNotOccluded()
                 && !keyguard.isInputRestricted();
         try {
             interrupt = interrupt && !mDreamManager.isDreaming();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 39333d7..bbbe8fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -21,6 +21,7 @@
 import android.os.Message;
 import android.service.notification.StatusBarNotification;
 
+import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
@@ -98,6 +99,7 @@
         public void hideSearchPanel();
         public void cancelPreloadRecentApps();
         public void setWindowState(int window, int state);
+
     }
 
     public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -232,6 +234,7 @@
         }
     }
 
+
     private final class H extends Handler {
         public void handleMessage(Message msg) {
             final int what = msg.what & MSG_MASK;
@@ -295,7 +298,7 @@
                     mCallbacks.topAppWindowChanged(msg.arg1 != 0);
                     break;
                 case MSG_SHOW_IME_BUTTON:
-                    mCallbacks.setImeWindowStatus((IBinder)msg.obj, msg.arg1, msg.arg2);
+                    mCallbacks.setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2);
                     break;
                 case MSG_SET_HARD_KEYBOARD_STATUS:
                     mCallbacks.setHardKeyboardStatus(msg.arg1 != 0, msg.arg2 != 0);
@@ -312,6 +315,7 @@
                 case MSG_SET_WINDOW_STATE:
                     mCallbacks.setWindowState(msg.arg1, msg.arg2);
                     break;
+
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 2daf619..fdf4dbf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -25,7 +25,8 @@
 import com.android.internal.widget.SizeAdaptiveLayout;
 import com.android.systemui.R;
 
-public class ExpandableNotificationRow extends FrameLayout {
+public class ExpandableNotificationRow extends FrameLayout
+        implements LatestItemView.OnActivatedListener {
     private int mRowMinHeight;
     private int mRowMaxHeight;
 
@@ -40,6 +41,8 @@
     /** Are we showing the "public" version */
     private boolean mShowingPublic;
 
+    private LatestItemView mLatestItemView;
+
     /**
      * Is this notification expanded by the system. The expansion state can be overridden by the
      * user expansion.
@@ -49,6 +52,8 @@
     private SizeAdaptiveLayout mPrivateLayout;
     private int mMaxExpandHeight;
     private boolean mMaxHeightNeedsUpdate;
+    private NotificationActivator mActivator;
+    private LatestItemView.OnActivatedListener mOnActivatedListener;
 
     public ExpandableNotificationRow(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -59,6 +64,10 @@
         super.onFinishInflate();
         mPublicLayout = (SizeAdaptiveLayout) findViewById(R.id.expandedPublic);
         mPrivateLayout = (SizeAdaptiveLayout) findViewById(R.id.expanded);
+        mLatestItemView = (LatestItemView) findViewById(R.id.container);
+
+        mActivator = new NotificationActivator(this);
+        mLatestItemView.setOnActivatedListener(this);
     }
 
     public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
@@ -152,8 +161,6 @@
         return mShowingPublic ? mRowMinHeight : getMaxExpandHeight();
     }
 
-
-
     private void updateMaxExpandHeight() {
         ViewGroup.LayoutParams lp = getLayoutParams();
         int oldHeight = lp.height;
@@ -195,6 +202,14 @@
         mPrivateLayout.setVisibility(show ? View.GONE : View.VISIBLE);
     }
 
+    /**
+     * Sets the notification as dimmed, meaning that it will appear in a more gray variant.
+     */
+    public void setDimmed(boolean dimmed) {
+        mLatestItemView.setDimmed(dimmed);
+        mActivator.setDimmed(dimmed);
+    }
+
     public int getMaxExpandHeight() {
         if (mMaxHeightNeedsUpdate) {
             updateMaxExpandHeight();
@@ -202,4 +217,44 @@
         }
         return mMaxExpandHeight;
     }
+
+    /**
+     * Sets the notification as locked. In the locked state, the first tap will produce a quantum
+     * ripple to make the notification brighter and only the second tap will cause a click.
+     */
+    public void setLocked(boolean locked) {
+        mLatestItemView.setLocked(locked);
+    }
+
+    public void setOnActivatedListener(LatestItemView.OnActivatedListener listener) {
+        mOnActivatedListener = listener;
+    }
+
+    public NotificationActivator getActivator() {
+        return mActivator;
+    }
+
+    @Override
+    public void onActivated(View view) {
+        if (mOnActivatedListener != null) {
+            mOnActivatedListener.onActivated(this);
+        }
+    }
+
+    @Override
+    public void onReset(View view) {
+        if (mOnActivatedListener != null) {
+            mOnActivatedListener.onReset(this);
+        }
+    }
+
+    /**
+     * Sets the resource id for the background of this notification.
+     *
+     * @param bgResId The background resource to use in normal state.
+     * @param dimmedBgResId The background resource to use in dimmed state.
+     */
+    public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
+        mLatestItemView.setBackgroundResourceIds(bgResId, dimmedBgResId);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
index 6419777..5e90084 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
@@ -18,15 +18,48 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 
+import com.android.internal.R;
+
 public class LatestItemView extends FrameLayout {
+
+    private static final long DOUBLETAP_TIMEOUT_MS = 1000;
+
+    private boolean mDimmed;
+    private boolean mLocked;
+
+    private int mBgResId = R.drawable.notification_quantum_bg;
+    private int mDimmedBgResId = R.drawable.notification_quantum_bg_dim;
+
+    /**
+     * Flag to indicate that the notification has been touched once and the second touch will
+     * click it.
+     */
+    private boolean mActivated;
+
+    private float mDownX;
+    private float mDownY;
+    private final float mTouchSlop;
+
+    private OnActivatedListener mOnActivatedListener;
+
     public LatestItemView(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
     }
 
+    private final Runnable mTapTimeoutRunnable = new Runnable() {
+        @Override
+        public void run() {
+            makeInactive();
+        }
+    };
+
     @Override
     public void setOnClickListener(OnClickListener l) {
         super.setOnClickListener(l);
@@ -45,4 +78,125 @@
         }
         return false;
     }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (mLocked) {
+            return handleTouchEventLocked(event);
+        } else {
+            return super.onTouchEvent(event);
+        }
+    }
+
+    private boolean handleTouchEventLocked(MotionEvent event) {
+        int action = event.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                mDownX = event.getX();
+                mDownY = event.getY();
+
+                // Call the listener tentatively directly, even if we don't know whether the user
+                // will stay within the touch slop, as the listener is implemented as a scale
+                // animation, which is cancellable without jarring effects when swiping away
+                // notifications.
+                if (mOnActivatedListener != null) {
+                    mOnActivatedListener.onActivated(this);
+                }
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (!isWithinTouchSlop(event)) {
+                    makeInactive();
+                    return false;
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (isWithinTouchSlop(event)) {
+                    if (!mActivated) {
+                        makeActive(event.getX(), event.getY());
+                        postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
+                    } else {
+                        performClick();
+                        makeInactive();
+                    }
+                } else {
+                    makeInactive();
+                }
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                makeInactive();
+                break;
+            default:
+                break;
+        }
+        return true;
+    }
+
+    private void makeActive(float x, float y) {
+        getBackground().setHotspot(0, x, y);
+        mActivated = true;
+    }
+
+    /**
+     * Cancels the hotspot and makes the notification inactive.
+     */
+    private void makeInactive() {
+        if (mActivated) {
+            // Make sure that we clear the hotspot from the center.
+            getBackground().setHotspot(0, getWidth() / 2, getHeight() / 2);
+            getBackground().removeHotspot(0);
+            mActivated = false;
+        }
+        if (mOnActivatedListener != null) {
+            mOnActivatedListener.onReset(this);
+        }
+        removeCallbacks(mTapTimeoutRunnable);
+    }
+
+    private boolean isWithinTouchSlop(MotionEvent event) {
+        return Math.abs(event.getX() - mDownX) < mTouchSlop
+                && Math.abs(event.getY() - mDownY) < mTouchSlop;
+    }
+
+    /**
+     * Sets the notification as dimmed, meaning that it will appear in a more gray variant.
+     */
+    public void setDimmed(boolean dimmed) {
+        if (mDimmed != dimmed) {
+            mDimmed = dimmed;
+            updateBackgroundResource();
+        }
+    }
+
+    /**
+     * Sets the notification as locked. In the locked state, the first tap will produce a quantum
+     * ripple to make the notification brighter and only the second tap will cause a click.
+     */
+    public void setLocked(boolean locked) {
+        mLocked = locked;
+    }
+
+    /**
+     * Sets the resource id for the background of this notification.
+     *
+     * @param bgResId The background resource to use in normal state.
+     * @param dimmedBgResId The background resource to use in dimmed state.
+     */
+    public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
+        mBgResId = bgResId;
+        mDimmedBgResId = dimmedBgResId;
+        updateBackgroundResource();
+    }
+
+    private void updateBackgroundResource() {
+        setBackgroundResource(mDimmed ? mDimmedBgResId : mBgResId);
+    }
+
+    public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
+        mOnActivatedListener = onActivatedListener;
+    }
+
+    public interface OnActivatedListener {
+        void onActivated(View view);
+        void onReset(View view);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java
new file mode 100644
index 0000000..620e457
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java
@@ -0,0 +1,87 @@
+/*
+ * 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 com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import com.android.systemui.R;
+
+/**
+ * A helper class used by both {@link com.android.systemui.statusbar.ExpandableNotificationRow} and
+ * {@link com.android.systemui.statusbar.NotificationOverflowIconsView} to make a notification look
+ * active after tapping it once on the Keyguard.
+ */
+public class NotificationActivator {
+
+    private static final int ANIMATION_LENGTH_MS = 220;
+    private static final float INVERSE_ALPHA = 0.9f;
+    private static final float DIMMED_SCALE = 0.95f;
+
+    private final View mTargetView;
+
+    private final Interpolator mFastOutSlowInInterpolator;
+    private final Interpolator mLinearOutSlowInInterpolator;
+    private final int mTranslationZ;
+
+    public NotificationActivator(View targetView) {
+        mTargetView = targetView;
+        Context ctx = targetView.getContext();
+        mFastOutSlowInInterpolator =
+                AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_slow_in);
+        mLinearOutSlowInInterpolator =
+                AnimationUtils.loadInterpolator(ctx, android.R.interpolator.linear_out_slow_in);
+        mTranslationZ =
+                ctx.getResources().getDimensionPixelSize(R.dimen.z_distance_between_notifications);
+        mTargetView.animate().setDuration(ANIMATION_LENGTH_MS);
+    }
+
+    public void activateInverse() {
+        mTargetView.animate().withLayer().alpha(INVERSE_ALPHA);
+    }
+
+    public void activate() {
+        mTargetView.animate()
+                .setInterpolator(mLinearOutSlowInInterpolator)
+                .scaleX(1)
+                .scaleY(1)
+                .translationZBy(mTranslationZ);
+    }
+
+    public void reset() {
+        mTargetView.animate()
+                .setInterpolator(mFastOutSlowInInterpolator)
+                .scaleX(DIMMED_SCALE)
+                .scaleY(DIMMED_SCALE)
+                .translationZBy(-mTranslationZ);
+        if (mTargetView.getAlpha() != 1.0f) {
+            mTargetView.animate().withLayer().alpha(1);
+        }
+    }
+
+    public void setDimmed(boolean dimmed) {
+        if (dimmed) {
+            mTargetView.setScaleX(DIMMED_SCALE);
+            mTargetView.setScaleY(DIMMED_SCALE);
+        } else {
+            mTargetView.setScaleX(1);
+            mTargetView.setScaleY(1);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
new file mode 100644
index 0000000..be58dad
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
@@ -0,0 +1,92 @@
+/*
+ * 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 com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+/**
+ * Container view for overflowing notification icons on Keyguard.
+ */
+public class NotificationOverflowContainer extends FrameLayout
+        implements LatestItemView.OnActivatedListener {
+
+    private NotificationOverflowIconsView mIconsView;
+    private LatestItemView.OnActivatedListener mOnActivatedListener;
+    private NotificationActivator mActivator;
+
+    public NotificationOverflowContainer(Context context) {
+        super(context);
+    }
+
+    public NotificationOverflowContainer(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public NotificationOverflowContainer(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public NotificationOverflowContainer(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mIconsView = (NotificationOverflowIconsView) findViewById(R.id.overflow_icons_view);
+        mIconsView.setMoreText((TextView) findViewById(R.id.more_text));
+
+        LatestItemView latestItemView = (LatestItemView) findViewById(R.id.container);
+        mActivator = new NotificationActivator(this);
+        mActivator.setDimmed(true);
+        latestItemView.setOnActivatedListener(this);
+        latestItemView.setLocked(true);
+    }
+
+    public NotificationOverflowIconsView getIconsView() {
+        return mIconsView;
+    }
+
+    public void setOnActivatedListener(LatestItemView.OnActivatedListener onActivatedListener) {
+        mOnActivatedListener = onActivatedListener;
+    }
+
+    @Override
+    public void onActivated(View view) {
+        if (mOnActivatedListener != null) {
+            mOnActivatedListener.onActivated(this);
+        }
+    }
+
+    @Override
+    public void onReset(View view) {
+        if (mOnActivatedListener != null) {
+            mOnActivatedListener.onReset(this);
+        }
+    }
+
+    public NotificationActivator getActivator() {
+        return mActivator;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
new file mode 100644
index 0000000..ce31894
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
@@ -0,0 +1,69 @@
+/*
+ * 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 com.android.systemui.statusbar;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.IconMerger;
+
+/**
+ * A view to display all the overflowing icons on Keyguard.
+ */
+public class NotificationOverflowIconsView extends IconMerger {
+
+    private TextView mMoreText;
+    private int mTintColor;
+
+    public NotificationOverflowIconsView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTintColor = getResources().getColor(R.color.keyguard_overflow_content_color);
+    }
+
+    public void setMoreText(TextView moreText) {
+        mMoreText = moreText;
+    }
+
+    public void addNotification(NotificationData.Entry notification) {
+        StatusBarIconView v = new StatusBarIconView(getContext(), "",
+                notification.notification.getNotification());
+        v.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+        v.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
+        addView(v);
+        v.set(notification.icon.getStatusBarIcon());
+        updateMoreText();
+    }
+
+    private void updateMoreText() {
+        mMoreText.setText(getResources().getQuantityString(
+                R.plurals.keyguard_more_overflow_text, getChildCount(), getChildCount()));
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
new file mode 100644
index 0000000..7cbde36
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -0,0 +1,139 @@
+/*
+ * 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 com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardViewBase;
+import com.android.keyguard.R;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+
+/**
+ * A class which manages the bouncer on the lockscreen.
+ */
+public class KeyguardBouncer {
+
+    private Context mContext;
+    private ViewMediatorCallback mCallback;
+    private LockPatternUtils mLockPatternUtils;
+    private ViewGroup mContainer;
+    private StatusBarWindowManager mWindowManager;
+    private KeyguardViewBase mKeyguardView;
+    private ViewGroup mRoot;
+
+    public KeyguardBouncer(Context context, ViewMediatorCallback callback,
+            LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
+            ViewGroup container) {
+        mContext = context;
+        mCallback = callback;
+        mLockPatternUtils = lockPatternUtils;
+        mContainer = container;
+        mWindowManager = windowManager;
+    }
+
+    public void prepare() {
+        ensureView();
+    }
+
+    public void show() {
+        ensureView();
+
+        // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
+        // Keyguard. If we need to authenticate, show the bouncer.
+        if (!mKeyguardView.dismiss()) {
+            mRoot.setVisibility(View.VISIBLE);
+            mKeyguardView.requestFocus();
+        }
+    }
+
+    public void hide() {
+        if (mKeyguardView != null) {
+            mKeyguardView.cleanUp();
+        }
+        removeView();
+    }
+
+    /**
+     * Reset the state of the view.
+     */
+    public void reset() {
+        inflateView();
+    }
+
+    public void onScreenTurnedOff() {
+        if (mKeyguardView != null) {
+            mKeyguardView.onScreenTurnedOff();
+        }
+    }
+
+    public void onScreenTurnedOn() {
+        if (mKeyguardView != null) {
+            mKeyguardView.onScreenTurnedOn();
+        }
+    }
+
+    public long getUserActivityTimeout() {
+        if (mKeyguardView != null) {
+            long timeout = mKeyguardView.getUserActivityTimeout();
+            if (timeout >= 0) {
+                return timeout;
+            }
+        }
+        return KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
+    }
+
+    public boolean isShowing() {
+        return mRoot != null && mRoot.getVisibility() == View.VISIBLE;
+    }
+
+    private void ensureView() {
+        if (mRoot == null) {
+            inflateView();
+        }
+    }
+
+    private void inflateView() {
+        removeView();
+        mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
+        mKeyguardView = (KeyguardViewBase) mRoot.findViewById(R.id.keyguard_host_view);
+        mKeyguardView.setLockPatternUtils(mLockPatternUtils);
+        mKeyguardView.setViewMediatorCallback(mCallback);
+        mContainer.addView(mRoot, mContainer.getChildCount());
+        mRoot.setVisibility(View.INVISIBLE);
+        mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
+    }
+
+    private void removeView() {
+        if (mRoot != null && mRoot.getParent() == mContainer) {
+            mContainer.removeView(mRoot);
+            mRoot = null;
+        }
+    }
+
+    public boolean onBackPressed() {
+        return mKeyguardView != null && mKeyguardView.handleBackKey();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
index 1ea920d..754075a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
@@ -39,8 +39,8 @@
  */
 public class KeyguardTouchDelegate {
     // TODO: propagate changes to these to {@link KeyguardServiceDelegate}
-    static final String KEYGUARD_PACKAGE = "com.android.keyguard";
-    static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService";
+    static final String KEYGUARD_PACKAGE = "com.android.systemui";
+    static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
 
     private static KeyguardTouchDelegate sInstance;
     private static final List<OnKeyguardConnectionListener> sConnectionListeners =
@@ -140,16 +140,16 @@
         return false;
     }
 
-    public boolean isShowingAndNotHidden() {
+    public boolean isShowingAndNotOccluded() {
         final IKeyguardService service = mService;
         if (service != null) {
             try {
-                return service.isShowingAndNotHidden();
+                return service.isShowingAndNotOccluded();
             } catch (RemoteException e) {
                 Slog.w(TAG , "Remote Exception", e);
             }
         } else {
-            Slog.w(TAG, "isShowingAndNotHidden(): NO SERVICE!");
+            Slog.w(TAG, "isShowingAndNotOccluded(): NO SERVICE!");
         }
         return false;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index a74230b..d26b32f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -117,7 +117,7 @@
     @Override
     public void setContentVisible(boolean visible) {
         final float alpha = visible ? 1 : 0;
-        fadeContent(mView.getCameraButton(), alpha);
+        fadeContent(mView.getBackButton(), alpha);
         fadeContent(mView.getSearchLight(), alpha);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d9e0903..db26a42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -34,17 +34,23 @@
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Message;
+import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.MediaStore;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Display;
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
@@ -92,12 +98,16 @@
     final static boolean WORKAROUND_INVALID_LAYOUT = true;
     final static int MSG_CHECK_INVALID_LAYOUT = 8686;
 
+    private final float mCameraDragDistance;
+
     // used to disable the camera icon in navbar when disabled by DPM
     private boolean mCameraDisabledByDpm;
 
     // performs manual animation in sync with layout transitions
     private final NavTransitionListener mTransitionListener = new NavTransitionListener();
 
+    private final PowerManager mPowerManager;
+
     private class NavTransitionListener implements TransitionListener {
         private boolean mBackTransitioning;
         private boolean mHomeAppearing;
@@ -155,22 +165,73 @@
         }
     };
 
+    private final int mScaledTouchSlop;
+
     private final OnTouchListener mCameraTouchListener = new OnTouchListener() {
+        private float mStartX;
+        private boolean mTouchSlopReached;
+        private boolean mSkipCancelAnimation;
+
         @Override
-        public boolean onTouch(View cameraButtonView, MotionEvent event) {
+        public boolean onTouch(final View cameraButtonView, MotionEvent event) {
+            float realX = event.getRawX();
             switch (event.getAction()) {
                 case MotionEvent.ACTION_DOWN:
                     // disable search gesture while interacting with camera
                     mDelegateHelper.setDisabled(true);
                     mBarTransitions.setContentVisible(false);
+                    mStartX = realX;
+                    mTouchSlopReached = false;
+                    mSkipCancelAnimation = false;
+                    break;
+                case MotionEvent.ACTION_MOVE:
+                    if (realX > mStartX) {
+                        realX = mStartX;
+                    }
+                    if (realX < mStartX - mCameraDragDistance) {
+                        ((KeyButtonView) cameraButtonView).setPressed(true);
+                        mPowerManager.userActivity(event.getEventTime(), false);
+                    } else {
+                        ((KeyButtonView) cameraButtonView).setPressed(false);
+                    }
+                    if (realX < mStartX - mScaledTouchSlop) {
+                        mTouchSlopReached = true;
+                    }
+                    cameraButtonView.setTranslationX(Math.max(realX - mStartX,
+                            -mCameraDragDistance));
                     break;
                 case MotionEvent.ACTION_UP:
+                    if (realX < mStartX - mCameraDragDistance) {
+                        mContext.startActivityAsUser(
+                                new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE),
+                                UserHandle.CURRENT);
+                    }
+                    if (realX < mStartX - mScaledTouchSlop) {
+                        mTouchSlopReached = true;
+                    }
+                    if (!mTouchSlopReached) {
+                        mSkipCancelAnimation = true;
+                        cameraButtonView.animate().translationX(-mCameraDragDistance / 2).
+                                        setInterpolator(new DecelerateInterpolator()).withEndAction(
+                                new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        cameraButtonView.animate().translationX(0).
+                                                setInterpolator(new AccelerateInterpolator());
+                                    }
+                                });
+                    }
                 case MotionEvent.ACTION_CANCEL:
+                    ((KeyButtonView) cameraButtonView).setPressed(false);
                     mDelegateHelper.setDisabled(false);
                     mBarTransitions.setContentVisible(true);
+                    if (!mSkipCancelAnimation) {
+                        cameraButtonView.animate().translationX(0)
+                                .setInterpolator(new AccelerateInterpolator(2f));
+                    }
                     break;
             }
-            return KeyguardTouchDelegate.getInstance(getContext()).dispatch(event);
+            return true;
         }
     };
 
@@ -235,6 +296,9 @@
         KeyguardTouchDelegate.addListener(mKeyguardConnectionListener);
         mCameraDisabledByDpm = isCameraDisabledByDpm();
         watchForDevicePolicyChanges();
+        mCameraDragDistance = res.getDimension(R.dimen.camera_drag_distance);
+        mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
     }
 
     private void watchForDevicePolicyChanges() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index a3e35d1..324d6f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -151,7 +151,8 @@
         if (DEBUG) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
         mPanelExpandedFractionSum = 0f;
         for (PanelView pv : mPanels) {
-            final boolean visible = pv.getVisibility() == View.VISIBLE;
+            boolean visible = pv.getExpandedHeight() > 0;
+            pv.setVisibility(visible ? View.VISIBLE : View.GONE);
             // adjust any other panels that may be partially visible
             if (pv.getExpandedHeight() > 0f) {
                 if (mState == STATE_CLOSED) {
@@ -166,11 +167,6 @@
                     if (thisFrac == 1f) fullyOpenedPanel = panel;
                 }
             }
-            if (pv.getExpandedHeight() > 0f) {
-                if (!visible) pv.setVisibility(View.VISIBLE);
-            } else {
-                if (visible) pv.setVisibility(View.GONE);
-            }
         }
         mPanelExpandedFractionSum /= mPanels.size();
         if (fullyOpenedPanel != null && !mTracking) {
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 6922ca5..0266144c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -334,6 +334,7 @@
 
         mTimeAnimator = new TimeAnimator();
         mTimeAnimator.setTimeListener(mAnimationCallback);
+        setOnHierarchyChangeListener(mHierarchyListener);
     }
 
     private void loadDimens() {
@@ -630,11 +631,6 @@
         return mViewName;
     }
 
-    @Override
-    protected void onViewAdded(View child) {
-        if (DEBUG) logf("onViewAdded: " + child);
-    }
-
     public View getHandle() {
         return mHandleView;
     }
@@ -651,6 +647,12 @@
         int newHeight = getMeasuredHeight();
         if (newHeight != mMaxPanelHeight) {
             mMaxPanelHeight = newHeight;
+            // If the user isn't actively poking us, let's rubberband to the content
+            if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
+                    && mExpandedHeight > 0 && mExpandedHeight != mMaxPanelHeight
+                    && mMaxPanelHeight > 0) {
+                mExpandedHeight = mMaxPanelHeight;
+            }
         }
         heightMeasureSpec = MeasureSpec.makeMeasureSpec(
                     getDesiredMeasureHeight(), MeasureSpec.AT_MOST);
@@ -828,4 +830,15 @@
                 mTimeAnimator, ((mTimeAnimator!=null && mTimeAnimator.isStarted())?" (started)":"")
         ));
     }
+
+    private final OnHierarchyChangeListener mHierarchyListener = new OnHierarchyChangeListener() {
+        @Override
+        public void onChildViewAdded(View parent, View child) {
+            if (DEBUG) logf("onViewAdded: " + child);
+        }
+
+        @Override
+        public void onChildViewRemoved(View parent, View child) {
+        }
+    };
 }
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 841f3ca..e89544c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -16,14 +16,16 @@
 
 package com.android.systemui.statusbar.phone;
 
+
 import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
 import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.StatusBarManager.windowStateToString;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
+import static com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -61,11 +63,13 @@
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
 import android.view.Display;
 import android.view.Gravity;
+import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
@@ -84,15 +88,20 @@
 import android.widget.TextView;
 
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.DemoMode;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.R;
+import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.InterceptedNotifications;
+import com.android.systemui.statusbar.LatestItemView;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationData.Entry;
+import com.android.systemui.statusbar.NotificationOverflowContainer;
+import com.android.systemui.statusbar.NotificationOverflowIconsView;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -103,10 +112,14 @@
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.RotationLockController;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 
 public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
     static final String TAG = "PhoneStatusBar";
@@ -139,6 +152,9 @@
             View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
     private static final long AUTOHIDE_TIMEOUT_MS = 3000;
 
+    /** The minimum delay in ms between reports of notification visibility. */
+    private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500;
+
     // fling gesture tuning parameters, scaled to display density
     private float mSelfExpandVelocityPx; // classic value: 2000px/s
     private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
@@ -174,6 +190,7 @@
     StatusBarWindowView mStatusBarWindow;
     PhoneStatusBarView mStatusBarView;
     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
+    private StatusBarWindowManager mStatusBarWindowManager;
 
     int mPixelFormat;
     Object mQueueLock = new Object();
@@ -212,9 +229,12 @@
 
     // top bar
     View mNotificationPanelHeader;
+    View mKeyguardStatusView;
+    int mKeyguardMaxNotificationCount;
     View mDateTimeView;
     View mClearButton;
     ImageView mSettingsButton, mNotificationButton;
+    View mKeyguardSettingsFlipButton;
 
     // carrier/wifi label
     private TextView mCarrierLabel;
@@ -337,6 +357,9 @@
     private int mNavigationBarMode;
     private Boolean mScreenOn;
 
+    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private ViewMediatorCallback mKeyguardViewMediatorCallback;
+
     private final Runnable mAutohide = new Runnable() {
         @Override
         public void run() {
@@ -349,10 +372,94 @@
     private Runnable mOnFlipRunnable;
     private InterceptedNotifications mIntercepted;
 
+    private final OnChildLocationsChangedListener mOnChildLocationsChangedListener =
+            new OnChildLocationsChangedListener() {
+        @Override
+        public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout) {
+            userActivity();
+        }
+    };
+
     public void setOnFlipRunnable(Runnable onFlipRunnable) {
         mOnFlipRunnable = onFlipRunnable;
     }
 
+    /** Keys of notifications currently visible to the user. */
+    private final ArraySet<String> mCurrentlyVisibleNotifications = new ArraySet<String>();
+    private long mLastVisibilityReportUptimeMs;
+
+    private static final int VISIBLE_LOCATIONS = ViewState.LOCATION_FIRST_CARD
+            | ViewState.LOCATION_TOP_STACK_PEEKING
+            | ViewState.LOCATION_MAIN_AREA
+            | ViewState.LOCATION_BOTTOM_STACK_PEEKING;
+
+    private final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
+            new OnChildLocationsChangedListener() {
+                @Override
+                public void onChildLocationsChanged(
+                        NotificationStackScrollLayout stackScrollLayout) {
+                    if (mHandler.hasCallbacks(mVisibilityReporter)) {
+                        // Visibilities will be reported when the existing
+                        // callback is executed.
+                        return;
+                    }
+                    // Calculate when we're allowed to run the visibility
+                    // reporter. Note that this timestamp might already have
+                    // passed. That's OK, the callback will just be executed
+                    // ASAP.
+                    long nextReportUptimeMs =
+                            mLastVisibilityReportUptimeMs + VISIBILITY_REPORT_MIN_DELAY_MS;
+                    mHandler.postAtTime(mVisibilityReporter, nextReportUptimeMs);
+                }
+            };
+
+    // Tracks notifications currently visible in mNotificationStackScroller and
+    // emits visibility events via NoMan on changes.
+    private final Runnable mVisibilityReporter = new Runnable() {
+        private final ArrayList<String> mTmpNewlyVisibleNotifications = new ArrayList<String>();
+        private final ArrayList<String> mTmpCurrentlyVisibleNotifications = new ArrayList<String>();
+
+        @Override
+        public void run() {
+            mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis();
+
+            // 1. Loop over mNotificationData entries:
+            //   A. Keep list of visible notifications.
+            //   B. Keep list of previously hidden, now visible notifications.
+            // 2. Compute no-longer visible notifications by removing currently
+            //    visible notifications from the set of previously visible
+            //    notifications.
+            // 3. Report newly visible and no-longer visible notifications.
+            // 4. Keep currently visible notifications for next report.
+            int N = mNotificationData.size();
+            for (int i = 0; i < N; i++) {
+                Entry entry = mNotificationData.get(i);
+                String key = entry.notification.getKey();
+                boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(key);
+                boolean currentlyVisible =
+                        (mStackScroller.getChildLocation(entry.row) & VISIBLE_LOCATIONS) != 0;
+                if (currentlyVisible) {
+                    // Build new set of visible notifications.
+                    mTmpCurrentlyVisibleNotifications.add(key);
+                }
+                if (!previouslyVisible && currentlyVisible) {
+                    mTmpNewlyVisibleNotifications.add(key);
+                }
+            }
+            ArraySet<String> noLongerVisibleNotifications = mCurrentlyVisibleNotifications;
+            noLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications);
+
+            logNotificationVisibilityChanges(
+                    mTmpNewlyVisibleNotifications, noLongerVisibleNotifications);
+
+            mCurrentlyVisibleNotifications.clear();
+            mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications);
+
+            mTmpNewlyVisibleNotifications.clear();
+            mTmpCurrentlyVisibleNotifications.clear();
+        }
+    };
+
     @Override
     public void setZenMode(int mode) {
         super.setZenMode(mode);
@@ -388,6 +495,7 @@
                     Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
                     mHeadsUpObserver);
         }
+        startKeyguard();
     }
 
     // ================================================================================
@@ -494,10 +602,18 @@
         mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
                 R.id.notification_stack_scroller);
         mStackScroller.setLongPressListener(getNotificationLongClicker());
+        mStackScroller.setChildLocationsChangedListener(mOnChildLocationsChangedListener);
+
+        mKeyguardIconOverflowContainer =
+                (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
+                        R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
+        mKeyguardIconOverflowContainer.setOnActivatedListener(this);
+        mStackScroller.addView(mKeyguardIconOverflowContainer);
 
         mExpandedContents = mStackScroller;
 
         mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
+        mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
 
         mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
         mClearButton.setOnClickListener(mClearButtonListener);
@@ -687,6 +803,13 @@
         return mStatusBarView;
     }
 
+    private void startKeyguard() {
+        KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
+        mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
+                mStatusBarWindow, mStatusBarWindowManager);
+        mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
+    }
+
     @Override
     protected void onShowSearchPanel() {
         if (mNavigationBarView != null) {
@@ -764,10 +887,6 @@
         }
     }
 
-    protected int getStatusBarGravity() {
-        return Gravity.TOP | Gravity.FILL_HORIZONTAL;
-    }
-
     public int getStatusBarHeight() {
         if (mNaturalBarHeight < 0) {
             final Resources res = mContext.getResources();
@@ -1024,7 +1143,7 @@
             }
 
             if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0
-                    && !mNotificationPanel.isTracking()) {
+                    && !mNotificationPanel.isTracking() && !mOnKeyguard) {
                 animateCollapsePanels();
             }
         }
@@ -1093,7 +1212,7 @@
         ArrayList<View> toRemove = new ArrayList<View>();
         for (int i=0; i< mStackScroller.getChildCount(); i++) {
             View child = mStackScroller.getChildAt(i);
-            if (!toShow.contains(child)) {
+            if (!toShow.contains(child) && child != mKeyguardIconOverflowContainer) {
                 toRemove.add(child);
             }
         }
@@ -1493,26 +1612,13 @@
 
         // Expand the window to encompass the full screen in anticipation of the drag.
         // This is only possible to do atomically because the status bar is at the top of the screen!
-        WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
-        lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-        lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
-        mWindowManager.updateViewLayout(mStatusBarWindow, lp);
+        mStatusBarWindowManager.setStatusBarExpanded(true);
 
         visibilityChanged(true);
 
         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
     }
 
-    private void releaseFocus() {
-        if (mStatusBarWindow == null) return;
-        WindowManager.LayoutParams lp =
-                (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
-        lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-        lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        mWindowManager.updateViewLayout(mStatusBarWindow, lp);
-    }
-
     public void animateCollapsePanels() {
         animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
     }
@@ -1524,9 +1630,6 @@
                     + " flags=" + flags);
         }
 
-        // release focus immediately to kick off focus change transition
-        releaseFocus();
-
         if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {
             mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
             mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
@@ -1538,6 +1641,10 @@
         }
 
         if (mStatusBarWindow != null) {
+
+            // release focus immediately to kick off focus change transition
+            mStatusBarWindowManager.setStatusBarFocusable(false);
+
             mStatusBarWindow.cancelExpandHelper();
             mStatusBarView.collapseAllPanels(true);
         }
@@ -1796,11 +1903,7 @@
         visibilityChanged(false);
 
         // Shrink the window to the size of the status bar only
-        WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
-        lp.height = getStatusBarHeight();
-        lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-        lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        mWindowManager.updateViewLayout(mStatusBarWindow, lp);
+        mStatusBarWindowManager.setStatusBarExpanded(false);
 
         if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
             setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
@@ -1815,6 +1918,8 @@
         }
 
         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
+
+        showBouncer();
     }
 
     public boolean interceptTouchEvent(MotionEvent event) {
@@ -2303,30 +2408,9 @@
     }
 
     private void addStatusBarWindow() {
-        // Put up the view
-        final int height = getStatusBarHeight();
-
-        // Now that the status bar window encompasses the sliding panel and its
-        // translucent backdrop, the entire thing is made TRANSLUCENT and is
-        // hardware-accelerated.
-        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                height,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR,
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
-                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
-                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
-                PixelFormat.TRANSLUCENT);
-
-        lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-
-        lp.gravity = getStatusBarGravity();
-        lp.setTitle("StatusBar");
-        lp.packageName = mContext.getPackageName();
-
         makeStatusBarView();
-        mWindowManager.addView(mStatusBarWindow, lp);
+        mStatusBarWindowManager = new StatusBarWindowManager(mContext);
+        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
     }
 
     void setNotificationIconVisibility(boolean visible, int anim) {
@@ -2464,8 +2548,6 @@
             }
             else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                 mScreenOn = false;
-                // no waiting!
-                makeExpandedInvisible();
                 notifyNavigationBarScreenOn(false);
                 notifyHeadsUpScreenOn(false);
                 finishBarAnimations();
@@ -2644,9 +2726,46 @@
         mRowMinHeight =  res.getDimensionPixelSize(R.dimen.notification_row_min_height);
         mRowMaxHeight =  res.getDimensionPixelSize(R.dimen.notification_row_max_height);
 
+        mKeyguardMaxNotificationCount = res.getInteger(R.integer.keyguard_max_notification_count);
+
         if (false) Log.v(TAG, "updateResources");
     }
 
+    // Visibility reporting
+
+    @Override
+    protected void visibilityChanged(boolean visible) {
+        if (visible) {
+            mStackScroller.setChildLocationsChangedListener(mNotificationLocationsChangedListener);
+        } else {
+            // Report all notifications as invisible and turn down the
+            // reporter.
+            if (!mCurrentlyVisibleNotifications.isEmpty()) {
+                logNotificationVisibilityChanges(
+                        Collections.<String>emptyList(), mCurrentlyVisibleNotifications);
+                mCurrentlyVisibleNotifications.clear();
+            }
+            mHandler.removeCallbacks(mVisibilityReporter);
+            mStackScroller.setChildLocationsChangedListener(null);
+        }
+        super.visibilityChanged(visible);
+    }
+
+    private void logNotificationVisibilityChanges(
+            Collection<String> newlyVisible, Collection<String> noLongerVisible) {
+        if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) {
+            return;
+        }
+
+        String[] newlyVisibleAr = newlyVisible.toArray(new String[newlyVisible.size()]);
+        String[] noLongerVisibleAr = noLongerVisible.toArray(new String[noLongerVisible.size()]);
+        try {
+            mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr);
+        } catch (RemoteException e) {
+            // Ignore.
+        }
+    }
+
     //
     // tracing
     //
@@ -2815,4 +2934,126 @@
             ((DemoMode)v).dispatchDemoCommand(command, args);
         }
     }
+
+    public boolean isOnKeyguard() {
+        return mOnKeyguard;
+    }
+
+    public void showKeyguard() {
+        mOnKeyguard = true;
+        instantExpandNotificationsPanel();
+        if (isFlippedToSettings()) {
+            flipToNotifications();
+        }
+        mStatusBarWindow.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
+        mKeyguardStatusView.setVisibility(View.VISIBLE);
+        mNotificationPanelHeader.setVisibility(View.GONE);
+        if (mKeyguardSettingsFlipButton == null) {
+            ViewStub flipStub = (ViewStub) mStatusBarWindow.findViewById(R.id.keyguard_flip_stub);
+            mKeyguardSettingsFlipButton = flipStub.inflate();
+            installSettingsButton(mKeyguardSettingsFlipButton);
+        }
+        mKeyguardSettingsFlipButton.setVisibility(View.VISIBLE);
+        mKeyguardSettingsFlipButton.findViewById(R.id.settings_button).setVisibility(View.VISIBLE);
+        mKeyguardSettingsFlipButton.findViewById(R.id.notification_button)
+                .setVisibility(View.INVISIBLE);
+        updateRowStates();
+    }
+
+    public void hideKeyguard() {
+        mOnKeyguard = false;
+        mStatusBarWindow.setSystemUiVisibility(0);
+        mKeyguardStatusView.setVisibility(View.GONE);
+        mNotificationPanelHeader.setVisibility(View.VISIBLE);
+        mKeyguardSettingsFlipButton.setVisibility(View.GONE);
+        updateRowStates();
+    }
+
+    public void userActivity() {
+        if (mOnKeyguard) {
+            mKeyguardViewMediatorCallback.userActivity();
+        }
+    }
+
+    public boolean onBackPressed() {
+        if (mOnKeyguard) {
+            return mStatusBarKeyguardViewManager.onBackPressed();
+        } else {
+            animateCollapsePanels();
+            return true;
+        }
+    }
+
+    private void showBouncer() {
+        if (mOnKeyguard) {
+            mStatusBarKeyguardViewManager.dismiss();
+        }
+    }
+
+    private void instantExpandNotificationsPanel() {
+        mExpandedVisible = true;
+        mNotificationPanel.setExpandedFraction(1);
+    }
+
+    @Override
+    public void onActivated(View view) {
+        userActivity();
+        super.onActivated(view);
+    }
+
+    @Override
+    protected int getMaxKeyguardNotifications() {
+        return mKeyguardMaxNotificationCount;
+    }
+
+    /**
+     * @return a ViewGroup that spans the entire panel which contains the quick settings
+     */
+    public ViewGroup getQuickSettingsOverlayParent() {
+        if (mHasSettingsPanel) {
+            if (mHasFlipSettings) {
+                return mNotificationPanel;
+            } else {
+                return mSettingsPanel;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    private void installSettingsButton(View parent) {
+        final ImageView settingsButton =
+                (ImageView) mStatusBarWindow.findViewById(R.id.settings_button);
+        final ImageView notificationButton =
+                (ImageView) mStatusBarWindow.findViewById(R.id.notification_button);
+        if (settingsButton != null) {
+            settingsButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    animateExpandSettingsPanel();
+                    v.setVisibility(View.INVISIBLE);
+                    notificationButton.setVisibility(View.VISIBLE);
+                }
+            });
+            settingsButton.setVisibility(View.VISIBLE);
+            if (mHasSettingsPanel) {
+                // the settings panel is hiding behind this button
+                settingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
+            } else {
+                // no settings panel, go straight to settings
+                settingsButton.setImageResource(R.drawable.ic_notify_settings);
+            }
+        }
+        if (notificationButton != null) {
+            notificationButton.setVisibility(View.INVISIBLE);
+            notificationButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    flipToNotifications();
+                    v.setVisibility(View.INVISIBLE);
+                    settingsButton.setVisibility(View.VISIBLE);
+                }
+            });
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index d9e3fdf..583fc3e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -37,6 +37,7 @@
 
     PhoneStatusBar mBar;
     int mScrimColor;
+    int mScrimColorKeyguard;
     float mSettingsPanelDragzoneFrac;
     float mSettingsPanelDragzoneMin;
 
@@ -52,6 +53,7 @@
 
         Resources res = getContext().getResources();
         mScrimColor = res.getColor(R.color.notification_panel_scrim_color);
+        mScrimColorKeyguard = res.getColor(R.color.notification_panel_scrim_color_keyguard);
         mSettingsPanelDragzoneMin = res.getDimension(R.dimen.settings_panel_dragzone_min);
         try {
             mSettingsPanelDragzoneFrac = res.getFraction(R.dimen.settings_panel_dragzone_fraction, 1, 1);
@@ -217,6 +219,7 @@
         if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx()
                 && mBar.mStatusBarWindow != null) {
             if (mShouldFade) {
+                int scrimColor = mBar.isOnKeyguard() ? mScrimColorKeyguard : mScrimColor;
                 frac = mPanelExpandedFractionSum; // don't judge me
                 // let's start this 20% of the way down the screen
                 frac = frac * 1.2f - 0.2f;
@@ -226,7 +229,7 @@
                     // woo, special effects
                     final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
                     // attenuate background color alpha by k
-                    final int color = (int) ((mScrimColor >>> 24) * k) << 24 | (mScrimColor & 0xFFFFFF);
+                    final int color = (int) ((scrimColor >>> 24) * k) << 24 | (scrimColor & 0xFFFFFF);
                     mBar.mStatusBarWindow.setBackgroundColor(color);
                 }
             }
@@ -249,5 +252,6 @@
         mBar.animateHeadsUp(mNotificationPanel == panel, mPanelExpandedFractionSum);
 
         mBar.updateCarrierLabelVisibility(false);
+        mBar.userActivity();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index d67f7cd..b3fba76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -71,6 +71,7 @@
 
 import com.android.internal.app.MediaRouteDialogPresenter;
 import com.android.systemui.R;
+import com.android.systemui.settings.UserSwitcherHostView;
 import com.android.systemui.statusbar.phone.QuickSettingsModel.ActivityState;
 import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
 import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
@@ -310,30 +311,28 @@
         collapsePanels();
     }
 
-    private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
+    private void addUserTiles(final ViewGroup parent, final LayoutInflater inflater) {
         QuickSettingsTileView userTile = (QuickSettingsTileView)
                 inflater.inflate(R.layout.quick_settings_tile, parent, false);
         userTile.setContent(R.layout.quick_settings_tile_user, inflater);
         userTile.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                collapsePanels();
                 final UserManager um = UserManager.get(mContext);
                 if (um.isUserSwitcherEnabled()) {
-                    // Since keyguard and systemui were merged into the same process to save
-                    // memory, they share the same Looper and graphics context.  As a result,
-                    // there's no way to allow concurrent animation while keyguard inflates.
-                    // The workaround is to add a slight delay to allow the animation to finish.
-                    mHandler.postDelayed(new Runnable() {
+                    final ViewGroup switcherParent = getService().getQuickSettingsOverlayParent();
+                    final UserSwitcherHostView switcher = (UserSwitcherHostView) inflater.inflate(
+                            R.layout.user_switcher_host, switcherParent, false);
+                    switcher.setFinishRunnable(new Runnable() {
+                        @Override
                         public void run() {
-                            try {
-                                WindowManagerGlobal.getWindowManagerService().lockNow(null);
-                            } catch (RemoteException e) {
-                                Log.e(TAG, "Couldn't show user switcher", e);
-                            }
+                            switcherParent.removeView(switcher);
                         }
-                    }, 400); // TODO: ideally this would be tied to the collapse of the panel
+                    });
+                    switcher.refreshUsers();
+                    switcherParent.addView(switcher);
                 } else {
+                    collapsePanels();
                     Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
                             mContext, v, ContactsContract.Profile.CONTENT_URI,
                             ContactsContract.QuickContact.MODE_LARGE, null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
new file mode 100644
index 0000000..b8592c3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -0,0 +1,194 @@
+/*
+ * 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 com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+
+import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardSimpleHostView;
+import com.android.keyguard.R;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+
+/**
+ * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
+ * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
+ * which is in turn, reported to this class by the current
+ * {@link com.android.keyguard.KeyguardViewBase}.
+ */
+public class StatusBarKeyguardViewManager {
+    private static String TAG = "StatusBarKeyguardViewManager";
+
+    private final Context mContext;
+
+    private LockPatternUtils mLockPatternUtils;
+    private ViewMediatorCallback mViewMediatorCallback;
+    private PhoneStatusBar mPhoneStatusBar;
+
+    private ViewGroup mContainer;
+    private StatusBarWindowManager mStatusBarWindowManager;
+
+    private boolean mScreenOn = false;
+    private KeyguardBouncer mBouncer;
+    private boolean mShowing;
+
+    public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
+            LockPatternUtils lockPatternUtils) {
+        mContext = context;
+        mViewMediatorCallback = callback;
+        mLockPatternUtils = lockPatternUtils;
+    }
+
+    public void registerStatusBar(PhoneStatusBar phoneStatusBar,
+            ViewGroup container, StatusBarWindowManager statusBarWindowManager) {
+        mPhoneStatusBar = phoneStatusBar;
+        mContainer = container;
+        mStatusBarWindowManager = statusBarWindowManager;
+        mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,
+                mStatusBarWindowManager, container);
+    }
+
+    /**
+     * Show the keyguard.  Will handle creating and attaching to the view manager
+     * lazily.
+     */
+    public void show(Bundle options) {
+        mShowing = true;
+        mStatusBarWindowManager.setKeyguardShowing(true);
+        mPhoneStatusBar.showKeyguard();
+        mBouncer.prepare();
+        updateBackButtonState();
+    }
+
+    public void showBouncer() {
+        mBouncer.show();
+        updateBackButtonState();
+    }
+
+    /**
+     * Reset the state of the view.
+     */
+    public void reset() {
+        mBouncer.reset();
+        mPhoneStatusBar.showKeyguard();
+        updateBackButtonState();
+    }
+
+    public void onScreenTurnedOff() {
+        mScreenOn = false;
+        mBouncer.onScreenTurnedOff();
+    }
+
+    public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
+        mScreenOn = true;
+        mBouncer.onScreenTurnedOn();
+        if (callback != null) {
+            callbackAfterDraw(callback);
+        }
+    }
+
+    private void callbackAfterDraw(final IKeyguardShowCallback callback) {
+        mContainer.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    callback.onShown(mContainer.getWindowToken());
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Exception calling onShown():", e);
+                }
+            }
+        });
+    }
+
+    public void verifyUnlock() {
+        dismiss();
+    }
+
+    public void setNeedsInput(boolean needsInput) {
+        mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
+    }
+
+    public void updateUserActivityTimeout() {
+        mStatusBarWindowManager.setKeyguardUserActivityTimeout(mBouncer.getUserActivityTimeout());
+    }
+
+    public void setOccluded(boolean occluded) {
+        mStatusBarWindowManager.setKeyguardOccluded(occluded);
+    }
+
+    /**
+     * Hides the keyguard view
+     */
+    public void hide() {
+        mShowing = false;
+        mPhoneStatusBar.hideKeyguard();
+        mStatusBarWindowManager.setKeyguardShowing(false);
+        mBouncer.hide();
+        mViewMediatorCallback.keyguardGone();
+    }
+
+    /**
+     * Dismisses the keyguard by going to the next screen or making it gone.
+     */
+    public void dismiss() {
+        if (mScreenOn) {
+            showBouncer();
+        }
+    }
+
+    /**
+     * @return Whether the keyguard is showing
+     */
+    public boolean isShowing() {
+        return mShowing;
+    }
+
+    /**
+     * Notifies this manager that the back button has been pressed.
+     *
+     * @return whether the back press has been handled
+     */
+    public boolean onBackPressed() {
+        if (mBouncer.isShowing()) {
+            mBouncer.hide();
+            mPhoneStatusBar.showKeyguard();
+            updateBackButtonState();
+            return true;
+        }
+        return false;
+    }
+
+    private void updateBackButtonState() {
+        int vis = mContainer.getSystemUiVisibility();
+        if (mBouncer.isShowing()) {
+            mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK);
+        } else {
+            mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
new file mode 100644
index 0000000..6153cde
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -0,0 +1,200 @@
+/*
+ * 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 com.android.systemui.statusbar.phone;
+
+import android.app.ActionBar;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.SystemProperties;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.android.keyguard.R;
+
+/**
+ * Encapsulates all logic for the status bar window state management.
+ */
+public class StatusBarWindowManager {
+
+    private final Context mContext;
+    private final WindowManager mWindowManager;
+    private View mStatusBarView;
+    private WindowManager.LayoutParams mLp;
+    private int mBarHeight;
+    private final boolean mKeyguardScreenRotation;
+
+    private final State mCurrentState = new State();
+
+    public StatusBarWindowManager(Context context) {
+        mContext = context;
+        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
+    }
+
+    private boolean shouldEnableKeyguardScreenRotation() {
+        Resources res = mContext.getResources();
+        return SystemProperties.getBoolean("lockscreen.rot_override", false)
+                || res.getBoolean(R.bool.config_enableLockScreenRotation);
+    }
+
+    /**
+     * Adds the status bar view to the window manager.
+     *
+     * @param statusBarView The view to add.
+     * @param barHeight The height of the status bar in collapsed state.
+     */
+    public void add(View statusBarView, int barHeight) {
+
+        // Now that the status bar window encompasses the sliding panel and its
+        // translucent backdrop, the entire thing is made TRANSLUCENT and is
+        // hardware-accelerated.
+        mLp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                barHeight,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                        | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
+                        | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
+                PixelFormat.TRANSLUCENT);
+
+        mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        mLp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+        mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+        mLp.setTitle("StatusBar");
+        mLp.packageName = mContext.getPackageName();
+        mStatusBarView = statusBarView;
+        mBarHeight = barHeight;
+        mWindowManager.addView(mStatusBarView, mLp);
+    }
+
+    private void applyKeyguardFlags(State state) {
+        if (state.keyguardShowing) {
+            mLp.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+            mLp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+        } else {
+            mLp.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+            mLp.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+        }
+    }
+
+    private void adjustScreenOrientation(State state) {
+        if (!state.isKeyguardShowingAndNotOccluded() || mKeyguardScreenRotation) {
+            mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
+        } else {
+            mLp.screenOrientation =  ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+        }
+    }
+
+    private void applyFocusableFlag(State state) {
+        if (state.isKeyguardShowingAndNotOccluded() && state.keyguardNeedsInput) {
+            mLp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+        } else if (state.isKeyguardShowingAndNotOccluded() || state.statusBarFocusable) {
+            mLp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+        } else {
+            mLp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+        }
+    }
+
+    private void applyHeight(State state) {
+        boolean expanded = state.isKeyguardShowingAndNotOccluded() || state.statusBarExpanded;
+        if (expanded) {
+            mLp.height = ViewGroup.LayoutParams.MATCH_PARENT;
+        } else {
+            mLp.height = mBarHeight;
+        }
+    }
+
+    private void applyUserActivityTimeout(State state) {
+        if (state.isKeyguardShowingAndNotOccluded()) {
+            mLp.userActivityTimeout = state.keyguardUserActivityTimeout;
+        } else {
+            mLp.userActivityTimeout = -1;
+        }
+    }
+
+    private void applyInputFeatures(State state) {
+        if (state.isKeyguardShowingAndNotOccluded()) {
+            mLp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+        } else {
+            mLp.inputFeatures &= ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+        }
+    }
+
+    private void apply(State state) {
+        applyKeyguardFlags(state);
+        applyFocusableFlag(state);
+        adjustScreenOrientation(state);
+        applyHeight(state);
+        applyUserActivityTimeout(state);
+        applyInputFeatures(state);
+        mWindowManager.updateViewLayout(mStatusBarView, mLp);
+    }
+
+    public void setKeyguardShowing(boolean showing) {
+        mCurrentState.keyguardShowing = showing;
+        apply(mCurrentState);
+    }
+
+    public void setKeyguardOccluded(boolean occluded) {
+        mCurrentState.keyguardOccluded = occluded;
+        apply(mCurrentState);
+    }
+
+    public void setKeyguardNeedsInput(boolean needsInput) {
+        mCurrentState.keyguardNeedsInput = needsInput;
+        apply(mCurrentState);
+    }
+
+    public void setStatusBarExpanded(boolean expanded) {
+        mCurrentState.statusBarExpanded = expanded;
+        mCurrentState.statusBarFocusable = expanded;
+        apply(mCurrentState);
+    }
+
+    public void setStatusBarFocusable(boolean focusable) {
+        mCurrentState.statusBarFocusable = focusable;
+        apply(mCurrentState);
+    }
+
+    public void setKeyguardUserActivityTimeout(long timeout) {
+        mCurrentState.keyguardUserActivityTimeout = timeout;
+        apply(mCurrentState);
+    }
+
+    private static class State {
+        boolean keyguardShowing;
+        boolean keyguardOccluded;
+        boolean keyguardNeedsInput;
+        boolean statusBarExpanded;
+        boolean statusBarFocusable;
+        long keyguardUserActivityTimeout;
+
+        private boolean isKeyguardShowingAndNotOccluded() {
+            return keyguardShowing && !keyguardOccluded;
+        }
+    }
+}
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 a7121c4..dd89f47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -79,7 +79,7 @@
         switch (event.getKeyCode()) {
         case KeyEvent.KEYCODE_BACK:
             if (!down) {
-                mService.animateCollapsePanels();
+                mService.onBackPressed();
             }
             return true;
         }
@@ -90,7 +90,8 @@
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         boolean intercept = false;
         if (mNotificationPanel.isFullyExpanded()
-                && mStackScrollLayout.getVisibility() == View.VISIBLE) {
+                && mStackScrollLayout.getVisibility() == View.VISIBLE
+                && !mService.isOnKeyguard()) {
             intercept = mExpandHelper.onInterceptTouchEvent(ev);
         }
         if (!intercept) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index f31896a..9800bc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -656,9 +656,11 @@
         int height = 0;
         for (int i = 0; i < getChildCount(); i++) {
             View child = getChildAt(i);
-            height += child.getHeight();
-            if (i < getChildCount()-1) {
-                height += mPaddingBetweenElements;
+            if (child.getVisibility() != View.GONE) {
+                height += child.getHeight();
+                if (i < getChildCount()-1) {
+                    height += mPaddingBetweenElements;
+                }
             }
         }
         mContentHeight = height;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 5506a55..431f6fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -23,6 +23,8 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 
+import java.util.ArrayList;
+
 /**
  * The Algorithm of the {@link com.android.systemui.statusbar.stack
  * .NotificationStackScrollLayout} which can be queried for {@link com.android.systemui.statusbar
@@ -98,6 +100,7 @@
         algorithmState.lastTopStackIndex = 0;
         algorithmState.scrollY = resultState.getScrollY();
         algorithmState.itemsInBottomStack = 0.0f;
+        updateVisibleChildren(resultState, algorithmState);
 
         // Phase 1:
         findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState);
@@ -113,6 +116,23 @@
     }
 
     /**
+     * Update the visible children on the state.
+     */
+    private void updateVisibleChildren(StackScrollState resultState,
+            StackScrollAlgorithmState state) {
+        ViewGroup hostView = resultState.getHostView();
+        int childCount = hostView.getChildCount();
+        state.visibleChildren.clear();
+        state.visibleChildren.ensureCapacity(childCount);
+        for (int i = 0; i < childCount; i++) {
+            View v = hostView.getChildAt(i);
+            if (v.getVisibility() != View.GONE) {
+                state.visibleChildren.add(v);
+            }
+        }
+    }
+
+    /**
      * Determine the positions for the views. This is the main part of the algorithm.
      *
      * @param resultState The result state to update if a change to the properties of a child occurs
@@ -135,11 +155,10 @@
         // How far in is the element currently transitioning into the bottom stack.
         float yPositionInScrollView = 0.0f;
 
-        ViewGroup hostView = resultState.getHostView();
-        int childCount = hostView.getChildCount();
+        int childCount = algorithmState.visibleChildren.size();
         int numberOfElementsCompletelyIn = (int) algorithmState.itemsInTopStack;
         for (int i = 0; i < childCount; i++) {
-            View child = hostView.getChildAt(i);
+            View child = algorithmState.visibleChildren.get(i);
             StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
             childViewState.yTranslation = currentYPosition;
             childViewState.location = StackScrollState.ViewState.LOCATION_UNKNOWN;
@@ -317,12 +336,11 @@
 
         // The y Position if the element would be in a regular scrollView
         float yPositionInScrollView = 0.0f;
-        ViewGroup hostView = resultState.getHostView();
-        int childCount = hostView.getChildCount();
+        int childCount = algorithmState.visibleChildren.size();
 
         // find the number of elements in the top stack.
         for (int i = 0; i < childCount; i++) {
-            View child = hostView.getChildAt(i);
+            View child = algorithmState.visibleChildren.get(i);
             StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
             int childHeight = child.getHeight();
             float yPositionInScrollViewAfterElement = yPositionInScrollView
@@ -397,10 +415,9 @@
      */
     private void updateZValuesForState(StackScrollState resultState,
             StackScrollAlgorithmState algorithmState) {
-        ViewGroup hostView = resultState.getHostView();
-        int childCount = hostView.getChildCount();
+        int childCount = algorithmState.visibleChildren.size();
         for (int i = 0; i < childCount; i++) {
-            View child = hostView.getChildAt(i);
+            View child = algorithmState.visibleChildren.get(i);
             StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
             if (i < algorithmState.itemsInTopStack) {
                 float stackIndex = algorithmState.itemsInTopStack - i;
@@ -434,8 +451,8 @@
     }
 
     private void updateFirstChildHeightWhileExpanding(ViewGroup hostView) {
-        if (hostView.getChildCount() > 0) {
-            mFirstChildWhileExpanding = hostView.getChildAt(0);
+        mFirstChildWhileExpanding = findFirstVisibleChild(hostView);
+        if (mFirstChildWhileExpanding != null) {
             if (mExpandedOnStart) {
 
                 // We are collapsing the shade, so the first child can get as most as high as the
@@ -447,11 +464,21 @@
                 mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
             }
         } else {
-            mFirstChildWhileExpanding = null;
             mFirstChildMaxHeight = 0;
         }
     }
 
+    private View findFirstVisibleChild(ViewGroup container) {
+        int childCount = container.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = container.getChildAt(i);
+            if (child.getVisibility() != View.GONE) {
+                return child;
+            }
+        }
+        return null;
+    }
+
     public void onExpansionStopped() {
         mIsExpansionChanging = false;
         mFirstChildWhileExpanding = null;
@@ -501,6 +528,11 @@
          * how far in is the element currently transitioning into the bottom stack
          */
         public float partialInBottom;
+
+        /**
+         * The children from the host view which are not gone.
+         */
+        public final ArrayList<View> visibleChildren = new ArrayList<View>();
     }
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 67a1735..06a08f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -63,7 +63,8 @@
             }
             // initialize with the default values of the view
             viewState.height = child.getHeight();
-            viewState.alpha = 1.0f;
+            viewState.alpha = 1;
+            viewState.gone = child.getVisibility() == View.GONE;
         }
     }
 
@@ -116,7 +117,7 @@
                 // apply visibility
                 int oldVisibility = child.getVisibility();
                 int newVisibility = becomesInvisible ? View.INVISIBLE : View.VISIBLE;
-                if (newVisibility != oldVisibility) {
+                if (newVisibility != oldVisibility && !state.gone) {
                     child.setVisibility(newVisibility);
                 }
 
@@ -164,6 +165,7 @@
         float yTranslation;
         float zTranslation;
         int height;
+        boolean gone;
 
         /**
          * The location this view is currently rendered at.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index dd13e31..d615542 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -22,6 +22,7 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 
+import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.statusbar.BaseStatusBar;
 
@@ -93,10 +94,6 @@
     }
 
     @Override
-    protected void createAndAddWindows() {
-    }
-
-    @Override
     protected WindowManager.LayoutParams getSearchLayoutParams(
             LayoutParams layoutParams) {
         return null;
@@ -141,10 +138,19 @@
     }
 
     @Override
+    protected int getMaxKeyguardNotifications() {
+        return 0;
+    }
+
+    @Override
     public void animateExpandSettingsPanel() {
     }
 
     @Override
+    protected void createAndAddWindows() {
+    }
+
+    @Override
     protected void refreshLayout(int layoutDirection) {
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 216f6a4..77e2462 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -96,6 +96,8 @@
 import android.view.animation.AnimationUtils;
 
 import com.android.internal.R;
+import com.android.internal.policy.IKeyguardService;
+import com.android.internal.policy.IKeyguardServiceConstants;
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate;
 import com.android.internal.statusbar.IStatusBarService;
@@ -174,6 +176,8 @@
      * Keyguard stuff
      */
     private WindowState mKeyguardScrim;
+    private boolean mKeyguardHidden;
+    private boolean mKeyguardDrawn;
 
     /* Table of Application Launch keys.  Maps from key codes to intent categories.
      *
@@ -248,7 +252,6 @@
     int[] mNavigationBarHeightForRotation = new int[4];
     int[] mNavigationBarWidthForRotation = new int[4];
 
-    WindowState mKeyguard = null;
     KeyguardServiceDelegate mKeyguardDelegate;
     GlobalActions mGlobalActions;
     volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
@@ -1311,7 +1314,6 @@
             case TYPE_BOOT_PROGRESS:
             case TYPE_DISPLAY_OVERLAY:
             case TYPE_HIDDEN_NAV_CONSUMER:
-            case TYPE_KEYGUARD:
             case TYPE_KEYGUARD_SCRIM:
             case TYPE_KEYGUARD_DIALOG:
             case TYPE_MAGNIFICATION_OVERLAY:
@@ -1348,6 +1350,22 @@
                         | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
                 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
                 break;
+            case TYPE_STATUS_BAR:
+
+                // If the Keyguard is in a hidden state (occluded by another window), we force to
+                // remove the wallpaper and keyguard flag so that any change in-flight after setting
+                // the keyguard as occluded wouldn't set these flags again.
+                // See {@link #processKeyguardSetHiddenResultLw}.
+                if (mKeyguardHidden) {
+                    attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+                    attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+                }
+                break;
+        }
+
+        if (attrs.type != TYPE_STATUS_BAR) {
+            // The status bar is the only window allowed to exhibit keyguard behavior.
+            attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         }
     }
     
@@ -1434,54 +1452,50 @@
         case TYPE_KEYGUARD_SCRIM:
             // the safety window that shows behind keyguard while keyguard is starting
             return 12;
-        case TYPE_KEYGUARD:
-            // the keyguard; nothing on top of these can take focus, since they are
-            // responsible for power management when displayed.
-            return 13;
-        case TYPE_KEYGUARD_DIALOG:
-            return 14;
         case TYPE_STATUS_BAR_SUB_PANEL:
-            return 15;
+            return 13;
         case TYPE_STATUS_BAR:
-            return 16;
+            return 14;
         case TYPE_STATUS_BAR_PANEL:
-            return 17;
+            return 15;
+        case TYPE_KEYGUARD_DIALOG:
+            return 16;
         case TYPE_VOLUME_OVERLAY:
             // the on-screen volume indicator and controller shown when the user
             // changes the device volume
-            return 18;
+            return 17;
         case TYPE_SYSTEM_OVERLAY:
             // the on-screen volume indicator and controller shown when the user
             // changes the device volume
-            return 19;
+            return 18;
         case TYPE_NAVIGATION_BAR:
             // the navigation bar, if available, shows atop most things
-            return 20;
+            return 19;
         case TYPE_NAVIGATION_BAR_PANEL:
             // some panels (e.g. search) need to show on top of the navigation bar
-            return 21;
+            return 20;
         case TYPE_SYSTEM_ERROR:
             // system-level error dialogs
-            return 22;
+            return 21;
         case TYPE_MAGNIFICATION_OVERLAY:
             // used to highlight the magnified portion of a display
-            return 23;
+            return 22;
         case TYPE_DISPLAY_OVERLAY:
             // used to simulate secondary display devices
-            return 24;
+            return 23;
         case TYPE_DRAG:
             // the drag layer: input for drag-and-drop is associated with this window,
             // which sits above all other focusable windows
-            return 25;
+            return 24;
         case TYPE_SECURE_SYSTEM_OVERLAY:
-            return 26;
+            return 25;
         case TYPE_BOOT_PROGRESS:
-            return 27;
+            return 26;
         case TYPE_POINTER:
             // the (mouse) pointer layer
-            return 28;
+            return 27;
         case TYPE_HIDDEN_NAV_CONSUMER:
-            return 29;
+            return 28;
         }
         Log.e(TAG, "Unknown window type: " + type);
         return 2;
@@ -1551,7 +1565,7 @@
 
     @Override
     public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
-        return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
+        return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
     }
 
     @Override
@@ -1562,7 +1576,6 @@
             case TYPE_WALLPAPER:
             case TYPE_DREAM:
             case TYPE_UNIVERSE_BACKGROUND:
-            case TYPE_KEYGUARD:
             case TYPE_KEYGUARD_SCRIM:
                 return false;
             default:
@@ -1761,12 +1774,6 @@
                         android.Manifest.permission.STATUS_BAR_SERVICE,
                         "PhoneWindowManager");
                 break;
-            case TYPE_KEYGUARD:
-                if (mKeyguard != null) {
-                    return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
-                }
-                mKeyguard = win;
-                break;
             case TYPE_KEYGUARD_SCRIM:
                 if (mKeyguardScrim != null) {
                     return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
@@ -1783,9 +1790,6 @@
         if (mStatusBar == win) {
             mStatusBar = null;
             mStatusBarController.setWindow(null);
-        } else if (mKeyguard == win) {
-            Log.v(TAG, "Removing keyguard window (Did it crash?)");
-            mKeyguard = null;
             mKeyguardDelegate.showScrim();
         } else if (mKeyguardScrim == win) {
             Log.v(TAG, "Removing keyguard scrim");
@@ -1804,12 +1808,13 @@
         if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
               + ": transit=" + transit);
         if (win == mStatusBar) {
+            boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
             if (transit == TRANSIT_EXIT
                     || transit == TRANSIT_HIDE) {
-                return R.anim.dock_top_exit;
+                return isKeyguard ? -1 : R.anim.dock_top_exit;
             } else if (transit == TRANSIT_ENTER
                     || transit == TRANSIT_SHOW) {
-                return R.anim.dock_top_enter;
+                return isKeyguard ? -1 : R.anim.dock_top_enter;
             }
         } else if (win == mNavigationBar) {
             // This can be on either the bottom or the right.
@@ -2030,9 +2035,9 @@
             WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
             if (attrs != null) {
                 final int type = attrs.type;
-                if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
-                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
-                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
+                if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
+                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
+                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                     // the "app" is keyguard, so give it the key
                     return 0;
                 }
@@ -2461,7 +2466,7 @@
      * given the situation with the keyguard.
      */
     void launchHomeFromHotKey() {
-        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotHidden()) {
+        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotOccluded()) {
             // don't launch home if keyguard showing
         } else if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
             // when in keyguard restricted mode, must first verify unlock
@@ -3083,9 +3088,8 @@
                                 + mOverscanScreenHeight;
                     } else if (canHideNavigationBar()
                             && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
-                            && (attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD || (
-                                attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
-                             && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
+                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
+                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                         // Asking for layout as if the nav bar is hidden, lets the
                         // application extend into the unrestricted overscan screen area.  We
                         // only do this for application windows to ensure no window that
@@ -3392,16 +3396,19 @@
             mForcingShowNavBar = true;
             mForcingShowNavBarLayer = win.getSurfaceLayer();
         }
+        if (attrs.type == TYPE_STATUS_BAR && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+            mForceStatusBarFromKeyguard = true;
+        }
         if (mTopFullscreenOpaqueWindowState == null &&
                 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
             if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
-                if (attrs.type == TYPE_KEYGUARD) {
+                if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                     mForceStatusBarFromKeyguard = true;
                 } else {
                     mForceStatusBar = true;
                 }
             }
-            if (attrs.type == TYPE_KEYGUARD) {
+            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                 mShowingLockscreen = true;
             }
             boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
@@ -3531,11 +3538,12 @@
 
         // Hide the key guard if a visible window explicitly specifies that it wants to be
         // displayed when the screen is locked.
-        if (mKeyguard != null) {
+        if (mKeyguardDelegate != null && mStatusBar != null) {
             if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
                     + mHideLockScreen);
             if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !isKeyguardSecure()) {
-                if (mKeyguard.hideLw(true)) {
+                mKeyguardHidden = true;
+                if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
                             | FINISH_LAYOUT_REDO_WALLPAPER;
@@ -3549,24 +3557,22 @@
                     });
                 }
             } else if (mHideLockScreen) {
-                if (mKeyguard.hideLw(true)) {
+                mKeyguardHidden = true;
+                if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
                             | FINISH_LAYOUT_REDO_WALLPAPER;
                 }
-                if (!mShowingDream) {
-                    mKeyguardDelegate.setHidden(true);
-                }
             } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
                 // This is the case of keyguard isSecure() and not mHideLockScreen.
                 if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
                     // Only launch the next keyguard unlock window once per window.
-                    if (mKeyguard.showLw(true)) {
+                    mKeyguardHidden = false;
+                    if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) {
                         changes |= FINISH_LAYOUT_REDO_LAYOUT
                                 | FINISH_LAYOUT_REDO_CONFIG
                                 | FINISH_LAYOUT_REDO_WALLPAPER;
                     }
-                    mKeyguardDelegate.setHidden(false);
                     mHandler.post(new Runnable() {
                         @Override
                         public void run() {
@@ -3576,12 +3582,12 @@
                 }
             } else {
                 mWinDismissingKeyguard = null;
-                if (mKeyguard.showLw(true)) {
+                mKeyguardHidden = false;
+                if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
                             | FINISH_LAYOUT_REDO_WALLPAPER;
                 }
-                mKeyguardDelegate.setHidden(false);
             }
         }
 
@@ -3596,9 +3602,39 @@
         return changes;
     }
 
+    /**
+     * Processes the result code of {@link IKeyguardService#setOccluded}. This is needed because we
+     * immediately need to put the wallpaper directly behind the Keyguard when a window with flag
+     * {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} gets dismissed. If we
+     * would wait for Keyguard to change the flags, that would be running asynchronously and thus be
+     * too late so the user might see the window behind.
+     *
+     * @param setHiddenResult The result code from {@link IKeyguardService#setOccluded}.
+     * @return Whether the flags have changed and we have to redo the layout.
+     */
+    private boolean processKeyguardSetHiddenResultLw(int setHiddenResult) {
+        if (setHiddenResult
+                == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS) {
+            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
+            mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+            return true;
+        } else if (setHiddenResult
+                == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS) {
+            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
+            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private boolean isStatusBarKeyguard() {
+        return mStatusBar != null
+                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
+    }
+
     public boolean allowAppAnimationsLw() {
-        if (mKeyguard != null && mKeyguard.isVisibleLw() && !mKeyguard.isAnimatingLw()
-                || mShowingDream) {
+        if (isStatusBarKeyguard() || mShowingDream) {
             // If keyguard or dreams is currently visible, no reason to animate behind it.
             return false;
         }
@@ -3820,7 +3856,7 @@
         // when the keyguard is hidden by another activity.
         final boolean keyguardActive = (mKeyguardDelegate == null ? false :
                                             (interactive ?
-                                                mKeyguardDelegate.isShowingAndNotHidden() :
+                                                mKeyguardDelegate.isShowingAndNotOccluded() :
                                                 mKeyguardDelegate.isShowing()));
 
         if (keyCode == KeyEvent.KEYCODE_POWER
@@ -4319,21 +4355,16 @@
 
     private void waitForKeyguard(final ScreenOnListener screenOnListener) {
         if (mKeyguardDelegate != null) {
-            if (screenOnListener != null) {
-                mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() {
-                    @Override
-                    public void onShown(IBinder windowToken) {
-                        waitForKeyguardWindowDrawn(windowToken, screenOnListener);
-                    }
-                });
-                return;
-            } else {
-                mKeyguardDelegate.onScreenTurnedOn(null);
-            }
+            mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() {
+                @Override
+                public void onShown(IBinder windowToken) {
+                    waitForKeyguardWindowDrawn(windowToken, screenOnListener);
+                }
+            });
         } else {
             Slog.i(TAG, "No keyguard interface!");
+            finishScreenTurningOn(screenOnListener);
         }
-        finishScreenTurningOn(screenOnListener);
     }
 
     private void waitForKeyguardWindowDrawn(IBinder windowToken,
@@ -4346,6 +4377,7 @@
                     public void sendResult(Bundle data) {
                         Slog.i(TAG, "Lock screen displayed!");
                         finishScreenTurningOn(screenOnListener);
+                        setKeyguardDrawn();
                     }
                 })) {
                     return;
@@ -4359,6 +4391,7 @@
 
         Slog.i(TAG, "No lock screen! windowToken=" + windowToken);
         finishScreenTurningOn(screenOnListener);
+        setKeyguardDrawn();
     }
 
     private void finishScreenTurningOn(ScreenOnListener screenOnListener) {
@@ -4402,7 +4435,7 @@
 
     private boolean keyguardIsShowingTq() {
         if (mKeyguardDelegate == null) return false;
-        return mKeyguardDelegate.isShowingAndNotHidden();
+        return mKeyguardDelegate.isShowingAndNotOccluded();
     }
 
 
@@ -4439,6 +4472,23 @@
         }
     }
 
+    private void setKeyguardDrawn() {
+        synchronized (mLock) {
+            mKeyguardDrawn = true;
+        }
+        try {
+            mWindowManager.enableScreenIfNeeded();
+        } catch (RemoteException unhandled) {
+        }
+    }
+
+    @Override
+    public boolean isKeyguardDrawnLw() {
+        synchronized (mLock) {
+            return mKeyguardDrawn;
+        }
+    }
+
     void sendCloseSystemWindows() {
         sendCloseSystemWindows(mContext, null);
     }
@@ -4722,6 +4772,7 @@
         synchronized (mLock) {
             mSystemBooted = true;
         }
+        waitForKeyguard(null);
     }
 
     ProgressDialog mBootMsgDialog = null;
@@ -5046,7 +5097,7 @@
         }
         final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
-        if (!always && (hapticsDisabled || mKeyguardDelegate.isShowingAndNotHidden())) {
+        if (!always && (hapticsDisabled || mKeyguardDelegate.isShowingAndNotOccluded())) {
             return false;
         }
         long[] pattern = null;
@@ -5097,7 +5148,7 @@
 
     @Override
     public void keepScreenOnStoppedLw() {
-        if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotHidden()) {
+        if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotOccluded()) {
             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
         }
     }
@@ -5109,7 +5160,7 @@
         if (win == null) {
             return 0;
         }
-        if (win.getAttrs().type == TYPE_KEYGUARD && mHideLockScreen == true) {
+        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
             // We are updating at a point where the keyguard has gotten
             // focus, but we were last in a state where the top window is
             // hiding it.  This is probably because the keyguard as been
@@ -5155,8 +5206,8 @@
 
     private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
         // apply translucent bar vis flags
-        WindowState transWin = mKeyguard != null && mKeyguard.isVisibleLw() && !mHideLockScreen
-                ? mKeyguard
+        WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
+                ? mStatusBar
                 : mTopFullscreenOpaqueWindowState;
         vis = mStatusBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
         vis = mNavigationBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
@@ -5167,9 +5218,10 @@
             int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                     | View.SYSTEM_UI_FLAG_IMMERSIVE
-                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
-                    | View.STATUS_BAR_TRANSLUCENT
-                    | View.NAVIGATION_BAR_TRANSLUCENT;
+                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+            if (!isStatusBarKeyguard() || mHideLockScreen) {
+                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
+            }
             vis = (vis & ~flags) | (oldVis & flags);
         }
 
@@ -5414,15 +5466,13 @@
         if (mStatusBar != null) {
             pw.print(prefix); pw.print("mStatusBar=");
                     pw.println(mStatusBar);
+            pw.print(prefix); pw.print("isStatusBarKeyguard=");
+                    pw.print(isStatusBarKeyguard());
         }
         if (mNavigationBar != null) {
             pw.print(prefix); pw.print("mNavigationBar=");
                     pw.println(mNavigationBar);
         }
-        if (mKeyguard != null) {
-            pw.print(prefix); pw.print("mKeyguard=");
-                    pw.println(mKeyguard);
-        }
         if (mFocusedWindow != null) {
             pw.print(prefix); pw.print("mFocusedWindow=");
                     pw.println(mFocusedWindow);
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 812e817..966924b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -29,8 +29,8 @@
  */
 public class KeyguardServiceDelegate {
     // TODO: propagate changes to these to {@link KeyguardTouchDelegate}
-    public static final String KEYGUARD_PACKAGE = "com.android.keyguard";
-    public static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService";
+    public static final String KEYGUARD_PACKAGE = "com.android.systemui";
+    public static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
 
     private static final String TAG = "KeyguardServiceDelegate";
     private static final boolean DEBUG = true;
@@ -44,13 +44,13 @@
             // the event something checks before the service is actually started.
             // KeyguardService itself should default to this state until the real state is known.
             showing = true;
-            showingAndNotHidden = true;
+            showingAndNotOccluded = true;
             secure = true;
         }
         boolean showing;
-        boolean showingAndNotHidden;
+        boolean showingAndNotOccluded;
         boolean inputRestricted;
-        boolean hidden;
+        boolean occluded;
         boolean secure;
         boolean dreaming;
         boolean systemIsReady;
@@ -109,7 +109,7 @@
                 Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
             if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
             mKeyguardState.showing = false;
-            mKeyguardState.showingAndNotHidden = false;
+            mKeyguardState.showingAndNotOccluded = false;
             mKeyguardState.secure = false;
         } else {
             if (DEBUG) Log.v(TAG, "*** Keyguard started");
@@ -148,11 +148,11 @@
         return mKeyguardState.showing;
     }
 
-    public boolean isShowingAndNotHidden() {
+    public boolean isShowingAndNotOccluded() {
         if (mKeyguardService != null) {
-            mKeyguardState.showingAndNotHidden = mKeyguardService.isShowingAndNotHidden();
+            mKeyguardState.showingAndNotOccluded = mKeyguardService.isShowingAndNotOccluded();
         }
-        return mKeyguardState.showingAndNotHidden;
+        return mKeyguardState.showingAndNotOccluded;
     }
 
     public boolean isInputRestricted() {
@@ -174,11 +174,13 @@
         }
     }
 
-    public void setHidden(boolean isHidden) {
+    public int setOccluded(boolean isOccluded) {
+        int result = 0;
         if (mKeyguardService != null) {
-            mKeyguardService.setHidden(isHidden);
+            result = mKeyguardService.setOccluded(isOccluded);
         }
-        mKeyguardState.hidden = isHidden;
+        mKeyguardState.occluded = isOccluded;
+        return result;
     }
 
     public void dismiss() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
index 9fb2a50..7cb48fa 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
@@ -22,6 +22,7 @@
 import android.util.Slog;
 import android.view.MotionEvent;
 
+import com.android.internal.policy.IKeyguardServiceConstants;
 import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
@@ -57,9 +58,9 @@
         return false; // TODO cache state
     }
 
-    public boolean isShowingAndNotHidden() {
+    public boolean isShowingAndNotOccluded() {
         try {
-            return mService.isShowingAndNotHidden();
+            return mService.isShowingAndNotOccluded();
         } catch (RemoteException e) {
             Slog.w(TAG , "Remote Exception", e);
         }
@@ -100,11 +101,12 @@
         }
     }
 
-    public void setHidden(boolean isHidden) {
+    public int setOccluded(boolean isOccluded) {
         try {
-            mService.setHidden(isHidden);
+            return mService.setOccluded(isOccluded);
         } catch (RemoteException e) {
             Slog.w(TAG , "Remote Exception", e);
+            return IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE;
         }
     }
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 038686b..3619112 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -3013,7 +3013,6 @@
                     return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
                 }
 
-                case WindowManager.LayoutParams.TYPE_KEYGUARD:
                 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 9768934..5083d44 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -63,6 +63,8 @@
 27500 notification_panel_revealed
 # when the notification panel is hidden
 27501 notification_panel_hidden
+# when notifications are newly displayed on screen, or disappear from screen
+27510 notification_visibility_changed (newlyVisibleKeys|3),(noLongerVisibleKeys|3)
 
 # ---------------------------
 # Watchdog.java
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 1ed943c..fa803e2 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -35,14 +35,19 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
+import com.android.server.NativeDaemonConnector.Command;
 
 /**
  * Network Service Discovery Service handles remote service discovery operation requests by
@@ -433,14 +438,14 @@
                     case NativeResponseCode.SERVICE_FOUND:
                         /* NNN uniqueId serviceName regType domain */
                         if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw);
-                        servInfo = new NsdServiceInfo(cooked[2], cooked[3], null);
+                        servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
                         clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0,
                                 clientId, servInfo);
                         break;
                     case NativeResponseCode.SERVICE_LOST:
                         /* NNN uniqueId serviceName regType domain */
                         if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw);
-                        servInfo = new NsdServiceInfo(cooked[2], cooked[3], null);
+                        servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
                         clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0,
                                 clientId, servInfo);
                         break;
@@ -453,7 +458,7 @@
                     case NativeResponseCode.SERVICE_REGISTERED:
                         /* NNN regId serviceName regType */
                         if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw);
-                        servInfo = new NsdServiceInfo(cooked[2], null, null);
+                        servInfo = new NsdServiceInfo(cooked[2], null);
                         clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED,
                                 id, clientId, servInfo);
                         break;
@@ -673,9 +678,22 @@
     private boolean registerService(int regId, NsdServiceInfo service) {
         if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service);
         try {
-            //Add txtlen and txtdata
-            mNativeConnector.execute("mdnssd", "register", regId, service.getServiceName(),
+            Command cmd = new Command("mdnssd", "register", regId, service.getServiceName(),
                     service.getServiceType(), service.getPort());
+
+            // Add TXT records as additional arguments.
+            Map<String, byte[]> txtRecords = service.getAttributes();
+            for (String key : txtRecords.keySet()) {
+                try {
+                    // TODO: Send encoded TXT record as bytes once NDC/netd supports binary data.
+                    cmd.appendArg(String.format(Locale.US, "%s=%s", key,
+                            new String(txtRecords.get(key), "UTF_8")));
+                } catch (UnsupportedEncodingException e) {
+                    Slog.e(TAG, "Failed to encode txtRecord " + e);
+                }
+            }
+
+            mNativeConnector.execute(cmd);
         } catch(NativeDaemonConnectorException e) {
             Slog.e(TAG, "Failed to execute registerService " + e);
             return false;
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index aa756a1..132ca00 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -86,19 +86,19 @@
         private final int     mRepeat;
         private final int     mStreamHint;
         private final int     mUid;
-        private final String  mPackageName;
+        private final String  mOpPkg;
 
-        Vibration(IBinder token, long millis, int streamHint, int uid, String packageName) {
-            this(token, millis, null, 0, streamHint, uid, packageName);
+        Vibration(IBinder token, long millis, int streamHint, int uid, String opPkg) {
+            this(token, millis, null, 0, streamHint, uid, opPkg);
         }
 
         Vibration(IBinder token, long[] pattern, int repeat, int streamHint, int uid,
-                String packageName) {
-            this(token, 0, pattern, repeat, streamHint, uid, packageName);
+                String opPkg) {
+            this(token, 0, pattern, repeat, streamHint, uid, opPkg);
         }
 
         private Vibration(IBinder token, long millis, long[] pattern,
-                int repeat, int streamHint, int uid, String packageName) {
+                int repeat, int streamHint, int uid, String opPkg) {
             mToken = token;
             mTimeout = millis;
             mStartTime = SystemClock.uptimeMillis();
@@ -106,7 +106,7 @@
             mRepeat = repeat;
             mStreamHint = streamHint;
             mUid = uid;
-            mPackageName = packageName;
+            mOpPkg = opPkg;
         }
 
         public void binderDied() {
@@ -194,7 +194,7 @@
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
     }
 
-    public void vibrate(int uid, String packageName, long milliseconds, int streamHint,
+    public void vibrate(int uid, String opPkg, long milliseconds, int streamHint,
             IBinder token) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -211,7 +211,7 @@
             return;
         }
 
-        Vibration vib = new Vibration(token, milliseconds, streamHint, uid, packageName);
+        Vibration vib = new Vibration(token, milliseconds, streamHint, uid, opPkg);
 
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -347,10 +347,10 @@
     private void startVibrationLocked(final Vibration vib) {
         try {
             int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
-                    vib.mStreamHint, vib.mUid, vib.mPackageName);
+                    vib.mStreamHint, vib.mUid, vib.mOpPkg);
             if (mode == AppOpsManager.MODE_ALLOWED) {
                 mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
-                    AppOpsManager.OP_VIBRATE, vib.mUid, vib.mPackageName);
+                    AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg);
             }
             if (mode != AppOpsManager.MODE_ALLOWED) {
                 if (mode == AppOpsManager.MODE_ERRORED) {
@@ -377,7 +377,7 @@
             try {
                 mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
                         AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
-                        mCurrentVibration.mPackageName);
+                        mCurrentVibration.mOpPkg);
             } catch (RemoteException e) {
             }
             mCurrentVibration = null;
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index e0591a2..ce4c1ed 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -31,4 +31,6 @@
     void onPanelRevealed();
     void onPanelHidden();
     boolean allowDisable(int what, IBinder token, String pkg);
+    void onNotificationVisibilityChanged(
+            String[] newlyVisibleKeys, String[] noLongerVisibleKeys);
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6534783..5b597a3 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1071,6 +1071,16 @@
             }
             return true;
         }
+
+        @Override
+        public void onNotificationVisibilityChanged(
+                String[] newlyVisibleKeys, String[] noLongerVisibleKeys) {
+            // Using ';' as separator since eventlogs uses ',' to separate
+            // args.
+            EventLogTags.writeNotificationVisibilityChanged(
+                    TextUtils.join(";", newlyVisibleKeys),
+                    TextUtils.join(";", noLongerVisibleKeys));
+        }
     };
 
     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -1487,9 +1497,9 @@
         }
 
         @Override
-        public void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id,
+        public void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
                 Notification notification, int[] idOut, int userId) throws RemoteException {
-            enqueueNotificationInternal(pkg, basePkg, Binder.getCallingUid(),
+            enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(),
                     Binder.getCallingPid(), tag, id, notification, idOut, userId);
         }
 
@@ -1839,14 +1849,14 @@
      */
     private final NotificationManagerInternal mInternalService = new NotificationManagerInternal() {
         @Override
-        public void enqueueNotification(String pkg, String basePkg, int callingUid, int callingPid,
+        public void enqueueNotification(String pkg, String opPkg, int callingUid, int callingPid,
                 String tag, int id, Notification notification, int[] idReceived, int userId) {
-            enqueueNotificationInternal(pkg, basePkg, callingUid, callingPid, tag, id, notification,
+            enqueueNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id, notification,
                     idReceived, userId);
         }
     };
 
-    void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid,
+    void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
             final int callingPid, final String tag, final int id, final Notification notification,
             int[] idOut, int incomingUserId) {
         if (DBG) {
@@ -1971,7 +1981,8 @@
                 if (DBG) Slog.v(TAG, "canInterrupt=" + canInterrupt + " intercept=" + intercept);
                 synchronized (mNotificationList) {
                     final StatusBarNotification n = new StatusBarNotification(
-                            pkg, id, tag, callingUid, callingPid, score, notification, user);
+                            pkg, opPkg, id, tag, callingUid, callingPid, score, notification,
+                            user);
                     NotificationRecord r = new NotificationRecord(n);
                     NotificationRecord old = null;
 
@@ -2147,7 +2158,7 @@
                                 // notifying app does not have the VIBRATE permission.
                                 long identity = Binder.clearCallingIdentity();
                                 try {
-                                    mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(),
+                                    mVibrator.vibrate(r.sbn.getUid(), r.sbn.getOpPkg(),
                                         useDefaultVibrate ? mDefaultVibrationPattern
                                             : mFallbackVibrationPattern,
                                         ((notification.flags & Notification.FLAG_INSISTENT) != 0)
@@ -2158,7 +2169,7 @@
                             } else if (notification.vibrate.length > 1) {
                                 // If you want your own vibration pattern, you need the VIBRATE
                                 // permission
-                                mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(),
+                                mVibrator.vibrate(r.sbn.getUid(), r.sbn.getOpPkg(),
                                         notification.vibrate,
                                     ((notification.flags & Notification.FLAG_INSISTENT) != 0)
                                             ? 0: -1, notification.audioStreamType);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index e4b5f3a..91f796b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -588,6 +588,19 @@
     }
 
     @Override
+    public void onNotificationVisibilityChanged(
+            String[] newlyVisibleKeys, String[] noLongerVisibleKeys) throws RemoteException {
+        enforceStatusBarService();
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mNotificationDelegate.onNotificationVisibilityChanged(
+                    newlyVisibleKeys, noLongerVisibleKeys);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void onClearAllNotifications(int userId) {
         enforceStatusBarService();
         final int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 79c4a50..16ed7fe 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -277,8 +277,14 @@
                 }
                 synchronized (mLock) {
                     sessionState.session = session;
-                    sendSessionTokenToClientLocked(sessionState.client, sessionState.name,
-                            sessionToken, sessionState.seq, userId);
+                    if (session == null) {
+                        removeSessionStateLocked(sessionToken, userId);
+                        sendSessionTokenToClientLocked(sessionState.client, sessionState.name, null,
+                                sessionState.seq, userId);
+                    } else {
+                        sendSessionTokenToClientLocked(sessionState.client, sessionState.name,
+                                sessionToken, sessionState.seq, userId);
+                    }
                 }
             }
         };
@@ -288,6 +294,7 @@
             service.createSession(callback);
         } catch (RemoteException e) {
             Log.e(TAG, "error in createSession", e);
+            removeSessionStateLocked(sessionToken, userId);
             sendSessionTokenToClientLocked(sessionState.client, sessionState.name, null,
                     sessionState.seq, userId);
         }
@@ -307,6 +314,19 @@
         }
     }
 
+    private void removeSessionStateLocked(IBinder sessionToken, int userId) {
+        // Remove the session state from the global session state map of the current user.
+        UserState userState = getUserStateLocked(userId);
+        SessionState sessionState = userState.sessionStateMap.remove(sessionToken);
+
+        // Also remove the session state from the session state map of the current service.
+        ServiceState serviceState = userState.serviceStateMap.get(sessionState.name);
+        if (serviceState != null) {
+            serviceState.sessionStateMap.remove(sessionToken);
+        }
+        updateServiceConnectionLocked(sessionState.name, userId);
+    }
+
     private final class BinderService extends ITvInputManager.Stub {
         @Override
         public List<TvInputInfo> getTvInputList(int userId) {
@@ -474,17 +494,7 @@
                         Log.e(TAG, "error in release", e);
                     }
 
-                    // Remove its state from the global session state map of the current user.
-                    UserState userState = getUserStateLocked(resolvedUserId);
-                    SessionState sessionState = userState.sessionStateMap.remove(sessionToken);
-
-                    // Also remove it from the session state map of the current service.
-                    ServiceState serviceState = userState.serviceStateMap.get(sessionState.name);
-                    if (serviceState != null) {
-                        serviceState.sessionStateMap.remove(sessionToken);
-                    }
-
-                    updateServiceConnectionLocked(sessionState.name, resolvedUserId);
+                    removeSessionStateLocked(sessionToken, resolvedUserId);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 7d8b5af..f17b2f4 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -147,6 +148,9 @@
     private int mNextAppTransitionStartWidth;
     private int mNextAppTransitionStartHeight;
 
+    private Rect mTmpFromClipRect = new Rect();
+    private Rect mTmpToClipRect = new Rect();
+
     private final static int APP_STATE_IDLE = 0;
     private final static int APP_STATE_READY = 1;
     private final static int APP_STATE_RUNNING = 2;
@@ -485,7 +489,7 @@
      * activity that is leaving, and the activity that is entering.
      */
     Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
-                                                    int appHeight, int transit,
+                                                    int appHeight, int orientation, int transit,
                                                     Rect containingFrame, Rect contentInsets) {
         Animation a;
         final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
@@ -493,21 +497,36 @@
         final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
         final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
 
+        // Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
+        float scale = 1f;
+        int scaledTopDecor = 0;
+
         switch (thumbTransitState) {
             case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
                 // Entering app scales up with the thumbnail
-                float scale = thumbWidth / appWidth;
-                int unscaledThumbHeight = (int) (thumbHeight / scale);
-                int scaledTopDecor = (int) (scale * contentInsets.top);
-                Rect fromClipRect = new Rect(containingFrame);
-                fromClipRect.bottom = (fromClipRect.top + unscaledThumbHeight);
-                Rect toClipRect = new Rect(containingFrame);
+                if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+                    // In portrait, we scale the width and clip to the top/left square
+                    scale = thumbWidth / appWidth;
+                    scaledTopDecor = (int) (scale * contentInsets.top);
+                    int unscaledThumbHeight = (int) (thumbHeight / scale);
+                    mTmpFromClipRect.set(containingFrame);
+                    mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
+                    mTmpToClipRect.set(containingFrame);
+                } else {
+                    // In landscape, we scale the height and clip to the top/left square
+                    scale = thumbHeight / (appHeight - contentInsets.top);
+                    scaledTopDecor = (int) (scale * contentInsets.top);
+                    int unscaledThumbWidth = (int) (thumbWidth / scale);
+                    mTmpFromClipRect.set(containingFrame);
+                    mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
+                    mTmpToClipRect.set(containingFrame);
+                }
 
                 Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
                         computePivot(mNextAppTransitionStartX, scale),
                         computePivot(mNextAppTransitionStartY, scale));
                 Animation alphaAnim = new AlphaAnimation(1, 1);
-                Animation clipAnim = new ClipRectAnimation(fromClipRect, toClipRect);
+                Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
                 Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
 
                 AnimationSet set = new AnimationSet(true);
@@ -539,18 +558,29 @@
             }
             case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
                 // Exiting the current app, the app should scale down with the thumbnail
-                float scale = thumbWidth / appWidth;
-                int unscaledThumbHeight = (int) (thumbHeight / scale);
-                int scaledTopDecor = (int) (scale * contentInsets.top);
-                Rect fromClipRect = new Rect(containingFrame);
-                Rect toClipRect = new Rect(containingFrame);
-                toClipRect.bottom = (toClipRect.top + unscaledThumbHeight);
+                if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+                    // In portrait, we scale the width and clip to the top/left square
+                    scale = thumbWidth / appWidth;
+                    scaledTopDecor = (int) (scale * contentInsets.top);
+                    int unscaledThumbHeight = (int) (thumbHeight / scale);
+                    mTmpFromClipRect.set(containingFrame);
+                    mTmpToClipRect.set(containingFrame);
+                    mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
+                } else {
+                    // In landscape, we scale the height and clip to the top/left square
+                    scale = thumbHeight / (appHeight - contentInsets.top);
+                    scaledTopDecor = (int) (scale * contentInsets.top);
+                    int unscaledThumbWidth = (int) (thumbWidth / scale);
+                    mTmpFromClipRect.set(containingFrame);
+                    mTmpToClipRect.set(containingFrame);
+                    mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
+                }
 
                 Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
                         computePivot(mNextAppTransitionStartX, scale),
                         computePivot(mNextAppTransitionStartY, scale));
                 Animation alphaAnim = new AlphaAnimation(1, 1);
-                Animation clipAnim = new ClipRectAnimation(fromClipRect, toClipRect);
+                Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
                 Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
 
                 AnimationSet set = new AnimationSet(true);
@@ -637,7 +667,8 @@
 
 
     Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
-                            int appWidth, int appHeight, Rect containingFrame, Rect contentInsets) {
+                            int appWidth, int appHeight, int orientation,
+                            Rect containingFrame, Rect contentInsets) {
         Animation a;
         if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
             a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -660,8 +691,8 @@
                     (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
             if (mUseAlternateThumbnailAnimation) {
                 a = createAlternateThumbnailEnterExitAnimationLocked(
-                        getThumbnailTransitionState(enter), appWidth, appHeight, transit,
-                        containingFrame, contentInsets);
+                        getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
+                        transit, containingFrame, contentInsets);
             } else {
                 a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
                         appWidth, appHeight, transit);
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index b27c8d6..f02c0e6 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -284,7 +284,7 @@
                 final boolean hasFocus = (child == mInputFocus);
                 final boolean isVisible = child.isVisibleLw();
                 final boolean hasWallpaper = (child == mService.mWallpaperTarget)
-                        && (type != WindowManager.LayoutParams.TYPE_KEYGUARD);
+                        && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0;
                 final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
 
                 // If there's a drag in progress and 'child' is a potential drop target,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 02d3d57..524d78b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1893,7 +1893,9 @@
                 int insertionIndex = 0;
                 if (visible && foundW != null) {
                     final int type = foundW.mAttrs.type;
-                    if (type == TYPE_KEYGUARD || type == TYPE_KEYGUARD_SCRIM) {
+                    final int privateFlags = foundW.mAttrs.privateFlags;
+                    if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
+                            || type == TYPE_KEYGUARD_SCRIM) {
                         insertionIndex = windows.indexOf(foundW);
                     }
                 }
@@ -3190,7 +3192,7 @@
             }
 
             Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
-                    containingFrame, contentInsets);
+                    mCurConfiguration.orientation, containingFrame, contentInsets);
             if (a != null) {
                 if (DEBUG_ANIM) {
                     RuntimeException e = null;
@@ -5291,6 +5293,13 @@
         performEnableScreen();
     }
 
+    @Override
+    public void enableScreenIfNeeded() {
+        synchronized (mWindowMap) {
+            enableScreenIfNeededLocked();
+        }
+    }
+
     void enableScreenIfNeededLocked() {
         if (DEBUG_BOOT) {
             RuntimeException here = new RuntimeException("here");
@@ -5355,18 +5364,6 @@
                 final int N = windows.size();
                 for (int i=0; i<N; i++) {
                     WindowState w = windows.get(i);
-                    if (w.mAttrs.type == TYPE_KEYGUARD) {
-                        // Only if there is a keyguard attached to the window manager
-                        // will we consider ourselves as having a keyguard.  If it
-                        // isn't attached, we don't know if it wants to be shown or
-                        // hidden.  If it is attached, we will say we have a keyguard
-                        // if the window doesn't want to be visible, because in that
-                        // case it explicitly doesn't want to be shown so we should
-                        // not delay turning the screen on for it.
-                        boolean vis = w.mViewVisibility == View.VISIBLE
-                                && w.mPolicyVisibility;
-                        haveKeyguard = !vis;
-                    }
                     if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
                         return;
                     }
@@ -5377,8 +5374,8 @@
                             haveApp = true;
                         } else if (w.mAttrs.type == TYPE_WALLPAPER) {
                             haveWallpaper = true;
-                        } else if (w.mAttrs.type == TYPE_KEYGUARD) {
-                            haveKeyguard = true;
+                        } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
+                            haveKeyguard = mPolicy.isKeyguardDrawnLw();
                         }
                     }
                 }
@@ -8335,7 +8332,7 @@
             // just don't display").
             if (!gone || !win.mHaveFrame || win.mLayoutNeeded
                     || ((win.isConfigChanged() || win.setInsetsChanged()) &&
-                            (win.mAttrs.type == TYPE_KEYGUARD ||
+                            ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
                             win.mAppToken != null && win.mAppToken.layoutConfigChanges))
                     || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
                 if (!win.mLayoutAttached) {
@@ -8875,8 +8872,8 @@
             if (canBeSeen
                     && (type == TYPE_SYSTEM_DIALOG
                      || type == TYPE_RECENTS_OVERLAY
-                     || type == TYPE_KEYGUARD
-                     || type == TYPE_SYSTEM_ERROR)) {
+                     || type == TYPE_SYSTEM_ERROR
+                     || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
                 mInnerFields.mSyswin = true;
             }
 
@@ -8889,7 +8886,7 @@
                     // content on secondary displays (by forcibly enabling mirroring unless
                     // there is other content we want to show) but still allow opaque
                     // keyguard dialogs to be shown.
-                    if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
+                    if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                         mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
                     }
                     mInnerFields.mDisplayHasContent = true;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index dff75ef..4318b0e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -23,12 +23,12 @@
 import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
 
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import android.app.AppOpsManager;
@@ -1010,7 +1010,7 @@
                 && (mConfiguration == null
                         || (mConfiguration.diff(mService.mCurConfiguration) != 0));
 
-        if (mAttrs.type == TYPE_KEYGUARD) {
+        if ((mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
             // Retain configuration changed status until resetConfiguration called.
             mConfigHasChanged |= configChanged;
             configChanged = mConfigHasChanged;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 35f9314..5a458a3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2905,7 +2905,8 @@
             try {
                 Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
                 intent.putExtra(Intent.EXTRA_USER, new UserHandle(UserHandle.getCallingUserId()));
-                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
+                        Intent.FLAG_RECEIVER_FOREGROUND);
                 mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
             } finally {
                 restoreCallingIdentity(id);
diff --git a/tests/CoreTests/android/core/NsdServiceInfoTest.java b/tests/CoreTests/android/core/NsdServiceInfoTest.java
new file mode 100644
index 0000000..5bf0167
--- /dev/null
+++ b/tests/CoreTests/android/core/NsdServiceInfoTest.java
@@ -0,0 +1,163 @@
+package android.core;
+
+import android.test.AndroidTestCase;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.StrictMode;
+import android.net.nsd.NsdServiceInfo;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+
+public class NsdServiceInfoTest extends AndroidTestCase {
+
+    public final static InetAddress LOCALHOST;
+    static {
+        // Because test.
+        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+        StrictMode.setThreadPolicy(policy);
+
+        InetAddress _host = null;
+        try {
+            _host = InetAddress.getLocalHost();
+        } catch (UnknownHostException e) { }
+        LOCALHOST = _host;
+    }
+
+    public void testLimits() throws Exception {
+        NsdServiceInfo info = new NsdServiceInfo();
+
+        // Non-ASCII keys.
+        boolean exceptionThrown = false;
+        try {
+            info.setAttribute("猫", "meow");
+        } catch (IllegalArgumentException e) {
+            exceptionThrown = true;
+        }
+        assertTrue(exceptionThrown);
+        assertEmptyServiceInfo(info);
+
+        // ASCII keys with '=' character.
+        exceptionThrown = false;
+        try {
+            info.setAttribute("kitten=", "meow");
+        } catch (IllegalArgumentException e) {
+            exceptionThrown = true;
+        }
+        assertTrue(exceptionThrown);
+        assertEmptyServiceInfo(info);
+
+        // Single key + value length too long.
+        exceptionThrown = false;
+        try {
+            String longValue = "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
+                    "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
+                    "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
+                    "ooooooooooooooooooooooooooooong";  // 248 characters.
+            info.setAttribute("longcat", longValue);  // Key + value == 255 characters.
+        } catch (IllegalArgumentException e) {
+            exceptionThrown = true;
+        }
+        assertTrue(exceptionThrown);
+        assertEmptyServiceInfo(info);
+
+        // Total TXT record length too long.
+        exceptionThrown = false;
+        int recordsAdded = 0;
+        try {
+            for (int i = 100; i < 300; ++i) {
+                // 6 char key + 5 char value + 2 bytes overhead = 13 byte record length.
+                String key = String.format("key%d", i);
+                info.setAttribute(key, "12345");
+                recordsAdded++;
+            }
+        } catch (IllegalArgumentException e) {
+            exceptionThrown = true;
+        }
+        assertTrue(exceptionThrown);
+        assertTrue(100 == recordsAdded);
+        assertTrue(info.getTxtRecord().length == 1300);
+    }
+
+    public void testParcel() throws Exception {
+        NsdServiceInfo emptyInfo = new NsdServiceInfo();
+        checkParcelable(emptyInfo);
+
+        NsdServiceInfo fullInfo = new NsdServiceInfo();
+        fullInfo.setServiceName("kitten");
+        fullInfo.setServiceType("_kitten._tcp");
+        fullInfo.setPort(4242);
+        fullInfo.setHost(LOCALHOST);
+        checkParcelable(fullInfo);
+
+        NsdServiceInfo noHostInfo = new NsdServiceInfo();
+        noHostInfo.setServiceName("kitten");
+        noHostInfo.setServiceType("_kitten._tcp");
+        noHostInfo.setPort(4242);
+        checkParcelable(noHostInfo);
+
+        NsdServiceInfo attributedInfo = new NsdServiceInfo();
+        attributedInfo.setServiceName("kitten");
+        attributedInfo.setServiceType("_kitten._tcp");
+        attributedInfo.setPort(4242);
+        attributedInfo.setHost(LOCALHOST);
+        attributedInfo.setAttribute("color", "pink");
+        attributedInfo.setAttribute("sound", (new String("にゃあ")).getBytes("UTF-8"));
+        attributedInfo.setAttribute("adorable", (String) null);
+        attributedInfo.setAttribute("sticky", "yes");
+        attributedInfo.setAttribute("siblings", new byte[] {});
+        attributedInfo.setAttribute("edge cases", new byte[] {0, -1, 127, -128});
+        attributedInfo.removeAttribute("sticky");
+        checkParcelable(attributedInfo);
+
+        // Sanity check that we actually wrote attributes to attributedInfo.
+        assertTrue(attributedInfo.getAttributes().keySet().contains("adorable"));
+        String sound = new String(attributedInfo.getAttributes().get("sound"), "UTF-8");
+        assertTrue(sound.equals("にゃあ"));
+        byte[] edgeCases = attributedInfo.getAttributes().get("edge cases");
+        assertTrue(Arrays.equals(edgeCases, new byte[] {0, -1, 127, -128}));
+        assertFalse(attributedInfo.getAttributes().keySet().contains("sticky"));
+    }
+
+    public void checkParcelable(NsdServiceInfo original) {
+        // Write to parcel.
+        Parcel p = Parcel.obtain();
+        Bundle writer = new Bundle();
+        writer.putParcelable("test_info", original);
+        writer.writeToParcel(p, 0);
+
+        // Extract from parcel.
+        p.setDataPosition(0);
+        Bundle reader = p.readBundle();
+        reader.setClassLoader(NsdServiceInfo.class.getClassLoader());
+        NsdServiceInfo result = reader.getParcelable("test_info");
+
+        // Assert equality of base fields.
+        assertEquality(original.getServiceName(), result.getServiceName());
+        assertEquality(original.getServiceType(), result.getServiceType());
+        assertEquality(original.getHost(), result.getHost());
+        assertTrue(original.getPort() == result.getPort());
+
+        // Assert equality of attribute map.
+        Map<String, byte[]> originalMap = original.getAttributes();
+        Map<String, byte[]> resultMap = result.getAttributes();
+        assertEquality(originalMap.keySet(), resultMap.keySet());
+        for (String key : originalMap.keySet()) {
+            assertTrue(Arrays.equals(originalMap.get(key), resultMap.get(key)));
+        }
+    }
+
+    public void assertEquality(Object expected, Object result) {
+        assertTrue(expected == result || expected.equals(result));
+    }
+
+    public void assertEmptyServiceInfo(NsdServiceInfo shouldBeEmpty) {
+        assertTrue(null == shouldBeEmpty.getTxtRecord());
+    }
+}
diff --git a/tools/layoutlib/bridge/resources/bars/action_bar.xml b/tools/layoutlib/bridge/resources/bars/action_bar.xml
deleted file mode 100644
index 7adc5af..0000000
--- a/tools/layoutlib/bridge/resources/bars/action_bar.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <include layout="@android:layout/action_bar_home" />
-    <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"/>
-</merge>
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 4dd1446..757cdd2 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -29,6 +29,8 @@
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
 
+import java.lang.Override;
+
 /**
  * Basic implementation of {@link IWindowManager} so that {@link Display} (and
  * {@link Display_Delegate}) can return a valid instance.
@@ -453,13 +455,19 @@
     }
 
     @Override
-    public boolean clearWindowContentFrameStats(IBinder token) {
+    public void enableScreenIfNeeded() throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public boolean clearWindowContentFrameStats(IBinder token) throws RemoteException {
         // TODO Auto-generated method stub
         return false;
     }
 
     @Override
-    public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
+    public WindowContentFrameStats getWindowContentFrameStats(IBinder token)
+            throws RemoteException {
         // TODO Auto-generated method stub
         return null;
     }
diff --git a/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java b/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java
new file mode 100644
index 0000000..40b6220
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java
@@ -0,0 +1,32 @@
+/*
+ * 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 com.android.internal.widget;
+
+import android.widget.ActionMenuPresenter;
+
+/**
+ * To access non public members of AbsActionBarView
+ */
+public class ActionBarAccessor {
+
+    /**
+     * Returns the {@link ActionMenuPresenter} associated with the {@link AbsActionBarView}
+     */
+    public static ActionMenuPresenter getActionMenuPresenter(AbsActionBarView view) {
+        return view.mActionMenuPresenter;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index ab4be71..fa8050f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -215,7 +215,8 @@
                 Capability.ADAPTER_BINDING,
                 Capability.EXTENDED_VIEWINFO,
                 Capability.FIXED_SCALABLE_NINE_PATCH,
-                Capability.RTL);
+                Capability.RTL,
+                Capability.ACTION_BAR);
 
 
         BridgeAssetManager.initSystem();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
index f9f4b3a..e0f87fd 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -64,6 +64,11 @@
     }
 
     @Override
+    public List<ViewInfo> getSystemRootViews() {
+        return mSession.getSystemViewInfos();
+    }
+
+    @Override
     public Map<String, String> getDefaultProperties(Object viewObject) {
         return mSession.getDefaultProperties(viewObject);
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 9ee2f60..6595ce1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -613,7 +613,8 @@
             }
 
             if (value != null) {
-                if (value.getFirst() == ResourceType.STYLE) {
+                if ((value.getFirst() == ResourceType.STYLE)
+                        || (value.getFirst() == ResourceType.ATTR)) {
                     // look for the style in the current theme, and its parent:
                     ResourceValue item = mRenderResources.findItemInTheme(value.getSecond(),
                             isFrameworkRes);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
new file mode 100644
index 0000000..49027c6
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
@@ -0,0 +1,354 @@
+/*
+ * 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 com.android.layoutlib.bridge.bars;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.ActionBarCallback;
+import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.SessionParams;
+import com.android.internal.R;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.widget.ActionBarAccessor;
+import com.android.internal.widget.ActionBarContainer;
+import com.android.internal.widget.ActionBarView;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.resources.ResourceType;
+
+import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+
+import java.util.ArrayList;
+
+/**
+ * A layout representing the action bar.
+ */
+public class ActionBarLayout extends LinearLayout {
+
+    // Store another reference to the context so that we don't have to cast it repeatedly.
+    @NonNull private final BridgeContext mBridgeContext;
+    @NonNull private final Context mThemedContext;
+
+    @NonNull private final ActionBar mActionBar;
+
+    // Data for Action Bar.
+    @Nullable private final String mIcon;
+    @Nullable private final String mTitle;
+    @Nullable private final String mSubTitle;
+    private final boolean mSplit;
+    private final boolean mShowHomeAsUp;
+    private final int mNavMode;
+
+    // Helper fields.
+    @NonNull private final MenuBuilder mMenuBuilder;
+    private final int mPopupMaxWidth;
+    @NonNull private final RenderResources res;
+    @Nullable private final ActionBarView mActionBarView;
+    @Nullable private FrameLayout mContentRoot;
+    @NonNull private final ActionBarCallback mCallback;
+
+    // A fake parent for measuring views.
+    @Nullable private ViewGroup mMeasureParent;
+
+    public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params) {
+
+        super(context);
+        setOrientation(LinearLayout.HORIZONTAL);
+        setGravity(Gravity.CENTER_VERTICAL);
+
+        // Inflate action bar layout.
+        LayoutInflater.from(context).inflate(R.layout.screen_action_bar, this,
+                true /*attachToRoot*/);
+        mActionBar = new WindowDecorActionBar(this);
+
+        // Set contexts.
+        mBridgeContext = context;
+        mThemedContext = mActionBar.getThemedContext();
+
+        // Set data for action bar.
+        mCallback = params.getProjectCallback().getActionBarCallback();
+        mIcon = params.getAppIcon();
+        mTitle = params.getAppLabel();
+        // Split Action Bar when the screen size is narrow and the application requests split action
+        // bar when narrow.
+        mSplit = context.getResources().getBoolean(R.bool.split_action_bar_is_narrow) &&
+                mCallback.getSplitActionBarWhenNarrow();
+        mNavMode = mCallback.getNavigationMode();
+        // TODO: Support Navigation Drawer Indicator.
+        mShowHomeAsUp = mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP;
+        mSubTitle = mCallback.getSubTitle();
+
+
+        // Set helper fields.
+        mMenuBuilder = new MenuBuilder(mThemedContext);
+        res = mBridgeContext.getRenderResources();
+        mPopupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
+                mThemedContext.getResources().getDimensionPixelSize(
+                        R.dimen.config_prefDialogWidth));
+        mActionBarView = (ActionBarView) findViewById(R.id.action_bar);
+        mContentRoot = (FrameLayout) findViewById(android.R.id.content);
+
+        setupActionBar();
+    }
+
+    /**
+     * Sets up the action bar by filling the appropriate data.
+     */
+    private void setupActionBar() {
+        // Add title and sub title.
+        ResourceValue titleValue = res.findResValue(mTitle, false /*isFramework*/);
+        if (titleValue != null && titleValue.getValue() != null) {
+            mActionBar.setTitle(titleValue.getValue());
+        } else {
+            mActionBar.setTitle(mTitle);
+        }
+        if (mSubTitle != null) {
+            mActionBar.setSubtitle(mSubTitle);
+        }
+
+        // Add show home as up icon.
+        if (mShowHomeAsUp) {
+            mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
+        }
+
+        // Set the navigation mode.
+        mActionBar.setNavigationMode(mNavMode);
+        if (mNavMode == ActionBar.NAVIGATION_MODE_TABS) {
+            setupTabs(3);
+        }
+
+        if (mActionBarView != null) {
+            // If the action bar style doesn't specify an icon, set the icon obtained from the session
+            // params.
+            if (!mActionBarView.hasIcon() && mIcon != null) {
+                Drawable iconDrawable = getDrawable(mIcon, false /*isFramework*/);
+                if (iconDrawable != null) {
+                    mActionBar.setIcon(iconDrawable);
+                }
+            }
+
+            // Set action bar to be split, if needed.
+            mActionBarView.setSplitView((ActionBarContainer) findViewById(R.id.split_action_bar));
+            mActionBarView.setSplitActionBar(mSplit);
+
+            inflateMenus();
+        }
+    }
+
+    /**
+     * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
+     * adds them to the action bar.
+     */
+    private void inflateMenus() {
+        if (mActionBarView == null) {
+            return;
+        }
+        final MenuInflater inflater = new MenuInflater(mThemedContext);
+        for (String name : mCallback.getMenuIdNames()) {
+            if (mBridgeContext.getRenderResources().getProjectResource(ResourceType.MENU, name)
+                    != null) {
+                int id = mBridgeContext.getProjectResourceValue(ResourceType.MENU, name, -1);
+                if (id > -1) {
+                    inflater.inflate(id, mMenuBuilder);
+                }
+            }
+        }
+        mActionBarView.setMenu(mMenuBuilder, null /*callback*/);
+    }
+
+    // TODO: Use an adapter, like List View to set up tabs.
+    private void setupTabs(int num) {
+        for (int i = 1; i <= num; i++) {
+            Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
+                @Override
+                public void onTabUnselected(Tab t, FragmentTransaction ft) {
+                    // pass
+                }
+                @Override
+                public void onTabSelected(Tab t, FragmentTransaction ft) {
+                    // pass
+                }
+                @Override
+                public void onTabReselected(Tab t, FragmentTransaction ft) {
+                    // pass
+                }
+            });
+            mActionBar.addTab(tab);
+        }
+    }
+
+    @Nullable
+    private Drawable getDrawable(@NonNull String name, boolean isFramework) {
+        ResourceValue value = res.findResValue(name, isFramework);
+        value = res.resolveResValue(value);
+        if (value != null) {
+            return ResourceHelper.getDrawable(value, mBridgeContext);
+        }
+        return null;
+    }
+
+    /**
+     * Creates a Popup and adds it to the content frame. It also adds another {@link FrameLayout} to
+     * the content frame which shall serve as the new content root.
+     */
+    public void createMenuPopup() {
+        assert mContentRoot != null && findViewById(android.R.id.content) == mContentRoot
+                : "Action Bar Menus have already been created.";
+
+        if (!isOverflowPopupNeeded()) {
+            return;
+        }
+
+        // Create a layout to hold the menus and the user's content.
+        RelativeLayout layout = new RelativeLayout(mThemedContext);
+        layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT));
+        mContentRoot.addView(layout);
+        // Create a layout for the user's content.
+        FrameLayout contentRoot = new FrameLayout(mBridgeContext);
+        contentRoot.setLayoutParams(new LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+        // Add contentRoot and menus to the layout.
+        layout.addView(contentRoot);
+        layout.addView(createMenuView());
+        // ContentRoot is now the view we just created.
+        mContentRoot = contentRoot;
+    }
+
+    /**
+     * Returns a {@link LinearLayout} containing the menu list view to be embedded in a
+     * {@link RelativeLayout}
+     */
+    @NonNull
+    private View createMenuView() {
+        DisplayMetrics metrics = mBridgeContext.getMetrics();
+        OverflowMenuAdapter adapter = new OverflowMenuAdapter(mMenuBuilder, mThemedContext);
+
+        LinearLayout layout = new LinearLayout(mThemedContext);
+        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
+                measureContentWidth(adapter), LayoutParams.WRAP_CONTENT);
+        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_END);
+        if (mSplit) {
+            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+            // TODO: Find correct value instead of hardcoded 10dp.
+            layoutParams.bottomMargin = getPixelValue("-10dp", metrics);
+        } else {
+            layoutParams.topMargin = getPixelValue("-10dp", metrics);
+        }
+        layout.setLayoutParams(layoutParams);
+        final TypedArray a = mThemedContext.obtainStyledAttributes(null,
+                R.styleable.PopupWindow, R.attr.popupMenuStyle, 0);
+        layout.setBackground(a.getDrawable(R.styleable.PopupWindow_popupBackground));
+        layout.setDividerDrawable(a.getDrawable(R.attr.actionBarDivider));
+        a.recycle();
+        layout.setOrientation(LinearLayout.VERTICAL);
+        layout.setDividerPadding(getPixelValue("12dp", metrics));
+        layout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
+
+        ListView listView = new ListView(mThemedContext, null, R.attr.dropDownListViewStyle);
+        listView.setAdapter(adapter);
+        layout.addView(listView);
+        return layout;
+    }
+
+    private boolean isOverflowPopupNeeded() {
+        boolean needed = mCallback.isOverflowPopupNeeded();
+        if (!needed) {
+            return false;
+        }
+        // Copied from android.widget.ActionMenuPresenter.updateMenuView()
+        ArrayList<MenuItemImpl> menus = mMenuBuilder.getNonActionItems();
+        if (ActionBarAccessor.getActionMenuPresenter(mActionBarView).isOverflowReserved() &&
+                menus != null) {
+            final int count = menus.size();
+            if (count == 1) {
+                needed = !menus.get(0).isActionViewExpanded();
+            } else {
+                needed = count > 0;
+            }
+        }
+        return needed;
+    }
+
+    @Nullable
+    public FrameLayout getContentRoot() {
+        return mContentRoot;
+    }
+
+    // Copied from com.android.internal.view.menu.MenuPopHelper.measureContentWidth()
+    private int measureContentWidth(@NonNull ListAdapter adapter) {
+        // Menus don't tend to be long, so this is more sane than it looks.
+        int maxWidth = 0;
+        View itemView = null;
+        int itemType = 0;
+
+        final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        final int count = adapter.getCount();
+        for (int i = 0; i < count; i++) {
+            final int positionType = adapter.getItemViewType(i);
+            if (positionType != itemType) {
+                itemType = positionType;
+                itemView = null;
+            }
+
+            if (mMeasureParent == null) {
+                mMeasureParent = new FrameLayout(mThemedContext);
+            }
+
+            itemView = adapter.getView(i, itemView, mMeasureParent);
+            itemView.measure(widthMeasureSpec, heightMeasureSpec);
+
+            final int itemWidth = itemView.getMeasuredWidth();
+            if (itemWidth >= mPopupMaxWidth) {
+                return mPopupMaxWidth;
+            } else if (itemWidth > maxWidth) {
+                maxWidth = itemWidth;
+            }
+        }
+
+        return maxWidth;
+    }
+
+    private int getPixelValue(@NonNull String value, @NonNull DisplayMetrics metrics) {
+        TypedValue typedValue = ResourceHelper.getValue(null, value, false /*requireUnit*/);
+        return (int) typedValue.getDimension(metrics);
+    }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
deleted file mode 100644
index 226649d..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.layoutlib.bridge.bars;
-
-import com.android.resources.Density;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class FakeActionBar extends CustomBar {
-
-    private TextView mTextView;
-
-    public FakeActionBar(Context context, Density density, String label, String icon)
-            throws XmlPullParserException {
-        super(context, density, LinearLayout.HORIZONTAL, "/bars/action_bar.xml", "action_bar.xml");
-
-        // Cannot access the inside items through id because no R.id values have been
-        // created for them.
-        // We do know the order though.
-        loadIconById(android.R.id.home, icon);
-        mTextView = setText(1, label);
-
-        setStyle("actionBarStyle");
-    }
-
-    @Override
-    protected TextView getStyleableTextView() {
-        return mTextView;
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java
new file mode 100644
index 0000000..778305d
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java
@@ -0,0 +1,99 @@
+/*
+ * 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 com.android.layoutlib.bridge.bars;
+
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuView;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import java.util.ArrayList;
+
+/**
+ * Provides an adapter for Overflow menu popup. This is very similar to
+ * {@code MenuPopupHelper.MenuAdapter}
+ */
+public class OverflowMenuAdapter extends BaseAdapter {
+
+    private final MenuBuilder mMenu;
+    private int mExpandedIndex = -1;
+    private final Context context;
+
+    public OverflowMenuAdapter(MenuBuilder menu, Context context) {
+        mMenu = menu;
+        findExpandedIndex();
+        this.context = context;
+    }
+
+    @Override
+    public int getCount() {
+        ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
+        if (mExpandedIndex < 0) {
+            return items.size();
+        }
+        return items.size() - 1;
+    }
+
+    @Override
+    public MenuItemImpl getItem(int position) {
+        ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
+        if (mExpandedIndex >= 0 && position >= mExpandedIndex) {
+            position++;
+        }
+        return items.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        // Since a menu item's ID is optional, we'll use the position as an
+        // ID for the item in the AdapterView
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        if (convertView == null) {
+            LayoutInflater mInflater = LayoutInflater.from(context);
+            convertView = mInflater.inflate(com.android.internal.R.layout.popup_menu_item_layout,
+                    parent, false);
+        }
+
+        MenuView.ItemView itemView = (MenuView.ItemView) convertView;
+        itemView.initialize(getItem(position), 0);
+        return convertView;
+    }
+
+    private void findExpandedIndex() {
+        final MenuItemImpl expandedItem = mMenu.getExpandedItem();
+        if (expandedItem != null) {
+            final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
+            final int count = items.size();
+            for (int i = 0; i < count; i++) {
+                final MenuItemImpl item = items.get(i);
+                if (item == expandedItem) {
+                    mExpandedIndex = i;
+                    return;
+                }
+            }
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 377d996..afcadef 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -43,12 +43,13 @@
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.bars.FakeActionBar;
 import com.android.layoutlib.bridge.bars.NavigationBar;
 import com.android.layoutlib.bridge.bars.StatusBar;
 import com.android.layoutlib.bridge.bars.TitleBar;
+import com.android.layoutlib.bridge.bars.ActionBarLayout;
 import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
 import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
+import com.android.resources.Density;
 import com.android.resources.ResourceType;
 import com.android.resources.ScreenOrientation;
 import com.android.util.Pair;
@@ -134,6 +135,7 @@
     // information being returned through the API
     private BufferedImage mImage;
     private List<ViewInfo> mViewInfoList;
+    private List<ViewInfo> mSystemViewInfoList;
 
     private static final class PostInflateException extends Exception {
         private static final long serialVersionUID = 1L;
@@ -146,10 +148,11 @@
     /**
      * Creates a layout scene with all the information coming from the layout bridge API.
      * <p>
-     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init()}, which act as a
+     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)},
+     * which act as a
      * call to {@link RenderSessionImpl#acquire(long)}
      *
-     * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
+     * @see Bridge#createSession(SessionParams)
      */
     public RenderSessionImpl(SessionParams params) {
         super(new SessionParams(params));
@@ -225,14 +228,15 @@
             HardwareConfig hardwareConfig = params.getHardwareConfig();
             BridgeContext context = getContext();
             boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
-            int direction = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+            int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+            ActionBarLayout actionBar = null;
 
             // the view group that receives the window background.
             ViewGroup backgroundView = null;
 
             if (mWindowIsFloating || params.isForceNoDecor()) {
                 backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
-                mViewRoot.setLayoutDirection(direction);
+                mViewRoot.setLayoutDirection(layoutDirection);
             } else {
                 if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
                     /*
@@ -254,18 +258,13 @@
                        the bottom
                      */
                     LinearLayout topLayout = new LinearLayout(context);
-                    topLayout.setLayoutDirection(direction);
+                    topLayout.setLayoutDirection(layoutDirection);
                     mViewRoot = topLayout;
                     topLayout.setOrientation(LinearLayout.HORIZONTAL);
 
                     try {
-                        NavigationBar navigationBar = new NavigationBar(context,
-                                hardwareConfig.getDensity(), LinearLayout.VERTICAL, isRtl,
-                                params.isRtlSupported());
-                        navigationBar.setLayoutParams(
-                                new LinearLayout.LayoutParams(
-                                        mNavigationBarSize,
-                                        LayoutParams.MATCH_PARENT));
+                        NavigationBar navigationBar = createNavigationBar(context,
+                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
                         topLayout.addView(navigationBar);
                     } catch (XmlPullParserException e) {
 
@@ -293,14 +292,15 @@
 
                 LinearLayout topLayout = new LinearLayout(context);
                 topLayout.setOrientation(LinearLayout.VERTICAL);
-                topLayout.setLayoutDirection(direction);
+                topLayout.setLayoutDirection(layoutDirection);
                 // if we don't already have a view root this is it
                 if (mViewRoot == null) {
                     mViewRoot = topLayout;
                 } else {
+                    int topLayoutWidth =
+                            params.getHardwareConfig().getScreenWidth() - mNavigationBarSize;
                     LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
-                            LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
-                    layoutParams.weight = 1;
+                            topLayoutWidth, LayoutParams.MATCH_PARENT);
                     topLayout.setLayoutParams(layoutParams);
 
                     // this is the case of soft buttons + vertical bar.
@@ -319,12 +319,9 @@
                 if (mStatusBarSize > 0) {
                     // system bar
                     try {
-                        StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity(),
-                                direction, params.isRtlSupported());
-                        systemBar.setLayoutParams(
-                                new LinearLayout.LayoutParams(
-                                        LayoutParams.MATCH_PARENT, mStatusBarSize));
-                        topLayout.addView(systemBar);
+                        StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
+                                layoutDirection, params.isRtlSupported());
+                        topLayout.addView(statusBar);
                     } catch (XmlPullParserException e) {
 
                     }
@@ -343,23 +340,17 @@
                 // if the theme says no title/action bar, then the size will be 0
                 if (mActionBarSize > 0) {
                     try {
-                        FakeActionBar actionBar = new FakeActionBar(context,
-                                hardwareConfig.getDensity(),
-                                params.getAppLabel(), params.getAppIcon());
-                        actionBar.setLayoutParams(
-                                new LinearLayout.LayoutParams(
-                                        LayoutParams.MATCH_PARENT, mActionBarSize));
+                        actionBar = createActionBar(context, params);
                         backgroundLayout.addView(actionBar);
+                        actionBar.createMenuPopup();
+                        mContentRoot = actionBar.getContentRoot();
                     } catch (XmlPullParserException e) {
 
                     }
                 } else if (mTitleBarSize > 0) {
                     try {
-                        TitleBar titleBar = new TitleBar(context,
+                        TitleBar titleBar = createTitleBar(context,
                                 hardwareConfig.getDensity(), params.getAppLabel());
-                        titleBar.setLayoutParams(
-                                new LinearLayout.LayoutParams(
-                                        LayoutParams.MATCH_PARENT, mTitleBarSize));
                         backgroundLayout.addView(titleBar);
                     } catch (XmlPullParserException e) {
 
@@ -367,23 +358,21 @@
                 }
 
                 // content frame
-                mContentRoot = new FrameLayout(context);
-                layoutParams = new LinearLayout.LayoutParams(
-                        LayoutParams.MATCH_PARENT, 0);
-                layoutParams.weight = 1;
-                mContentRoot.setLayoutParams(layoutParams);
-                backgroundLayout.addView(mContentRoot);
+                if (mContentRoot == null) {
+                    mContentRoot = new FrameLayout(context);
+                    layoutParams = new LinearLayout.LayoutParams(
+                            LayoutParams.MATCH_PARENT, 0);
+                    layoutParams.weight = 1;
+                    mContentRoot.setLayoutParams(layoutParams);
+                    backgroundLayout.addView(mContentRoot);
+                }
 
                 if (mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
                         mNavigationBarSize > 0) {
                     // system bar
                     try {
-                        NavigationBar navigationBar = new NavigationBar(context,
-                                hardwareConfig.getDensity(), LinearLayout.HORIZONTAL, isRtl,
-                                params.isRtlSupported());
-                        navigationBar.setLayoutParams(
-                                new LinearLayout.LayoutParams(
-                                        LayoutParams.MATCH_PARENT, mNavigationBarSize));
+                        NavigationBar navigationBar = createNavigationBar(context,
+                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
                         topLayout.addView(navigationBar);
                     } catch (XmlPullParserException e) {
 
@@ -441,7 +430,7 @@
      * @throws IllegalStateException if the current context is different than the one owned by
      *      the scene, or if {@link #acquire(long)} was not called.
      *
-     * @see RenderParams#getRenderingMode()
+     * @see SessionParams#getRenderingMode()
      * @see RenderSession#render(long)
      */
     public Result render(boolean freshRender) {
@@ -584,7 +573,7 @@
                 mViewRoot.draw(mCanvas);
             }
 
-            mViewInfoList = startVisitingViews(mViewRoot, 0, params.getExtendedViewInfoMode());
+            mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(), false);
 
             // success!
             return SUCCESS.createResult();
@@ -1369,50 +1358,126 @@
         }
     }
 
-    private List<ViewInfo> startVisitingViews(View view, int offset, boolean setExtendedInfo) {
-        if (view == null) {
-            return null;
-        }
-
-        // adjust the offset to this view.
-        offset += view.getTop();
-
-        if (view == mContentRoot) {
-            return visitAllChildren(mContentRoot, offset, setExtendedInfo);
-        }
-
-        // otherwise, look for mContentRoot in the children
-        if (view instanceof ViewGroup) {
-            ViewGroup group = ((ViewGroup) view);
-
-            for (int i = 0; i < group.getChildCount(); i++) {
-                List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset,
-                        setExtendedInfo);
-                if (list != null) {
-                    return list;
-                }
-            }
-        }
-
-        return null;
-    }
-
     /**
-     * Visits a View and its children and generate a {@link ViewInfo} containing the
+     * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the
      * bounds of all the views.
+     *
      * @param view the root View
      * @param offset an offset for the view bounds.
      * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
+     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
+     *                       content frame.
+     *
+     * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
      */
-    private ViewInfo visit(View view, int offset, boolean setExtendedInfo) {
+    private ViewInfo visit(View view, int offset, boolean setExtendedInfo,
+            boolean isContentFrame) {
+        ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame);
+
+        if (view instanceof ViewGroup) {
+            ViewGroup group = ((ViewGroup) view);
+            result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset,
+                    setExtendedInfo, isContentFrame));
+        }
+        return result;
+    }
+
+    /**
+     * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo}
+     * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with
+     * the children of the {@code mContentRoot}.
+     *
+     * @param viewGroup the root View
+     * @param offset an offset from the top for the content view frame.
+     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
+     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
+     *                       content frame. {@code false} if the {@code ViewInfo} to be created is
+     *                       part of the system decor.
+     */
+    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
+            boolean setExtendedInfo, boolean isContentFrame) {
+        if (viewGroup == null) {
+            return null;
+        }
+
+        if (!isContentFrame) {
+            offset += viewGroup.getTop();
+        }
+
+        int childCount = viewGroup.getChildCount();
+        if (viewGroup == mContentRoot) {
+            List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount);
+            List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount);
+            for (int i = 0; i < childCount; i++) {
+                ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset,
+                        setExtendedInfo);
+                childrenWithoutOffset.add(childViewInfo[0]);
+                childrenWithOffset.add(childViewInfo[1]);
+            }
+            mViewInfoList = childrenWithOffset;
+            return childrenWithoutOffset;
+        } else {
+            List<ViewInfo> children = new ArrayList<ViewInfo>(childCount);
+            for (int i = 0; i < childCount; i++) {
+                children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo,
+                        isContentFrame));
+            }
+            return children;
+        }
+    }
+
+    /**
+     * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the
+     * bounds of all the views. It returns two {@code ViewInfo} objects with the same children,
+     * one with the {@code offset} and other without the {@code offset}. The offset is needed to
+     * get the right bounds if the {@code ViewInfo} hierarchy is accessed from
+     * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
+     * offset is not needed.
+     *
+     * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
+     *         index 1 is with the offset.
+     */
+    private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) {
+        ViewInfo[] result = new ViewInfo[2];
+        if (view == null) {
+            return result;
+        }
+
+        result[0] = createViewInfo(view, 0, setExtendedInfo, true);
+        result[1] = createViewInfo(view, offset, setExtendedInfo, true);
+        if (view instanceof ViewGroup) {
+            List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true);
+            result[0].setChildren(children);
+            result[1].setChildren(children);
+        }
+        return result;
+    }
+
+    /**
+     * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
+     * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
+     * set.
+     * @param offset an offset for the view bounds. Used only if view is part of the content frame.
+     */
+    private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo,
+            boolean isContentFrame) {
         if (view == null) {
             return null;
         }
 
-        ViewInfo result = new ViewInfo(view.getClass().getName(),
-                getContext().getViewKey(view),
-                view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset,
-                view, view.getLayoutParams());
+        ViewInfo result;
+        if (isContentFrame) {
+            result = new ViewInfo(view.getClass().getName(),
+                    getContext().getViewKey(view),
+                    view.getLeft(), view.getTop() + offset, view.getRight(),
+                    view.getBottom() + offset, view, view.getLayoutParams());
+
+        } else {
+            result = new SystemViewInfo(view.getClass().getName(),
+                    getContext().getViewKey(view),
+                    view.getLeft(), view.getTop(), view.getRight(),
+                    view.getBottom(), view, view.getLayoutParams());
+        }
 
         if (setExtendedInfo) {
             MarginLayoutParams marginParams = null;
@@ -1427,39 +1492,67 @@
                     marginParams != null ? marginParams.bottomMargin : 0);
         }
 
-        if (view instanceof ViewGroup) {
-            ViewGroup group = ((ViewGroup) view);
-            result.setChildren(visitAllChildren(group, 0 /*offset*/, setExtendedInfo));
-        }
-
         return result;
     }
 
-    /**
-     * Visits all the children of a given ViewGroup generate a list of {@link ViewInfo}
-     * containing the bounds of all the views.
-     * @param view the root View
-     * @param offset an offset for the view bounds.
-     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
-     */
-    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
-            boolean setExtendedInfo) {
-        if (viewGroup == null) {
-            return null;
-        }
-
-        List<ViewInfo> children = new ArrayList<ViewInfo>();
-        for (int i = 0; i < viewGroup.getChildCount(); i++) {
-            children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo));
-        }
-        return children;
-    }
-
-
     private void invalidateRenderingSize() {
         mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
     }
 
+    /**
+     * Creates the status bar with wifi and battery icons.
+     */
+    private StatusBar createStatusBar(BridgeContext context, Density density, int direction,
+            boolean isRtlSupported) throws XmlPullParserException {
+        StatusBar statusBar = new StatusBar(context, density,
+                direction, isRtlSupported);
+        statusBar.setLayoutParams(
+                new LinearLayout.LayoutParams(
+                        LayoutParams.MATCH_PARENT, mStatusBarSize));
+        return statusBar;
+    }
+
+    /**
+     * Creates the navigation bar with back, home and recent buttons.
+     *
+     * @param isRtl true if the current locale is right-to-left
+     * @param isRtlSupported true is the project manifest declares that the application
+     *        is RTL aware.
+     */
+    private NavigationBar createNavigationBar(BridgeContext context, Density density,
+            boolean isRtl, boolean isRtlSupported) throws XmlPullParserException {
+        NavigationBar navigationBar = new NavigationBar(context,
+                density, mNavigationBarOrientation, isRtl,
+                isRtlSupported);
+        if (mNavigationBarOrientation == LinearLayout.VERTICAL) {
+            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(mNavigationBarSize,
+                    LayoutParams.MATCH_PARENT));
+        } else {
+            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+                    mNavigationBarSize));
+        }
+        return navigationBar;
+    }
+
+    private TitleBar createTitleBar(BridgeContext context, Density density, String title)
+            throws XmlPullParserException {
+        TitleBar titleBar = new TitleBar(context, density, title);
+        titleBar.setLayoutParams(
+                new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize));
+        return titleBar;
+    }
+
+    /**
+     * Creates the action bar. Also queries the project callback for missing information.
+     */
+    private ActionBarLayout createActionBar(BridgeContext context, SessionParams params)
+            throws XmlPullParserException {
+        ActionBarLayout actionBar = new ActionBarLayout(context, params);
+        actionBar.setLayoutParams(new LinearLayout.LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+        return actionBar;
+    }
+
     public BufferedImage getImage() {
         return mImage;
     }
@@ -1472,6 +1565,10 @@
         return mViewInfoList;
     }
 
+    public List<ViewInfo> getSystemViewInfos() {
+        return mSystemViewInfoList;
+    }
+
     public Map<String, String> getDefaultProperties(Object viewObject) {
         return getContext().getDefaultPropMap(viewObject);
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 6dcb693..adb0937 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -165,6 +165,9 @@
      * @param context the current context
      */
     public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
+        if (value == null) {
+            return null;
+        }
         String stringValue = value.getValue();
         if (RenderResources.REFERENCE_NULL.equals(stringValue)) {
             return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
new file mode 100644
index 0000000..5c267df
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
@@ -0,0 +1,38 @@
+/*
+ * 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 com.android.layoutlib.bridge.impl;
+
+import com.android.ide.common.rendering.api.ViewInfo;
+
+public class SystemViewInfo extends ViewInfo {
+
+    public SystemViewInfo(String name, Object cookie, int left, int top,
+            int right, int bottom) {
+        super(name, cookie, left, top, right, bottom);
+    }
+
+    public SystemViewInfo(String name, Object cookie, int left, int top,
+            int right, int bottom, Object viewObject, Object layoutParamsObject) {
+        super(name, cookie, left, top, right, bottom, viewObject,
+                layoutParamsObject);
+    }
+
+    @Override
+    public boolean isSystemView() {
+        return true;
+    }
+}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index 7c3ab6f..2e952fc 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -116,6 +116,7 @@
                         "com.android.i18n.phonenumbers.*",  // for TextView with autolink attribute
                         "android.app.DatePickerDialog",     // b.android.com/28318
                         "android.app.TimePickerDialog",     // b.android.com/61515
+                        "com.android.internal.view.menu.ActionMenu",
                     },
                     excludeClasses,
                     new String[] {