Merge "DO / PO Shouldn't be removed as active admin..."
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b5b2753..c22a941 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5078,11 +5078,11 @@
                 Log.e(TAG, "Unable to setupGraphicsSupport and setupJitProfileSupport " +
                         "due to missing code-cache directory");
             }
-        }
 
-        // Add the lib dir path to hardware renderer so that vulkan layers
-        // can be searched for within that directory.
-        ThreadedRenderer.setLibDir(data.info.getLibDir());
+            // Add the lib dir path to hardware renderer so that vulkan layers
+            // can be searched for within that directory.
+            ThreadedRenderer.setLibDir(data.info.getLibDir());
+        }
 
         // Install the Network Security Config Provider. This must happen before the application
         // code is loaded to prevent issues with instances of TLS objects being created before
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1561d46..5535eaa 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6895,6 +6895,15 @@
        public static final String TETHER_DUN_APN = "tether_dun_apn";
 
        /**
+        * List of carrier apps which are whitelisted to prompt the user for install when
+        * a sim card with matching uicc carrier privilege rules is inserted.
+        *
+        * The value is "package1;package2;..."
+        * @hide
+        */
+       public static final String CARRIER_APP_WHITELIST = "carrier_app_whitelist";
+
+       /**
         * USB Mass Storage Enabled
         */
        public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 34713ad..501c6e9 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -33,7 +33,7 @@
  * @hide
  */
 @RemoteViews.RemoteView
-public class NotificationHeaderView extends LinearLayout {
+public class NotificationHeaderView extends ViewGroup {
     public static final int NO_COLOR = -1;
     private final int mHeaderMinWidth;
     private final int mExpandTopPadding;
@@ -134,27 +134,46 @@
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        super.onLayout(changed, l, t, r, b);
-        if (mProfileBadge.getVisibility() != View.GONE) {
-            int paddingEnd = getPaddingEnd();
-            if (mShowWorkBadgeAtEnd) {
-                paddingEnd = mContentEndMargin;
+        int left = getPaddingStart();
+        int childCount = getChildCount();
+        int ownHeight = getHeight() - getPaddingTop() - getPaddingBottom();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() == GONE) {
+                continue;
+            }
+            int childHeight = child.getMeasuredHeight();
+            MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
+            left += params.getMarginStart();
+            int right = left + child.getMeasuredWidth();
+            int top = (int) (getPaddingTop() + (ownHeight - childHeight) / 2.0f);
+            int bottom = top + childHeight;
+            int layoutLeft = left;
+            int layoutRight = right;
+            if (child == mProfileBadge) {
+                int paddingEnd = getPaddingEnd();
+                if (mShowWorkBadgeAtEnd) {
+                    paddingEnd = mContentEndMargin;
+                }
+                layoutRight = getWidth() - paddingEnd;
+                layoutLeft = layoutRight - child.getMeasuredWidth();
             }
             if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
-                mProfileBadge.layout(paddingEnd,
-                        mProfileBadge.getTop(),
-                        paddingEnd + mProfileBadge.getMeasuredWidth(),
-                        mProfileBadge.getBottom());
-            } else {
-                mProfileBadge.layout(getWidth() - paddingEnd - mProfileBadge.getMeasuredWidth(),
-                        mProfileBadge.getTop(),
-                        getWidth() - paddingEnd,
-                        mProfileBadge.getBottom());
+                int ltrLeft = layoutLeft;
+                layoutLeft = getWidth() - layoutRight;
+                layoutRight = getWidth() - ltrLeft;
             }
+            child.layout(layoutLeft, top, layoutRight, bottom);
+            left = right + params.getMarginEnd();
         }
         updateTouchListener();
     }
 
