Merge "Adding some automated tests for apps on SD (and their corresponding apps)."
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index fa6abec..a556a32 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -278,6 +278,10 @@
 
         int mClientCount = 0;
 
+        Application getApplication() {
+            return mApplication;
+        }
+
         public PackageInfo(ActivityThread activityThread, ApplicationInfo aInfo,
                 ActivityThread mainThread, ClassLoader baseLoader,
                 boolean securityViolation, boolean includeCode) {
@@ -648,7 +652,7 @@
             }
             mActivityThread.mAllApplications.add(app);
             mApplication = app;
-            
+
             if (instrumentation != null) {
                 try {
                     instrumentation.callApplicationOnCreate(app);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index f296f43..4c2b36f 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -260,7 +260,8 @@
     
     @Override
     public Context getApplicationContext() {
-        return mMainThread.getApplication();
+        return (mPackageInfo != null) ?
+                mPackageInfo.getApplication() : mMainThread.getApplication();
     }
     
     @Override
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 9df8ac3..74943f3 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1500,8 +1500,10 @@
                         focus.getFocusedRect(mTempRect);
                         if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Focus " + focus
                                 + ": focusRect=" + mTempRect.toShortString());
-                        ((ViewGroup) mView).offsetDescendantRectToMyCoords(
-                                focus, mTempRect);
+                        if (mView instanceof ViewGroup) {
+                            ((ViewGroup) mView).offsetDescendantRectToMyCoords(
+                                    focus, mTempRect);
+                        }
                         if (DEBUG_INPUT_RESIZE) Log.v(TAG,
                                 "Focus in window: focusRect="
                                 + mTempRect.toShortString()
@@ -2491,8 +2493,12 @@
                                 // of previous focused into the coord system of
                                 // newly focused view
                                 focused.getFocusedRect(mTempRect);
-                                ((ViewGroup) mView).offsetDescendantRectToMyCoords(focused, mTempRect);
-                                ((ViewGroup) mView).offsetRectIntoDescendantCoords(v, mTempRect);
+                                if (mView instanceof ViewGroup) {
+                                    ((ViewGroup) mView).offsetDescendantRectToMyCoords(
+                                            focused, mTempRect);
+                                    ((ViewGroup) mView).offsetRectIntoDescendantCoords(
+                                            v, mTempRect);
+                                }
                                 focusPassed = v.requestFocus(direction, mTempRect);
                             }
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index f886eef..714ae70 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1668,7 +1668,7 @@
         }
         nativeClearCursor(); // start next trackball movement from page edge
         if (bottom) {
-            return pinScrollTo(mScrollX, computeVerticalScrollRange(), true, 0);
+            return pinScrollTo(mScrollX, computeRealVerticalScrollRange(), true, 0);
         }
         // Page down.
         int h = getHeight();
@@ -1907,7 +1907,7 @@
     private int pinLocY(int y) {
         if (mInOverScrollMode) return y;
         return pinLoc(y, getViewHeightWithTitle(),
-                      computeVerticalScrollRange() + getTitleHeight());
+                      computeRealVerticalScrollRange() + getTitleHeight());
     }
 
     /**
@@ -2258,8 +2258,7 @@
         return false;
     }
 
-    @Override
-    protected int computeHorizontalScrollRange() {
+    private int computeRealHorizontalScrollRange() {
         if (mDrawHistory) {
             return mHistoryWidth;
         } else {
@@ -2269,7 +2268,27 @@
     }
 
     @Override
-    protected int computeVerticalScrollRange() {
+    protected int computeHorizontalScrollRange() {
+        int range = computeRealHorizontalScrollRange();
+
+        // Adjust reported range if overscrolled to compress the scroll bars
+        final int scrollX = mScrollX;
+        final int overscrollRight = computeMaxScrollX();
+        if (scrollX < 0) {
+            range -= scrollX;
+        } else if (scrollX > overscrollRight) {
+            range += scrollX - overscrollRight;
+        }
+
+        return range;
+    }
+
+    @Override
+    protected int computeHorizontalScrollOffset() {
+        return Math.max(mScrollX, 0);
+    }
+
+    private int computeRealVerticalScrollRange() {
         if (mDrawHistory) {
             return mHistoryHeight;
         } else {
@@ -2279,6 +2298,22 @@
     }
 
     @Override
+    protected int computeVerticalScrollRange() {
+        int range = computeRealVerticalScrollRange();
+
+        // Adjust reported range if overscrolled to compress the scroll bars
+        final int scrollY = mScrollY;
+        final int overscrollBottom = computeMaxScrollY();
+        if (scrollY < 0) {
+            range -= scrollY;
+        } else if (scrollY > overscrollBottom) {
+            range += scrollY - overscrollBottom;
+        }
+
+        return range;
+    }
+
+    @Override
     protected int computeVerticalScrollOffset() {
         return Math.max(mScrollY - getTitleHeight(), 0);
     }
@@ -3134,14 +3169,14 @@
             canvas.save();
             canvas.translate(mScrollX, mScrollY);
             canvas.clipRect(-mScrollX, top - mScrollY,
-                    computeHorizontalScrollRange() - mScrollX, top
-                            + computeVerticalScrollRange() - mScrollY,
+                    computeRealHorizontalScrollRange() - mScrollX, top
+                            + computeRealVerticalScrollRange() - mScrollY,
                     Region.Op.DIFFERENCE);
             canvas.drawPaint(mOverScrollBackground);
             canvas.restore();
             // next clip the region for the content
-            canvas.clipRect(0, top, computeHorizontalScrollRange(), top
-                    + computeVerticalScrollRange());
+            canvas.clipRect(0, top, computeRealHorizontalScrollRange(), top
+                    + computeRealVerticalScrollRange());
         }
         if (mTitleBar != null) {
             canvas.translate(0, (int) mTitleBar.getHeight());
@@ -4272,7 +4307,7 @@
         public DragTrackerHandler(float x, float y, DragTracker proxy) {
             mProxy = proxy;
 
-            int docBottom = computeVerticalScrollRange() + getTitleHeight();
+            int docBottom = computeRealVerticalScrollRange() + getTitleHeight();
             int viewTop = getScrollY();
             int viewBottom = viewTop + getHeight();
 
@@ -5364,11 +5399,11 @@
     }
 
     private int computeMaxScrollX() {
-        return Math.max(computeHorizontalScrollRange() - getViewWidth(), 0);
+        return Math.max(computeRealHorizontalScrollRange() - getViewWidth(), 0);
     }
 
     private int computeMaxScrollY() {
-        return Math.max(computeVerticalScrollRange() + getTitleHeight()
+        return Math.max(computeRealVerticalScrollRange() + getTitleHeight()
                 - getViewHeightWithTitle(), 0);
     }
 
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java
index 3dab9f2..6b845b0 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -206,7 +206,12 @@
         if (format == null || "".equals(format)) {
             return DateFormat.getDateInstance(DateFormat.SHORT);
         } else {
-            return new SimpleDateFormat(format);
+            try {
+                return new SimpleDateFormat(format);
+            } catch (IllegalArgumentException e) {
+                // If we tried to use a bad format string, fall back to a default.
+                return DateFormat.getDateInstance(DateFormat.SHORT);
+            }
         }
     }