Merge change 25291 into eclair

* changes:
  Try to fix sdk build again.
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 8f7e8ca..4f9531e 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -20,14 +20,15 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.ContentResolver.OpenResourceIdResult;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
 import android.database.Cursor;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.DrawableContainer;
 import android.graphics.drawable.StateListDrawable;
 import android.net.Uri;
 import android.os.Bundle;
@@ -38,14 +39,15 @@
 import android.util.SparseArray;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.Filter;
 import android.widget.ImageView;
 import android.widget.ResourceCursorAdapter;
 import android.widget.TextView;
-import android.widget.Filter;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.List;
 import java.util.WeakHashMap;
 
 /**
@@ -580,14 +582,26 @@
             // Not cached, try using it as a plain resource ID in the provider's context.
             int resourceId = Integer.parseInt(drawableId);
             drawable = mProviderContext.getResources().getDrawable(resourceId);
-            if (DBG) Log.d(LOG_TAG, "Found icon by resource ID: " + drawableId);
         } catch (NumberFormatException nfe) {
-            // The id was not an integer resource id.
-            // Let the ContentResolver handle content, android.resource and file URIs.
+            // The id was not an integer resource id, use it as a URI
             try {
                 Uri uri = Uri.parse(drawableId);
-                InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
-                if (stream != null) {
+                String scheme = uri.getScheme();
+                if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
+                    // Load drawables through Resources, to get the source density information
+                    OpenResourceIdResult r =
+                            mProviderContext.getContentResolver().getResourceId(uri);
+                    try {
+                        drawable = r.r.getDrawable(r.id);
+                    } catch (Resources.NotFoundException ex) {
+                        throw new FileNotFoundException("Resource does not exist: " + uri);
+                    }
+                } else {
+                    // Let the ContentResolver handle content and file URIs.
+                    InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
+                    if (stream == null) {
+                        throw new FileNotFoundException("Failed to open " + uri);
+                    }
                     try {
                         drawable = Drawable.createFromStream(stream, null);
                     } finally {
@@ -598,22 +612,25 @@
                         }
                     }
                 }
-                if (DBG) Log.d(LOG_TAG, "Opened icon input stream: " + drawableId);
             } catch (FileNotFoundException fnfe) {
-                if (DBG) Log.d(LOG_TAG, "Icon stream not found: " + drawableId);
+                Log.w(LOG_TAG, "Icon not found: " + drawableId + ", " + fnfe.getMessage());
                 // drawable = null;
             }
-
-            // If we got a drawable for this resource id, then stick it in the
-            // map so we don't do this lookup again.
-            if (drawable != null) {
-                mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
-            }
         } catch (Resources.NotFoundException nfe) {
-            if (DBG) Log.d(LOG_TAG, "Icon resource not found: " + drawableId);
+            Log.w(LOG_TAG, "Icon resource not found: " + drawableId);
             // drawable = null;
         }
 
+        if (drawable == null) {
+            if (DBG) Log.d(LOG_TAG, "Didn't find icon: " + drawableId);
+        } else {
+            if (DBG) {
+                Log.d(LOG_TAG, "Found icon: " + drawableId);
+            }
+            // Cache it so we don't do this lookup again
+            mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
+        }
+
         return drawable;
     }
 
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 88a4d02f..307899a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -527,12 +527,22 @@
         }
     }
 
-    class OpenResourceIdResult {
-        Resources r;
-        int id;
+    /**
+     * A resource identified by the {@link Resources} that contains it, and a resource id.
+     *
+     * @hide
+     */
+    public class OpenResourceIdResult {
+        public Resources r;
+        public int id;
     }
-    
-    OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
+
+    /**
+     * Resolves an android.resource URI to a {@link Resources} and a resource id.
+     *
+     * @hide
+     */
+    public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
         String authority = uri.getAuthority();
         Resources r;
         if (TextUtils.isEmpty(authority)) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 081f67a..4ca17ac 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4791,8 +4791,11 @@
                             mMaxZoomScale = restoreState.mMaxScale;
                         }
                         setNewZoomScale(mLastScale, false);