+    @Override
+    public LayoutParams generateLayoutParams(AttributeSet attrs) {
+        return new ViewGroup.MarginLayoutParams(getContext(), attrs);
+    }
+
     private void updateTouchListener() {
         if (mExpandClickListener != null) {
             mTouchListener.bindTouchRects();
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index ba456f9..e239852 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -883,6 +883,15 @@
     }
 
     /**
+     * Determine if the device is file encrypted
+     * @return true if device is file encrypted
+     */
+    public static boolean isFileEncryptionEnabled() {
+        final String status = SystemProperties.get("ro.crypto.type", "");
+        return "file".equalsIgnoreCase(status);
+    }
+
+    /**
      * Clears the encryption password.
      */
     public void clearEncryptionPassword() {
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 163db30..b45f8bb 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -22,8 +22,6 @@
     android:layout_width="wrap_content"
     android:layout_height="48dp"
     android:clipChildren="false"
-    android:layout_gravity="start|top"
-    android:gravity="center_vertical"
     android:paddingTop="5dp"
     android:paddingBottom="16dp"
     android:paddingStart="@dimen/notification_content_margin_start"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b2f5f8a..e5a6226 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2869,6 +2869,14 @@
     <string name="sim_added_message">Restart your device to access the cellular network.</string>
     <!-- See SIM_ADDED_DIALOG.  This is the button of that dialog. -->
     <string name="sim_restart_button">Restart</string>
+    <!-- See Carrier_App_Dialog. This is the message of that dialog. -->
+    <string name="carrier_app_dialog_message">To get your new SIM working properly, you\'ll need to install and open an app from your carrier.</string>
+    <!-- See Carrier_App_Dialog. This is the button of that dialog. -->
+    <string name="carrier_app_dialog_button">GET THE APP</string>
+    <string name="carrier_app_dialog_not_now">NOT NOW</string>
+    <!-- See carrier_app_notification. This is the headline. -->
+    <string name="carrier_app_notification_title">New SIM inserted</string>
+    <string name="carrier_app_notification_text">Tap to set it up</string>
 
     <!-- Date/Time picker dialogs strings -->
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index bc609c6..73cd175 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2530,4 +2530,9 @@
   <java-symbol type="array" name="resolver_target_actions_pin" />
   <java-symbol type="array" name="resolver_target_actions_unpin" />
 
+  <java-symbol type="string" name="carrier_app_dialog_message" />
+  <java-symbol type="string" name="carrier_app_dialog_button" />
+  <java-symbol type="string" name="carrier_app_dialog_not_now" />
+  <java-symbol type="string" name="carrier_app_notification_title" />
+  <java-symbol type="string" name="carrier_app_notification_text" />
 </resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Events.java b/packages/DocumentsUI/src/com/android/documentsui/Events.java
index 10a78b9..99b425e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Events.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Events.java
@@ -78,6 +78,27 @@
     }
 
     /**
+     * Whether or not the given keyCode represents a navigation keystroke (e.g. up, down, home).
+     *
+     * @param keyCode
+     * @return
+     */
+    public static boolean isNavigationKeyCode(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_DPAD_UP:
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+            case KeyEvent.KEYCODE_MOVE_HOME:
+            case KeyEvent.KEYCODE_MOVE_END:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+
+    /**
      * Returns true if the "SHIFT" bit is set.
      */
     public static boolean hasShiftBit(int metaState) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 2aabc99..eef7760 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -66,6 +66,7 @@
 import android.view.ActionMode;
 import android.view.DragEvent;
 import android.view.GestureDetector;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -99,7 +100,6 @@
 import com.android.documentsui.model.RootInfo;
 import com.android.documentsui.services.FileOperationService;
 import com.android.documentsui.services.FileOperations;
-
 import com.google.common.collect.Lists;
 
 import java.util.ArrayList;
@@ -529,6 +529,9 @@
             final Cursor cursor = mModel.getItem(modelId);
             checkNotNull(cursor, "Cursor cannot be null.");
 
+            // TODO: Should this be happening in onSelectionChanged? Technically this callback is
+            // triggered on "silent" selection updates (i.e. we might be reacting to unfinalized
+            // selection changes here)
             final int docFlags = getCursorInt(cursor, Document.COLUMN_FLAGS);
             if ((docFlags & Document.FLAG_SUPPORTS_DELETE) == 0) {
                 mNoDeleteCount += selected ? 1 : -1;
@@ -827,7 +830,6 @@
     @Override
     public void initDocumentHolder(DocumentHolder holder) {
         holder.addEventListener(mItemEventListener);
-        holder.addOnKeyListener(mSelectionManager);
     }
 
     @Override
@@ -1230,7 +1232,12 @@
     private class ItemEventListener implements DocumentHolder.EventListener {
         @Override
         public boolean onActivate(DocumentHolder doc) {
-            handleViewItem(doc.modelId);
+            // Toggle selection if we're in selection mode, othewise, view item.
+            if (mSelectionManager.hasSelection()) {
+                mSelectionManager.toggleSelection(doc.modelId);
+            } else {
+                handleViewItem(doc.modelId);
+            }
             return true;
         }
 
@@ -1240,6 +1247,128 @@
             mSelectionManager.setSelectionRangeBegin(doc.getAdapterPosition());
             return true;
         }
+
+        @Override
+        public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event) {
+            // Only handle key-down events. This is simpler, consistent with most other UIs, and
+            // enables the handling of repeated key events from holding down a key.
+            if (event.getAction() != KeyEvent.ACTION_DOWN) {
+                return false;
+            }
+
+            boolean handled = false;
+            if (Events.isNavigationKeyCode(keyCode)) {
+                // Find the target item and focus it.
+                int endPos = findTargetPosition(doc.itemView, keyCode);
+
+                if (endPos != RecyclerView.NO_POSITION) {
+                    focusItem(endPos);
+
+                    // Handle any necessary adjustments to selection.
+                    boolean extendSelection = event.isShiftPressed();
+                    if (extendSelection) {
+                        int startPos = doc.getAdapterPosition();
+                        mSelectionManager.selectRange(startPos, endPos);
+                    }
+                    handled = true;
+                }
+            } else {
+                // Handle enter key events
+                if (keyCode == KeyEvent.KEYCODE_ENTER) {
+                    handled = onActivate(doc);
+                }
+            }
+
+            return handled;
+        }
+
+        /**
+         * Finds the destination position where the focus should land for a given navigation event.
+         *
+         * @param view The view that received the event.
+         * @param keyCode The key code for the event.
+         * @return The adapter position of the destination item. Could be RecyclerView.NO_POSITION.
+         */
+        private int findTargetPosition(View view, int keyCode) {
+            if (keyCode == KeyEvent.KEYCODE_MOVE_HOME) {
+                return 0;
+            }
+
+            if (keyCode == KeyEvent.KEYCODE_MOVE_END) {
+                return mAdapter.getItemCount() - 1;
+            }
+
+            // Find a navigation target based on the arrow key that the user pressed.
+            int searchDir = -1;
+            switch (keyCode) {
+                case KeyEvent.KEYCODE_DPAD_UP:
+                    searchDir = View.FOCUS_UP;
+                    break;
+                case KeyEvent.KEYCODE_DPAD_DOWN:
+                    searchDir = View.FOCUS_DOWN;
+                    break;
+                case KeyEvent.KEYCODE_DPAD_LEFT:
+                    searchDir = View.FOCUS_LEFT;
+                    break;
+                case KeyEvent.KEYCODE_DPAD_RIGHT:
+                    searchDir = View.FOCUS_RIGHT;
+                    break;
+            }
+
+            if (searchDir != -1) {
+                View targetView = view.focusSearch(searchDir);
+                // TargetView can be null, for example, if the user pressed <down> at the bottom
+                // of the list.
+                if (targetView != null) {
+                    // Ignore navigation targets that aren't items in the RecyclerView.
+                    if (targetView.getParent() == mRecView) {
+                        return mRecView.getChildAdapterPosition(targetView);
+                    }
+                }
+            }
+
+            return RecyclerView.NO_POSITION;
+        }
+
+        /**
+         * Requests focus for the item in the given adapter position, scrolling the RecyclerView if
+         * necessary.
+         *
+         * @param pos
+         */
+        public void focusItem(final int pos) {
+            // If the item is already in view, focus it; otherwise, scroll to it and focus it.
+            RecyclerView.ViewHolder vh = mRecView.findViewHolderForAdapterPosition(pos);
+            if (vh != null) {
+                vh.itemView.requestFocus();
+            } else {
+                mRecView.smoothScrollToPosition(pos);
+                // Set a one-time listener to request focus when the scroll has completed.
+                mRecView.addOnScrollListener(
+                    new RecyclerView.OnScrollListener() {
+                        @Override
+                        public void onScrollStateChanged (RecyclerView view, int newState) {
+                            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+                                // When scrolling stops, find the item and focus it.
+                                RecyclerView.ViewHolder vh =
+                                        view.findViewHolderForAdapterPosition(pos);
+                                if (vh != null) {
+                                    vh.itemView.requestFocus();
+                                } else {
+                                    // This might happen in weird corner cases, e.g. if the user is
+                                    // scrolling while a delete operation is in progress.  In that
+                                    // case, just don't attempt to focus the missing item.
+                                    Log.w(
+                                        TAG, "Unable to focus position " + pos + " after a scroll");
+                                }
+                                view.removeOnScrollListener(this);
+                            }
+                        }
+                    });
+            }
+        }
+
+
     }
 
     private final class ModelUpdateListener implements Model.UpdateListener {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
index 8acf1af..1bfc6e9 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DocumentHolder.java
@@ -84,13 +84,7 @@
     public boolean onKey(View v, int keyCode, KeyEvent event) {
         // Event listener should always be set.
         checkNotNull(mEventListener);
-        // Intercept enter key-up events, and treat them as clicks.  Forward other events.
-        if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_ENTER) {
-            return mEventListener.onActivate(this);
-        } else if (mKeyListener != null) {
-            return mKeyListener.onKey(v, keyCode, event);
-        }
-        return false;
+        return mEventListener.onKey(this,  keyCode,  event);
     }
 
     public void addEventListener(DocumentHolder.EventListener listener) {
@@ -159,15 +153,29 @@
      */
     interface EventListener {
         /**
+         * Handles activation events on the document holder.
+         *
          * @param doc The target DocumentHolder
          * @return Whether the event was handled.
          */
         public boolean onActivate(DocumentHolder doc);
 
         /**
+         * Handles selection events on the document holder.
+         *
          * @param doc The target DocumentHolder
          * @return Whether the event was handled.
          */
         public boolean onSelect(DocumentHolder doc);
+
+        /**
+         * Handles key events on the document holder.
+         *
+         * @param doc The target DocumentHolder.
+         * @param keyCode Key code for the event.
+         * @param event KeyEvent for the event.
+         * @return Whether the event was handled.
+         */
+        public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event);
     }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
