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))) {