Merge "Don't apply overscan insets to freeform windows."
diff --git a/api/current.txt b/api/current.txt
index f13601e..cabaad4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -22496,6 +22496,7 @@
     method public void setRatingType(int);
     method public void setSessionActivity(android.app.PendingIntent);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+    field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
@@ -22574,6 +22575,7 @@
     field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
+    field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
     field public static final int STATE_BUFFERING = 6; // 0x6
     field public static final int STATE_CONNECTING = 8; // 0x8
@@ -22890,7 +22892,7 @@
     method public void onInputAdded(java.lang.String);
     method public void onInputRemoved(java.lang.String);
     method public void onInputStateChanged(java.lang.String, int);
-    method public void onTvInputInfoChanged(java.lang.String, android.media.tv.TvInputInfo);
+    method public void onTvInputInfoChanged(android.media.tv.TvInputInfo);
   }
 
   public abstract class TvInputService extends android.app.Service {
@@ -22898,7 +22900,7 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public android.media.tv.TvInputService.RecordingSession onCreateRecordingSession(java.lang.String);
     method public abstract android.media.tv.TvInputService.Session onCreateSession(java.lang.String);
-    method public final void setTvInputInfo(java.lang.String, android.media.tv.TvInputInfo);
+    method public static final void setTvInputInfo(android.content.Context, android.media.tv.TvInputInfo);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.tv.TvInputService";
     field public static final java.lang.String SERVICE_META_DATA = "android.media.tv.input";
   }
diff --git a/api/system-current.txt b/api/system-current.txt
index 0d33503..cfa3969 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -23837,6 +23837,7 @@
     method public void setRatingType(int);
     method public void setSessionActivity(android.app.PendingIntent);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+    field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
@@ -23915,6 +23916,7 @@
     field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
+    field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
     field public static final int STATE_BUFFERING = 6; // 0x6
     field public static final int STATE_CONNECTING = 8; // 0x8
@@ -24405,7 +24407,7 @@
     method public void onInputRemoved(java.lang.String);
     method public void onInputStateChanged(java.lang.String, int);
     method public void onInputUpdated(java.lang.String);
-    method public void onTvInputInfoChanged(java.lang.String, android.media.tv.TvInputInfo);
+    method public void onTvInputInfoChanged(android.media.tv.TvInputInfo);
   }
 
   public abstract class TvInputService extends android.app.Service {
@@ -24417,7 +24419,7 @@
     method public java.lang.String onHardwareRemoved(android.media.tv.TvInputHardwareInfo);
     method public android.media.tv.TvInputInfo onHdmiDeviceAdded(android.hardware.hdmi.HdmiDeviceInfo);
     method public java.lang.String onHdmiDeviceRemoved(android.hardware.hdmi.HdmiDeviceInfo);
-    method public final void setTvInputInfo(java.lang.String, android.media.tv.TvInputInfo);
+    method public static final void setTvInputInfo(android.content.Context, android.media.tv.TvInputInfo);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.tv.TvInputService";
     field public static final java.lang.String SERVICE_META_DATA = "android.media.tv.input";
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 48fd6f0..8f534a3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -22505,6 +22505,7 @@
     method public void setRatingType(int);
     method public void setSessionActivity(android.app.PendingIntent);
     field public static final int FLAG_HANDLES_MEDIA_BUTTONS = 1; // 0x1
+    field public static final int FLAG_HANDLES_PREPARE_ONLY = 4; // 0x4
     field public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 2; // 0x2
   }
 
@@ -22583,6 +22584,7 @@
     field public static final long ACTION_SKIP_TO_QUEUE_ITEM = 4096L; // 0x1000L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator<android.media.session.PlaybackState> CREATOR;
+    field public static final java.lang.String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
     field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
     field public static final int STATE_BUFFERING = 6; // 0x6
     field public static final int STATE_CONNECTING = 8; // 0x8
@@ -22899,7 +22901,7 @@
     method public void onInputAdded(java.lang.String);
     method public void onInputRemoved(java.lang.String);
     method public void onInputStateChanged(java.lang.String, int);
-    method public void onTvInputInfoChanged(java.lang.String, android.media.tv.TvInputInfo);
+    method public void onTvInputInfoChanged(android.media.tv.TvInputInfo);
   }
 
   public abstract class TvInputService extends android.app.Service {
@@ -22907,7 +22909,7 @@
     method public final android.os.IBinder onBind(android.content.Intent);
     method public android.media.tv.TvInputService.RecordingSession onCreateRecordingSession(java.lang.String);
     method public abstract android.media.tv.TvInputService.Session onCreateSession(java.lang.String);
-    method public final void setTvInputInfo(java.lang.String, android.media.tv.TvInputInfo);
+    method public static final void setTvInputInfo(android.content.Context, android.media.tv.TvInputInfo);
     field public static final java.lang.String SERVICE_INTERFACE = "android.media.tv.TvInputService";
     field public static final java.lang.String SERVICE_META_DATA = "android.media.tv.input";
   }
diff --git a/core/java/android/hardware/input/KeyboardLayout.java b/core/java/android/hardware/input/KeyboardLayout.java
index 584008c..2cafa08 100644
--- a/core/java/android/hardware/input/KeyboardLayout.java
+++ b/core/java/android/hardware/input/KeyboardLayout.java
@@ -16,8 +16,10 @@
 
 package android.hardware.input;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.LocaleList;
 
 import java.util.Locale;
 
@@ -32,7 +34,8 @@
     private final String mLabel;
     private final String mCollection;
     private final int mPriority;
-    private final Locale[] mLocales;
+    @NonNull
+    private final LocaleList mLocales;
     private final int mVendorId;
     private final int mProductId;
 