-                        setContentScrollTo(restoreState.mScrollX,
-                                restoreState.mScrollY);
+                        if (getVisibleTitleHeight() == 0
+                                || restoreState.mScrollY != 0) {
+                            setContentScrollTo(restoreState.mScrollX,
+                                    restoreState.mScrollY);
+                        }
                         if (useWideViewport
                                 && settings.getLoadWithOverviewMode()) {
                             if (restoreState.mViewScale == 0
diff --git a/include/media/stagefright/SoftwareRenderer.h b/include/media/stagefright/SoftwareRenderer.h
index b61858c..1545493 100644
--- a/include/media/stagefright/SoftwareRenderer.h
+++ b/include/media/stagefright/SoftwareRenderer.h
@@ -45,6 +45,7 @@
 
     void renderCbYCrY(const void *data, size_t size);
     void renderYUV420Planar(const void *data, size_t size);
+    void renderQCOMYUV420SemiPlanar(const void *data, size_t size);
 
     OMX_COLOR_FORMATTYPE mColorFormat;
     sp<ISurface> mISurface;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 1dd644b..d6463a1 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -345,6 +345,9 @@
 
     /**
      * Adjusts the volume of a particular stream by one step in a direction.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
      * {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC} or
@@ -370,6 +373,9 @@
      * active, it will have the highest priority regardless of if the in-call
      * screen is showing. Another example, if music is playing in the background
      * and a call is not active, the music stream will be adjusted.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param direction The direction to adjust the volume. One of
      *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
@@ -391,6 +397,9 @@
     /**
      * Adjusts the volume of the most relevant stream, or the given fallback
      * stream.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param direction The direction to adjust the volume. One of
      *            {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
@@ -541,6 +550,9 @@
      * <p>
      * For a better user experience, applications MUST unmute a muted stream
      * in onPause() and mute is again in onResume() if appropriate.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param streamType The stream to be muted/unmuted.
      * @param state The required mute state: true for mute ON, false for mute OFF
@@ -608,6 +620,9 @@
 
     /**
      * Sets the setting for when the vibrate type should vibrate.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param vibrateType The type of vibrate. One of
      *            {@link #VIBRATE_TYPE_NOTIFICATION} or
@@ -630,6 +645,9 @@
 
     /**
      * Sets the speakerphone on or off.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param on set <var>true</var> to turn on speakerphone;
      *           <var>false</var> to turn it off
@@ -660,6 +678,9 @@
 
     /**
      * Request use of Bluetooth SCO headset for communications.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param on set <var>true</var> to use bluetooth SCO for communications;
      *               <var>false</var> to not use bluetooth SCO for communications
@@ -739,6 +760,9 @@
 
     /**
      * Sets the microphone mute on or off.
+     * <p>
+     * This method should only be used by applications that replace the platform-wide
+     * management of audio settings or the main telephony application.
      *
      * @param on set <var>true</var> to mute the microphone;
      *           <var>false</var> to turn mute off
@@ -758,6 +782,13 @@
 
     /**
      * Sets the audio mode.
+     * <p>
+     * The audio mode encompasses audio routing AND the behavior of
+     * the telephony layer. Therefore this method should only be used by applications that
+     * replace the platform-wide management of audio settings or the main telephony application.
+     * In particular, the {@link #MODE_IN_CALL} mode should only be used by the telephony
+     * application when it places a phone call, as it will cause signals from the radio layer
+     * to feed the platform mixer.
      *
      * @param mode  the requested audio mode (NORMAL, RINGTONE, or IN_CALL).
      *              Informs the HAL about the current audio state so that
diff --git a/media/libstagefright/omx/SoftwareRenderer.cpp b/media/libstagefright/omx/SoftwareRenderer.cpp
index a1c478f..4ed6869 100644
--- a/media/libstagefright/omx/SoftwareRenderer.cpp
+++ b/media/libstagefright/omx/SoftwareRenderer.cpp
@@ -65,6 +65,8 @@
 
 void SoftwareRenderer::render(
         const void *data, size_t size, void *platformPrivate) {
+    static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
     switch (mColorFormat) {
         case OMX_COLOR_FormatYUV420Planar:
             return renderYUV420Planar(data, size);
@@ -72,6 +74,9 @@
         case OMX_COLOR_FormatCbYCrY:
             return renderCbYCrY(data, size);
 
+        case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+            return renderQCOMYUV420SemiPlanar(data, size);
+
         default:
         {
             LOGW("Cannot render color format %ld", mColorFormat);
@@ -242,6 +247,76 @@
     mIndex = 1 - mIndex;
 }
 
+void SoftwareRenderer::renderQCOMYUV420SemiPlanar(
+        const void *data, size_t size) {
+    if (size != (mDecodedHeight * mDecodedWidth * 3) / 2) {
+        LOGE("size is %d, expected %d",
+                size, (mDecodedHeight * mDecodedWidth * 3) / 2);
+    }
+    CHECK(size >= (mDecodedWidth * mDecodedHeight * 3) / 2);
+
+    uint8_t *kAdjustedClip = initClip();
+
+    size_t offset = mIndex * mFrameSize;
+
+    void *dst = (uint8_t *)mMemoryHeap->getBase() + offset;
+
+    uint32_t *dst_ptr = (uint32_t *)dst;
+
+    const uint8_t *src_y = (const uint8_t *)data;
+
+    const uint8_t *src_u =
+        (const uint8_t *)src_y + mDecodedWidth * mDecodedHeight;
+
+    for (size_t y = 0; y < mDecodedHeight; ++y) {
+        for (size_t x = 0; x < mDecodedWidth; x += 2) {
+            signed y1 = (signed)src_y[x] - 16;
+            signed y2 = (signed)src_y[x + 1] - 16;
+
+            signed u = (signed)src_u[x & ~1] - 128;
+            signed v = (signed)src_u[(x & ~1) + 1] - 128;
+
+            signed u_b = u * 517;
+            signed u_g = -u * 100;
+            signed v_g = -v * 208;
+            signed v_r = v * 409;
+
+            signed tmp1 = y1 * 298;
+            signed b1 = (tmp1 + u_b) / 256;
+            signed g1 = (tmp1 + v_g + u_g) / 256;
+            signed r1 = (tmp1 + v_r) / 256;
+
+            signed tmp2 = y2 * 298;
+            signed b2 = (tmp2 + u_b) / 256;
+            signed g2 = (tmp2 + v_g + u_g) / 256;
+            signed r2 = (tmp2 + v_r) / 256;
+
+            uint32_t rgb1 =
+                ((kAdjustedClip[b1] >> 3) << 11)
+                | ((kAdjustedClip[g1] >> 2) << 5)
+                | (kAdjustedClip[r1] >> 3);
+
+            uint32_t rgb2 =
+                ((kAdjustedClip[b2] >> 3) << 11)
+                | ((kAdjustedClip[g2] >> 2) << 5)
+                | (kAdjustedClip[r2] >> 3);
+
+            dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
+        }
+
+        src_y += mDecodedWidth;
+
+        if (y & 1) {
+            src_u += mDecodedWidth;
+        }
+
+        dst_ptr += mDecodedWidth / 2;
+    }
+
+    mISurface->postBuffer(offset);
+    mIndex = 1 - mIndex;
+}
+
 uint8_t *SoftwareRenderer::initClip() {
     static const signed kClipMin = -278;
     static const signed kClipMax = 535;
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 82cf1bc..45e0ceb 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -3611,9 +3611,18 @@
         mHandler.post(new Runnable() {
             public void run() {
                 mHandler.removeCallbacks(this);
-                PackageInstalledInfo res;
-                synchronized (mInstallLock) {
-                    res = installPackageLI(packageURI, flags, true, installerPackageName);
+                 // Result object to be returned
+                PackageInstalledInfo res = new PackageInstalledInfo();
+                res.returnCode = PackageManager.INSTALL_SUCCEEDED;
+                res.uid = -1;
+                res.pkg = null;
+                res.removedInfo = new PackageRemovedInfo();
+                // Make a temporary copy of file from given packageURI
+                File tmpPackageFile = copyTempInstallFile(packageURI, res);
+                if (tmpPackageFile != null) {
+                    synchronized (mInstallLock) {
+                        installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
+                    }
                 }
                 if (observer != null) {
                     try {
@@ -3828,11 +3837,30 @@
             // Since we failed to install the new package we need to restore the old
             // package that we deleted.
             if(deletedPkg) {
+                File restoreFile = new File(deletedPackage.mPath);
+                if (restoreFile == null) {
+                    Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
+                    return;
+                }
+                File restoreTmpFile = createTempPackageFile();
+                if (restoreTmpFile == null) {
+                    Log.e(TAG, "Failed creating temp file when restoring pkg :  " + pkgName);
+                    return;
+                }
+                if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
+                    Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
+                    return;
+                }
+                PackageInstalledInfo restoreRes = new PackageInstalledInfo();
+                restoreRes.removedInfo = new PackageRemovedInfo();
                 installPackageLI(
-                        Uri.fromFile(new File(deletedPackage.mPath)),
+                        Uri.fromFile(restoreFile),
                         isForwardLocked(deletedPackage)
                         ? PackageManager.INSTALL_FORWARD_LOCK
-                                : 0, false, oldInstallerPackageName);
+                                : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
+                if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
+                    Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
+                }
             }
         }
     }
@@ -3995,50 +4023,36 @@
         return new File(mAppInstallDir, publicZipFileName);
     }
 
-    private PackageInstalledInfo installPackageLI(Uri pPackageURI,
-            int pFlags, boolean newInstall, String installerPackageName) {
-        File tmpPackageFile = null;
-        String pkgName = null;
-        boolean forwardLocked = false;
-        boolean replacingExistingPackage = false;
-        // Result object to be returned
-        PackageInstalledInfo res = new PackageInstalledInfo();
-        res.returnCode = PackageManager.INSTALL_SUCCEEDED;
-        res.uid = -1;
-        res.pkg = null;
-        res.removedInfo = new PackageRemovedInfo();
+    private File copyTempInstallFile(Uri pPackageURI,
+            PackageInstalledInfo res) {
+        File tmpPackageFile = createTempPackageFile();
+        int retCode = PackageManager.INSTALL_SUCCEEDED;
+        if (tmpPackageFile == null) {
+            res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+            return null;
+        }
 
-        main_flow: try {
-            tmpPackageFile = createTempPackageFile();
-            if (tmpPackageFile == null) {
-                res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                break main_flow;
+        if (pPackageURI.getScheme().equals("file")) {
+            final File srcPackageFile = new File(pPackageURI.getPath());
+            // We copy the source package file to a temp file and then rename it to the
+            // destination file in order to eliminate a window where the package directory
+            // scanner notices the new package file but it's not completely copied yet.
+            if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
+                Log.e(TAG, "Couldn't copy package file to temp file.");
+                retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
             }
-            tmpPackageFile.deleteOnExit();  // paranoia
-            if (pPackageURI.getScheme().equals("file")) {
-                final File srcPackageFile = new File(pPackageURI.getPath());
-                // We copy the source package file to a temp file and then rename it to the
-                // destination file in order to eliminate a window where the package directory
-                // scanner notices the new package file but it's not completely copied yet.
-                if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
-                    Log.e(TAG, "Couldn't copy package file to temp file.");
-                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                    break main_flow;
-                }
-            } else if (pPackageURI.getScheme().equals("content")) {
-                ParcelFileDescriptor fd;
-                try {
-                    fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
-                } catch (FileNotFoundException e) {
-                    Log.e(TAG, "Couldn't open file descriptor from download service.");
-                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                    break main_flow;
-                }
-                if (fd == null) {
-                    Log.e(TAG, "Couldn't open file descriptor from download service (null).");
-                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                    break main_flow;
-                }
+        } else if (pPackageURI.getScheme().equals("content")) {
+            ParcelFileDescriptor fd = null;
+            try {
+                fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
+            } catch (FileNotFoundException e) {
+                Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
+                retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+            }
+            if (fd == null) {
+                Log.e(TAG, "Couldn't open file descriptor from download service (null).");
+                retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+            } else {
                 if (Config.LOGV) {
                     Log.v(TAG, "Opened file descriptor from download service.");
                 }
@@ -4049,14 +4063,34 @@
                 // scanner notices the new package file but it's not completely copied yet.
                 if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
                     Log.e(TAG, "Couldn't copy package stream to temp file.");
-                    res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-                    break main_flow;
+                    retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
                 }
-            } else {
-                Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
-                res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
-                break main_flow;
             }
+        } else {
+            Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
+            retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
+        }
+
+        res.returnCode = retCode;
+        if (retCode != PackageManager.INSTALL_SUCCEEDED) {
+            if (tmpPackageFile != null && tmpPackageFile.exists()) {
+                tmpPackageFile.delete();
+            }
+            return null;
+        }
+        return tmpPackageFile;
+    }
+
+    private void installPackageLI(Uri pPackageURI,
+            int pFlags, boolean newInstall, String installerPackageName,
+            File tmpPackageFile, PackageInstalledInfo res) {
+        String pkgName = null;
+        boolean forwardLocked = false;
+        boolean replacingExistingPackage = false;
+        // Result object to be returned
+        res.returnCode = PackageManager.INSTALL_SUCCEEDED;
+
+        main_flow: try {
             pkgName = PackageParser.parsePackageName(
                     tmpPackageFile.getAbsolutePath(), 0);
             if (pkgName == null) {
@@ -4128,7 +4162,6 @@
                 tmpPackageFile.delete();
             }
         }
-        return res;
     }
     
     private int setPermissionsLI(String pkgName,