index eea91a0..516b25e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/MultiSelectManager.java
@@ -34,7 +34,6 @@
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
-import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
 
@@ -57,7 +56,7 @@
  * Additionally it can be configured to restrict selection to a single element, @see
  * #setSelectMode.
  */
-public final class MultiSelectManager implements View.OnKeyListener {
+public final class MultiSelectManager {
 
     /** Selection mode for multiple select. **/
     public static final int MODE_MULTIPLE = 0;
@@ -239,7 +238,8 @@
     }
 
     /**
-     * Clears the selection, without notifying anyone.
+     * Clears the selection, without notifying selection listeners. UI elements still need to be
+     * notified about state changes so that they can update their appearance.
      */
     private void clearSelectionQuietly() {
         mRanger = null;
@@ -248,10 +248,10 @@
             return;
         }
 
-        Selection intermediateSelection = getSelection(new Selection());
+        Selection oldSelection = getSelection(new Selection());
         mSelection.clear();
 
-        for (String id: intermediateSelection.getAll()) {
+        for (String id: oldSelection.getAll()) {
             notifyItemStateChanged(id, false);
         }
     }
@@ -334,21 +334,7 @@
         if (mSelection.contains(modelId)) {
             changed = attemptDeselect(modelId);
         } else {
-            boolean canSelect = notifyBeforeItemStateChange(modelId, true);
-            if (!canSelect) {
-                return;
-            }
-            if (mSingleSelect && hasSelection()) {
-                clearSelectionQuietly();
-            }
-
-            // Here we're already in selection mode. In that case
-            // When a simple click/tap (without SHIFT) creates causes
-            // an item to be selected.
-            // By recreating Ranger at this point, we allow the user to create
-            // multiple separate contiguous ranges with SHIFT+Click & Click.
-            selectAndNotify(modelId);
-            changed = true;
+            changed = attemptSelect(modelId);
         }
 
         if (changed) {
@@ -357,9 +343,46 @@
     }
 
     /**
-     * Sets the magic location at which a selection range begins. This
-     * value is consulted when determining how to extend, and modify
-     * selection ranges.
+     * Handle a range selection event.
+     * <li> If the MSM is currently in single-select mode, only the last item in the range will
+     * actually be selected.
+     * <li>If a range selection is not already active, one will be started, and the given range of
+     * items will be selected.  The given startPos becomes the anchor for the range selection.
+     * <li>If a range selection is already active, the anchor is not changed. The range is extended
+     * from its current anchor to endPos.
+     *
+     * @param startPos
+     * @param endPos
+     */
+    public void selectRange(int startPos, int endPos) {
+        // In single-select mode, just select the last item in the range.
+        if (mSingleSelect) {
+            attemptSelect(mAdapter.getModelId(endPos));
+            return;
+        }
+
+        // In regular (i.e. multi-select) mode
+        if (!isRangeSelectionActive()) {
+            // If a range selection isn't active, start one up
+            attemptSelect(mAdapter.getModelId(startPos));
+            setSelectionRangeBegin(startPos);
+        }
+        // Extend the range selection
+        mRanger.snapSelection(endPos);
+        notifySelectionChanged();
+    }
+
+    /**
+     * @return Whether or not there is a current range selection active.
+     */
+    private boolean isRangeSelectionActive() {
+        return mRanger != null;
+    }
+
+    /**
+     * Sets the magic location at which a selection range begins (the selection anchor). This value
+     * is consulted when determining how to extend, and modify selection ranges. Calling this when a
+     * range selection is active will reset the range selection.
      *
      * @throws IllegalStateException if {@code position} is not already be selected
      * @param position
@@ -434,6 +457,24 @@
         }
     }
 
+    /**
+     * @param id
+     * @return True if the update was applied.
+     */
+    private boolean attemptSelect(String id) {
+        checkArgument(id != null);
+        boolean canSelect = notifyBeforeItemStateChange(id, true);
+        if (!canSelect) {
+            return false;
+        }
+        if (mSingleSelect && hasSelection()) {
+            clearSelectionQuietly();
+        }
+
+        selectAndNotify(id);
+        return true;
+    }
+
     private boolean notifyBeforeItemStateChange(String id, boolean nextState) {
         int lastListener = mCallbacks.size() - 1;
         for (int i = lastListener; i > -1; i--) {
@@ -786,12 +827,10 @@
         Point createAbsolutePoint(Point relativePoint);
         Rect getAbsoluteRectForChildViewAt(int index);
         int getAdapterPositionAt(int index);
-        int getAdapterPositionForChildView(View view);
         int getColumnCount();
         int getRowCount();
         int getChildCount();
         int getVisibleChildCount();
-        void focusItem(int position);
         /**
          * Layout items are excluded from the GridModel.
          */
@@ -812,17 +851,8 @@
         }
 
         @Override
-        public int getAdapterPositionForChildView(View view) {
-            if (view.getParent() == mView) {
-                return mView.getChildAdapterPosition(view);
-            } else {
-                return RecyclerView.NO_POSITION;
-            }
-        }
-
-        @Override
         public int getAdapterPositionAt(int index) {
-            return getAdapterPositionForChildView(mView.getChildAt(index));
+            return mView.getChildAdapterPosition(mView.getChildAt(index));
         }
 
         @Override
@@ -921,39 +951,6 @@
         }
 
         @Override
-        public void focusItem(final int pos) {
-            // If the item is already in view, focus it; otherwise, scroll to it and focus it.
-            RecyclerView.ViewHolder vh = mView.findViewHolderForAdapterPosition(pos);
-            if (vh != null) {
-                vh.itemView.requestFocus();
-            } else {
-                mView.smoothScrollToPosition(pos);
-                // Set a one-time listener to request focus when the scroll has completed.
-                mView.addOnScrollListener(
-                    new RecyclerView.OnScrollListener() {
-                        @Override
-                        public void onScrollStateChanged (RecyclerView view, int newState) {
-                            if (newState == RecyclerView.SCROLL_STATE_IDLE) {
-                                // When scrolling stops, find the item and focus it.
-                                RecyclerView.ViewHolder vh =
-                                        view.findViewHolderForAdapterPosition(pos);
-                                if (vh != null) {
-                                    vh.itemView.requestFocus();
-                                } else {
-                                    // This might happen in weird corner cases, e.g. if the user is
-                                    // scrolling while a delete operation is in progress.  In that
-                                    // case, just don't attempt to focus the missing item.
-                                    Log.w(
-                                        TAG, "Unable to focus position " + pos + " after a scroll");
-                                }
-                                view.removeOnScrollListener(this);
-                            }
-                        }
-                    });
-            }
-        }
-
-        @Override
         public boolean isLayoutItem(int pos) {
             // The band selection model only operates on documents and directories. Exclude other
             // types of adapter items (e.g. whitespace items like dividers).
@@ -1907,99 +1904,4 @@
             return true;
         }
     }