@@ -47,16 +50,12 @@
     };
 
     public KeyboardLayout(String descriptor, String label, String collection, int priority,
-            Locale[] locales, int vid, int pid) {
+            LocaleList locales, int vid, int pid) {
         mDescriptor = descriptor;
         mLabel = label;
         mCollection = collection;
         mPriority = priority;
-        if (locales != null) {
-            mLocales = locales;
-        } else {
-            mLocales = new Locale[0];
-        }
+        mLocales = locales;
         mVendorId = vid;
         mProductId = pid;
     }
@@ -66,11 +65,7 @@
         mLabel = source.readString();
         mCollection = source.readString();
         mPriority = source.readInt();
-        int N = source.readInt();
-        mLocales = new Locale[N];
-        for (int i = 0; i < N; i++) {
-            mLocales[i] = Locale.forLanguageTag(source.readString());
-        }
+        mLocales = LocaleList.CREATOR.createFromParcel(source);
         mVendorId = source.readInt();
         mProductId = source.readInt();
     }
@@ -108,7 +103,7 @@
      * This may be empty if a locale has not been assigned to this keyboard layout.
      * @return The keyboard layout's intended locale.
      */
-    public Locale[] getLocales() {
+    public LocaleList getLocales() {
         return mLocales;
     }
 
@@ -141,14 +136,7 @@
         dest.writeString(mLabel);
         dest.writeString(mCollection);
         dest.writeInt(mPriority);
-        if (mLocales != null) {
-            dest.writeInt(mLocales.length);
-            for (Locale l : mLocales) {
-                dest.writeString(l.toLanguageTag());
-            }
-        } else {
-            dest.writeInt(0);
-        }
+        mLocales.writeToParcel(dest, 0);
         dest.writeInt(mVendorId);
         dest.writeInt(mProductId);
     }
