Merge "Removing unused assets in mdpi" into honeycomb
diff --git a/api/current.xml b/api/current.xml
index b7d7b3a..0122b83 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -53808,6 +53808,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_LOCAL_ONLY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.intent.extra.LOCAL_ONLY&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_PHONE_NUMBER"
  type="java.lang.String"
  transient="false"
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 6388dc5..5bdc79d 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -195,6 +195,13 @@
     public static final String KEY_CALLER_UID = "callerUid";
     public static final String KEY_CALLER_PID = "callerPid";
 
+    /**
+     * Boolean, if set and 'customTokens' the authenticator is responsible for
+     * notifications.
+     * @hide
+     */
+    public static final String KEY_NOTIFY_ON_FAILURE = "notifyOnAuthFailure";
+
     public static final String ACTION_AUTHENTICATOR_INTENT =
             "android.accounts.AccountAuthenticator";
     public static final String AUTHENTICATOR_META_DATA_NAME =
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 2c99f14..fb16609 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -897,6 +897,9 @@
             // let authenticator know the identity of the caller
             loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
             loginOptions.putInt(AccountManager.KEY_CALLER_PID, callerPid);
+            if (notifyOnAuthFailure) {
+                loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
+            }
         }
 
         long identityToken = clearCallingIdentity();
@@ -964,7 +967,7 @@
                         }
 
                         Intent intent = result.getParcelable(AccountManager.KEY_INTENT);