-
-    // TODO: Might have to move this to a more global level.  e.g. What should happen if the
-    // user taps a file and then presses shift-down?  Currently the RecyclerView never even sees
-    // the key event.  Perhaps install a global key handler to catch those events while in
-    // selection mode?
-    @Override
-    public boolean onKey(View view, int keyCode, KeyEvent event) {
-        // Listen for key-down events.  This allows the handler to respond appropriately when
-        // the user holds down the arrow keys for navigation.
-        if (event.getAction() != KeyEvent.ACTION_DOWN) {
-            return false;
-        }
-
-        // Here we unpack information from the event and pass it to an more
-        // easily tested method....basically eliminating the need to synthesize
-        // events and views and so on in our tests.
-        int endPos = findTargetPosition(view, keyCode);
-        if (endPos == RecyclerView.NO_POSITION) {
-            // If there is no valid navigation target, don't handle the keypress.
-            return false;
-        }
-
-        int startPos = mEnvironment.getAdapterPositionForChildView(view);
-
-        return changeFocus(startPos, endPos, event.isShiftPressed());
-    }
-
-    /**
-     * @param startPosition The current focus position.
-     * @param targetPosition The adapter position to focus.
-     * @param extendSelection
-     */
-    @VisibleForTesting
-    boolean changeFocus(int startPosition, int targetPosition, boolean extendSelection) {
-        // Focus the new file.
-        mEnvironment.focusItem(targetPosition);
-
-        if (extendSelection) {
-            if (mSingleSelect) {
-                // We're in single select and have an existing selection.
-                // Our best guess as to what the user would expect is to advance the selection.
-                clearSelection();
-                toggleSelection(targetPosition);
-            } else {
-                if (!hasSelection()) {
-                    // No selection - start a selection when the user presses shift-arrow.
-                    toggleSelection(startPosition);
-                    setSelectionRangeBegin(startPosition);
-                }
-                mRanger.snapSelection(targetPosition);
-                notifySelectionChanged();
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * Returns the adapter position that the key combo is targeted at.
-     */
-    private int findTargetPosition(View view, int keyCode) {
-        int position = RecyclerView.NO_POSITION;
-        if (keyCode == KeyEvent.KEYCODE_MOVE_HOME) {
-            position = 0;
-        } else if (keyCode == KeyEvent.KEYCODE_MOVE_END) {
-            position = mAdapter.getItemCount() - 1;
-        } else {
-            // Find a navigation target based on the arrow key that the user pressed.  Ignore
-            // navigation targets that aren't items in the recycler view.
-            int searchDir = -1;
-            switch (keyCode) {
-                case KeyEvent.KEYCODE_DPAD_UP:
-                    searchDir = View.FOCUS_UP;
-                    break;
-                case KeyEvent.KEYCODE_DPAD_DOWN:
-                    searchDir = View.FOCUS_DOWN;
-                    break;
-                case KeyEvent.KEYCODE_DPAD_LEFT:
-                    searchDir = View.FOCUS_LEFT;
-                    break;
-                case KeyEvent.KEYCODE_DPAD_RIGHT:
-                    searchDir = View.FOCUS_RIGHT;
-                    break;
-            }
-            if (searchDir != -1) {
-                View targetView = view.focusSearch(searchDir);
-                // TargetView can be null, for example, if the user pressed <down> at the bottom of
-                // the list.
-                if (targetView != null) {
-                    position = mEnvironment.getAdapterPositionForChildView(targetView);
-                }
-            }
-        }
-        return position;
-    }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/DocumentHolderTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/DocumentHolderTest.java
index 16efc6e..87cd42f 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/DocumentHolderTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/DocumentHolderTest.java
@@ -22,6 +22,7 @@
 import android.os.SystemClock;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.MotionEvent.PointerCoords;
@@ -130,5 +131,10 @@
             return true;
         }
 
+        @Override
+        public boolean onKey(DocumentHolder doc, int keyCode, KeyEvent event) {
+            return false;
+        }
+
     }
 }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java