diff --git a/core/java/android/view/KeyboardShortcutGroup.java b/core/java/android/view/KeyboardShortcutGroup.java
index 013255b..57d07c0 100644
--- a/core/java/android/view/KeyboardShortcutGroup.java
+++ b/core/java/android/view/KeyboardShortcutGroup.java
@@ -32,6 +32,8 @@
 public final class KeyboardShortcutGroup implements Parcelable {
     private final CharSequence mLabel;
     private final List<KeyboardShortcutInfo> mItems;
+    // The system group looks different UI wise.
+    private boolean mSystemGroup;
 
     /**
      * @param label The title to be used for this group, or null if there is none.
@@ -50,10 +52,33 @@
         this(label, Collections.<KeyboardShortcutInfo>emptyList());
     }
 
+    /**
+     * @param label The title to be used for this group, or null if there is none.
+     * @param items The set of items to be included.
+     * @param isSystemGroup Set this to {@code true} if this is s system group.
+     * @hide
+     */
+    public KeyboardShortcutGroup(@Nullable CharSequence label,
+            @NonNull List<KeyboardShortcutInfo> items, boolean isSystemGroup) {
+        mLabel = label;
+        mItems = new ArrayList<>(checkNotNull(items));
+        mSystemGroup = isSystemGroup;
+    }
+
+    /**
+     * @param label The title to be used for this group, or null if there is none.
+     * @param isSystemGroup Set this to {@code true} if this is s system group.
+     * @hide
+     */
+    public KeyboardShortcutGroup(@Nullable CharSequence label, boolean isSystemGroup) {
+        this(label, Collections.<KeyboardShortcutInfo>emptyList(), isSystemGroup);
+    }
+
     private KeyboardShortcutGroup(Parcel source) {
         mItems = new ArrayList<>();
         mLabel = source.readCharSequence();
         source.readTypedList(mItems, KeyboardShortcutInfo.CREATOR);
+        mSystemGroup = source.readInt() == 1;
     }
 
     /**
@@ -70,6 +95,11 @@
         return mItems;
     }
 
+    /** @hide **/
+    public boolean isSystemGroup() {
+        return mSystemGroup;
+    }
+
     /**
      * Adds an item to the existing list.
      *
@@ -88,6 +118,7 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeCharSequence(mLabel);
         dest.writeTypedList(mItems);
+        dest.writeInt(mSystemGroup ? 1 : 0);
     }
 
     public static final Creator<KeyboardShortcutGroup> CREATOR =
@@ -99,4 +130,4 @@
             return new KeyboardShortcutGroup[size];
         }
     };
-}
\ No newline at end of file
+}
diff --git a/core/java/android/view/PointerIcon.java b/core/java/android/view/PointerIcon.java
index 7ba046b..81bb638 100644
--- a/core/java/android/view/PointerIcon.java
+++ b/core/java/android/view/PointerIcon.java
@@ -139,9 +139,7 @@
 
     private static final PointerIcon gNullIcon = new PointerIcon(STYLE_NULL);
     private static final SparseArray<PointerIcon> gSystemIcons = new SparseArray<PointerIcon>();
-
-    /** @hide */
-    public static boolean sUseLargeIcons = false;
+    private static boolean sUseLargeIcons = false;
 
     private final int mStyle;
     private int mSystemIconResourceId;
@@ -235,6 +233,15 @@
     }
 
     /**
+     * Updates wheter accessibility large icons are used or not.
+     * @hide
+     */
+    public static void setUseLargeIcons(boolean use) {
+        sUseLargeIcons = use;
+        gSystemIcons.clear();
+    }
+
+    /**
      * Creates a custom pointer from the given bitmap and hotspot information.
      *
      * @param bitmap The bitmap for the icon.
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b2eab4c..26421fb 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4191,10 +4191,10 @@
     <string name="new_sms_notification_content">Open SMS app to view</string>
 
     <!-- Notification title shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
-    <string name="user_encrypted_title">Device encrypted</string>
+    <string name="user_encrypted_title">Some functions might not be available</string>
     <!-- Notification message shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
-    <string name="user_encrypted_message">Some functions might not be available</string>
+    <string name="user_encrypted_message">Touch to continue</string>
     <!-- Notification detail shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
-    <string name="user_encrypted_detail">Touch to continue</string>
+    <string name="user_encrypted_detail">User profile locked</string>
 
 </resources>
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index b1a51a56..3d9b60d 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -605,6 +605,7 @@
         /**
          * Request that the player start playback for a specific media id.
          *
+         * @see PlaybackState#EXTRA_PREPARE_ONLY
          * @param mediaId The id of the requested media.
          * @param extras Optional extras that can include extra information about the media item
          *               to be played.
@@ -626,6 +627,7 @@
          * An empty or null query should be treated as a request to play any
          * music.
          *
+         * @see PlaybackState#EXTRA_PREPARE_ONLY
          * @param query The search query.
          * @param extras Optional extras that can include extra information
          *            about the query.
@@ -646,6 +648,7 @@
         /**
          * Request that the player start playback for a specific {@link Uri}.
          *
+         * @see PlaybackState#EXTRA_PREPARE_ONLY
          * @param uri  The URI of the requested media.
          * @param extras Optional extras that can include extra information about the media item
          *               to be played.
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index e1e9b79..8c5b19c 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -87,6 +87,12 @@
     public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1;
 
     /**
+     * Set this flag on the session to indicate that it can handle
+     * the {@link PlaybackState#EXTRA_PREPARE_ONLY} field.
+     */
+    public static final int FLAG_HANDLES_PREPARE_ONLY = 1 << 2;
+
+    /**
      * System only flag for a session that needs to have priority over all other
      * sessions. This flag ensures this session will receive media button events
      * regardless of the current ordering in the system.
@@ -100,6 +106,7 @@
     @IntDef(flag = true, value = {
             FLAG_HANDLES_MEDIA_BUTTONS,
             FLAG_HANDLES_TRANSPORT_CONTROLS,
+            FLAG_HANDLES_PREPARE_ONLY,
             FLAG_EXCLUSIVE_GLOBAL_PRIORITY })
     public @interface SessionFlags { }
 
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index bbe04b5..1079a1f 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -133,6 +133,21 @@
     public static final long ACTION_PLAY_FROM_URI = 1 << 13;
 
     /**
+     * Used as an optional boolean extra field in
+     * {@link MediaController.TransportControls#playFromMediaId},
+     * {@link MediaController.TransportControls#playFromSearch}, and
+     * {@link MediaController.TransportControls#playFromUri}. Value of {@code true} overrides
+     * the default behavior of starting the playback after preparing. Check
+     * {@link MediaSession#FLAG_HANDLES_PREPARE_ONLY} to see if the media session supports this.
+     *
+     * @see MediaSession#FLAG_HANDLES_PREPARE_ONLY
+     * @see MediaController.TransportControls#playFromMediaId
+     * @see MediaController.TransportControls#playFromSearch
+     * @see MediaController.TransportControls#playFromUri
+     */
+    public static final String EXTRA_PREPARE_ONLY = "android.media.session.extra.PREPARE_ONLY";
+
+    /**
      * This is the default playback state and indicates that no media has been
      * added yet, or the performer has been reset and has no content to play.
      *
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 0febc16..d189333 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -41,6 +41,7 @@
 interface ITvInputManager {
     List<TvInputInfo> getTvInputList(int userId);
     TvInputInfo getTvInputInfo(in String inputId, int userId);
+    void setTvInputInfo(in TvInputInfo inputInfo, int userId);
     int getTvInputState(in String inputId, int userId);
 
     List<TvContentRatingSystemInfo> getTvContentRatingSystemList(int userId);
diff --git a/media/java/android/media/tv/ITvInputManagerCallback.aidl b/media/java/android/media/tv/ITvInputManagerCallback.aidl
index 3bf415b..395c9f3 100644
--- a/media/java/android/media/tv/ITvInputManagerCallback.aidl
+++ b/media/java/android/media/tv/ITvInputManagerCallback.aidl
@@ -29,5 +29,5 @@
 
     void onInputStateChanged(in String inputId, int state);
 
-    void onTvInputInfoChanged(in String inputId, in TvInputInfo TvInputInfo);
+    void onTvInputInfoChanged(in TvInputInfo TvInputInfo);
 }
diff --git a/media/java/android/media/tv/ITvInputServiceCallback.aidl b/media/java/android/media/tv/ITvInputServiceCallback.aidl
index 9f13882..74ab562 100644
--- a/media/java/android/media/tv/ITvInputServiceCallback.aidl
+++ b/media/java/android/media/tv/ITvInputServiceCallback.aidl
@@ -27,6 +27,4 @@
     void addHardwareTvInput(in int deviceId, in TvInputInfo inputInfo);
     void addHdmiTvInput(in int id, in TvInputInfo inputInfo);
     void removeTvInput(in String inputId);
-
-    void setTvInputInfo(in String inputId, in TvInputInfo inputInfo);
 }
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index f1de8fd..86bded9 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -726,12 +726,11 @@
         }
 
         /**
-         * This is called when the information about a given TV input is changed.
+         * This is called when the information about a given TV input has been changed.
          *
-         * @param inputId The ID of the TV input.
          * @param inputInfo TvInputInfo object that contains the information about the TV input.
          */
-        public void onTvInputInfoChanged(String inputId, TvInputInfo inputInfo) {
+        public void onTvInputInfoChanged(TvInputInfo inputInfo) {
         }
     }
 