-                        if (intent != null && notifyOnAuthFailure) {
+                        if (intent != null && notifyOnAuthFailure && !customTokens) {
                             doNotification(
                                     account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
                                     intent);
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 7365670..f4fa567 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -85,6 +85,7 @@
      */
     protected boolean mCancelable = true;
 
+    private String mCancelAndDismissTaken;
     private Message mCancelMessage;
     private Message mDismissMessage;
     private Message mShowMessage;
@@ -1029,6 +1030,11 @@
      * @param listener The {@link DialogInterface.OnCancelListener} to use.
      */
     public void setOnCancelListener(final OnCancelListener listener) {
+        if (mCancelAndDismissTaken != null) {
+            throw new IllegalStateException(
+                    "OnCancelListener is already taken by "
+                    + mCancelAndDismissTaken + " and can not be replaced.");
+        }
         if (listener != null) {
             mCancelMessage = mListenersHandler.obtainMessage(CANCEL, listener);
         } else {
@@ -1050,6 +1056,11 @@
      * @param listener The {@link DialogInterface.OnDismissListener} to use.
      */
     public void setOnDismissListener(final OnDismissListener listener) {
+        if (mCancelAndDismissTaken != null) {
+            throw new IllegalStateException(
+                    "OnDismissListener is already taken by "
+                    + mCancelAndDismissTaken + " and can not be replaced.");
+        }
         if (listener != null) {
             mDismissMessage = mListenersHandler.obtainMessage(DISMISS, listener);
         } else {
@@ -1077,6 +1088,22 @@
         mDismissMessage = msg;
     }
 
+    /** @hide */
+    public boolean takeCancelAndDismissListeners(String msg, final OnCancelListener cancel,
+            final OnDismissListener dismiss) {
+        if (mCancelAndDismissTaken != null) {
+            mCancelAndDismissTaken = null;
+        } else if (mCancelMessage != null || mDismissMessage != null) {
+            return false;
+        }
+        
+        setOnCancelListener(cancel);
+        setOnDismissListener(dismiss);
+        mCancelAndDismissTaken = msg;
+        
+        return true;
+    }
+    
     /**
      * By default, this will use the owner Activity's suggested stream type.
      * 
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index 8bdd086..50953d7 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -378,6 +378,12 @@
      * default implementation simply instantiates and returns a {@link Dialog}
      * class.
      * 
+     * <p><em>Note: DialogFragment own the {@link Dialog#setOnCancelListener
+     * Dialog.setOnCancelListener} and {@link Dialog#setOnDismissListener
+     * Dialog.setOnDismissListener} callbacks.  You must not set them yourself.</em>
+     * To find out about these events, override {@link #onCancel(DialogInterface)}
+     * and {@link #onDismiss(DialogInterface)}.</p>
+     * 
      * @param savedInstanceState The last saved instance state of the Fragment,
      * or null if this is a freshly created Fragment.
      * 
@@ -417,8 +423,10 @@
         }
         mDialog.setOwnerActivity(getActivity());
         mDialog.setCancelable(mCancelable);
-        mDialog.setOnCancelListener(this);
-        mDialog.setOnDismissListener(this);
+        if (!mDialog.takeCancelAndDismissListeners("DialogFragment", this, this)) {
+            throw new IllegalStateException(
+                    "You can not set Dialog's OnCancelListener or OnDismissListener");
+        }
         if (savedInstanceState != null) {
             Bundle dialogState = savedInstanceState.getBundle(SAVED_DIALOG_STATE_TAG);
             if (dialogState != null) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index ca5ff24..6e3663e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -859,11 +859,19 @@
      * only pick from data that can be represented as a stream.  This is
      * accomplished by requiring the {@link #CATEGORY_OPENABLE} in the Intent.
      * <p>
+     * Callers can optionally specify {@link #EXTRA_LOCAL_ONLY} to request that
+     * the launched content chooser only return results representing data that
+     * is locally available on the device.  For example, if this extra is set
+     * to true then an image picker should not show any pictures that are available
+     * from a remote server but not already on the local device (thus requiring
+     * they be downloaded when opened).
+     * <p>
      * Input: {@link #getType} is the desired MIME type to retrieve.  Note
      * that no URI is supplied in the intent, as there are no constraints on
      * where the returned data originally comes from.  You may also include the
      * {@link #CATEGORY_OPENABLE} if you can only accept data that can be
-     * opened as a stream.
+     * opened as a stream.  You may use {@link #EXTRA_LOCAL_ONLY} to limit content
+     * selection to local data.
      * <p>
      * Output: The URI of the item that was picked.  This must be a content:
      * URI so that any receiver can access it.
@@ -2397,6 +2405,18 @@
     public static final String EXTRA_CLIENT_INTENT =
             "android.intent.extra.client_intent";
 
+    /**
+     * Used to indicate that a {@link #ACTION_GET_CONTENT} intent should only return
+     * data that is on the local device.  This is a boolean extra; the default
+     * is false.  If true, an implementation of ACTION_GET_CONTENT should only allow
+     * the user to select media that is already on the device, not requiring it
+     * be downloaded from a remote service when opened.  Another way to look
+     * at it is that such content should generally have a "_data" column to the
+     * path of the content on local external storage.
+     */
+    public static final String EXTRA_LOCAL_ONLY =
+        "android.intent.extra.LOCAL_ONLY";
+    
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Intent flags (see mFlags variable).
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 52b0643..44887ed 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -546,7 +546,8 @@
                         sizeChanged = true;
                         mCurHeight = h;
                     }
-                    
+
+                    mSurfaceHolder.setSurfaceFrameSize(w, h);
                     mSurfaceHolder.mSurfaceLock.unlock();
 
                     if (!mSurfaceHolder.mSurface.isValid()) {
diff --git a/core/java/android/text/method/LinkMovementMethod.java b/core/java/android/text/method/LinkMovementMethod.java
index 9e73371..aff233d 100644
--- a/core/java/android/text/method/LinkMovementMethod.java
+++ b/core/java/android/text/method/LinkMovementMethod.java
@@ -42,9 +42,9 @@
             case KeyEvent.KEYCODE_DPAD_CENTER:
             case KeyEvent.KEYCODE_ENTER:
                 if (KeyEvent.metaStateHasNoModifiers(movementMetaState)) {
-                    if (event.getAction() == KeyEvent.ACTION_DOWN
-                            && event.getRepeatCount() == 0) {
-                        return action(CLICK, widget, buffer);
+                    if (event.getAction() == KeyEvent.ACTION_DOWN &&
+                            event.getRepeatCount() == 0 && action(CLICK, widget, buffer)) {
+                        return true;
                     }
                 }
                 break;
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6451d47..8a95664 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -158,6 +158,7 @@
     int mHeight = -1;
     int mFormat = -1;
     final Rect mSurfaceFrame = new Rect();
+    Rect mTmpDirty;
     int mLastSurfaceWidth = -1, mLastSurfaceHeight = -1;
     boolean mUpdateWindowNeeded;
     boolean mReportDrawNeeded;
@@ -739,9 +740,16 @@
 
             Canvas c = null;
             if (!mDrawingStopped && mWindow != null) {
-                Rect frame = dirty != null ? dirty : mSurfaceFrame;
+                if (dirty == null) {
+                    if (mTmpDirty == null) {
+                        mTmpDirty = new Rect();
+                    }
+                    mTmpDirty.set(mSurfaceFrame);
+                    dirty = mTmpDirty;
+                }
+
                 try {
-                    c = mSurface.lockCanvas(frame);
+                    c = mSurface.lockCanvas(dirty);
                 } catch (Exception e) {
                     Log.e(LOG_TAG, "Exception locking surface", e);
                 }
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 68b6a8a..ca19da2 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1082,6 +1082,7 @@
                     //mSurfaceHolder.mSurface.copyFrom(mSurface);
                     mSurfaceHolder.mSurface = mSurface;
                 }
+                mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight);
                 mSurfaceHolder.mSurfaceLock.unlock();
                 if (mSurface.isValid()) {
                     if (!hadSurface) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ae6ecfb..fedda68 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8596,7 +8596,6 @@
         private long mTouchTimer;
         private boolean mIsInsertionHandle = false;
         private PastePopupMenu mPastePopupWindow;
-        private Runnable mLongPressCallback;
 
         // Touch-up filter: number of previous positions remembered
         private static final int HISTORY_SIZE = 5;
@@ -8839,73 +8838,49 @@
         @Override
         public boolean onTouchEvent(MotionEvent ev) {
             switch (ev.getActionMasked()) {
-            case MotionEvent.ACTION_DOWN: {
-                startTouchUpFilter(mController.getCurrentOffset(this));
-                mDownPositionX = ev.getRawX();
-                mDownPositionY = ev.getRawY();
-                mTouchToWindowOffsetX = mDownPositionX - mPositionX;
-                mTouchToWindowOffsetY = mDownPositionY - mPositionY;
-                final int[] coords = mTempCoords;
-                TextView.this.getLocationInWindow(coords);
-                mLastParentX = coords[0];
-                mLastParentY = coords[1];
-                mIsDragging = true;
-                if (mIsInsertionHandle) {
-                    mTouchTimer = SystemClock.uptimeMillis();
-                    if (mLongPressCallback == null) {
-                        mLongPressCallback = new Runnable() {
-                            public void run() {
-                                mController.hide();
-                                startSelectionActionMode();
+                case MotionEvent.ACTION_DOWN: {
+                    startTouchUpFilter(mController.getCurrentOffset(this));
+                    mDownPositionX = ev.getRawX();
+                    mDownPositionY = ev.getRawY();
+                    mTouchToWindowOffsetX = mDownPositionX - mPositionX;
+                    mTouchToWindowOffsetY = mDownPositionY - mPositionY;
+                    final int[] coords = mTempCoords;
+                    TextView.this.getLocationInWindow(coords);
+                    mLastParentX = coords[0];
+                    mLastParentY = coords[1];
+                    mIsDragging = true;
+                    break;
+                }
+
+                case MotionEvent.ACTION_MOVE: {
+                    final float rawX = ev.getRawX();
+                    final float rawY = ev.getRawY();
+                    final float newPosX = rawX - mTouchToWindowOffsetX + mHotspotX;
+                    final float newPosY = rawY - mTouchToWindowOffsetY + mHotspotY + mTouchOffsetY;
+
+                    mController.updatePosition(this, Math.round(newPosX), Math.round(newPosY));
+                    break;
+                }
+
+                case MotionEvent.ACTION_UP:
+                    if (mIsInsertionHandle) {
+                        long delay = SystemClock.uptimeMillis() - mTouchTimer;
+                        if (delay < ViewConfiguration.getTapTimeout()) {
+                            if (mPastePopupWindow != null && mPastePopupWindow.isShowing()) {
+                                // Tapping on the handle dismisses the displayed paste view,
+                                mPastePopupWindow.hide();
+                            } else {
+                                ((InsertionPointCursorController) mController).show(0);
                             }
-                        };
-                    }
-                    postDelayed(mLongPressCallback, ViewConfiguration.getLongPressTimeout());
-                }
-                break;
-            }
-
-            case MotionEvent.ACTION_MOVE: {
-                final float rawX = ev.getRawX();
-                final float rawY = ev.getRawY();
-                final float newPosX = rawX - mTouchToWindowOffsetX + mHotspotX;
-                final float newPosY = rawY - mTouchToWindowOffsetY + mHotspotY + mTouchOffsetY;
-
-                mController.updatePosition(this, Math.round(newPosX), Math.round(newPosY));
-
-                if (mIsInsertionHandle) {
-                    final float dx = rawX - mDownPositionX;
-                    final float dy = rawY - mDownPositionY;
-                    final float distanceSquared = dx * dx + dy * dy;
-                    if (distanceSquared >= mSquaredTouchSlopDistance) {
-                        removeLongPressCallback();
-                    }
-                }
-                break;
-            }
-
-            case MotionEvent.ACTION_UP:
-                if (mIsInsertionHandle) {
-                    removeLongPressCallback();
-                    long delay = SystemClock.uptimeMillis() - mTouchTimer;
-                    if (delay < ViewConfiguration.getTapTimeout()) {
-                        if (mPastePopupWindow != null && mPastePopupWindow.isShowing()) {
-                            // Tapping on the handle dismisses the displayed paste view,
-                            mPastePopupWindow.hide();
-                        } else {
-                            ((InsertionPointCursorController) mController).show(0);
                         }
                     }
-                }
-                filterOnTouchUp();
-                mIsDragging = false;
-                break;
+                    filterOnTouchUp();
+                    mIsDragging = false;
+                    break;
 
-            case MotionEvent.ACTION_CANCEL:
-                if (mIsInsertionHandle) {
-                    removeLongPressCallback();
-                }
-                mIsDragging = false;
+                case MotionEvent.ACTION_CANCEL:
+                    mIsDragging = false;
+                    break;
             }
             return true;
         }
@@ -8943,16 +8918,6 @@
                 mPastePopupWindow.show();
             }
         }
-
-        private void removeLongPressCallback() {
-            if (mLongPressCallback != null) {
-                removeCallbacks(mLongPressCallback);
-            }
-        }
-
-        void onDetached() {
-            removeLongPressCallback();
-        }
     }
 
     private class InsertionPointCursorController implements CursorController {
@@ -9079,9 +9044,6 @@
         public void onDetached() {
             removeHiderCallback();
             removePastePopupCallback();
-            if (mHandle != null) {
-                mHandle.onDetached();
-            }
         }
     }
 
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 78688ee..595c634 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -88,9 +88,13 @@
 
         class WallpaperObserver extends BroadcastReceiver {
             public void onReceive(Context context, Intent intent) {
+                if (DEBUG) {
+                    Log.d(TAG, "onReceive");
+                }
+
                 synchronized (mLock) {
                     updateWallpaperLocked();
-                    drawFrameLocked(true, false);
+                    drawFrameLocked();
                 }
 
                 // Assume we are the only one using the wallpaper in this
@@ -101,6 +105,10 @@
 
         @Override
         public void onCreate(SurfaceHolder surfaceHolder) {
+            if (DEBUG) {
+                Log.d(TAG, "onCreate");
+            }
+
             super.onCreate(surfaceHolder);
             IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
             mReceiver = new WallpaperObserver();
@@ -120,9 +128,18 @@
 
         @Override
         public void onVisibilityChanged(boolean visible) {
+            if (DEBUG) {
+                Log.d(TAG, "onVisibilityChanged: visible=" + visible);
+            }
+
             synchronized (mLock) {
-                mVisible = visible;
-                drawFrameLocked(false, false);
+                if (mVisible != visible) {
+                    if (DEBUG) {
+                        Log.d(TAG, "Visibility changed to visible=" + visible);
+                    }
+                    mVisible = visible;
+                    drawFrameLocked();
+                }
             }
         }
 
@@ -135,6 +152,12 @@
         public void onOffsetsChanged(float xOffset, float yOffset,
                 float xOffsetStep, float yOffsetStep,
                 int xPixels, int yPixels) {
+            if (DEBUG) {
+                Log.d(TAG, "onOffsetsChanged: xOffset=" + xOffset + ", yOffset=" + yOffset
+                        + ", xOffsetStep=" + xOffsetStep + ", yOffsetStep=" + yOffsetStep
+                        + ", xPixels=" + xPixels + ", yPixels=" + yPixels);
+            }
+
             synchronized (mLock) {
                 if (mXOffset != xOffset || mYOffset != yOffset) {
                     if (DEBUG) {
@@ -142,36 +165,27 @@
                     }
                     mXOffset = xOffset;
                     mYOffset = yOffset;
-                    drawFrameLocked(false, true);
-                } else {
-                    drawFrameLocked(false, false);
+                    mOffsetsChanged = true;
                 }
+                drawFrameLocked();
             }
         }
 
         @Override
         public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+            if (DEBUG) {
+                Log.d(TAG, "onSurfaceChanged: width=" + width + ", height=" + height);
+            }
+
             super.onSurfaceChanged(holder, format, width, height);
-            
+
             synchronized (mLock) {
-                drawFrameLocked(true, false);
+                mRedrawNeeded = true;
+                drawFrameLocked();
             }
         }
 
-        @Override
-        public void onSurfaceCreated(SurfaceHolder holder) {
-            super.onSurfaceCreated(holder);
-        }
-
-        @Override
-        public void onSurfaceDestroyed(SurfaceHolder holder) {
-            super.onSurfaceDestroyed(holder);
-        }
-
-        void drawFrameLocked(boolean redrawNeeded, boolean offsetsChanged) {
-            mRedrawNeeded |= redrawNeeded;
-            mOffsetsChanged |= offsetsChanged;
-
+        void drawFrameLocked() {
             if (!mVisible) {
                 if (DEBUG) {
                     Log.d(TAG, "Suppressed drawFrame since wallpaper is not visible.");
diff --git a/core/java/com/android/internal/view/BaseSurfaceHolder.java b/core/java/com/android/internal/view/BaseSurfaceHolder.java
index 1e97cd6..f9f94be 100644
--- a/core/java/com/android/internal/view/BaseSurfaceHolder.java
+++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java
@@ -49,6 +49,7 @@
     
     int mType = -1;
     final Rect mSurfaceFrame = new Rect();
+    Rect mTmpDirty;
     
     public abstract void onUpdateSurface();
     public abstract void onRelayoutContainer();
@@ -171,9 +172,16 @@
 
         Canvas c = null;
         if (onAllowLockCanvas()) {
-            Rect frame = dirty != null ? dirty : mSurfaceFrame;
+            if (dirty == null) {
+                if (mTmpDirty == null) {
+                    mTmpDirty = new Rect();
+                }
+                mTmpDirty.set(mSurfaceFrame);
+                dirty = mTmpDirty;
+            }
+
             try {
-                c = mSurface.lockCanvas(frame);
+                c = mSurface.lockCanvas(dirty);
             } catch (Exception e) {
                 Log.e(TAG, "Exception locking surface", e);
             }
@@ -215,4 +223,11 @@
     public Rect getSurfaceFrame() {
         return mSurfaceFrame;
     }
+
+    public void setSurfaceFrameSize(int width, int height) {
+        mSurfaceFrame.top = 0;
+        mSurfaceFrame.left = 0;
+        mSurfaceFrame.right = width;
+        mSurfaceFrame.bottom = height;
+    }
 };
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index b93fac4..1f93eac 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -19,6 +19,7 @@
 import com.android.internal.view.menu.MenuBuilder.MenuAdapter;
 
 import android.content.Context;
+import android.os.Handler;
 import android.util.DisplayMetrics;
 import android.view.KeyEvent;
 import android.view.MenuItem;
@@ -46,6 +47,8 @@
     private boolean mOverflowOnly;
     private ViewTreeObserver mTreeObserver;
 
+    private final Handler mHandler = new Handler();
+
     public MenuPopupHelper(Context context, MenuBuilder menu) {
         this(context, menu, null, false);
     }
@@ -137,8 +140,14 @@
         } else {
             item = mMenu.getVisibleItems().get(position);
         }
-        mMenu.performItemAction(item, 0);
         dismiss();
+
+        final MenuItem performItem = item;
+        mHandler.post(new Runnable() {
+            public void run() {
+                mMenu.performItemAction(performItem, 0);
+            }
+        });
     }
 
     public boolean onKey(View v, int keyCode, KeyEvent event) {
diff --git a/core/res/res/drawable-hdpi/ic_contact_picture.png b/core/res/res/drawable-hdpi/ic_contact_picture.png
index a60565a..e29e63a 100644
--- a/core/res/res/drawable-hdpi/ic_contact_picture.png
+++ b/core/res/res/drawable-hdpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_contact_picture.png b/core/res/res/drawable-mdpi/ic_contact_picture.png
index 3a338e8..faa3dc0 100644
--- a/core/res/res/drawable-mdpi/ic_contact_picture.png
+++ b/core/res/res/drawable-mdpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/password_keyboard_background_holo.9.png b/core/res/res/drawable-mdpi/password_keyboard_background_holo.9.png
new file mode 100644
index 0000000..c56c704
--- /dev/null
+++ b/core/res/res/drawable-mdpi/password_keyboard_background_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/sym_keyboard_delete_holo.png b/core/res/res/drawable-xlarge-mdpi/sym_keyboard_delete_holo.png
new file mode 100644
index 0000000..1555791
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/sym_keyboard_delete_holo.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/sym_keyboard_shift.png b/core/res/res/drawable-xlarge-mdpi/sym_keyboard_shift.png
new file mode 100644
index 0000000..91d6e32
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/sym_keyboard_shift.png
Binary files differ
diff --git a/core/res/res/drawable-xlarge-mdpi/sym_keyboard_shift_locked.png b/core/res/res/drawable-xlarge-mdpi/sym_keyboard_shift_locked.png
new file mode 100644
index 0000000..2bd0536
--- /dev/null
+++ b/core/res/res/drawable-xlarge-mdpi/sym_keyboard_shift_locked.png
Binary files differ
diff --git a/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml b/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
index c1149e3..16bfc31 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_password_landscape.xml
@@ -69,7 +69,7 @@
             <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
                 android:layout_width="330dip"
                 android:layout_height="330dip"
-                android:background="#00000000"
+                android:background="#40000000"
                 android:layout_marginTop="5dip"
                 android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
                 android:visibility="gone"
@@ -88,8 +88,9 @@
     <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboardAlpha"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:background="#00000000"
+        android:background="@drawable/password_keyboard_background_holo"
         android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+        android:keyTextSize="28dip"
         android:visibility="gone"
     />
 
diff --git a/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml b/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
index e4a1b81..b87b51f 100644
--- a/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
+++ b/core/res/res/layout-xlarge/keyguard_screen_password_portrait.xml
@@ -61,19 +61,28 @@
             android:textColor="#ffffffff"
             />
 
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="0dip"
+            android:layout_weight="1"
+        />
+
         <!-- Numeric keyboard -->
         <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboard"
             android:layout_width="330dip"
             android:layout_height="260dip"
-            android:background="#00000000"
+            android:background="#40000000"
             android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+            android:layout_marginBottom="80dip"
         />
+
         <!-- Alphanumeric keyboard -->
         <com.android.internal.widget.PasswordEntryKeyboardView android:id="@+id/keyboardAlpha"
             android:layout_width="match_parent"
             android:layout_height="230dip"
-            android:background="#00000000"
+            android:background="@drawable/password_keyboard_background_holo"
             android:keyBackground="@drawable/btn_keyboard_key_fulltrans"
+            android:keyTextSize="28dip"
             android:visibility="gone"
         />
 
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a404fba..260c7c6 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1832,7 +1832,7 @@
         </attr>
         
         <!-- Specifies the type of layer backing this view. The default value is none.
-             Refer to {@link android.view.View#setLayerType(int, android.graphics.Paint)
+             Refer to {@link android.view.View#setLayerType(int, android.graphics.Paint)}
              for more information.-->
         <attr name="layerType">
             <!-- Don't use a layer. -->
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 03eca1c..ddaeb82 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -522,6 +522,7 @@
         <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
         <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
         <item name="android:windowCloseOnTouchOutside">@bool/config_closeDialogWhenTouchOutside</item>
+        <item name="android:windowActionModeOverlay">true</item>
 
         <item name="android:colorBackgroundCacheHint">@null</item>
         
diff --git a/core/res/res/xml-xlarge/password_kbd_numeric.xml b/core/res/res/xml-xlarge/password_kbd_numeric.xml
new file mode 100755
index 0000000..0253122
--- /dev/null
+++ b/core/res/res/xml-xlarge/password_kbd_numeric.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2011, 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.
+*/
+-->
+<Keyboard xmlns:android="http://schemas.android.com/apk/res/android"
+    android:keyWidth="33.33%p"
+    android:verticalGap="0px"
+    android:keyHeight="@dimen/password_keyboard_key_height_numeric"
+    >
+
+    <Row android:rowEdgeFlags="top">
+        <Key android:codes="49" android:keyIcon="@drawable/sym_keyboard_num1"
+             android:keyEdgeFlags="left"/>
+        <Key android:codes="50" android:keyIcon="@drawable/sym_keyboard_num2"/>
+        <Key android:codes="51" android:keyIcon="@drawable/sym_keyboard_num3"
+             android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row>
+        <Key android:codes="52" android:keyIcon="@drawable/sym_keyboard_num4"
+             android:keyEdgeFlags="left"/>
+        <Key android:codes="53" android:keyIcon="@drawable/sym_keyboard_num5"/>
+        <Key android:codes="54" android:keyIcon="@drawable/sym_keyboard_num6"
+             android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row>
+        <Key android:codes="55" android:keyIcon="@drawable/sym_keyboard_num7"
+             android:keyEdgeFlags="left"/>
+        <Key android:codes="56" android:keyIcon="@drawable/sym_keyboard_num8"/>
+        <Key android:codes="57" android:keyIcon="@drawable/sym_keyboard_num9"
+             android:keyEdgeFlags="right"/>
+    </Row>
+
+    <Row android:rowEdgeFlags="bottom">
+        <Key android:codes="10" android:keyIcon="@drawable/sym_keyboard_ok"
+             android:keyEdgeFlags="left"/>
+        <Key android:codes="48" android:keyIcon="@drawable/sym_keyboard_num0_no_plus"/>
+        <Key android:codes="-5" android:keyIcon="@drawable/sym_keyboard_delete"
+             android:iconPreview="@drawable/sym_keyboard_feedback_delete"
+             android:isRepeatable="true" android:keyEdgeFlags="right"/>
+    </Row>
+
+</Keyboard>
diff --git a/core/res/res/xml-xlarge/password_kbd_qwerty.xml b/core/res/res/xml-xlarge/password_kbd_qwerty.xml
index fd1d5f1..1009c9a 100755
--- a/core/res/res/xml-xlarge/password_kbd_qwerty.xml
+++ b/core/res/res/xml-xlarge/password_kbd_qwerty.xml
@@ -38,10 +38,9 @@
         <Key android:keyLabel="i"/>
         <Key android:keyLabel="o"/>
         <Key android:keyLabel="p"/>
-        <Key android:keyIcon="@drawable/sym_keyboard_delete"
+        <Key android:keyIcon="@drawable/sym_keyboard_delete_holo"
             android:codes="-5"
             android:keyWidth="9.331%p"
-            android:iconPreview="@drawable/sym_keyboard_feedback_delete"
             android:isRepeatable="true"
             android:keyEdgeFlags="right"/>
     </Row>
@@ -62,7 +61,6 @@
         <Key android:keyLabel="l"/>
         <Key android:codes="10"
             android:keyIcon="@drawable/sym_keyboard_ok"
-            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
             android:keyWidth="15.750%p"
             android:keyEdgeFlags="right"/>
     </Row>
@@ -72,7 +70,6 @@
             android:keyIcon="@drawable/sym_keyboard_shift"
             android:keyWidth="15.192%p"
             android:isModifier="true"
-            android:iconPreview="@drawable/sym_keyboard_feedback_shift"
             android:isSticky="true"
             android:keyEdgeFlags="left"/>
         <Key android:keyLabel="z"/>
@@ -88,7 +85,6 @@
             android:keyIcon="@drawable/sym_keyboard_shift"
             android:keyWidth="12.530%p"
             android:isModifier="true"
-            android:iconPreview="@drawable/sym_keyboard_feedback_shift"
             android:isSticky="true"
             android:keyEdgeFlags="right"/>
     </Row>
@@ -96,9 +92,7 @@
     <Row android:keyWidth="8.042%p"
         android:keyboardMode="@+id/mode_normal">
         <Key android:keyLabel="/" android:horizontalGap="24.126%p"/>
-        <Key android:codes="32"
-            android:keyIcon="@drawable/sym_keyboard_space"
-            android:iconPreview="@drawable/sym_keyboard_feedback_space"
+        <Key android:keyLabel=" "
             android:keyWidth="37.454%p"/>
         <Key android:keyLabel="'" />
         <Key android:keyLabel="-" />
diff --git a/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml b/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml
index 671d87f..cbf17c3 100755
--- a/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml
+++ b/core/res/res/xml-xlarge/password_kbd_qwerty_shifted.xml
@@ -38,10 +38,9 @@
         <Key android:keyLabel="I"/>
         <Key android:keyLabel="O"/>
         <Key android:keyLabel="P"/>
-        <Key android:keyIcon="@drawable/sym_keyboard_delete"
+        <Key android:keyIcon="@drawable/sym_keyboard_delete_holo"
             android:codes="-5"
             android:keyWidth="9.331%p"
-            android:iconPreview="@drawable/sym_keyboard_feedback_delete"
             android:isRepeatable="true"
             android:keyEdgeFlags="right"/>
     </Row>
@@ -62,7 +61,6 @@
         <Key android:keyLabel="L"/>
         <Key android:codes="10"
             android:keyIcon="@drawable/sym_keyboard_ok"
-            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
             android:keyWidth="15.750%p"
             android:keyEdgeFlags="right"/>
     </Row>
@@ -72,7 +70,6 @@
             android:keyIcon="@drawable/sym_keyboard_shift"
             android:keyWidth="15.192%p"
             android:isModifier="true"
-            android:iconPreview="@drawable/sym_keyboard_feedback_shift"
             android:isSticky="true"
             android:keyEdgeFlags="left"/>
         <Key android:keyLabel="Z"/>
@@ -88,7 +85,6 @@
             android:keyIcon="@drawable/sym_keyboard_shift"
             android:keyWidth="12.530%p"
             android:isModifier="true"
-            android:iconPreview="@drawable/sym_keyboard_feedback_shift"
             android:isSticky="true"
             android:keyEdgeFlags="right"/>
     </Row>
@@ -96,9 +92,7 @@
     <Row android:keyWidth="8.042%p"
         android:keyboardMode="@+id/mode_normal">
         <Key android:keyLabel="\@" android:horizontalGap="24.126%p"/>
-        <Key android:codes="32"
-            android:keyIcon="@drawable/sym_keyboard_space"
-            android:iconPreview="@drawable/sym_keyboard_feedback_space"
+        <Key android:keyLabel=" "
             android:keyWidth="37.454%p"/>
         <Key android:keyLabel="&quot;" />
         <Key android:keyLabel="_" />
diff --git a/core/res/res/xml-xlarge/password_kbd_symbols.xml b/core/res/res/xml-xlarge/password_kbd_symbols.xml
index 5ae5577..a58a023 100755
--- a/core/res/res/xml-xlarge/password_kbd_symbols.xml
+++ b/core/res/res/xml-xlarge/password_kbd_symbols.xml
@@ -38,10 +38,9 @@
         <Key android:keyLabel="8"/>
         <Key android:keyLabel="9"/>
         <Key android:keyLabel="0"/>
-        <Key android:keyIcon="@drawable/sym_keyboard_delete"
+        <Key android:keyIcon="@drawable/sym_keyboard_delete_holo"
             android:codes="-5"
             android:keyWidth="9.331%p"
-            android:iconPreview="@drawable/sym_keyboard_feedback_delete"
             android:isRepeatable="true"
             android:keyEdgeFlags="right"/>
     </Row>
@@ -62,7 +61,6 @@
         <Key android:keyLabel=")"/>
         <Key android:codes="10"
             android:keyIcon="@drawable/sym_keyboard_ok"
-            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
             android:keyWidth="15.750%p"
             android:keyEdgeFlags="right"/>
     </Row>
@@ -94,9 +92,7 @@
     <Row android:keyWidth="8.042%p">
         <Key android:keyLabel="\@" android:horizontalGap="16.084%p"/>
         <Key android:keyLabel="/" />
-        <Key android:codes="32"
-            android:keyIcon="@drawable/sym_keyboard_space"
-            android:iconPreview="@drawable/sym_keyboard_feedback_space"
+        <Key android:keyLabel=" "
             android:keyWidth="37.454%p"/>
         <Key android:keyLabel="\'" />
         <Key android:keyLabel="-" />
diff --git a/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml b/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml
index 26ade76..9d9acf5 100755
--- a/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml
+++ b/core/res/res/xml-xlarge/password_kbd_symbols_shift.xml
@@ -37,10 +37,9 @@
         <Key android:keyLabel="×" />
         <Key android:keyLabel="§" />
         <Key android:keyLabel="Δ" />
-        <Key android:keyIcon="@drawable/sym_keyboard_delete"
+        <Key android:keyIcon="@drawable/sym_keyboard_delete_holo"
             android:codes="-5"
             android:keyWidth="9.331%p"
-            android:iconPreview="@drawable/sym_keyboard_feedback_delete"
             android:isRepeatable="true"
             android:keyEdgeFlags="right"/>
     </Row>
@@ -61,7 +60,6 @@
         <Key android:keyLabel="}" />
         <Key android:codes="10"
             android:keyIcon="@drawable/sym_keyboard_ok"
-            android:iconPreview="@drawable/sym_keyboard_feedback_ok"
             android:keyWidth="15.750%p"
             android:keyEdgeFlags="right"/>
     </Row>
@@ -92,9 +90,7 @@
 
     <!-- This row is intentionally not marked as a bottom row -->
     <Row android:keyWidth="8.042%p">
-        <Key android:codes="32" android:horizontalGap="32.168%p"
-            android:keyIcon="@drawable/sym_keyboard_space"
-            android:iconPreview="@drawable/sym_keyboard_feedback_space"
+        <Key android:keyLabel=" " android:horizontalGap="32.168%p"
             android:keyWidth="37.454%p"/>
     </Row>
 </Keyboard>
diff --git a/docs/html/sdk/android-3.0.jd b/docs/html/sdk/android-3.0.jd
index 9ca6a04..2c8a7f0 100644
--- a/docs/html/sdk/android-3.0.jd
+++ b/docs/html/sdk/android-3.0.jd
@@ -72,7 +72,7 @@
 states</li>
   <li>By <a
 href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">providing
-alternative resources</a>, you can mix and match fragments, based
+alternative layouts</a>, you can mix and match fragments, based
 on the screen size and orientation</li>
   <li>Fragments have direct access to their container activity and can contribute items to the
 activity's Action Bar (discussed next)</li>
@@ -83,15 +83,15 @@
 as finding fragments in the activity and popping fragments off the back stack to restore them
 after they've been removed or hidden.</p>
 
-<p>To perform transactions, such as add or remove fragments, you must create a {@link
+<p>To perform a transaction, such as add or remove a fragment, you must create a {@link
 android.app.FragmentTransaction}. You can then call methods such as {@link
 android.app.FragmentTransaction#add add()} {@link android.app.FragmentTransaction#remove
-remove()}, {@link android.app.FragmentTransaction#replace replace()}. Once you've applied all
+remove()}, or {@link android.app.FragmentTransaction#replace replace()}. Once you've applied all
 the changes you want to perform for the transaction, you must call {@link
-android.app.FragmentTransaction#commit commit()} and the system will apply the transaction to
+android.app.FragmentTransaction#commit commit()} and the system applies the fragment transaction to
 the activity.</p>
 
-<p>For more information about using fragments in your application, read the <a
+<p>For more information about using fragments, read the <a
 href="{@docRoot}guide/topics/fundamentals/fragments.html">Fragments</a> developer guide.</p>
 
 
@@ -99,38 +99,37 @@
 
 <h3>Action Bar</h3>
 
-<p>The Action Bar is a replacement for the traditional title bar at the top of the activity
-window. It includes the application logo in the left corner and also replaces the previous Options
-Menu UI with a drop-down list for the menu items. Additionally, the Action Bar allows you
-to:</p></p>
+<p>The Action Bar is a replacement for the traditional title bar at the top of the activity window.
+It includes the application logo in the left corner and provides a new interface for items in the
+activity's Options Menu. Additionally, the Action Bar allows you to:</p>
 
 <ul>
   <li>Include select menu items directly in the Action Bar&mdash;as "action
-items"&mdash;for quick access to global actions.
+items"&mdash;for quick access to global user actions.
     <p>In your XML declaration for the menu item, include the attribute, {@code
 android:showAsAction} with a value of {@code "ifRoom"}. When there's enough room in the
-Action Bar, the menu item appears directly in the bar. Otherwise, it is placed in the
+Action Bar, the menu item appears directly in the bar. Otherwise, the item is placed in the
 overflow menu, revealed by the icon on the right side of the Action Bar.</p></li>
-  <li>Add interactive widgets ("action views"), such as a search box.
-    <p>In your XML, include the attribute, {@code android:actionViewLayout} with a layout
-resource for the action view, or {@code android:actionViewClass} with the class name of the
+
+  <li>Add interactive widgets to the Action Bar&mdash;as "action views"&mdash;such as a search box.
+    <p>In the XML for the menu item that should behave as an action view, include the {@code
+android:actionViewLayout} attribute with a layout
+resource for the action view or {@code android:actionViewClass} with the class name of the
 widget. Like action items, an action view appears only when there's room for it in the Action
 Bar. If there's not enough room, it is placed in the overflow menu and behaves like a regular
 menu item (for example, an item can provide a {@link android.widget.SearchView} as an action
-view, but when in the overflow menu, selecting the item will activate the search dialog).</p>
-    <p></p></li>
+view, but when in the overflow menu, selecting the item activates the search dialog).</p></li>
+
   <li>Add an action to the application logo when tapped and replace it with a custom logo
     <p>The application logo is automatically assigned the {@code android.R.id.home} ID,
-which is delivered to your activity's {@link android.app.Activity#onOptionsItemSelected
+which the system deliveres to your activity's {@link android.app.Activity#onOptionsItemSelected
 onOptionsItemSelected()} callback when tapped. Simply respond to this ID in your callback
 method to perform an action such as go to your application's "home" activity.</p>
-    <p>If your activity does not respond to the icon action, you should hide it by calling {@link
-android.app.ActionBar#setDisplayShowHomeEnabled setDisplayShowHomeEnabled(false)}.</p>
-    <p>By default, this is true, so the icon will visually respond when pressed, even if you don't
-respond. Thus, you should remove the icon if you don't respond to it.</p></li>
+    <p>To replace the icon with a logo, </p></li>
+
   <li>Add breadcrumbs for navigating backward through fragments</li>
   <li>Add built in tabs and a drop-down list for navigation</li>
-  <li>Customize the Action Bar  themes and custom backgrounds</li>
+  <li>Customize the Action Bar themes and custom backgrounds</li>
 </ul>
 
 <p>The Action Bar is standard for all applications that set either the <a
@@ -139,9 +138,11 @@
 href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
 android:targetSdkVersion}</a> to {@code "Honeycomb"}. (The "Honeycomb" API Level is provisional
 and effective only while using the preview SDK&mdash;you must change it to the official API
-Level when the final SDK becomes available.)</p>
+Level when the final SDK becomes available&mdash;see <a
+href="{@docRoot}sdk/preview/start.html">Getting Started</a> for more information.)</p>
 
-<p>For more information, read the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action
+<p>For more information about the Action Bar, read the <a
+href="{@docRoot}guide/topics/ui/actionbar.html">Action
 Bar</a> developer guide.</p>
 
 
@@ -159,10 +160,10 @@
 <p>To start using the clipboard, get the global {@link android.content.ClipboardManager} object
 by calling {@link android.content.Context#getSystemService getSystemService(CLIPBOARD_SERVICE)}.</p>
 
-<p>To create an item to attach to the clipboard, you need to create a new {@link
+<p>To create an item to attach to the clipboard ("copy"), you need to create a new {@link
 android.content.ClipData} object, which holds one or more {@link android.content.ClipData.Item}
 objects, each describing a single entity. To create a {@link android.content.ClipData} object with
-just one {@link android.content.ClipData.Item}, you can use one of the helper methods such as,
+just one {@link android.content.ClipData.Item}, you can use one of the helper methods, such as
 {@link android.content.ClipData#newPlainText newPlainText()}, {@link
 android.content.ClipData#newUri newUri()}, and {@link android.content.ClipData#newIntent
 newIntent()}, which each return a {@link android.content.ClipData} object pre-loaded with the
@@ -186,7 +187,7 @@
 
 <h3>Drag and drop</h3>
 
-<p>New APIs now facilitate the ability for your application to implement drag and drop
+<p>New APIs facilitate the ability for your application to implement drag and drop
 functionality in the UI.</p>
 
 <p>To begin dragging content in your activity, call {@link android.view.View#startDrag startDrag()}
@@ -196,13 +197,16 @@
 the drag object with views that may receive the object.</p>
 
 <p>To accept a drag object (receive the "drop") in a
-{@link android.view.View}, register the view with an {@link android.view.View.OnDragListener} by
+{@link android.view.View}, register the view with an {@link android.view.View.OnDragListener
+OnDragListener} by
 calling {@link android.view.View#setOnDragListener setOnDragListener()}. When a drag event occurs on
 the view, the system calls {@link android.view.View.OnDragListener#onDrag onDrag()} for the  {@link
-android.view.View.OnDragListener}, which receives a {@link android.view.DragEvent} describing the
-type of event has occurred (such as "drag started", "drag ended", and "drop"). During a drag
-operation, there is a stream of drag events, so the system calls {@link
-android.view.View.OnDragListener#onDrag onDrag()} repeatedly on the view. The receiving view can
+android.view.View.OnDragListener OnDragListener}, which receives a {@link android.view.DragEvent}
+describing the
+type of event has occurred (such as "drag started", "drag ended", or "drop"). During a drag, the
+system repeatedly calls {@link
+android.view.View.OnDragListener#onDrag onDrag()} for the view underneath the drag, to
+deliver a stream of events. The receiving view can
 inquire the event type delivered to {@link android.view.View#onDragEvent onDragEvent()} by calling
 {@link android.view.DragEvent#getAction getAction()} on the {@link android.view.DragEvent}.</p>
 
@@ -217,16 +221,14 @@
 
 <h3>App widgets</h3>
 
-<p>App widgets can now be more interactive with scrolling list views, grid views, view flippers, and
-a new 3D stack widget.</p>
-
-<p>Android 3.0 supports several new widget classes for app widgets, including: {@link
+<p>Android 3.0 supports several new widget classes for more interactive app widgets, including:
+{@link
 android.widget.GridView}, {@link android.widget.ListView}, {@link android.widget.StackView}, {@link
 android.widget.ViewFlipper}, and {@link android.widget.AdapterViewFlipper}.</p>
 
-<p>You can use the new {@link android.widget.RemoteViewsService} to populate the new remote
-collection views ({@link android.widget.GridView}, {@link android.widget.ListView}, and {@link
-android.widget.StackView}).</p>
+<p>You can also use the new {@link android.widget.RemoteViewsService} to populate
+collection views such as ({@link android.widget.GridView}, {@link android.widget.ListView}, and
+{@link android.widget.StackView}).</p>
 
 <p>{@link android.appwidget.AppWidgetProviderInfo} also supports two new fields: {@link
 android.appwidget.AppWidgetProviderInfo#autoAdvanceViewId} and {@link
@@ -234,11 +236,11 @@
 android.appwidget.AppWidgetProviderInfo#autoAdvanceViewId} field lets you specify the view ID of the
 app widget subview, which is auto-advanced by the app widget’s host. The
 {@link android.appwidget.AppWidgetProviderInfo#previewImage} field specifies a preview of what the
-App Widget looks like and is shown to the user from the widget picker. If this field is not
+app widget looks like and is shown to the user from the widget picker. If this field is not
 supplied, the app widget's icon is used for the preview.</p>
 
-<p>Android also provides a new widget preview tool (WidgetPreview), located in the SDK tools, to
-take a screenshot of your app widget, which you can use when specifying the {@link
+<p>Android also provides a new widget preview tool ({@code WidgetPreview}), located in the SDK
+tools, to take a screenshot of your app widget, which you can use when specifying the {@link
 android.appwidget.AppWidgetProviderInfo#previewImage} field.</p>
 
 
@@ -249,12 +251,13 @@
 
 <p>The {@link android.app.Notification} APIs have been extended to support more content-rich status
 bar notifications, plus a new {@link android.app.Notification.Builder} class allows you to easily
-control the notification properties. New features include:</p>
+control the notification properties.</p>
+<p>New features include:</p>
 <ul>
-  <li>Support for a large icon in the notification. This is usually for
+  <li>Support for a large icon in the notification, using {@link
+android.app.Notification.Builder#setLargeIcon setLargeIcon()}. This is usually for
 social applications to show the contact photo of the person who is the source of the
-notification or for media apps to show an album thumbnail. Set using {@link
-android.app.Notification.Builder#setLargeIcon setLargeIcon()}.</li>
+notification or for media apps to show an album thumbnail.</li>
   <li>Support for custom layouts in the status bar ticker, using {@link
 android.app.Notification.Builder#setTicker(CharSequence,RemoteViews) setTicker()}.</li>
   <li>Support for custom notification layouts to include buttons with {@link
@@ -269,7 +272,7 @@
 
 <p>New framework APIs facilitate asynchronous loading of data using the {@link
 android.content.Loader} class. You can use it in combination with UI components such as views and
-fragments to dynamically load data from background threads. The {@link
+fragments to dynamically load data from worker threads. The {@link
 android.content.CursorLoader} subclass is specially designed to help do so for data queried from
 a {@link android.content.ContentResolver}.</p>
 
@@ -280,21 +283,25 @@
 <h3>Bluetooth A2DP and headset APIs</h3>
 
 <p>Android now includes APIs for applications to verify the state of connected Bluetooth A2DP and
-headset profile devices. You can initialize the respective {@link
-android.bluetooth.BluetoothProfile} by calling {@link
+headset profile devices. For example, applications can identify when a Bluetooth headset is
+connected for listening to music and notify the user as appropriate. Applications can also receive
+broadcasts for vendor specific AT commands and notify the user about the state of the connected
+device, such as when the connected device's battery is low.</p>
+
+<p>You can initialize the respective {@link android.bluetooth.BluetoothProfile} by calling {@link
 android.bluetooth.BluetoothAdapter#getProfileProxy getProfileProxy()} with either the {@link
 android.bluetooth.BluetoothProfile#A2DP} or {@link android.bluetooth.BluetoothProfile#HEADSET}
 profile constant and a {@link android.bluetooth.BluetoothProfile.ServiceListener} to receive
-callbacks when the client is connected or disconnected.</p>
+callbacks when the Bluetooth client is connected or disconnected.</p>
 
 
 
 
 <h3>Animation framework</h3>
 
-<p>An all new flexible animation framework allows you to animate the properties of any object
-(View, Drawable, Fragment, Object, anything). It allows you to define many aspects of an animation,
-such as:</p>
+<p>An all new flexible animation framework allows you to animate arbitrary properties of any object
+(View, Drawable, Fragment, Object, or anything else). It allows you to define many aspects of an
+animation, such as:</p>
 <ul>
   <li>Duration</li>
   <li>Repeat amount and behavior</li>
@@ -308,7 +315,7 @@
 the values for that given type, by implementing the {@link android.animation.TypeEvaluator}
 interface.</p>
 
-<p>There are two animators that you can use to animate values of a property: {@link
+<p>There are two animators you can use to animate values of a property: {@link
 android.animation.ValueAnimator} and {@link android.animation.ObjectAnimator}. The {@link
 android.animation.ValueAnimator} computes the animation values, but is not aware of the specific
 object or property that is animated as a result. It simply performs the calculations, and you must
@@ -320,13 +327,13 @@
 time in order to animate it, then start the animation.</p>
 
 <p>Additionally, the {@link android.animation.LayoutTransition} class enables automatic transition
-animations for changes you make to your activity layout. To enable transitions for a {@link
-android.view.ViewGroup}, create a {@link android.animation.LayoutTransition} object and set it on
+animations for changes you make to your activity layout. To enable transitions for part of the
+layout, create a {@link android.animation.LayoutTransition} object and set it on
 any {@link android.view.ViewGroup} by calling {@link
 android.view.ViewGroup#setLayoutTransition setLayoutTransition()}. This causes default
 animations to run whenever items are added to or removed from the group. To specify custom
 animations, call {@link android.animation.LayoutTransition#setAnimator setAnimator()} on the {@link
-android.animation.LayoutTransition} to provide a custom {@link android.animation.Animator},
+android.animation.LayoutTransition} and provide a custom {@link android.animation.Animator},
 such as a {@link android.animation.ValueAnimator} or {@link android.animation.ObjectAnimator}
 discussed above.</p>
 
@@ -397,14 +404,14 @@
   <li><b>New holographic themes</b>
 
     <p>The standard system widgets and overall look have been redesigned for use on larger screens
-such as tablets and incorporate the new holographic UI theme. These style changes are applied
+such as tablets and incorporate the new "holographic" UI theme. The system applies these styles
 using the standard <a href="{@docRoot}guide/topics/ui/themes.html">style and theme</a> system.
-Any application that targets the Android 3.0 platform inherit the holographic theme by default.
+Any application that targets the Android 3.0 platform inherits the holographic theme by default.
 However, if your application also applies its own styles, then it will override the holographic
-theme, unless you update your styles to inherit them.</p>
+theme, unless you update your styles to inherit the holographic theme.</p>
 
 <p>To apply the holographic theme to individual activities or to inherit them in your own theme
-definitions, you can use one of several new {@link android.R.style#Theme_Holo Theme.Holo}
+definitions, use one of several new {@link android.R.style#Theme_Holo Theme.Holo}
 themes.</p>
   </li>
   
@@ -522,20 +529,40 @@
 
 
 <ul>
-  <li><b>Camcorder profiles</b>
 
-<p>New {@link android.media.CamcorderProfile#hasProfile hasProfile()} method and several video
-quality profiles, such as {@link android.media.CamcorderProfile#QUALITY_1080P}, {@link
-android.media.CamcorderProfile#QUALITY_720P}, {@link
-android.media.CamcorderProfile#QUALITY_CIF}, and more, to determine the camcorder quality
-profiles.</p></li>
-
-  <li><b>Time lapse video mode</b>
+  <li><b>Time lapse video</b>
 
 <p>Camcorder APIs now support the ability to record time lapse video. The {@link
 android.media.MediaRecorder#setCaptureRate setCaptureRate()} sets the rate at which frames
 should be captured.</p></li>
 
+  <li><b>Texture support for image streams</b>
+    
+<p>New {@link android.graphics.SurfaceTexture} allows you to capture an image stream as an OpenGL ES
+texture. By calling {@link android.hardware.Camera#setPreviewTexture setPreviewTexture()} for your
+{@link android.hardware.Camera} instance, you can specify the {@link
+android.graphics.SurfaceTexture} upon which to draw video playback or preview frames from the
+camera.</p></li>
+
+  <li><b>HTTP Live streaming</b>
+    
+<p>Applications can now pass an M3U playlist URL to the media framework to begin an HTTP Live
+streaming session. The media framework supports most of the HTTP Live streaming specification,
+including adaptive bit rate.</p></li>
+
+  <li><b>EXIF data</b>
+    
+<p>The {@link android.media.ExifInterface} includes new fields for photo aperture, ISO, and exposure
+time.</p></li>
+
+  <li><b>Camcorder profiles</b>
+
+<p>New {@link android.media.CamcorderProfile#hasProfile hasProfile()} method and several video
+quality profiles (such as {@link android.media.CamcorderProfile#QUALITY_1080P}, {@link
+android.media.CamcorderProfile#QUALITY_720P}, {@link
+android.media.CamcorderProfile#QUALITY_CIF}, and others) allow you to determine camcorder
+quality options.</p></li>
+
   <li><b>Digital media file transfer</b>
 
 <p>The platform includes built-in support for Media/Picture Transfer Protocol (MTP/PTP) over USB,
diff --git a/include/media/stagefright/StagefrightMediaScanner.h b/include/media/stagefright/StagefrightMediaScanner.h
index 4437eee..108acb4 100644
--- a/include/media/stagefright/StagefrightMediaScanner.h
+++ b/include/media/stagefright/StagefrightMediaScanner.h
@@ -22,8 +22,6 @@
 
 namespace android {
 
-struct MediaMetadataRetriever;
-
 struct StagefrightMediaScanner : public MediaScanner {
     StagefrightMediaScanner();
     virtual ~StagefrightMediaScanner();
@@ -35,8 +33,6 @@
     virtual char *extractAlbumArt(int fd);
 
 private:
-    sp<MediaMetadataRetriever> mRetriever;
-
     StagefrightMediaScanner(const StagefrightMediaScanner &);
     StagefrightMediaScanner &operator=(const StagefrightMediaScanner &);
 };
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index 8156439..f078cf6 100755
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -3021,7 +3021,7 @@
      */
     public void doPreview(Surface surface, long fromMs, long toMs, boolean loop,
             int callbackAfterFrameCount, PreviewProgressListener listener) {
-        mPreviewProgress = 0;
+        mPreviewProgress = fromMs;
         if (listener != null) {
             mPreviewProgressListener = listener;
         }
diff --git a/media/java/android/mtp/MtpPropertyGroup.java b/media/java/android/mtp/MtpPropertyGroup.java
index fff96c7..57e2304 100644
--- a/media/java/android/mtp/MtpPropertyGroup.java
+++ b/media/java/android/mtp/MtpPropertyGroup.java
@@ -282,7 +282,7 @@
     }
 
     MtpPropertyList getPropertyList(int handle, int format, int depth, int storageID) {
-        Log.d(TAG, "getPropertyList handle: " + handle + " format: " + format + " depth: " + depth);
+        //Log.d(TAG, "getPropertyList handle: " + handle + " format: " + format + " depth: " + depth);
         if (depth > 1) {
             // we only support depth 0 and 1
             // depth 0: single object, depth 1: immediate children
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index 2e69373..d433887 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -54,12 +54,8 @@
         native_set_ptp_mode(usePtp);
     }
 
-    // used by the JNI code
-    private int mNativeContext;
-
     private native final void native_setup(MtpDatabase database, String storagePath,
             long reserveSpace);
-    private native final void native_finalize();
     private native final void native_start();
     private native final void native_stop();
     private native final void native_send_object_added(int handle);
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 1452d21..3883fb2 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -40,9 +40,6 @@
 
 // ----------------------------------------------------------------------------
 
-static jfieldID field_context;
-static Mutex    sMutex;
-
 // in android_mtp_MtpDatabase.cpp
 extern MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database);
 
@@ -61,96 +58,74 @@
     MtpServer*      mServer;
     String8         mStoragePath;
     uint64_t        mReserveSpace;
-    jobject         mJavaServer;
-    bool            mDone;
+    Mutex           mMutex;
+    bool            mUsePtp;
     int             mFd;
 
 public:
-    MtpThread(MtpDatabase* database, const char* storagePath, uint64_t reserveSpace,
-                jobject javaServer)
+    MtpThread(MtpDatabase* database, const char* storagePath, uint64_t reserveSpace)
         :   mDatabase(database),
             mServer(NULL),
             mStoragePath(storagePath),
             mReserveSpace(reserveSpace),
-            mJavaServer(javaServer),
-            mDone(false),
             mFd(-1)
     {
     }
 
     void setPtpMode(bool usePtp) {
-        sMutex.lock();
-        if (mFd >= 0) {
-            ioctl(mFd, MTP_SET_INTERFACE_MODE,
-                    (usePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
-        } else {
-            int fd = open("/dev/mtp_usb", O_RDWR);
-            if (fd >= 0) {
-                ioctl(fd, MTP_SET_INTERFACE_MODE,
-                        (usePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
-                close(fd);
-            }
-        }
-        sMutex.unlock();
+        mMutex.lock();
+        mUsePtp = usePtp;
+        mMutex.unlock();
     }
 
     virtual bool threadLoop() {
-        sMutex.lock();
-
-        while (!mDone) {
-            mFd = open("/dev/mtp_usb", O_RDWR);
-            printf("open returned %d\n", mFd);
-            if (mFd < 0) {
-                LOGE("could not open MTP driver\n");
-                sMutex.unlock();
-                return false;
-            }
+        mMutex.lock();
+        mFd = open("/dev/mtp_usb", O_RDWR);
+        if (mFd >= 0) {
+            ioctl(mFd, MTP_SET_INTERFACE_MODE,
+                    (mUsePtp ? MTP_INTERFACE_MODE_PTP : MTP_INTERFACE_MODE_MTP));
 
             mServer = new MtpServer(mFd, mDatabase, AID_MEDIA_RW, 0664, 0775);
             mServer->addStorage(mStoragePath, mReserveSpace);
 
-            sMutex.unlock();
-
+            mMutex.unlock();
             mServer->run();
-            sleep(1);
-
-            sMutex.lock();
+            mMutex.lock();
 
             close(mFd);
             mFd = -1;
             delete mServer;
             mServer = NULL;
+        } else {
+            LOGE("could not open MTP driver, errno: %d", errno);
+        }
+        mMutex.unlock();
+        // delay a bit before retrying to avoid excessive spin
+        if (!exitPending()) {
+            sleep(1);
         }
 
-        JNIEnv* env = AndroidRuntime::getJNIEnv();
-        env->SetIntField(mJavaServer, field_context, 0);
-        env->DeleteGlobalRef(mJavaServer);
-        sMutex.unlock();
-
-        return false;
-    }
-
-    void stop() {
-        sMutex.lock();
-        mDone = true;
-        sMutex.unlock();
+        return true;
     }
 
     void sendObjectAdded(MtpObjectHandle handle) {
-        sMutex.lock();
+        mMutex.lock();
         if (mServer)
             mServer->sendObjectAdded(handle);
-        sMutex.unlock();
+        mMutex.unlock();
     }
 
     void sendObjectRemoved(MtpObjectHandle handle) {
-        sMutex.lock();
+        mMutex.lock();
         if (mServer)
             mServer->sendObjectRemoved(handle);
-        sMutex.unlock();
+        mMutex.unlock();
     }
 };
 
+// This smart pointer is necessary for preventing MtpThread from exiting too early
+static sp<MtpThread> sThread;
+
 #endif // HAVE_ANDROID_OS
 
 static void
@@ -161,9 +136,8 @@
     MtpDatabase* database = getMtpDatabase(env, javaDatabase);
     const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
 
-    MtpThread* thread = new MtpThread(database, storagePathStr,
-            reserveSpace, env->NewGlobalRef(thiz));
-    env->SetIntField(thiz, field_context, (int)thread);
+    // create the thread and assign it to the smart pointer
+    sThread = new MtpThread(database, storagePathStr, reserveSpace);
 
     env->ReleaseStringUTFChars(storagePath, storagePathStr);
 #endif
@@ -173,8 +147,9 @@
 android_mtp_MtpServer_start(JNIEnv *env, jobject thiz)
 {
 #ifdef HAVE_ANDROID_OS
-    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
-    thread->run("MtpThread");
+    MtpThread *thread = sThread.get();
+    if (thread)
+        thread->run("MtpThread");
 #endif // HAVE_ANDROID_OS
 }
 
@@ -182,9 +157,11 @@
 android_mtp_MtpServer_stop(JNIEnv *env, jobject thiz)
 {
 #ifdef HAVE_ANDROID_OS
-    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
-    if (thread)
-        thread->stop();
+    MtpThread *thread = sThread.get();
+    if (thread) {
+        thread->requestExitAndWait();
+        sThread = NULL;
+    }
 #endif
 }
 
@@ -192,7 +169,7 @@
 android_mtp_MtpServer_send_object_added(JNIEnv *env, jobject thiz, jint handle)
 {
 #ifdef HAVE_ANDROID_OS
-    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
+    MtpThread *thread = sThread.get();
     if (thread)
         thread->sendObjectAdded(handle);
 #endif
@@ -202,7 +179,7 @@
 android_mtp_MtpServer_send_object_removed(JNIEnv *env, jobject thiz, jint handle)
 {
 #ifdef HAVE_ANDROID_OS
-    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
+    MtpThread *thread = sThread.get();
     if (thread)
         thread->sendObjectRemoved(handle);
 #endif
@@ -212,7 +189,7 @@
 android_mtp_MtpServer_set_ptp_mode(JNIEnv *env, jobject thiz, jboolean usePtp)
 {
 #ifdef HAVE_ANDROID_OS
-    MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
+    MtpThread *thread = sThread.get();
     if (thread)
         thread->setPtpMode(usePtp);
 #endif
@@ -241,11 +218,6 @@
         LOGE("Can't find android/mtp/MtpServer");
         return -1;
     }
-    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
-    if (field_context == NULL) {
-        LOGE("Can't find MtpServer.mNativeContext");
-        return -1;
-    }
 
     return AndroidRuntime::registerNativeMethods(env,
                 "android/mtp/MtpServer", gMethods, NELEM(gMethods));
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 235d752..f96df18 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -91,14 +91,17 @@
         mStartTimeUs = startTimeUs;
     }
     status_t err = mRecord->start();
-
     if (err == OK) {
         mGroup = new MediaBufferGroup;
         mGroup->add_buffer(new MediaBuffer(kMaxBufferSize));
 
         mStarted = true;
+    } else {
+        delete mRecord;
+        mRecord = NULL;
     }
 
+
     return err;
 }
 
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index a47ee3a..d1a497f8 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -78,6 +78,7 @@
     volatile bool mDone;
     volatile bool mPaused;
     volatile bool mResumed;
+    volatile bool mStarted;
     bool mIsAvc;
     bool mIsAudio;
     bool mIsMPEG4;
@@ -951,6 +952,7 @@
       mDone(false),
       mPaused(false),
       mResumed(false),
+      mStarted(false),
       mTrackDurationUs(0),
       mEstimatedTrackSizeBytes(0),
       mSamplesHaveSameSize(true),
@@ -1279,6 +1281,7 @@
     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
 
     mDone = false;
+    mStarted = true;
     mTrackDurationUs = 0;
     mReachedEOS = false;
     mEstimatedTrackSizeBytes = 0;
@@ -1307,10 +1310,14 @@
 
 status_t MPEG4Writer::Track::stop() {
     LOGD("Stopping %s track", mIsAudio? "Audio": "Video");
+    if (!mStarted) {
+        LOGE("Stop() called but track is not started");
+        return ERROR_END_OF_STREAM;
+    }
+
     if (mDone) {
         return OK;
     }
-
     mDone = true;
 
     void *dummy;
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 39b0021..be3df7c 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -28,9 +28,7 @@
 
 namespace android {
 
-StagefrightMediaScanner::StagefrightMediaScanner()
-    : mRetriever(new MediaMetadataRetriever) {
-}
+StagefrightMediaScanner::StagefrightMediaScanner() {}
 
 StagefrightMediaScanner::~StagefrightMediaScanner() {}
 
@@ -131,37 +129,41 @@
         if (status != OK) {
             return status;
         }
-    } else if (mRetriever->setDataSource(path) == OK) {
-        const char *value;
-        if ((value = mRetriever->extractMetadata(
-                        METADATA_KEY_MIMETYPE)) != NULL) {
-            client.setMimeType(value);
-        }
+    } else {
+        sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
 
-        struct KeyMap {
-            const char *tag;
-            int key;
-        };
-        static const KeyMap kKeyMap[] = {
-            { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
-            { "discnumber", METADATA_KEY_DISC_NUMBER },
-            { "album", METADATA_KEY_ALBUM },
-            { "artist", METADATA_KEY_ARTIST },
-            { "albumartist", METADATA_KEY_ALBUMARTIST },
-            { "composer", METADATA_KEY_COMPOSER },
-            { "genre", METADATA_KEY_GENRE },
-            { "title", METADATA_KEY_TITLE },
-            { "year", METADATA_KEY_YEAR },
-            { "duration", METADATA_KEY_DURATION },
-            { "writer", METADATA_KEY_WRITER },
-            { "compilation", METADATA_KEY_COMPILATION },
-        };
-        static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
-
-        for (size_t i = 0; i < kNumEntries; ++i) {
+         if (mRetriever->setDataSource(path) == OK) {
             const char *value;
-            if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
-                client.addStringTag(kKeyMap[i].tag, value);
+            if ((value = mRetriever->extractMetadata(
+                            METADATA_KEY_MIMETYPE)) != NULL) {
+                client.setMimeType(value);
+            }
+
+            struct KeyMap {
+                const char *tag;
+                int key;
+            };
+            static const KeyMap kKeyMap[] = {
+                { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
+                { "discnumber", METADATA_KEY_DISC_NUMBER },
+                { "album", METADATA_KEY_ALBUM },
+                { "artist", METADATA_KEY_ARTIST },
+                { "albumartist", METADATA_KEY_ALBUMARTIST },
+                { "composer", METADATA_KEY_COMPOSER },
+                { "genre", METADATA_KEY_GENRE },
+                { "title", METADATA_KEY_TITLE },
+                { "year", METADATA_KEY_YEAR },
+                { "duration", METADATA_KEY_DURATION },
+                { "writer", METADATA_KEY_WRITER },
+                { "compilation", METADATA_KEY_COMPILATION },
+            };
+            static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
+
+            for (size_t i = 0; i < kNumEntries; ++i) {
+                const char *value;
+                if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
+                    client.addStringTag(kKeyMap[i].tag, value);
+                }
             }
         }
     }
@@ -180,6 +182,7 @@
     }
     lseek64(fd, 0, SEEK_SET);
 
+    sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
     if (mRetriever->setDataSource(fd, 0, size) == OK) {
         sp<IMemory> mem = mRetriever->extractAlbumArt();
 
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
index 9524884..a8b1292 100644
--- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -151,7 +151,11 @@
     mInputFrame = new int16_t[mChannels * kNumSamplesPerFrame];
     CHECK(mInputFrame != NULL);
 
-    mSource->start(params);
+    status_t err = mSource->start(params);
+    if (err != OK) {
+         LOGE("AudioSource is not available");
+        return err;
+    }
 
     mStarted = true;
 
@@ -159,11 +163,6 @@
 }
 
 status_t AACEncoder::stop() {
-    if (!mStarted) {
-        LOGW("Call stop() when encoder has not started");
-        return OK;
-    }
-
     if (mInputBuffer) {
         mInputBuffer->release();
         mInputBuffer = NULL;
@@ -172,8 +171,17 @@
     delete mBufferGroup;
     mBufferGroup = NULL;
 
-    mSource->stop();
+    if (mInputFrame) {
+        delete[] mInputFrame;
+        mInputFrame = NULL;
+    }
 
+    if (!mStarted) {
+        LOGW("Call stop() when encoder has not started");
+        return ERROR_END_OF_STREAM;
+    }
+
+    mSource->stop();
     if (mEncoderHandle) {
         CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
         mEncoderHandle = NULL;
@@ -182,10 +190,6 @@
     mApiHandle = NULL;
 
     mStarted = false;
-    if (mInputFrame) {
-        delete[] mInputFrame;
-        mInputFrame = NULL;
-    }
 
     return OK;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
index 7544f46..a5e2fda 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java
@@ -98,10 +98,12 @@
     };
 
     public boolean isInContentArea(int x, int y) {
-        final int l = mRecentsContainer.getPaddingLeft();
-        final int r = mRecentsContainer.getWidth() - mRecentsContainer.getPaddingRight();
-        final int t = mRecentsContainer.getPaddingTop();
-        final int b = mRecentsContainer.getHeight() - mRecentsContainer.getPaddingBottom();
+        // use mRecentsContainer's exact bounds to determine horizontal position
+        final int l = mRecentsContainer.getLeft();
+        final int r = mRecentsContainer.getRight();
+        // use surrounding mRecentsGlowView's position in parent determine vertical bounds
+        final int t = mRecentsGlowView.getTop();
+        final int b = mRecentsGlowView.getBottom();
         return x >= l && x < r && y >= t && y < b;
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 6a1d199..88f30ed 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -116,7 +116,6 @@
     private ViewGroup mContentParent;
 
     SurfaceHolder.Callback2 mTakeSurfaceCallback;
-    BaseSurfaceHolder mSurfaceHolder;
     
     InputQueue.Callback mTakeInputQueueCallback;
     
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
index 5bcf727..622fb0e 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -16,8 +16,6 @@
 
 package com.android.dumprendertree;
 
-import dalvik.system.VMRuntime;
-
 import android.app.Instrumentation;
 import android.content.Context;
 import android.content.Intent;
@@ -34,12 +32,15 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintStream;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 
 public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShellActivity> {
 
     private final static String LOGTAG = "LoadTest";
     private final static String LOAD_TEST_RESULT =
         Environment.getExternalStorageDirectory() + "/load_test_result.txt";
+    private final static int MAX_GC_WAIT_SEC = 10;
     private boolean mFinished;
     static final String LOAD_TEST_RUNNER_FILES[] = {
         "run_page_cycler.py"
@@ -90,14 +91,23 @@
 
     private void freeMem() {
         Log.v(LOGTAG, "freeMem: calling gc...");
-        final VMRuntime runtime = VMRuntime.getRuntime();
-
-        runtime.gcSoftReferences();
-        runtime.gcSoftReferences();
-        runtime.gcSoftReferences();
-        Runtime.getRuntime().gc();
-        Runtime.getRuntime().gc();
-
+        final CountDownLatch latch = new CountDownLatch(1);
+        Object dummy = new Object() {
+            @Override
+            protected void finalize() throws Throwable {
+                latch.countDown();
+                super.finalize();
+            }
+        };
+        dummy = null;
+        System.gc();
+        try {
+            if (!latch.await(MAX_GC_WAIT_SEC, TimeUnit.SECONDS)) {
+                Log.w(LOGTAG, "gc did not happen in 10s");
+            }
+        } catch (InterruptedException e) {
+            //ignore
+        }
     }
 
     private void printRow(PrintStream ps, String format, Object...objs) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
index 9b6fb82..d2b6b27 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Region_Delegate.java
@@ -446,6 +446,15 @@
         return region1.mArea.equals(region2.mArea);
     }
 
+    /*package*/ static String nativeToString(int native_region) {
+        Region_Delegate region = sManager.getDelegate(native_region);
+        if (region == null) {
+            return "not found";
+        }
+
+        return region.mArea.toString();
+    }
+
     // ---- Private delegate/helper methods ----
 
 }
diff --git a/tools/layoutlib/bridge/src/android/os/Build_Delegate.java b/tools/layoutlib/bridge/src/android/os/Build_Delegate.java
new file mode 100644
index 0000000..f71860f
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/os/Build_Delegate.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+package android.os;
+
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+
+import java.util.Map;
+
+/**
+ * Delegate implementing the native methods of android.os.Build
+ *
+ * Through the layoutlib_create tool, the original native methods of Build have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager}
+ * around to map int to instance of the delegate.
+ *
+ */
+public class Build_Delegate {
+
+    /*package*/ static String getString(String property) {
+        Map<String, String> properties = Bridge.getPlatformProperties();
+        String value = properties.get(property);
+        if (value != null) {
+            return value;
+        }
+
+        return Build.UNKNOWN;
+    }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 37576b4..0c3aef4 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -93,6 +93,7 @@
         new HashMap<String, SoftReference<NinePatchChunk>>();
 
     private static Map<String, Map<String, Integer>> sEnumValueMap;
+    private static Map<String, String> sPlatformProperties;
 
     /**
      * int[] wrapper to use as keys in maps.
@@ -157,10 +158,8 @@
      */
     private static LayoutLog sCurrentLog = sDefaultLog;
 
-
     private EnumSet<Capability> mCapabilities;
 
-
     @Override
     public int getApiLevel() {
         return com.android.ide.common.rendering.api.Bridge.API_CURRENT;
@@ -172,8 +171,11 @@
     }
 
     @Override
-    public boolean init(File fontLocation, Map<String, Map<String, Integer>> enumValueMap,
+    public boolean init(Map<String,String> platformProperties,
+            File fontLocation,
+            Map<String, Map<String, Integer>> enumValueMap,
             LayoutLog log) {
+        sPlatformProperties = platformProperties;
         sEnumValueMap = enumValueMap;
 
         // don't use EnumSet.allOf(), because the bridge doesn't come with its specific version
@@ -429,6 +431,13 @@
     }
 
     /**
+     * Returns the platform build properties.
+     */
+    public static Map<String, String> getPlatformProperties() {
+        return sPlatformProperties;
+    }
+
+    /**
      * Returns the bitmap for a specific path, from a specific project cache, or from the
      * framework cache.
      * @param value the path of the bitmap
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
index bc2301d..3bc0202 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -30,6 +30,7 @@
 import android.view.ViewParent;
 
 import java.awt.image.BufferedImage;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -55,8 +56,8 @@
     }
 
     @Override
-    public ViewInfo getRootView() {
-        return mSession.getViewInfo();
+    public List<ViewInfo> getRootViews() {
+        return mSession.getViewInfos();
     }
 
     @Override
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 63d52e9..d7b7009 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -116,7 +116,7 @@
 
     // information being returned through the API
     private BufferedImage mImage;
-    private ViewInfo mViewInfo;
+    private List<ViewInfo> mViewInfoList;
 
     private static final class PostInflateException extends Exception {
         private static final long serialVersionUID = 1L;
@@ -478,7 +478,7 @@
 
             mViewRoot.draw(mCanvas);
 
-            mViewInfo = visit(((ViewGroup)mViewRoot).getChildAt(0), mContext);
+            mViewInfoList = visitAllChildren((ViewGroup)mViewRoot, mContext);
 
             // success!
             return SUCCESS.createResult();
@@ -1101,16 +1101,25 @@
 
         if (view instanceof ViewGroup) {
             ViewGroup group = ((ViewGroup) view);
-            List<ViewInfo> children = new ArrayList<ViewInfo>();
-            for (int i = 0; i < group.getChildCount(); i++) {
-                children.add(visit(group.getChildAt(i), context));
-            }
-            result.setChildren(children);
+            result.setChildren(visitAllChildren(group, context));
         }
 
         return result;
     }
 
+    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, BridgeContext context) {
+        if (viewGroup == null) {
+            return null;
+        }
+
+        List<ViewInfo> children = new ArrayList<ViewInfo>();
+        for (int i = 0; i < viewGroup.getChildCount(); i++) {
+            children.add(visit(viewGroup.getChildAt(i), context));
+        }
+        return children;
+    }
+
+
     private void invalidateRenderingSize() {
         mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
     }
@@ -1119,8 +1128,8 @@
         return mImage;
     }
 
-    public ViewInfo getViewInfo() {
-        return mViewInfo;
+    public List<ViewInfo> getViewInfos() {
+        return mViewInfoList;
     }
 
     public Map<String, String> getDefaultProperties(Object viewObject) {
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index e3c5b4b..55e9e48 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -96,6 +96,7 @@
     private final static String[] DELEGATE_METHODS = new String[] {
         "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
         "android.os.Handler#sendMessageAtTime",
+        "android.os.Build#getString",
         "android.view.LayoutInflater#rInflate",
         "android.view.View#isInEditMode",
         "com.android.internal.util.XmlUtils#convertValueToInt",