index d3ef9aa..b1cb29e 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManagerTest.java
@@ -173,12 +173,6 @@
         assertRangeSelection(0, 7);
     }
 
-    public void testKeyboardSelection() {
-        // This simulates shift-navigation.
-        keyToPosition(5, 10, true);
-        assertRangeSelection(5, 10);
-    }
-
     public void testSingleSelectMode() {
         mManager = new MultiSelectManager(mEnv, mAdapter, MultiSelectManager.MODE_SINGLE);
         mManager.addCallback(mCallback);
@@ -195,14 +189,6 @@
         assertSelection(items.get(20));
     }
 
-    public void testSingleSelectMode_ShiftDoesNotExtendSelection() {
-        mManager = new MultiSelectManager(mEnv, mAdapter, MultiSelectManager.MODE_SINGLE);
-        mManager.addCallback(mCallback);
-        longPress(20);
-        keyToPosition(20, 22, true);
-        assertSelection(items.get(22));
-    }
-
     public void testProvisionalSelection() {
         Selection s = mManager.getSelection();
         assertSelection();
@@ -263,10 +249,6 @@
         mManager.onSingleTapUp(TestInputEvent.shiftClick(position));
     }
 
-    private void keyToPosition(int startPos, int endPos, boolean shift) {
-        mManager.changeFocus(startPos, endPos, shift);
-    }
-
     private void assertSelected(String... expected) {
         for (int i = 0; i < expected.length; i++) {
             Selection selection = mManager.getSelection();
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
index 7920c50..353d4bd 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/MultiSelectManager_GridModelTest.java
@@ -23,7 +23,6 @@
 import android.support.v7.widget.RecyclerView.OnScrollListener;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
-import android.view.View;
 
 import com.android.documentsui.dirlist.MultiSelectManager.GridModel;
 
@@ -326,16 +325,6 @@
         }
 
         @Override
-        public int getAdapterPositionForChildView(View view) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public void focusItem(int i) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
         public boolean isLayoutItem(int adapterPosition) {
             return false;
         }
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
index 0e79561..8e624a0 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/TestSelectionEnvironment.java
@@ -19,7 +19,6 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.support.v7.widget.RecyclerView.OnScrollListener;
-import android.view.View;
 
 import com.android.documentsui.dirlist.MultiSelectManager.SelectionEnvironment;
 
@@ -83,11 +82,6 @@
     }
 
     @Override