@@ -784,11 +783,11 @@
             });
         }
 
-        public void postTvInputInfoChanged(final String inputId, final TvInputInfo inputInfo) {
+        public void postTvInputInfoChanged(final TvInputInfo inputInfo) {
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    mCallback.onTvInputInfoChanged(inputId, inputInfo);
+                    mCallback.onTvInputInfoChanged(inputInfo);
                 }
             });
         }
@@ -1089,10 +1088,10 @@
             }
 
             @Override
-            public void onTvInputInfoChanged(String inputId, TvInputInfo inputInfo) {
+            public void onTvInputInfoChanged(TvInputInfo inputInfo) {
                 synchronized (mLock) {
                     for (TvInputCallbackRecord record : mCallbackRecords) {
-                        record.postTvInputInfoChanged(inputId, inputInfo);
+                        record.postTvInputInfoChanged(inputInfo);
                     }
                 }
             }
@@ -1143,6 +1142,23 @@
     }
 
     /**
+     * Sets a new TvInputInfo object for a given input.
+     *
+     * <p>This is called internally only by {@link TvInputService}.
+     *
+     * @param inputInfo The TvInputInfo object to set.
+     * @throws IllegalArgumentException if the argument is {@code null}.
+     */
+    void setTvInputInfo(@NonNull TvInputInfo inputInfo) {
+        Preconditions.checkNotNull(inputInfo);
+        try {
+            mService.setTvInputInfo(inputInfo, mUserId);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Error trying to set " + inputInfo, e);
+        }
+    }
+
+    /**
      * Returns the state of a given TV input.
      *
      * <p>The state is one of the following:
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index f74ae66..a2b6346 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -262,16 +262,16 @@
      * <p>The system service automatically creates the TvInputInfo for each TV input based on
      * information collected from the AndroidManifest.xml, thus it is not necessary to call this
      * method unless the TV input has additional information to pass such as ability to record and
-     * tuner count.
+     * tuner count. Attempting to change information about a TV input that the calling package does
+     * not own does nothing.
      *
-     * @param inputId The ID of the TV input.
+     * @param context The application context.
      * @param inputInfo The TvInputInfo object that contains that new information.
      */
