Merge "Separate sessionCreated and finishedEvents callbacks" into jb-mr2-dev
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index a746370..0dd567b 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -288,6 +288,9 @@
             // Get more expandable list-related info for this item
             pos = mConnector.getUnflattenedPos(childFlPos);
 
+            final boolean isLayoutRtl = isLayoutRtl();
+            final int width = getWidth();
+
             // If this item type and the previous item type are different, then we need to change
             // the left & right bounds
             if (pos.position.type != lastItemType) {
@@ -300,9 +303,18 @@
                     indicatorRect.left = mIndicatorLeft;
                     indicatorRect.right = mIndicatorRight;
                 }
-                
-                indicatorRect.left += mPaddingLeft;
-                indicatorRect.right += mPaddingLeft;
+
+                if (isLayoutRtl) {
+                    final int temp = indicatorRect.left;
+                    indicatorRect.left = width - indicatorRect.right;
+                    indicatorRect.right = width - temp;
+
+                    indicatorRect.left -= mPaddingRight;
+                    indicatorRect.right -= mPaddingRight;
+                } else {
+                    indicatorRect.left += mPaddingLeft;
+                    indicatorRect.right += mPaddingLeft;
+                }
 
                 lastItemType = pos.position.type; 
             }
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 7c40a64..4b62c2d 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2417,6 +2417,34 @@
     }
 
     /**
+     * Used by {@link #arrowScrollImpl(int)} to help determine the next selected position
+     * to move to. This can return a position currently not represented by a view on screen
+     * but only in the direction given.
+     *
+     * @param selectedPos Current selected position to move from
+     * @param direction Direction to move in
+     * @return Desired selected position after moving in the given direction
+     */
+    private final int nextSelectedPositionForDirection(int selectedPos, int direction) {
+        int nextSelected;
+        if (direction == View.FOCUS_DOWN) {
+            nextSelected = selectedPos != INVALID_POSITION && selectedPos >= mFirstPosition ?
+                    selectedPos + 1 :
+                    mFirstPosition;
+        } else {
+            final int lastPos = mFirstPosition + getChildCount() - 1;
+            nextSelected = selectedPos != INVALID_POSITION && selectedPos < lastPos?
+                    selectedPos - 1 :
+                    lastPos;
+        }
+
+        if (nextSelected < 0 || nextSelected >= mAdapter.getCount()) {
+            return INVALID_POSITION;
+        }
+        return lookForSelectablePosition(nextSelected, direction == View.FOCUS_DOWN);
+    }
+
+    /**
      * Handle an arrow scroll going up or down.  Take into account whether items are selectable,
      * whether there are focusable items etc.
      *
@@ -2431,7 +2459,7 @@
         View selectedView = getSelectedView();
         int selectedPos = mSelectedPosition;
 
-        int nextSelectedPosition = lookForSelectablePositionOnScreen(direction);
+        int nextSelectedPosition = nextSelectedPositionForDirection(selectedPos, direction);
         int amountToScroll = amountToScroll(direction, nextSelectedPosition);
 
         // if we are moving focus, we may OVERRIDE the default behavior
@@ -2643,14 +2671,18 @@
         final int listBottom = getHeight() - mListPadding.bottom;
         final int listTop = mListPadding.top;
 
-        final int numChildren = getChildCount();
+        int numChildren = getChildCount();
 
         if (direction == View.FOCUS_DOWN) {
             int indexToMakeVisible = numChildren - 1;
             if (nextSelectedPosition != INVALID_POSITION) {
                 indexToMakeVisible = nextSelectedPosition - mFirstPosition;
             }
-
+            while (numChildren <= indexToMakeVisible) {
+                // Child to view is not attached yet.
+                addViewBelow(getChildAt(numChildren - 1), mFirstPosition + numChildren - 1);
+                numChildren++;
+            }
             final int positionToMakeVisible = mFirstPosition + indexToMakeVisible;
             final View viewToMakeVisible = getChildAt(indexToMakeVisible);
 
@@ -2684,6 +2716,12 @@
             if (nextSelectedPosition != INVALID_POSITION) {
                 indexToMakeVisible = nextSelectedPosition - mFirstPosition;
             }
+            while (indexToMakeVisible < 0) {
+                // Child to view is not attached yet.
+                addViewAbove(getChildAt(0), mFirstPosition);
+                mFirstPosition--;
+                indexToMakeVisible = nextSelectedPosition - mFirstPosition;
+            }
             final int positionToMakeVisible = mFirstPosition + indexToMakeVisible;
             final View viewToMakeVisible = getChildAt(indexToMakeVisible);
             int goalTop = listTop;
diff --git a/core/res/res/layout/simple_expandable_list_item_1.xml b/core/res/res/layout/simple_expandable_list_item_1.xml
index 9810a60..7cce12a 100644
--- a/core/res/res/layout/simple_expandable_list_item_1.xml
+++ b/core/res/res/layout/simple_expandable_list_item_1.xml
@@ -21,4 +21,5 @@
     android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
     android:textAppearance="?android:attr/textAppearanceListItem"
     android:gravity="center_vertical"
+    android:textAlignment="viewStart"
 />
diff --git a/core/res/res/layout/simple_expandable_list_item_2.xml b/core/res/res/layout/simple_expandable_list_item_2.xml
index ed845f8..da60d7a 100644
--- a/core/res/res/layout/simple_expandable_list_item_2.xml
+++ b/core/res/res/layout/simple_expandable_list_item_2.xml
@@ -28,6 +28,7 @@
         android:layout_height="wrap_content"
         android:layout_marginTop="6dip"
         android:textAppearance="?android:attr/textAppearanceListItem"
+        android:textAlignment="viewStart"
     />
 
     <TextView android:id="@android:id/text2"
@@ -36,6 +37,7 @@
         android:layout_below="@android:id/text1"
         android:layout_alignStart="@android:id/text1"
         android:textAppearance="?android:attr/textAppearanceSmall"
+        android:textAlignment="viewStart"
     />
 
 </TwoLineListItem>
diff --git a/services/java/com/android/server/content/ContentService.java b/services/java/com/android/server/content/ContentService.java
index 3b92338..545ec93 100644
--- a/services/java/com/android/server/content/ContentService.java
+++ b/services/java/com/android/server/content/ContentService.java
@@ -37,7 +37,9 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.text.format.DateUtils;
 import android.util.Log;
+import android.util.Slog;
 import android.util.SparseIntArray;
 
 import java.io.FileDescriptor;
@@ -406,6 +408,12 @@
                 "no permission to write the sync settings");
         int userId = UserHandle.getCallingUserId();
 
+        if (pollFrequency <= DateUtils.MINUTE_IN_MILLIS) {
+            Slog.w(TAG, "Requested poll frequency of " + pollFrequency
+                    + "ms being rounded up to 60 seconds.");
+            pollFrequency = DateUtils.MINUTE_IN_MILLIS;
+        }
+
         long identityToken = clearCallingIdentity();
         try {
             getSyncManager().getSyncStorageEngine().addPeriodicSync(