-    public int getAdapterPositionForChildView(View view) {
-        return 0;
-    }
-
-    @Override
     public int getColumnCount() {
         return 0;
     }
@@ -108,10 +102,6 @@
     }
 
     @Override
-    public void focusItem(int position) {
-    }
-
-    @Override
     public boolean isLayoutItem(int adapterPosition) {
         return false;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 00b9888..76e522e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -197,9 +197,13 @@
                 if (expandedSize != collapsedSize) {
                     int paddingEnd = contractedHeader.getMeasuredWidth() - expandedSize;
                     contractedHeader.setPadding(
-                            isLayoutRtl() ? paddingEnd : contractedHeader.getPaddingLeft(),
+                            contractedHeader.isLayoutRtl()
+                                    ? paddingEnd
+                                    : contractedHeader.getPaddingLeft(),
                             contractedHeader.getPaddingTop(),
-                            isLayoutRtl() ? contractedHeader.getPaddingLeft() : paddingEnd,
+                            contractedHeader.isLayoutRtl()
+                                    ? contractedHeader.getPaddingLeft()
+                                    : paddingEnd,
                             contractedHeader.getPaddingBottom());
                     contractedHeader.setShowWorkBadgeAtEnd(true);
                     return true;
@@ -208,9 +212,13 @@
                 int paddingEnd = mNotificationContentMarginEnd;
                 if (contractedHeader.getPaddingEnd() != paddingEnd) {
                     contractedHeader.setPadding(
-                            isLayoutRtl() ? paddingEnd : contractedHeader.getPaddingLeft(),
+                            contractedHeader.isLayoutRtl()
+                                    ? paddingEnd
+                                    : contractedHeader.getPaddingLeft(),
                             contractedHeader.getPaddingTop(),
-                            isLayoutRtl() ? contractedHeader.getPaddingLeft() : paddingEnd,
+                            contractedHeader.isLayoutRtl()
+                                    ? contractedHeader.getPaddingLeft()
+                                    : paddingEnd,
                             contractedHeader.getPaddingBottom());
                     contractedHeader.setShowWorkBadgeAtEnd(false);
                     return true;
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 91d4c9e..daf839a 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -600,9 +600,18 @@
                     null, null);
         }
 
-        Intent startServiceIntent = new Intent(mContext, SyncJobService.class);
+        // Set up the communication channel between the scheduled job and the sync manager.
+        // This is posted to the *main* looper intentionally, to defer calling startService()
+        // until after the lengthy primary boot sequence completes on that thread, to avoid
+        // spurious ANR triggering.
+        final Intent startServiceIntent = new Intent(mContext, SyncJobService.class);
         startServiceIntent.putExtra(SyncJobService.EXTRA_MESSENGER, new Messenger(mSyncHandler));
-        mContext.startService(startServiceIntent);
+        new Handler(mContext.getMainLooper()).post(new Runnable() {
+            @Override
+            public void run() {
+                mContext.startService(startServiceIntent);
+            }
+        });
     }
 
     private boolean isDeviceProvisioned() {
diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java
index 56eb7ec..d45938c 100644
--- a/telecomm/java/android/telecom/Phone.java
+++ b/telecomm/java/android/telecom/Phone.java
@@ -348,11 +348,6 @@
     }
 
     private void checkCallTree(ParcelableCall parcelableCall) {
-        if (parcelableCall.getParentCallId() != null &&
-                !mCallByTelecomCallId.containsKey(parcelableCall.getParentCallId())) {
-            Log.wtf(this, "ParcelableCall %s has nonexistent parent %s",
-                    parcelableCall.getId(), parcelableCall.getParentCallId());
-        }
         if (parcelableCall.getChildCallIds() != null) {
             for (int i = 0; i < parcelableCall.getChildCallIds().size(); i++) {
                 if (!mCallByTelecomCallId.containsKey(parcelableCall.getChildCallIds().get(i))) {