-    public final void setTvInputInfo(String inputId, TvInputInfo inputInfo) {
-        SomeArgs args = SomeArgs.obtain();
-        args.arg1 = inputId;
-        args.arg2 = inputInfo;
-        mServiceHandler.obtainMessage(ServiceHandler.DO_SET_TV_INPUT_INFO, args).sendToTarget();
+    public static final void setTvInputInfo(Context context, TvInputInfo inputInfo) {
+        TvInputManager manager = (TvInputManager) context.getSystemService(
+                Context.TV_INPUT_SERVICE);
+        manager.setTvInputInfo(inputInfo);
     }
 
     private boolean isPassthroughInput(String inputId) {
@@ -1938,7 +1938,6 @@
         private static final int DO_REMOVE_HARDWARE_TV_INPUT = 5;
         private static final int DO_ADD_HDMI_TV_INPUT = 6;
         private static final int DO_REMOVE_HDMI_TV_INPUT = 7;
-        private static final int DO_SET_TV_INPUT_INFO = 8;
 
         private void broadcastAddHardwareTvInput(int deviceId, TvInputInfo inputInfo) {
             int n = mCallbacks.beginBroadcast();
@@ -1976,18 +1975,6 @@
             mCallbacks.finishBroadcast();
         }
 
-        private void broadcastSetTvInputInfo(String inputId, TvInputInfo inputInfo) {
-            int n = mCallbacks.beginBroadcast();
-            for (int i = 0; i < n; ++i) {
-                try {
-                    mCallbacks.getBroadcastItem(i).setTvInputInfo(inputId, inputInfo);
-                } catch (RemoteException e) {
-                    Log.e(TAG, "error in broadcastSetTvInputInfo", e);
-                }
-            }
-            mCallbacks.finishBroadcast();
-        }
-
         @Override
         public final void handleMessage(Message msg) {
             switch (msg.what) {
@@ -2120,16 +2107,6 @@
                     }
                     return;
                 }
-                case DO_SET_TV_INPUT_INFO: {
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    String inputId = (String) args.arg1;
-                    TvInputInfo inputInfo = (TvInputInfo) args.arg2;
-                    if (inputInfo != null) {
-                        broadcastSetTvInputInfo(inputId, inputInfo);
-                    }
-                    args.recycle();
-                    return;
-                }
                 default: {
                     Log.w(TAG, "Unhandled message code: " + msg.what);
                     return;
diff --git a/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
new file mode 100644
index 0000000..5a6553f
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcut_app_item.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/keyboard_shortcuts_keyword_wrapper"
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="24dp"
+        android:paddingEnd="24dp"
+        android:paddingBottom="8dp">
+    <TextView
+            android:id="@+id/keyboard_shortcuts_keyword"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingEnd="12dp"
+            android:background="@android:color/white"
+            android:textColor="#D9000000"
+            android:textSize="16sp"
+            android:maxLines="5"
+            android:singleLine="false"
+            android:scrollHorizontally="false"
+            android:layout_alignParentStart="true"
+            android:minWidth="100dp"
+            android:maxWidth="260dp"/>
+    <!--TODO: introduce and use a layout that allows wrapping and right align -->
+    <LinearLayout
+            android:id="@+id/keyboard_shortcuts_item_container"
+            android:layout_toEndOf="@+id/keyboard_shortcuts_keyword"
+            android:orientation="horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@android:color/white"
+            android:layout_alignParentEnd="true"
+            android:gravity="end"
+            android:textSize="14sp"
+            android:paddingStart="0dp"
+            android:paddingEnd="0dp"
+            android:scrollHorizontally="false"
+            android:minWidth="100dp"
+            android:maxWidth="260dp"/>
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml
new file mode 100644
index 0000000..80a478a
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_category_title.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:layout_width="match_parent"
+          android:layout_height="match_parent"
+          android:textSize="14sp"
+          android:paddingStart="24dp"
+          android:paddingTop="20dp"
+          android:paddingEnd="24dp"
+          android:paddingBottom="13dp" />
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml
new file mode 100644
index 0000000..fa07eb1
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_container.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="horizontal"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content">
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
new file mode 100644
index 0000000..5002c12
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_key_view.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:layout_marginStart="4dp"
+          android:padding="4dp"
+          android:background="#EEEEEE"
+          android:textColor="#8C000000"
+          android:singleLine="true"
+          android:textSize="14sp"/>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
index 460433e..77b1264 100644
--- a/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_view.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-  ~ Copyright (C) 2015 The Android Open Source Project
+  ~ Copyright (C) 2016 The Android Open Source Project
   ~
   ~ Licensed under the Apache License, Version 2.0 (the "License");
   ~ you may not use this file except in compliance with the License.
@@ -14,11 +14,25 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<RelativeLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/keyboard_shortcuts_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:layout_marginTop="40dp"
-    android:focusable="true">
-</RelativeLayout>
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/keyboard_shortcuts_wrapper"
+        android:layout_width="488dp"
+        android:layout_height="wrap_content"
+        android:focusable="true">
+    <ScrollView
+            android:id="@+id/keyboard_shortcuts_scroll_view"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1">
+        <LinearLayout
+                android:id="@+id/keyboard_shortcuts_container"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical"/>
+    </ScrollView>
+    <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="?android:attr/listDivider"/>
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml b/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml
new file mode 100644
index 0000000..802acfe
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyboard_shortcuts_wrapper.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:orientation="vertical"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content">
+</LinearLayout>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index f0d9949..9bb6dc6 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -154,4 +154,9 @@
 
     <color name="switch_bar_background">#ff37474f</color>
     <color name="switch_accent_color">#ff7fcac3</color>
+
+    <!-- Keyboard shortcuts colors -->
+    <color name="ksh_system_group_color">#ff00bcd4</color>
+    <color name="ksh_application_group_color">#fff44336</color>
+    <color name="ksh_dialog_background_color">#ffffffff</color>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 240d32e..4edb976 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1175,7 +1175,7 @@
     }
 
     protected void toggleKeyboardShortcuts() {
-        getKeyboardShortcuts().toggleKeyboardShortcuts(mContext);
+        getKeyboardShortcuts().toggleKeyboardShortcuts();
     }
 
     protected void cancelPreloadingRecents() {
@@ -1518,7 +1518,7 @@
 
     protected KeyboardShortcuts getKeyboardShortcuts() {
         if (mKeyboardShortcuts == null) {
-            mKeyboardShortcuts = new KeyboardShortcuts();
+            mKeyboardShortcuts = new KeyboardShortcuts(mContext);
         }
 
         return mKeyboardShortcuts;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index b36fb7e..25e9a7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -19,25 +19,38 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.graphics.Color;
+import android.graphics.Typeface;
 import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
 import android.os.Handler;
+import android.os.Looper;
+import android.util.DisplayMetrics;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.KeyEvent;
 import android.view.KeyboardShortcutGroup;
 import android.view.KeyboardShortcutInfo;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
 import android.view.Window;
-import android.view.WindowManager;
 import android.view.WindowManager.KeyboardShortcutsReceiver;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
 
 import com.android.systemui.R;
 import com.android.systemui.recents.Recents;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import static android.content.Context.LAYOUT_INFLATER_SERVICE;
-import static android.graphics.Color.TRANSPARENT;
+import static android.graphics.Color.WHITE;
 import static android.view.Gravity.TOP;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
 
@@ -45,33 +58,44 @@
  * Contains functionality for handling keyboard shortcuts.
  */
 public class KeyboardShortcuts {
-    private static final String TAG = "KeyboardShortcuts";
+    private static final char SYSTEM_HOME_BASE_CHARACTER = '\u2386';
+    private static final char SYSTEM_BACK_BASE_CHARACTER = '\u007F';
+    private static final char SYSTEM_RECENTS_BASE_CHARACTER = '\u0009';
+
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private final Context mContext;
+    private final OnClickListener dialogCloseListener =  new DialogInterface.OnClickListener() {
+        public void onClick(DialogInterface dialog, int id) {
+            dismissKeyboardShortcutsDialog();
+        }
+    };
 
     private Dialog mKeyboardShortcutsDialog;
 
-    public KeyboardShortcuts() {}
+    public KeyboardShortcuts(Context context) {
+        this.mContext = context;
+    }
 
-    public void toggleKeyboardShortcuts(final Context context) {
+    public void toggleKeyboardShortcuts() {
         if (mKeyboardShortcutsDialog == null) {
-            Recents.getSystemServices().requestKeyboardShortcuts(context,
+            Recents.getSystemServices().requestKeyboardShortcuts(mContext,
                 new KeyboardShortcutsReceiver() {
                     @Override
                     public void onKeyboardShortcutsReceived(
                             final List<KeyboardShortcutGroup> result) {
                         KeyboardShortcutGroup systemGroup = new KeyboardShortcutGroup(
-                            context.getString(R.string.keyboard_shortcut_group_system));
+                            mContext.getString(R.string.keyboard_shortcut_group_system), true);
                         systemGroup.addItem(new KeyboardShortcutInfo(
-                            context.getString(R.string.keyboard_shortcut_group_system_home),
-                            '\u2386', KeyEvent.META_META_ON));
+                            mContext.getString(R.string.keyboard_shortcut_group_system_home),
+                            SYSTEM_HOME_BASE_CHARACTER, KeyEvent.META_META_ON));
                         systemGroup.addItem(new KeyboardShortcutInfo(
-                            context.getString(R.string.keyboard_shortcut_group_system_back),
-                            '\u007F', KeyEvent.META_META_ON));
+                            mContext.getString(R.string.keyboard_shortcut_group_system_back),
+                            SYSTEM_BACK_BASE_CHARACTER, KeyEvent.META_META_ON));
                         systemGroup.addItem(new KeyboardShortcutInfo(
-                            context.getString(R.string.keyboard_shortcut_group_system_recents),
-                            '\u0009', KeyEvent.META_ALT_ON));
+                            mContext.getString(R.string.keyboard_shortcut_group_system_recents),
+                            SYSTEM_RECENTS_BASE_CHARACTER, KeyEvent.META_ALT_ON));
                         result.add(systemGroup);
-                        Log.i(TAG, "Keyboard shortcuts received: " + String.valueOf(result));
-                        showKeyboardShortcutsDialog(context);
+                        showKeyboardShortcutsDialog(result);
                     }
                 });
         } else {
@@ -79,33 +103,6 @@
         }
     }
 
-    private void showKeyboardShortcutsDialog(Context context) {
-        // Create dialog.
-        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
-        LayoutInflater inflater = (LayoutInflater) context.getSystemService(
-                LAYOUT_INFLATER_SERVICE);
-        final View keyboardShortcutsView = inflater.inflate(
-                R.layout.keyboard_shortcuts_view, null);
-
-        populateKeyboardShortcuts(keyboardShortcutsView.findViewById(
-                R.id.keyboard_shortcuts_wrapper));
-        dialogBuilder.setView(keyboardShortcutsView);
-        mKeyboardShortcutsDialog = dialogBuilder.create();
-        mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
-
-        // Setup window.
-        Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
-        keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
-        keyboardShortcutsWindow.setBackgroundDrawable(
-                new ColorDrawable(TRANSPARENT));
-        keyboardShortcutsWindow.setGravity(TOP);
-        keyboardShortcutsView.post(new Runnable() {
-            public void run() {
-                mKeyboardShortcutsDialog.show();
-            }
-        });
-    }
-
     public void dismissKeyboardShortcutsDialog() {
         if (mKeyboardShortcutsDialog != null) {
             mKeyboardShortcutsDialog.dismiss();
@@ -113,11 +110,99 @@
         }
     }
 
-    /**
-     * @return {@code true} if the keyboard shortcuts have been successfully populated.
-     */
-    private boolean populateKeyboardShortcuts(View keyboardShortcutsLayout) {
-        // TODO: Populate shortcuts.
-        return true;
+    private void showKeyboardShortcutsDialog(
+            final List<KeyboardShortcutGroup> keyboardShortcutGroups) {
+        // Need to post on the main thread.
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                // TODO: break all this code out into a handleShowKeyboard...
+                // Might add more things posted; should consider adding a custom handler so
+                // you can send the keyboardShortcutsGroups as part of the message.
+                AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
+                LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+                        LAYOUT_INFLATER_SERVICE);
+                final View keyboardShortcutsView = inflater.inflate(
+                        R.layout.keyboard_shortcuts_view, null);
+                DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
+                ScrollView scrollView = (ScrollView) keyboardShortcutsView.findViewById(
+                        R.id.keyboard_shortcuts_scroll_view);
+                // TODO: find a better way to set the height.
+                scrollView.setLayoutParams(new LinearLayout.LayoutParams(
+                        LayoutParams.WRAP_CONTENT,
+                        (int) (dm.heightPixels * dm.density)));
+
+                populateKeyboardShortcuts((LinearLayout) keyboardShortcutsView.findViewById(
+                        R.id.keyboard_shortcuts_container), keyboardShortcutGroups);
+                dialogBuilder.setView(keyboardShortcutsView);
+                dialogBuilder.setPositiveButton(R.string.quick_settings_done, dialogCloseListener);
+                mKeyboardShortcutsDialog = dialogBuilder.create();
+                mKeyboardShortcutsDialog.setCanceledOnTouchOutside(true);
+
+                // Setup window.
+                Window keyboardShortcutsWindow = mKeyboardShortcutsDialog.getWindow();
+                keyboardShortcutsWindow.setType(TYPE_SYSTEM_DIALOG);
+                keyboardShortcutsWindow.setBackgroundDrawable(
+                        mContext.getDrawable(R.color.ksh_dialog_background_color));
+                keyboardShortcutsWindow.setGravity(TOP);
+                mKeyboardShortcutsDialog.show();
+            }
+        });
+    }
+
+    private void populateKeyboardShortcuts(LinearLayout keyboardShortcutsLayout,
+            List<KeyboardShortcutGroup> keyboardShortcutGroups) {
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        final int keyboardShortcutGroupsSize = keyboardShortcutGroups.size();
+        for (int i = 0; i < keyboardShortcutGroupsSize; i++) {
+            KeyboardShortcutGroup group = keyboardShortcutGroups.get(i);
+            TextView categoryTitle = (TextView) inflater.inflate(
+                    R.layout.keyboard_shortcuts_category_title, keyboardShortcutsLayout, false);
+            categoryTitle.setText(group.getLabel());
+            categoryTitle.setTextColor(group.isSystemGroup()
+                    ? mContext.getColor(R.color.ksh_system_group_color)
+                    : mContext.getColor(R.color.ksh_application_group_color));
+            keyboardShortcutsLayout.addView(categoryTitle);
+
+            LinearLayout shortcutWrapper = (LinearLayout) inflater.inflate(
+                    R.layout.keyboard_shortcuts_wrapper, null);
+            final int itemsSize = group.getItems().size();
+            for (int j = 0; j < itemsSize; j++) {
+                KeyboardShortcutInfo info = group.getItems().get(j);
+                View shortcutView = inflater.inflate(R.layout.keyboard_shortcut_app_item, null);
+                TextView textView = (TextView) shortcutView
+                        .findViewById(R.id.keyboard_shortcuts_keyword);
+                textView.setText(info.getLabel());
+
+                List<String> shortcutKeys = getHumanReadableShortcutKeys(info);
+                final int shortcutKeysSize = shortcutKeys.size();
+                for (int k = 0; k < shortcutKeysSize; k++) {
+                    String shortcutKey = shortcutKeys.get(k);
+                    TextView shortcutKeyView = (TextView) inflater.inflate(
+                            R.layout.keyboard_shortcuts_key_view, null);
+                    shortcutKeyView.setText(shortcutKey);
+                    LinearLayout shortcutItemsContainer = (LinearLayout) shortcutView
+                            .findViewById(R.id.keyboard_shortcuts_item_container);
+                    shortcutItemsContainer.addView(shortcutKeyView);
+                }
+                shortcutWrapper.addView(shortcutView);
+            }
+
+            // TODO: merge container and wrapper into one xml file - wrapper is always a child of
+            // container.
+            LinearLayout shortcutsContainer = (LinearLayout) inflater.inflate(
+                    R.layout.keyboard_shortcuts_container, null);
+            shortcutsContainer.addView(shortcutWrapper);
+            keyboardShortcutsLayout.addView(shortcutsContainer);
+        }
+    }
+
+    private List<String> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
+        // TODO: fix the shortcuts. Find or build an util which can produce human readable
+        // names of the baseCharacter and the modifiers.
+        List<String> shortcutKeys = new ArrayList<>();
+        shortcutKeys.add(KeyEvent.metaStateToString(info.getModifiers()).toUpperCase());
+        shortcutKeys.add(Character.getName(info.getBaseCharacter()).toUpperCase());
+        return shortcutKeys;
     }
 }
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index e9f0a7a..d0cd536 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -200,7 +200,7 @@
                 PendingIntent.FLAG_UPDATE_CURRENT);
 
         Notification notification = new Notification.Builder(mContext)
-                .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
+                .setSmallIcon(com.android.internal.R.drawable.ic_secure)
                 .setWhen(0)
                 .setOngoing(true)
                 .setTicker(title)
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 573afd6..033a243 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -16,7 +16,9 @@
 
 package com.android.server.input;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.util.LocaleList;
 import android.view.Display;
 import com.android.internal.inputmethod.InputMethodSubtypeHandle;
 import com.android.internal.os.SomeArgs;
@@ -780,8 +782,10 @@
                         || layout.getProductId() != d.getProductId()) {
                     return;
                 }
-                for (Locale l : layout.getLocales()) {
-                    if (isCompatibleLocale(systemLocale, l)) {
+                final LocaleList locales = layout.getLocales();
+                final int numLocales = locales.size();
+                for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
+                    if (isCompatibleLocale(systemLocale, locales.get(localeIndex))) {
                         layouts.add(layout);
                         break;
                     }
@@ -799,9 +803,12 @@
         final int N = layouts.size();
         for (int i = 0; i < N; i++) {
             KeyboardLayout layout = layouts.get(i);
-            for (Locale l : layout.getLocales()) {
-                if (l.getCountry().equals(systemLocale.getCountry())
-                        && l.getVariant().equals(systemLocale.getVariant())) {
+            final LocaleList locales = layout.getLocales();
+            final int numLocales = locales.size();
+            for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
+                final Locale locale = locales.get(localeIndex);
+                if (locale.getCountry().equals(systemLocale.getCountry())
+                        && locale.getVariant().equals(systemLocale.getVariant())) {
                     return layout.getDescriptor();
                 }
             }
@@ -809,8 +816,11 @@
         // Then try an exact match of language and country
         for (int i = 0; i < N; i++) {
             KeyboardLayout layout = layouts.get(i);
-            for (Locale l : layout.getLocales()) {
-                if (l.getCountry().equals(systemLocale.getCountry())) {
+            final LocaleList locales = layout.getLocales();
+            final int numLocales = locales.size();
+            for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
+                final Locale locale = locales.get(localeIndex);
+                if (locale.getCountry().equals(systemLocale.getCountry())) {
                     return layout.getDescriptor();
                 }
             }
@@ -1170,7 +1180,7 @@
                                     0);
                             String languageTags = a.getString(
                                     com.android.internal.R.styleable.KeyboardLayout_locale);
-                            Locale[] locales = getLocalesFromLanguageTags(languageTags);
+                            LocaleList locales = getLocalesFromLanguageTags(languageTags);
                             int vid = a.getInt(
                                     com.android.internal.R.styleable.KeyboardLayout_vendorId, -1);
                             int pid = a.getInt(
@@ -1210,16 +1220,12 @@
         }
     }
 
-    private static Locale[] getLocalesFromLanguageTags(String languageTags) {
+    @NonNull
+    private static LocaleList getLocalesFromLanguageTags(String languageTags) {
         if (TextUtils.isEmpty(languageTags)) {
-            return new Locale[0];
+            return LocaleList.getEmptyLocaleList();
         }
-        String[] tags = languageTags.split("\\|");
-        Locale[] locales = new Locale[tags.length];
-        for (int i = 0; i < tags.length; i++) {
-            locales[i] = Locale.forLanguageTag(tags[i]);
-        }
-        return locales;
+        return LocaleList.forLanguageTags(languageTags.replace('|', ','));
     }
 
     /**
@@ -1596,7 +1602,7 @@
         final int accessibilityConfig = Settings.Secure.getIntForUser(
                 mContext.getContentResolver(), Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON,
                 0, UserHandle.USER_CURRENT);
-        PointerIcon.sUseLargeIcons = (accessibilityConfig == 1);
+        PointerIcon.setUseLargeIcons(accessibilityConfig == 1);
         nativeReloadPointerIcons(mPtr);
     }
 
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 62e7fb4..318f966 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -71,6 +71,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.InputChannel;
@@ -779,15 +780,14 @@
         }
     }
 
-    private void notifyTvInputInfoChanged(UserState userState, String inputId,
-            TvInputInfo inputInfo) {
+    private void setTvInputInfoLocked(UserState userState, TvInputInfo inputInfo) {
         if (DEBUG) {
-            Slog.d(TAG, "notifyTvInputInfoChanged(inputId=" + inputId + ", inputInfo=" + inputInfo
-                    + ")");
+            Slog.d(TAG, "setTvInputInfoLocked(inputInfo=" + inputInfo + ")");
         }
+        // TODO: Also update the internal input list.
         for (ITvInputManagerCallback callback : userState.callbackSet) {
             try {
-                callback.onTvInputInfoChanged(inputId, inputInfo);
+                callback.onTvInputInfoChanged(inputInfo);
             } catch (RemoteException e) {
                 Slog.e(TAG, "failed to report changed input info to callback", e);
             }
@@ -846,6 +846,36 @@
             }
         }
 
+        public void setTvInputInfo(TvInputInfo inputInfo, int userId) {
+            String inputInfoPackageName = inputInfo.getServiceInfo().packageName;
+            String callingPackageName = getCallingPackageName();
+            if (!TextUtils.equals(inputInfoPackageName, callingPackageName)) {
+                throw new IllegalArgumentException("calling package " + callingPackageName
+                        + " is not allowed to change TvInputInfo for " + inputInfoPackageName);
+            }
+
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, "setTvInputInfoChanged");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    UserState userState = getOrCreateUserStateLocked(resolvedUserId);
+                    setTvInputInfoLocked(userState, inputInfo);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        private String getCallingPackageName() {
+            final String[] packages = mContext.getPackageManager().getPackagesForUid(
+                    Binder.getCallingUid());
+            if (packages != null && packages.length > 0) {
+                return packages[0];
+            }
+            return "unknown";
+        }
+
         @Override
         public int getTvInputState(String inputId, int userId) {
             final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
@@ -2233,18 +2263,6 @@
                 }
             }
         }
-
-        @Override
-        public void setTvInputInfo(String inputId, TvInputInfo inputInfo) {
-            ensureValidInput(inputInfo);
-            synchronized (mLock) {
-                if (DEBUG) {
-                    Slog.d(TAG, "setTvInputInfo(" + inputInfo + ")");
-                }
-                UserState userState = getOrCreateUserStateLocked(mUserId);
-                notifyTvInputInfoChanged(userState, inputId, inputInfo);
-            }
-        }
     }
 
     private final class SessionCallback extends ITvInputSessionCallback.Stub {
diff --git a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
index 0979cd3..66aa863 100644
--- a/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
+++ b/services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
@@ -35,10 +35,10 @@
 
     static final boolean DEBUG_RESIZE = false;
     static final boolean DEBUG = false;
-    static final boolean DEBUG_ADD_REMOVE = false;
+    static final boolean DEBUG_ADD_REMOVE = true;
     static final boolean DEBUG_FOCUS = false;
     static final boolean DEBUG_FOCUS_LIGHT = DEBUG_FOCUS || false;
-    static final boolean DEBUG_ANIM = false;
+    static final boolean DEBUG_ANIM = true;
     static final boolean DEBUG_KEYGUARD = false;
     static final boolean DEBUG_LAYOUT = false;
     static final boolean DEBUG_LAYERS = false;
@@ -50,7 +50,7 @@
     static final boolean DEBUG_ORIENTATION = false;
     static final boolean DEBUG_APP_ORIENTATION = false;
     static final boolean DEBUG_CONFIGURATION = false;
-    static final boolean DEBUG_APP_TRANSITIONS = false;
+    static final boolean DEBUG_APP_TRANSITIONS = true;
     static final boolean DEBUG_STARTING_WINDOW = false;
     static final boolean DEBUG_WALLPAPER = false;
     static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 7ed7006..4dd2b4d 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2239,7 +2239,8 @@
         }
         pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
                 pw.print(" mShownPosition="); mShownPosition.printShortString(pw);
-                pw.print(" isReadyForDisplay()="); pw.println(isReadyForDisplay());
+                pw.print(" isReadyForDisplay()="); pw.print(isReadyForDisplay());
+                pw.print(" hasSavedSurface()="); pw.println(hasSavedSurface());
         if (dumpAll) {
             pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
                     pw.print(" last="); mLastFrame.printShortString(pw);
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index cffcc5d..428ab7a 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -567,6 +567,10 @@
 
     WindowSurfaceController createSurfaceLocked() {
         final WindowState w = mWin;
+        if (w.hasSavedSurface()) {
+            Slog.i(TAG, "***** createSurface: " + this + ": called when we had a saved surface");
+        }
+
         if (mSurfaceController == null) {
             if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
                     "createSurface " + this + ": mDrawState=DRAW_PENDING");