Merge "Small fixes to battery stats." into gingerbread
diff --git a/Android.mk b/Android.mk
index 03582c7..4e77679 100644
--- a/Android.mk
+++ b/Android.mk
@@ -429,10 +429,10 @@
 framework_docs_SDK_PREVIEW:=0
 
 ## Latest ADT version identifiers, for reference from published docs
-framework_docs_ADT_VERSION:=0.9.7
-framework_docs_ADT_DOWNLOAD:=ADT-0.9.7.zip
-framework_docs_ADT_BYTES:=8033750
-framework_docs_ADT_CHECKSUM:=de2431c8d4786d127ae5bfc95b4605df
+framework_docs_ADT_VERSION:=0.9.8
+framework_docs_ADT_DOWNLOAD:=ADT-0.9.8.zip
+framework_docs_ADT_BYTES:=8703591
+framework_docs_ADT_CHECKSUM:=22070f8e52924605a3b3abf87c1ba39f
 
 framework_docs_LOCAL_DROIDDOC_OPTIONS += \
 		-hdf sdk.version $(framework_docs_SDK_VERSION) \
diff --git a/api/current.xml b/api/current.xml
index 1abf681..1a8953d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -96234,7 +96234,7 @@
  type="java.lang.String"
  transient="false"
  volatile="false"
- value=""id""
+ value=""_id""
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -140773,6 +140773,17 @@
  visibility="public"
 >
 </field>
+<field name="INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.action.MEDIA_PLAY_FROM_SEARCH&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="INTENT_ACTION_MEDIA_SEARCH"
  type="java.lang.String"
  transient="false"
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 280ded6..331ce10 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -102,6 +102,14 @@
      * it with {@link android.content.Intent#getStringExtra(String)}.
      */
     public static final String EXTRA_EXTRA_INFO = "extraInfo";
+    /**
+     * The lookup key for an int that provides information about
+     * our connection to the internet at large.  0 indicates no connection,
+     * 100 indicates a great connection.  Retrieve it with
+     * {@link android.content.Intent@getIntExtra(String)}.
+     * {@hide}
+     */
+    public static final String EXTRA_INET_CONDITION = "inetCondition";
 
     /**
      * Broadcast Action: The setting for background data usage has changed
@@ -524,5 +532,17 @@
         } catch (RemoteException e) {
             return TETHER_ERROR_SERVICE_UNAVAIL;
         }
-   }
+    }
+
+    /**
+     * @param networkType The type of network you want to report on
+     * @param percentage The quality of the connection 0 is bad, 100 is good
+     * {@hide}
+     */
+    public void reportInetCondition(int networkType, int percentage) {
+        try {
+            mService.reportInetCondition(networkType, percentage);
+        } catch (RemoteException e) {
+        }
+    }
 }
diff --git a/core/java/android/net/DownloadManager.java b/core/java/android/net/DownloadManager.java
index cafe0f9..e04367a 100644
--- a/core/java/android/net/DownloadManager.java
+++ b/core/java/android/net/DownloadManager.java
@@ -21,6 +21,7 @@
 import android.database.Cursor;
 import android.database.CursorWrapper;
 import android.os.ParcelFileDescriptor;
+import android.provider.BaseColumns;
 import android.provider.Downloads;
 
 import java.io.File;
@@ -48,7 +49,7 @@
      * An identifier for a particular download, unique across the system.  Clients use this ID to
      * make subsequent calls related to the download.
      */
-    public final static String COLUMN_ID = "id";
+    public final static String COLUMN_ID = BaseColumns._ID;
 
     /**
      * The client-supplied title for this download.  This will be displayed in system notifications.
@@ -441,8 +442,22 @@
      * This class may be used to filter download manager queries.
      */
     public static class Query {
-        private Long mId;
+        /**
+         * Constant for use with {@link #orderBy}
+         * @hide
+         */
+        public static final int ORDER_ASCENDING = 1;
+
+        /**
+         * Constant for use with {@link #orderBy}
+         * @hide
+         */
+        public static final int ORDER_DESCENDING = 2;
+
+        private Long mId = null;
         private Integer mStatusFlags = null;
+        private String mOrderByColumn = Downloads.COLUMN_LAST_MODIFICATION;
+        private int mOrderDirection = ORDER_DESCENDING;
 
         /**
          * Include only the download with the given ID.
@@ -464,6 +479,32 @@
         }
 
         /**
+         * Change the sort order of the returned Cursor.
+         *
+         * @param column one of the COLUMN_* constants; currently, only
+         *         {@link #COLUMN_LAST_MODIFIED_TIMESTAMP} and {@link #COLUMN_TOTAL_SIZE_BYTES} are
+         *         supported.
+         * @param direction either {@link #ORDER_ASCENDING} or {@link #ORDER_DESCENDING}
+         * @return this object
+         * @hide
+         */
+        public Query orderBy(String column, int direction) {
+            if (direction != ORDER_ASCENDING && direction != ORDER_DESCENDING) {
+                throw new IllegalArgumentException("Invalid direction: " + direction);
+            }
+
+            if (column.equals(COLUMN_LAST_MODIFIED_TIMESTAMP)) {
+                mOrderByColumn = Downloads.COLUMN_LAST_MODIFICATION;
+            } else if (column.equals(COLUMN_TOTAL_SIZE_BYTES)) {
+                mOrderByColumn = Downloads.COLUMN_TOTAL_BYTES;
+            } else {
+                throw new IllegalArgumentException("Cannot order by " + column);
+            }
+            mOrderDirection = direction;
+            return this;
+        }
+
+        /**
          * Run this query using the given ContentResolver.
          * @param projection the projection to pass to ContentResolver.query()
          * @return the Cursor returned by ContentResolver.query()
@@ -497,7 +538,10 @@
                 }
                 selection = joinStrings(" OR ", parts);
             }
-            String orderBy = Downloads.COLUMN_LAST_MODIFICATION + " DESC";
+
+            String orderDirection = (mOrderDirection == ORDER_ASCENDING ? "ASC" : "DESC");
+            String orderBy = mOrderByColumn + " " + orderDirection;
+
             return resolver.query(uri, projection, selection, null, orderBy);
         }
 
@@ -567,6 +611,9 @@
      */
     public Cursor query(Query query) {
         Cursor underlyingCursor = query.runQuery(mResolver, UNDERLYING_COLUMNS);
+        if (underlyingCursor == null) {
+            return null;
+        }
         return new CursorTranslator(underlyingCursor);
     }
 
@@ -608,7 +655,7 @@
         public int getColumnIndexOrThrow(String columnName) throws IllegalArgumentException {
             int index = getColumnIndex(columnName);
             if (index == -1) {
-                throw new IllegalArgumentException();
+                throw new IllegalArgumentException("No such column: " + columnName);
             }
             return index;
         }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index b05c2ed..b734ac7 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -72,4 +72,6 @@
     String[] getTetherableUsbRegexs();
 
     String[] getTetherableWifiRegexs();
+
+    void reportInetCondition(int networkType, int percentage);
 }
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 0277d2d..c5a3277 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -62,6 +62,15 @@
     public static final int EVENT_ROAMING_CHANGED = 5;
     public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 6;
     public static final int EVENT_RESTORE_DEFAULT_NETWORK = 7;
+    /**
+     * arg1: network type
+     * arg2: condition (0 bad, 100 good)
+     */
+    public static final int EVENT_INET_CONDITION_CHANGE = 8;
+    /**
+     * arg1: network type
+     */
+    public static final int EVENT_INET_CONDITION_HOLD_END = 9;
 
     public NetworkStateTracker(Context context,
             Handler target,
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index d20e89d..075da33 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -75,6 +75,22 @@
     public static final String INTENT_ACTION_MEDIA_SEARCH = "android.intent.action.MEDIA_SEARCH";
 
     /**
+     * An intent to perform a search for music media and automatically play content from the
+     * result when possible. This can be fired, for example, by the result of a voice recognition
+     * command to listen to music.
+     * <p>
+     * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string
+     * that can contain any type of unstructured music search, like the name of an artist,
+     * an album, a song, a genre, or any combination of these.
+     * <p>
+     * Because this intent includes an open-ended unstructured search string, it makes the most
+     * sense for apps that can support large-scale search of music, such as services connected
+     * to an online database of music which can be streamed and played on the device.
+     */
+    public static final String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH =
+            "android.media.action.MEDIA_PLAY_FROM_SEARCH";
+    
+    /**
      * The name of the Intent-extra used to define the artist
      */
     public static final String EXTRA_MEDIA_ARTIST = "android.intent.extra.artist";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7c80420..f37ef99 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3427,6 +3427,21 @@
         public static final String DOWNLOAD_MAX_BYTES_OVER_MOBILE =
                 "download_manager_max_bytes_over_mobile";
 
+        /**
+         * ms during which to consume extra events related to Inet connection condition
+         * after a transtion to fully-connected
+         * @hide
+         */
+        public static final String INET_CONDITION_DEBOUNCE_UP_DELAY =
+                "inet_condition_debounce_up_delay";
+
+        /**
+         * ms during which to consume extra events related to Inet connection condtion
+         * after a transtion to partly-connected
+         * @hide
+         */
+        public static final String INET_CONDITION_DEBOUNCE_DOWN_DELAY =
+                "inet_condition_debounce_down_delay";
 
         /**
          * @hide
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index e1d3f13..094258b 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -404,7 +404,13 @@
             mBluetoothService.sendUuidIntent(address);
         } else if (name.equals("Paired")) {
             if (propValues[1].equals("true")) {
-                mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED);
+                // If locally initiated pairing, we will
+                // not go to BOND_BONDED state until we have received a
+                // successful return value in onCreatePairedDeviceResult
+                if (null == mBluetoothService.getBondState().getPendingOutgoingBonding()) {
+                    mBluetoothService.getBondState().setBondState(address,
+                            BluetoothDevice.BOND_BONDED);
+                }
             } else {
                 mBluetoothService.getBondState().setBondState(address,
                         BluetoothDevice.BOND_NONE);
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 57a72bf..2b083dc 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -30,6 +30,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Configuration;
+import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -178,6 +179,9 @@
         };
         
         final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
+            {
+                mRequestedFormat = PixelFormat.RGB_565;
+            }
 
             @Override
             public boolean onAllowLockCanvas() {
diff --git a/core/java/android/text/method/TextKeyListener.java b/core/java/android/text/method/TextKeyListener.java
index 5be2a48..09cbbb8 100644
--- a/core/java/android/text/method/TextKeyListener.java
+++ b/core/java/android/text/method/TextKeyListener.java
@@ -246,8 +246,10 @@
     private void initPrefs(Context context) {
         final ContentResolver contentResolver = context.getContentResolver();
         mResolver = new WeakReference<ContentResolver>(contentResolver);
-        mObserver = new SettingsObserver();
-        contentResolver.registerContentObserver(Settings.System.CONTENT_URI, true, mObserver);
+        if (mObserver == null) {
+            mObserver = new SettingsObserver();
+            contentResolver.registerContentObserver(Settings.System.CONTENT_URI, true, mObserver);
+        }
 
         updatePrefs(contentResolver);
         mPrefsInited = true;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3428206..e97bbfb 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5761,18 +5761,25 @@
     }
 
     private void convertFromViewportToContentCoordinates(Rect r) {
-        int paddingTop = getExtendedPaddingTop();
+        final int horizontalOffset = viewportToContentHorizontalOffset();
+        r.left += horizontalOffset;
+        r.right += horizontalOffset;
+
+        final int verticalOffset = viewportToContentVerticalOffset();
+        r.top += verticalOffset;
+        r.bottom += verticalOffset;
+    }
+
+    private int viewportToContentHorizontalOffset() {
+        return getCompoundPaddingLeft() - mScrollX;
+    }
+
+    private int viewportToContentVerticalOffset() {
+        int offset = getExtendedPaddingTop() - mScrollY;
         if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
-            paddingTop += getVerticalOffset(false);
+            offset += getVerticalOffset(false);
         }
-        r.top += paddingTop;
-        r.bottom += paddingTop;
-
-        int paddingLeft = getCompoundPaddingLeft();
-        r.left += paddingLeft;
-        r.right += paddingLeft;
-
-        r.offset(-mScrollX, -mScrollY);
+        return offset;
     }
 
     @Override
@@ -6492,6 +6499,8 @@
             if (!mFrozenWithFocus || (selStart < 0 || selEnd < 0)) {
                 // Has to be done before onTakeFocus, which can be overloaded.
                 if (mLastTouchOffset >= 0) {
+                    // Can happen when a TextView is displayed after its content has been deleted.
+                    mLastTouchOffset = Math.min(mLastTouchOffset, mText.length());
                     Selection.setSelection((Spannable) mText, mLastTouchOffset);
                 }
 
@@ -6508,7 +6517,8 @@
                 // ExtractEditText clears focus, which gives focus to the ExtractEditText.
                 // This special case ensure that we keep current selection in that case.
                 // It would be better to know why the DecorView does not have focus at that time.
-                if (((this instanceof ExtractEditText) || mSelectionMoved) && selStart >= 0 && selEnd >= 0) {
+                if (((this instanceof ExtractEditText) || mSelectionMoved) &&
+                        selStart >= 0 && selEnd >= 0) {
                     /*
                      * Someone intentionally set the selection, so let them
                      * do whatever it is that they wanted to do instead of
@@ -6621,6 +6631,8 @@
 
         if (start == end) {
             if (start >= prevStart && start < prevEnd) {
+                // Restore previous selection
+                Selection.setSelection((Spannable)mText, prevStart, prevEnd);
                 // Tapping inside the selection displays the cut/copy/paste context menu.
                 showContextMenu();
                 return;
@@ -7651,9 +7663,7 @@
             bounds.right = bounds.left + drawableWidth;
             bounds.bottom = bounds.top + drawableHeight;
 
-            int boundTopBefore = bounds.top;
             convertFromViewportToContentCoordinates(bounds);
-            mHotSpotVerticalPosition += bounds.top - boundTopBefore;
             mDrawable.setBounds(bounds);
             postInvalidate();
         }
@@ -7797,6 +7807,9 @@
                             mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
                             mOffsetY = mHandle.mHotSpotVerticalPosition - y;
 
+                            mOffsetX += viewportToContentHorizontalOffset();
+                            mOffsetY += viewportToContentVerticalOffset();
+
                             mOnDownTimerStart = event.getEventTime();
                         }
                         break;
@@ -7986,6 +7999,9 @@
                                     mOffsetX = (bounds.left + bounds.right) / 2.0f - x;
                                     mOffsetY = draggedHandle.mHotSpotVerticalPosition - y;
 
+                                    mOffsetX += viewportToContentHorizontalOffset();
+                                    mOffsetY += viewportToContentVerticalOffset();
+
                                     mOnDownTimerStart = event.getEventTime();
                                     ((ArrowKeyMovementMethod)mMovement).setCursorController(this);
                                 }
diff --git a/core/java/com/android/internal/view/BaseSurfaceHolder.java b/core/java/com/android/internal/view/BaseSurfaceHolder.java
index 3a04993..1e97cd6 100644
--- a/core/java/com/android/internal/view/BaseSurfaceHolder.java
+++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java
@@ -41,7 +41,8 @@
 
     int mRequestedWidth = -1;
     int mRequestedHeight = -1;
-    int mRequestedFormat = PixelFormat.OPAQUE;
+    /** @hide */
+    protected int mRequestedFormat = PixelFormat.OPAQUE;
     int mRequestedType = -1;
 
     long mLastLockTime = 0;
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 01b6711..db45d6d 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -388,7 +388,7 @@
             LOG_AND_FREE_DBUS_ERROR(&err);
         }
         dbus_bus_remove_match(nat->conn,
-                "type='signal',interface='org.bluez.audio.Device'",
+                "type='signal',interface='org.bluez.Device'",
                 &err);
         if (dbus_error_is_set(&err)) {
             LOG_AND_FREE_DBUS_ERROR(&err);
diff --git a/docs/html/guide/developing/eclipse-adt.jd b/docs/html/guide/developing/eclipse-adt.jd
index 9c77ece..d0fc9b8 100644
--- a/docs/html/guide/developing/eclipse-adt.jd
+++ b/docs/html/guide/developing/eclipse-adt.jd
@@ -21,6 +21,7 @@
         <li><a href="#librarySetup">Setting up a library project</a></li>
         <li><a href="#libraryReference">Referencing a library project</a></li>
         <li><a href="#considerations">Development considerations</a></li>
+        <li><a href="#libraryMigrating">Migrating library projects to ADT 0.9.8</a></li>
       </ol>
     </li>
     <li><a href="#Tips">Eclipse Tips</a></li>
@@ -644,10 +645,6 @@
 is because the library project is compiled by the main project to use the
 correct resource IDs.</p>
 
-<p><strong>One library project cannot reference another</strong></p>
-
-<p>A library cannot depend on another library.</p>
-
 <p><strong>A library project can include a JAR library</strong></p>
 
 <p>You can develop a library project that itself includes a JAR library, however
@@ -664,13 +661,6 @@
 href="{@docRoot}guide/topics/manifest/uses-library-element.html"><code>&lt;uses-library&gt;</code></a>
 element. </p>
 
-<p><strong>Library project can not include AIDL files</strong></p>
-
-<p>The tools do not support the use of <a
-href="{@docRoot}guide/developing/tools/aidl.html">AIDL</a> files in a library project.
-Any AIDL files used by an application must be stored in the application project
-itself.</p>
-
 <p><strong>Library project can not include raw assets</strong></p>
 
 <p>The tools do not support the use of raw asset files in a library project.
@@ -730,8 +720,76 @@
 library project What is important is that the main project can reference the
 library project through a relative link.</p>
 
+<h3 id="libraryMigrating">Migrating library projects to ADT 0.9.8</h3>
 
-<h2 id="Tips">Eclipse Tips </h2>
+<p>This section provides information about how to migrate a library project
+created with ADT 0.9.7 to ADT 0.9.8 (or higher). The migration is needed only if
+you are developing in Eclipse with ADT and assumes that you have also upgraded
+to SDK Tools r7 (or higher). </p>
+
+<p>The way that ADT handles library projects has changed between
+ADT 0.9.7 and ADT 0.9.8. Specifically, in ADT 0.9.7, the <code>src/</code>
+source folder of the library was linked into the dependent application project
+as a folder that had the same name as the library project. This worked because
+of two restrictions on the library projects:</p>
+
+<ul>
+<li>The library was only able to contain a single source folder (excluding the
+special <code>gen/</code> source folder), and</li>
+<li>The source folder was required to have the name <code>src/</code> and be
+stored at the root of the project.</li>
+</ul>
+
+<p>In ADT 0.9.8, both of those restrictions were removed. A library project can
+have as many source folders as needed and each can have any name. Additionally,
+a library project can store source folders in any location of the project. For
+example, you could store sources in a <code>src/java/</code> directory. In order
+to support this, the name of the linked source folders in the main project are
+now called &lt;<em>library-name</em>&gt;_&lt;<em>folder-name</em>&gt; For
+example: <code>MyLibrary_src/</code> or <code>MyLibrary_src_java/</code>.</p>
+
+<p>Additionally, the linking process now flags those folders in order for ADT to
+recognize that it created them. This will allow ADT to automatically migrate the
+project to new versions of ADT, should they contain changes to the handling of
+library projects. ADT 0.9.7 did not flag the linked source folders, so ADT 0.9.8
+cannot be sure whether the old linked folders can be removed safely. After
+upgrading ADT to 0.9.8, you will need to remove the old linked folders manually
+in a simple two-step process, as described below.</p>
+
+<p>Before you begin, make sure to create a backup copy of your application or
+save the latest version to your code version control system. This ensures that
+you will be able to easily revert the migration changes in case there is a
+problem in your environment.</p>
+
+<p>When you first upgrade to ADT 0.9.8, your main project will look as shown
+below, with two linked folders (in this example, <code>MyLibrary</code> and
+<code>MyLibrary_src</code> &mdash; both of which link to
+<code>MyLibrary/src</code>. Eclipse shows an error on one of them because they
+are duplicate links to a single class.</p>
+
+<img src="{@docRoot}images/developing/lib-migration-0.png" alt="">
+
+<p>To fix the error, remove the linked folder that <em>does not</em> contain the
+<code>_src</code> suffix. </p>
+
+<ol>
+<li>Right click the folder that you want to remove (in this case, the
+<code>MyLibrary</code> folder) and choose <strong>Build Path</strong> &gt;
+<strong>Remove from Build Path</strong>, as shown below.</li>
+
+<img src="{@docRoot}images/developing/lib-migration-1.png" style="height:600px"
+alt="">
+
+<li>Next, When asked about unlinking the folder from the project, select
+<strong>Yes</strong>, as shown below.</li>
+
+<img src="{@docRoot}images/developing/lib-migration-2.png" alt="">
+</ol>
+
+<p>This should resolve the error and migrate your library project to the new
+ADT environment. </p>
+
+<h2 id="Tips">Eclipse Tips</h2>
 
 <h3 id="arbitraryexpressions">Executing arbitrary Java expressions in Eclipse</h3>
 
diff --git a/docs/html/guide/developing/other-ide.jd b/docs/html/guide/developing/other-ide.jd
index 1d67aa9..ff13f43 100644
--- a/docs/html/guide/developing/other-ide.jd
+++ b/docs/html/guide/developing/other-ide.jd
@@ -838,10 +838,6 @@
 is because the library project is compiled by the main project to use the
 correct resource IDs.</p>
 
-<p><strong>One library project cannot reference another</strong></p>
-
-<p>A library cannot depend on another library.</p>
-
 <p><strong>A library project can include a JAR library</strong></p>
 
 <p>You can develop a library project that itself includes a JAR library. When
@@ -858,13 +854,6 @@
 href="{@docRoot}guide/topics/manifest/uses-library-element.html"><code>&lt;uses-library&gt;</code></a>
 element. </p>
 
-<p><strong>Library project cannot include AIDL files</strong></p>
-
-<p>The tools do not support the use of <a
-href="{@docRoot}guide/developing/tools/aidl.html">AIDL</a> files in a library project.
-Any AIDL files used by an application must be stored in the application project
-itself.</p>
-
 <p><strong>Library project cannot include raw assets</strong></p>
 
 <p>The tools do not support the use of raw asset files in a library project.
diff --git a/docs/html/images/developing/lib-migration-0.png b/docs/html/images/developing/lib-migration-0.png
new file mode 100644
index 0000000..226b0a5
--- /dev/null
+++ b/docs/html/images/developing/lib-migration-0.png
Binary files differ
diff --git a/docs/html/images/developing/lib-migration-1.png b/docs/html/images/developing/lib-migration-1.png
new file mode 100644
index 0000000..f413dab
--- /dev/null
+++ b/docs/html/images/developing/lib-migration-1.png
Binary files differ
diff --git a/docs/html/images/developing/lib-migration-2.png b/docs/html/images/developing/lib-migration-2.png
new file mode 100644
index 0000000..0aa5849
--- /dev/null
+++ b/docs/html/images/developing/lib-migration-2.png
Binary files differ
diff --git a/docs/html/sdk/adt_download.jd b/docs/html/sdk/adt_download.jd
index f98caf5..126c052 100644
--- a/docs/html/sdk/adt_download.jd
+++ b/docs/html/sdk/adt_download.jd
@@ -22,11 +22,18 @@
     <th>Notes</th>
   </tr>
   <tr>
-     <td>0.9.7</td>
-     <td><a href="http://dl-ssl.google.com/android/ADT-0.9.7.zip">ADT-0.9.7.zip</a></td>
+     <td>0.9.8</td>
+     <td><a href="http://dl-ssl.google.com/android/ADT-0.9.8.zip">ADT-0.9.8.zip</a></td>
      <td><nobr>{@adtZipBytes} bytes</nobr></td>
      <td>{@adtZipChecksum}</td>
-     <td>Requires SDK Tools, Revision 6 <em><nobr>May 2010</nobr></em></td>
+     <td>Requires SDK Tools, Revision 7 <em><nobr>September 2010</nobr></em></td>
+  </tr>
+  <tr>
+     <td>0.9.7</td>
+     <td><a href="http://dl-ssl.google.com/android/ADT-0.9.7.zip">ADT-0.9.7.zip</a></td>
+     <td><nobr>8033750 bytes</nobr></td>
+     <td>de2431c8d4786d127ae5bfc95b4605df</td>
+     <td>Requires SDK Tools, Revision 5 <em><nobr>May 2010</nobr></em></td>
   </tr>
   <tr>
      <td>0.9.6</td>
diff --git a/docs/html/sdk/eclipse-adt.jd b/docs/html/sdk/eclipse-adt.jd
index bd7eeed..4594bb5 100644
--- a/docs/html/sdk/eclipse-adt.jd
+++ b/docs/html/sdk/eclipse-adt.jd
@@ -95,8 +95,62 @@
 }
 </style>
 
+
+
+
 <div class="toggleable opened">
   <a href="#" onclick="return toggleDiv(this)">
+        <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
+ADT 0.9.8</a> <em>(September 2010)</em>
+  <div class="toggleme">
+
+
+</ul>
+</dd>
+
+<dl>
+
+<dt>Dependencies:</dt>
+
+<dd><p>ADT 0.9.8 is designed for use with SDK Tools r7 and later. Before 
+updating to ADT 0.9.8, we highly recommend that you use the Android SDK and
+AVD Manager to install SDK Tools r7 into your SDK.</p></dd>
+
+<dt>General notes:</dt>
+<dd>
+<ul>
+<li>Adds a new Action, "Rename Application Package", to the Android Tools
+contextual menu. The Action does a full application package refactoring.
+<li>Adds support for library projects that don't have a source folder
+called <code>src/</code>. There is now support for any number of source folders,
+with no name restriction. They can even be in subfolder such as
+<code>src/java</code>. If you are already working with library projects created
+in ADT 0.9.7, see <a 
+href="{@docRoot}guide/developing/eclipse-adt.html#libraryMigrating">Migrating
+library projects to ADT 0.9.8</a> for important information about moving
+to the new ADT environment.</li>
+<li>Adds support for library projects that depend on other library
+projects.</li>
+<li>Adds support for additional resource qualifiers:
+<code>car</code>/<code>desk</code>, <code>night</code>/<code>notnight</code> and
+<code>navexposed</code>/<code>navhidden</code>.</li>
+<li>Adds more device screen types in the layout editor. All screen
+resolution/density combinations listed in the <a 
+href="{@docRoot}guide/practices/screens_support.html#range">Supporting
+Multiple Screens</a> are now available.</li>
+<li>Fixes problems with handling of library project names that
+contain characters that are incompatible with the Eclipse path variable.
+Now properly sets up the link between the main project and the library
+project.</li>
+</ul>
+</dd>
+</dl>
+ </div>
+</div>
+
+
+<div class="toggleable closed">
+  <a href="#" onclick="return toggleDiv(this)">
         <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px" />
 ADT 0.9.7</a> <em>(May 2010)</em>
   <div class="toggleme">
@@ -120,6 +174,7 @@
  </div>
 </div>
 
+
 <div class="toggleable closed">
   <a href="#" onclick="return toggleDiv(this)">
         <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px" />
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 5e92253..7016eee 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -1,17 +1,17 @@
 page.title=Android SDK
 sdk.redirect=0
 
-sdk.win_download=android-sdk_r06-windows.zip
-sdk.win_bytes=23293160
-sdk.win_checksum=7c7fcec3c6b5c7c3df6ae654b27effb5
+sdk.win_download=android-sdk_r07-windows.zip
+sdk.win_bytes=23669664
+sdk.win_checksum=69c40c2d2e408b623156934f9ae574f0
 
-sdk.mac_download=android-sdk_r06-mac_86.zip
-sdk.mac_bytes=19108077
-sdk.mac_checksum=c92abf66a82c7a3f2b8493ebe025dd22
+sdk.mac_download=android-sdk_r07-mac_x86.zip
+sdk.mac_bytes=19229546
+sdk.mac_checksum=0f330ed3ebb36786faf6dc72b8acf819
 
-sdk.linux_download=android-sdk_r06-linux_86.tgz
-sdk.linux_bytes=16971139
-sdk.linux_checksum=848371e4bf068dbb582b709f4e56d903
+sdk.linux_download=android-sdk_r07-linux_x86.tgz
+sdk.linux_bytes=17114517
+sdk.linux_checksum=e10c75da3d1aa147ddd4a5c58bfc3646
 
 @jd:body
 
@@ -50,7 +50,7 @@
 <p><strong>4. Add Android platforms and other components to your SDK</strong></p>
 
 <p>Use the Android SDK and AVD Manager, included in the SDK starter package, to
-add one or more Android platforms (for example, Android 1.6 or Android 2.0) and
+add one or more Android platforms (for example, Android 1.6 or Android 2.2) and
 other components to your SDK. If you aren't sure what to add, see <a
 href="installing.html#which">Which components do I need?</a></p>
 
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 404e938..a665e95 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -75,8 +75,8 @@
       </li>
     </ul>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r6</a>
-      </li>
+      <li><a href="<?cs var:toroot ?>sdk/tools-notes.html">SDK Tools, r7</a>
+      <span class="new">new!</span></li>
       <li><a href="<?cs var:toroot ?>sdk/win-usb.html">USB Driver for
       Windows, r3</a>
       </li>
@@ -94,7 +94,7 @@
       <span style="display:none" class="zh-TW"></span>
       </h2>
     <ul>
-      <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 0.9.7
+      <li><a href="<?cs var:toroot ?>sdk/eclipse-adt.html">ADT 0.9.8
       <span style="display:none" class="de"></span>
       <span style="display:none" class="es"></span>
       <span style="display:none" class="fr"></span>
@@ -102,7 +102,7 @@
       <span style="display:none" class="ja"></span>
       <span style="display:none" class="zh-CN"></span>
       <span style="display:none" class="zh-TW"></span></a>
-      </li>
+      <span class="new">new!</span></li>
     </ul>
   </li>
   <li>
diff --git a/docs/html/sdk/tools-notes.jd b/docs/html/sdk/tools-notes.jd
index c9be6ff..0f075e5 100644
--- a/docs/html/sdk/tools-notes.jd
+++ b/docs/html/sdk/tools-notes.jd
@@ -64,6 +64,39 @@
 <div class="toggleable opened">
   <a href="#" onclick="return toggleDiv(this)">
         <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
+SDK Tools, Revision 7</a> <em>(September 2010)</em>
+  <div class="toggleme">
+
+<dl>
+<dt>Dependencies:</dt>
+<dd>
+<p>If you are developing in Eclipse with ADT, note that SDK Tools r7 is
+designed for use with ADT 0.9.8 and later. After installing SDK Tools r7, we
+highly recommend updating your ADT Plugin to 0.9.8.</p>
+</dd>
+
+<dt>General notes:</dt>
+<dd>
+<ul>
+<li>Added support for library projects that depend on other library projects.</li>
+<li>Adds support for aidl files in library projects.</li>
+<li>Adds support for extension targets in Ant build to perform tasks between the
+normal tasks: <code>-pre-build</code>, <code>-pre-compile</code>, and
+<code>-post-compile</code>.</li>
+<li>Adds support for "headless" SDK update. See <code>android -h update sdk</code>
+for more information.</li>
+<li>Fixes location control in DDMS to work in any locale not using '.' as a
+decimal point.</li>
+</li>
+</ul>
+</dd>
+</dl>
+ </div>
+</div>
+
+<div class="toggleable closed">
+  <a href="#" onclick="return toggleDiv(this)">
+        <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px" />
 SDK Tools, Revision 6</a> <em>(May 2010)</em>
   <div class="toggleme">
 
@@ -94,7 +127,7 @@
 
 <div class="toggleable closed">
   <a href="#" onclick="return toggleDiv(this)">
-        <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-img" height="9px" width="9px" />
+        <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px" width="9px" />
 SDK Tools, Revision 5</a> <em>(March 2010)</em>
   <div class="toggleme">
 
diff --git a/include/media/EffectEnvironmentalReverbApi.h b/include/media/EffectEnvironmentalReverbApi.h
index 2233e3f..36accd8 100644
--- a/include/media/EffectEnvironmentalReverbApi.h
+++ b/include/media/EffectEnvironmentalReverbApi.h
@@ -48,16 +48,16 @@
 
 //t_reverb_settings is equal to SLEnvironmentalReverbSettings defined in OpenSL ES specification.
 typedef struct s_reverb_settings {
-    int16_t roomLevel;
-    int16_t roomHFLevel;
-    int32_t decayTime;
-    int16_t decayHFRatio;
-    int16_t reflectionsLevel;
-    int32_t reflectionsDelay;
-    int16_t reverbLevel;
-    int32_t reverbDelay;
-    int16_t diffusion;
-    int16_t density;
+    int16_t     roomLevel;
+    int16_t     roomHFLevel;
+    uint32_t    decayTime;
+    int16_t     decayHFRatio;
+    int16_t     reflectionsLevel;
+    uint32_t    reflectionsDelay;
+    int16_t     reverbLevel;
+    uint32_t    reverbDelay;
+    int16_t     diffusion;
+    int16_t     density;
 } __attribute__((packed)) t_reverb_settings;
 
 
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 1e447f1..1594e31 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -49,6 +49,7 @@
     kKeyNTPTime           = 'ntpT',  // uint64_t (ntp-timestamp)
     kKeyTargetTime        = 'tarT',  // int64_t (usecs)
     kKeyDriftTime         = 'dftT',  // int64_t (usecs)
+    kKeyAnchorTime        = 'ancT',  // int64_t (usecs)
     kKeyDuration          = 'dura',  // int64_t (usecs)
     kKeyColorFormat       = 'colf',
     kKeyPlatformPrivate   = 'priv',  // pointer
diff --git a/keystore/java/android/security/SystemKeyStore.java b/keystore/java/android/security/SystemKeyStore.java
index abdb0ae..1093219 100644
--- a/keystore/java/android/security/SystemKeyStore.java
+++ b/keystore/java/android/security/SystemKeyStore.java
@@ -20,6 +20,8 @@
 import android.os.FileUtils;
 import android.os.Process;
 
+import org.apache.harmony.luni.util.InputStreamHelper;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -108,26 +110,19 @@
         return keyFile;
     }
 
-    public String retrieveKeyHexString(String keyName) {
+    public String retrieveKeyHexString(String keyName) throws IOException {
         return toHexString(retrieveKey(keyName));
     }
 
-    public byte[] retrieveKey(String keyName) {
-
+    public byte[] retrieveKey(String keyName) throws IOException {
         File keyFile = getKeyFile(keyName);
+
         if (!keyFile.exists()) {
             return null;
         }
 
-        try {
-            FileInputStream fis = new FileInputStream(keyFile);
-            int keyLen = fis.available();
-            byte[] retKey = new byte[keyLen];
-            fis.read(retKey);
-            fis.close();
-            return retKey;
-        } catch (IOException ioe) { }
-        throw new IllegalArgumentException();
+        FileInputStream fis = new FileInputStream(keyFile);
+        return InputStreamHelper.readFullyAndClose(fis);
     }
 
     public void deleteKey(String keyName) {
diff --git a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
index 45ef416..b3e1531 100755
--- a/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
+++ b/media/libeffects/lvm/wrapper/Reverb/EffectReverb.cpp
@@ -1133,7 +1133,7 @@
     //LOGV("\tReverbSetDecayTime() just Got -> %d\n", ActiveParams.T60);
 
     if (time <= LVREV_MAX_T60) {
-        ActiveParams.T60 = time;
+        ActiveParams.T60 = (LVM_UINT16)time;
     }
     else {
         ActiveParams.T60 = LVREV_MAX_T60;
@@ -1146,7 +1146,7 @@
 
     pContext->SamplesToExitCount = (ActiveParams.T60 * pContext->config.inputCfg.samplingRate)/1000;
     //LOGV("\tReverbSetDecayTime() just Set SamplesToExitCount-> %d\n",pContext->SamplesToExitCount);
-    pContext->SavedDecayTime = time;
+    pContext->SavedDecayTime = (int16_t)time;
     //LOGV("\tReverbSetDecayTime end");
     return;
 }
@@ -1162,7 +1162,7 @@
 //
 //----------------------------------------------------------------------------
 
-int32_t ReverbGetDecayTime(ReverbContext *pContext){
+uint32_t ReverbGetDecayTime(ReverbContext *pContext){
     //LOGV("\tReverbGetDecayTime start");
 
     LVREV_ControlParams_st    ActiveParams;              /* Current control Parameters */
@@ -1181,7 +1181,7 @@
     }
 
     //LOGV("\tReverbGetDecayTime end");
-    return ActiveParams.T60;
+    return (uint32_t)ActiveParams.T60;
 }
 
 //----------------------------------------------------------------------------
@@ -1606,7 +1606,7 @@
             //        *(int16_t *)pValue);
             break;
         case REVERB_PARAM_DECAY_TIME:
-            *(int32_t *)pValue = ReverbGetDecayTime(pContext);
+            *(uint32_t *)pValue = ReverbGetDecayTime(pContext);
 
             //LOGV("\tReverb_getParameter() REVERB_PARAM_DECAY_TIME Value is %d",
             //        *(int32_t *)pValue);
@@ -1671,6 +1671,7 @@
 int Reverb_setParameter (ReverbContext *pContext, void *pParam, void *pValue){
     int status = 0;
     int16_t level;
+    int16_t ratio;
     uint32_t time;
     t_reverb_settings *pProperties;
     int32_t *pParamTemp = (int32_t *)pParam;
@@ -1688,6 +1689,7 @@
             return -EINVAL;
         }
         pContext->nextPreset = preset;
+        return 0;
     }
 
     switch (param){
@@ -1724,10 +1726,10 @@
             //LOGV("\tReverb_setParameter() Called ReverbSetDecayTime");
            break;
         case REVERB_PARAM_DECAY_HF_RATIO:
-            time = *(int16_t *)pValue;
-            //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_HF_RATIO value is %d", time);
+            ratio = *(int16_t *)pValue;
+            //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_HF_RATIO value is %d", ratio);
             //LOGV("\tReverb_setParameter() Calling ReverbSetDecayHfRatio");
-            ReverbSetDecayHfRatio(pContext, time);
+            ReverbSetDecayHfRatio(pContext, ratio);
             //LOGV("\tReverb_setParameter() Called ReverbSetDecayHfRatio");
             break;
          case REVERB_PARAM_REVERB_LEVEL:
@@ -1738,17 +1740,17 @@
             //LOGV("\tReverb_setParameter() Called ReverbSetReverbLevel");
            break;
         case REVERB_PARAM_DIFFUSION:
-            time = *(int16_t *)pValue;
-            //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DIFFUSION value is %d", time);
+            ratio = *(int16_t *)pValue;
+            //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DIFFUSION value is %d", ratio);
             //LOGV("\tReverb_setParameter() Calling ReverbSetDiffusion");
-            ReverbSetDiffusion(pContext, time);
+            ReverbSetDiffusion(pContext, ratio);
             //LOGV("\tReverb_setParameter() Called ReverbSetDiffusion");
             break;
         case REVERB_PARAM_DENSITY:
-            time = *(int16_t *)pValue;
-            //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DENSITY value is %d", time);
+            ratio = *(int16_t *)pValue;
+            //LOGV("\tReverb_setParameter() REVERB_PARAM_DECAY_DENSITY value is %d", ratio);
             //LOGV("\tReverb_setParameter() Calling ReverbSetDensity");
-            ReverbSetDensity(pContext, time);
+            ReverbSetDensity(pContext, ratio);
             //LOGV("\tReverb_setParameter() Called ReverbSetDensity");
             break;
            break;
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index c2f79e8..8d7ada3 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -316,8 +316,10 @@
         }
 
         if (numFramesRecorded == 0) {
-            buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs);
+            buffer->meta_data()->setInt64(kKeyAnchorTime, mStartTimeUs);
         }
+
+        buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs + mPrevSampleTimeUs);
         buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
         CHECK(timestampUs > mPrevSampleTimeUs);
         mPrevSampleTimeUs = timestampUs;
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 2e36968..82c0426 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -459,7 +459,8 @@
 
 MP3Extractor::MP3Extractor(
         const sp<DataSource> &source, const sp<AMessage> &meta)
-    : mDataSource(source),
+    : mInitCheck(NO_INIT),
+      mDataSource(source),
       mFirstFramePos(-1),
       mFixedHeader(0),
       mByteNumber(0) {
@@ -480,53 +481,54 @@
         success = true;
     } else {
         success = Resync(mDataSource, 0, &pos, &header);
-        CHECK(success);
     }
 
-    if (success) {
-        mFirstFramePos = pos;
-        mFixedHeader = header;
+    if (!success) {
+        // mInitCheck will remain NO_INIT
+        return;
+    }
 
-        size_t frame_size;
-        int sample_rate;
-        int num_channels;
-        int bitrate;
-        get_mp3_frame_size(
-                header, &frame_size, &sample_rate, &num_channels, &bitrate);
+    mFirstFramePos = pos;
+    mFixedHeader = header;
 
-        mMeta = new MetaData;
+    size_t frame_size;
+    int sample_rate;
+    int num_channels;
+    int bitrate;
+    get_mp3_frame_size(
+            header, &frame_size, &sample_rate, &num_channels, &bitrate);
 
-        mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
-        mMeta->setInt32(kKeySampleRate, sample_rate);
-        mMeta->setInt32(kKeyBitRate, bitrate * 1000);
-        mMeta->setInt32(kKeyChannelCount, num_channels);
+    mMeta = new MetaData;
 
-        int64_t duration;
-        parse_xing_header(
-                mDataSource, mFirstFramePos, NULL, &mByteNumber,
-                mTableOfContents, NULL, &duration);
-        if (duration > 0) {
-            mMeta->setInt64(kKeyDuration, duration);
-        } else {
-            off_t fileSize;
-            if (mDataSource->getSize(&fileSize) == OK) {
-                mMeta->setInt64(
-                        kKeyDuration,
-                        8000LL * (fileSize - mFirstFramePos) / bitrate);
-            }
+    mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
+    mMeta->setInt32(kKeySampleRate, sample_rate);
+    mMeta->setInt32(kKeyBitRate, bitrate * 1000);
+    mMeta->setInt32(kKeyChannelCount, num_channels);
+
+    int64_t duration;
+    parse_xing_header(
+            mDataSource, mFirstFramePos, NULL, &mByteNumber,
+            mTableOfContents, NULL, &duration);
+    if (duration > 0) {
+        mMeta->setInt64(kKeyDuration, duration);
+    } else {
+        off_t fileSize;
+        if (mDataSource->getSize(&fileSize) == OK) {
+            mMeta->setInt64(
+                    kKeyDuration,
+                    8000LL * (fileSize - mFirstFramePos) / bitrate);
         }
     }
-}
 
-MP3Extractor::~MP3Extractor() {
+    mInitCheck = OK;
 }
 
 size_t MP3Extractor::countTracks() {
-    return (mFirstFramePos < 0) ? 0 : 1;
+    return mInitCheck != OK ? 0 : 1;
 }
 
 sp<MediaSource> MP3Extractor::getTrack(size_t index) {
-    if (mFirstFramePos < 0 || index != 0) {
+    if (mInitCheck != OK || index != 0) {
         return NULL;
     }
 
@@ -536,7 +538,7 @@
 }
 
 sp<MetaData> MP3Extractor::getTrackMetaData(size_t index, uint32_t flags) {
-    if (mFirstFramePos < 0 || index != 0) {
+    if (mInitCheck != OK || index != 0) {
         return NULL;
     }
 
@@ -713,7 +715,7 @@
 sp<MetaData> MP3Extractor::getMetaData() {
     sp<MetaData> meta = new MetaData;
 
-    if (mFirstFramePos < 0) {
+    if (mInitCheck != OK) {
         return meta;
     }
 
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index ba90407..4bbc251 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -872,7 +872,11 @@
             }
 
             size_t max_size;
-            CHECK_EQ(mLastTrack->sampleTable->getMaxSampleSize(&max_size), OK);
+            err = mLastTrack->sampleTable->getMaxSampleSize(&max_size);
+
+            if (err != OK) {
+                return err;
+            }
 
             // Assume that a given buffer only contains at most 10 fragments,
             // each fragment originally prefixed with a 2 byte length will
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 806836d..de4233d 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -346,9 +346,10 @@
         // If file size is set to be larger than the 32 bit file
         // size limit, treat it as an error.
         if (mMaxFileSizeLimitBytes > kMax32BitFileSize) {
-            LOGE("32-bit file size limit too big: %lld bytes",
-                mMaxFileSizeLimitBytes);
-            return UNKNOWN_ERROR;
+            LOGW("32-bi file size limit (%lld bytes) too big. "
+                 "It is changed to %lld bytes",
+                mMaxFileSizeLimitBytes, kMax32BitFileSize);
+            mMaxFileSizeLimitBytes = kMax32BitFileSize;
         }
     }
 
diff --git a/media/libstagefright/TimedEventQueue.cpp b/media/libstagefright/TimedEventQueue.cpp
index 0dacb53..5a453e9 100644
--- a/media/libstagefright/TimedEventQueue.cpp
+++ b/media/libstagefright/TimedEventQueue.cpp
@@ -26,6 +26,8 @@
 
 #include "include/TimedEventQueue.h"
 
+#include <cutils/sched_policy.h>
+
 #include <sys/prctl.h>
 #include <sys/time.h>
 #include <sys/resource.h>
@@ -209,6 +211,8 @@
 #endif
 
     setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_FOREGROUND);
+    set_sched_policy(androidGetTid(), SP_FOREGROUND);
+
     static_cast<TimedEventQueue *>(me)->threadEntry();
 
 #ifdef ANDROID_SIMULATOR
diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
index e391c72..df9f107 100644
--- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp
+++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp
@@ -243,7 +243,7 @@
             if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
                 wallClockTimeUs = timeUs;
             }
-            if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+            if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
                 mAnchorTimeUs = timeUs;
             }
             readFromSource = true;
diff --git a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
index 858e6d0..94a79ab 100644
--- a/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
+++ b/media/libstagefright/codecs/amrnb/enc/AMRNBEncoder.cpp
@@ -174,7 +174,7 @@
             if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
                 wallClockTimeUs = timeUs;
             }
-            if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+            if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
                 mAnchorTimeUs = timeUs;
             }
         } else {
diff --git a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
index cd28413..002f055 100644
--- a/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
+++ b/media/libstagefright/codecs/amrwbenc/AMRWBEncoder.cpp
@@ -224,7 +224,7 @@
             if (mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs)) {
                 wallClockTimeUs = timeUs;
             }
-            if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
+            if (mInputBuffer->meta_data()->findInt64(kKeyAnchorTime, &timeUs)) {
                 mAnchorTimeUs = timeUs;
             }
             readFromSource = true;
diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
index 0e6ccde..30136e7d 100644
--- a/media/libstagefright/include/MP3Extractor.h
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -37,10 +37,9 @@
 
     virtual sp<MetaData> getMetaData();
 
-protected:
-    virtual ~MP3Extractor();
-
 private:
+    status_t mInitCheck;
+
     sp<DataSource> mDataSource;
     off_t mFirstFramePos;
     sp<MetaData> mMeta;
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 5e61607..df21358d 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -239,7 +239,7 @@
         memset(images, 0, sizeof(images));
     }
     EGLDisplay dpy;
-    EGLConfig context;
+    EGLContext context;
     EGLImageKHR images[IMPL_NUM_IMPLEMENTATIONS];
 };
 
@@ -1769,7 +1769,7 @@
          egl_connection_t* const cnx = &gEGLImpl[i];
          if (image->images[i] != EGL_NO_IMAGE_KHR) {
              if (cnx->dso) {
-                 if (cnx->egl.eglCreateImageKHR) {
+                 if (cnx->egl.eglDestroyImageKHR) {
                      if (cnx->egl.eglDestroyImageKHR(
                              dp->disp[i].dpy, image->images[i])) {
                          success = true;
diff --git a/opengl/tests/angeles/app-linux.cpp b/opengl/tests/angeles/app-linux.cpp
index 06fa0c2..4d10ee5 100644
--- a/opengl/tests/angeles/app-linux.cpp
+++ b/opengl/tests/angeles/app-linux.cpp
@@ -63,7 +63,7 @@
 int gAppAlive = 1;
 
 static const char sAppName[] =
-    "San Angeles Observation OpenGL ES version example (Linux)";
+        "San Angeles Observation OpenGL ES version example (Linux)";
 
 static int sWindowWidth = WINDOW_DEFAULT_WIDTH;
 static int sWindowHeight = WINDOW_DEFAULT_HEIGHT;
@@ -74,22 +74,22 @@
 const char *egl_strerror(unsigned err)
 {
     switch(err){
-    case EGL_SUCCESS: return "SUCCESS";
-    case EGL_NOT_INITIALIZED: return "NOT INITIALIZED";
-    case EGL_BAD_ACCESS: return "BAD ACCESS";
-    case EGL_BAD_ALLOC: return "BAD ALLOC";
-    case EGL_BAD_ATTRIBUTE: return "BAD_ATTRIBUTE";
-    case EGL_BAD_CONFIG: return "BAD CONFIG";
-    case EGL_BAD_CONTEXT: return "BAD CONTEXT";
-    case EGL_BAD_CURRENT_SURFACE: return "BAD CURRENT SURFACE";
-    case EGL_BAD_DISPLAY: return "BAD DISPLAY";
-    case EGL_BAD_MATCH: return "BAD MATCH";
-    case EGL_BAD_NATIVE_PIXMAP: return "BAD NATIVE PIXMAP";
-    case EGL_BAD_NATIVE_WINDOW: return "BAD NATIVE WINDOW";
-    case EGL_BAD_PARAMETER: return "BAD PARAMETER";
-    case EGL_BAD_SURFACE: return "BAD_SURFACE";
-//    case EGL_CONTEXT_LOST: return "CONTEXT LOST";
-    default: return "UNKNOWN";
+        case EGL_SUCCESS: return "SUCCESS";
+        case EGL_NOT_INITIALIZED: return "NOT INITIALIZED";
+        case EGL_BAD_ACCESS: return "BAD ACCESS";
+        case EGL_BAD_ALLOC: return "BAD ALLOC";
+        case EGL_BAD_ATTRIBUTE: return "BAD_ATTRIBUTE";
+        case EGL_BAD_CONFIG: return "BAD CONFIG";
+        case EGL_BAD_CONTEXT: return "BAD CONTEXT";
+        case EGL_BAD_CURRENT_SURFACE: return "BAD CURRENT SURFACE";
+        case EGL_BAD_DISPLAY: return "BAD DISPLAY";
+        case EGL_BAD_MATCH: return "BAD MATCH";
+        case EGL_BAD_NATIVE_PIXMAP: return "BAD NATIVE PIXMAP";
+        case EGL_BAD_NATIVE_WINDOW: return "BAD NATIVE WINDOW";
+        case EGL_BAD_PARAMETER: return "BAD PARAMETER";
+        case EGL_BAD_SURFACE: return "BAD_SURFACE";
+        //    case EGL_CONTEXT_LOST: return "CONTEXT LOST";
+        default: return "UNKNOWN";
     }
 }
 
@@ -118,52 +118,59 @@
         fprintf(stderr, "EGL Error: 0x%04x\n", (int)error);
 }
 
-static int initGraphics()
+static int initGraphics(unsigned samples)
 {
     EGLint configAttribs[] = {
-         EGL_DEPTH_SIZE, 16,
-         EGL_NONE
-     };
-     
-     EGLint majorVersion;
-     EGLint minorVersion;
-     EGLContext context;
-     EGLConfig config;
-     EGLSurface surface;
-     EGLint w, h;
-     EGLDisplay dpy;
+            EGL_DEPTH_SIZE, 16,
+            EGL_SAMPLE_BUFFERS, samples ? 1 : 0,
+                    EGL_SAMPLES, samples,
+                    EGL_NONE
+    };
 
-     EGLNativeWindowType window = android_createDisplaySurface();
-     
-     dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-     eglInitialize(dpy, &majorVersion, &minorVersion);
-          
-     status_t err = EGLUtils::selectConfigForNativeWindow(
-             dpy, configAttribs, window, &config);
-     if (err) {
-         fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
-         return 0;
-     }
+    EGLint majorVersion;
+    EGLint minorVersion;
+    EGLContext context;
+    EGLConfig config;
+    EGLSurface surface;
+    EGLint w, h;
+    EGLDisplay dpy;
 
-     surface = eglCreateWindowSurface(dpy, config, window, NULL);
-     egl_error("eglCreateWindowSurface");
+    EGLNativeWindowType window = android_createDisplaySurface();
 
-     fprintf(stderr,"surface = %p\n", surface);
+    dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    eglInitialize(dpy, &majorVersion, &minorVersion);
 
-     context = eglCreateContext(dpy, config, NULL, NULL);
-     egl_error("eglCreateContext");
-     fprintf(stderr,"context = %p\n", context);
-     
-     eglMakeCurrent(dpy, surface, surface, context);   
-     egl_error("eglMakeCurrent");
+    status_t err = EGLUtils::selectConfigForNativeWindow(
+            dpy, configAttribs, window, &config);
+    if (err) {
+        fprintf(stderr, "couldn't find an EGLConfig matching the screen format\n");
+        return 0;
+    }
 
-     eglQuerySurface(dpy, surface, EGL_WIDTH, &sWindowWidth);
-     eglQuerySurface(dpy, surface, EGL_HEIGHT, &sWindowHeight);
+    surface = eglCreateWindowSurface(dpy, config, window, NULL);
+    egl_error("eglCreateWindowSurface");
+
+    fprintf(stderr,"surface = %p\n", surface);
+
+    context = eglCreateContext(dpy, config, NULL, NULL);
+    egl_error("eglCreateContext");
+    fprintf(stderr,"context = %p\n", context);
+
+    eglMakeCurrent(dpy, surface, surface, context);
+    egl_error("eglMakeCurrent");
+
+    eglQuerySurface(dpy, surface, EGL_WIDTH, &sWindowWidth);
+    eglQuerySurface(dpy, surface, EGL_HEIGHT, &sWindowHeight);
 
     sEglDisplay = dpy;
     sEglSurface = surface;
     sEglContext = context;
 
+    if (samples == 0) {
+        // GL_MULTISAMPLE is enabled by default
+        glDisable(GL_MULTISAMPLE);
+    }
+
     return EGL_TRUE;
 }
 
@@ -179,35 +186,47 @@
 
 int main(int argc, char *argv[])
 {
-    // not referenced:
-    argc = argc;
-    argv = argv;
+    unsigned samples = 0;
+    printf("usage: %s [samples]\n", argv[0]);
+    if (argc == 2) {
+        samples = atoi( argv[1] );
+        printf("Multisample enabled: GL_SAMPLES = %u\n", samples);
+    }
 
-    if (!initGraphics())
+    if (!initGraphics(samples))
     {
         fprintf(stderr, "Graphics initialization failed.\n");
         return EXIT_FAILURE;
     }
 
     appInit();
-    
+
+    struct timeval timeTemp;
+    int frameCount = 0;
+    gettimeofday(&timeTemp, NULL);
+    double totalTime = timeTemp.tv_usec/1000000.0 + timeTemp.tv_sec;
+
     while (gAppAlive)
     {
         struct timeval timeNow;
 
-        if (gAppAlive)
-        {
-            gettimeofday(&timeNow, NULL);
-            appRender(timeNow.tv_sec * 1000 + timeNow.tv_usec / 1000,
-                      sWindowWidth, sWindowHeight);
-            checkGLErrors();
-            eglSwapBuffers(sEglDisplay, sEglSurface);
-            checkEGLErrors();
-        }
+        gettimeofday(&timeNow, NULL);
+        appRender(timeNow.tv_sec * 1000 + timeNow.tv_usec / 1000,
+                sWindowWidth, sWindowHeight);
+        checkGLErrors();
+        eglSwapBuffers(sEglDisplay, sEglSurface);
+        checkEGLErrors();
+        frameCount++;
     }
 
+    gettimeofday(&timeTemp, NULL);
+
     appDeinit();
     deinitGraphics();
 
+    totalTime = (timeTemp.tv_usec/1000000.0 + timeTemp.tv_sec) - totalTime;
+    printf("totalTime=%f s, frameCount=%d, %.2f fps\n",
+            totalTime, frameCount, frameCount/totalTime);
+
     return EXIT_SUCCESS;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
index e828f68..c5688e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
@@ -36,6 +36,7 @@
 import android.media.AudioManager;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
+import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.Uri;
 import android.net.wifi.WifiManager;
@@ -91,6 +92,8 @@
 
     private static final int AM_PM_STYLE = AM_PM_STYLE_GONE;
 
+    private static final int INET_CONDITION_THRESHOLD = 50;
+
     private final Context mContext;
     private final StatusBarManager mService;
     private final Handler mHandler = new StatusBarHandler();
@@ -232,42 +235,62 @@
     };
 
     //***** Data connection icons
-    private int[] mDataIconList = sDataNetType_g;
+    private int[] mDataIconList = sDataNetType_g[0];
     //GSM/UMTS
-    private static final int[] sDataNetType_g = new int[] {
-            R.drawable.stat_sys_data_connected_g,
-            R.drawable.stat_sys_data_in_g,
-            R.drawable.stat_sys_data_out_g,
-            R.drawable.stat_sys_data_inandout_g,
+    private static final int[][] sDataNetType_g = {
+            { R.drawable.stat_sys_data_connected_g,
+              R.drawable.stat_sys_data_in_g,
+              R.drawable.stat_sys_data_out_g,
+              R.drawable.stat_sys_data_inandout_g },
+            { R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0 }
         };
-    private static final int[] sDataNetType_3g = new int[] {
-            R.drawable.stat_sys_data_connected_3g,
-            R.drawable.stat_sys_data_in_3g,
-            R.drawable.stat_sys_data_out_3g,
-            R.drawable.stat_sys_data_inandout_3g,
+    private static final int[][] sDataNetType_3g = {
+            { R.drawable.stat_sys_data_connected_3g,
+              R.drawable.stat_sys_data_in_3g,
+              R.drawable.stat_sys_data_out_3g,
+              R.drawable.stat_sys_data_inandout_3g },
+            { R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0 }
         };
-    private static final int[] sDataNetType_e = new int[] {
-            R.drawable.stat_sys_data_connected_e,
-            R.drawable.stat_sys_data_in_e,
-            R.drawable.stat_sys_data_out_e,
-            R.drawable.stat_sys_data_inandout_e,
+    private static final int[][] sDataNetType_e = {
+            { R.drawable.stat_sys_data_connected_e,
+              R.drawable.stat_sys_data_in_e,
+              R.drawable.stat_sys_data_out_e,
+              R.drawable.stat_sys_data_inandout_e },
+            { R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0 }
         };
     //3.5G
-    private static final int[] sDataNetType_h = new int[] {
-            R.drawable.stat_sys_data_connected_h,
-            R.drawable.stat_sys_data_in_h,
-            R.drawable.stat_sys_data_out_h,
-            R.drawable.stat_sys_data_inandout_h,
+    private static final int[][] sDataNetType_h = {
+            { R.drawable.stat_sys_data_connected_h,
+              R.drawable.stat_sys_data_in_h,
+              R.drawable.stat_sys_data_out_h,
+              R.drawable.stat_sys_data_inandout_h },
+            { R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0 }
     };
 
     //CDMA
     // Use 3G icons for EVDO data and 1x icons for 1XRTT data
-    private static final int[] sDataNetType_1x = new int[] {
-        R.drawable.stat_sys_data_connected_1x,
-        R.drawable.stat_sys_data_in_1x,
-        R.drawable.stat_sys_data_out_1x,
-        R.drawable.stat_sys_data_inandout_1x,
-    };
+    private static final int[][] sDataNetType_1x = {
+            { R.drawable.stat_sys_data_connected_1x,
+              R.drawable.stat_sys_data_in_1x,
+              R.drawable.stat_sys_data_out_1x,
+              R.drawable.stat_sys_data_inandout_1x },
+            { R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0,
+              R.drawable.stat_sys_roaming_cdma_0 }
+            };
 
     // Assume it's all good unless we hear otherwise.  We don't always seem
     // to get broadcasts that it *is* there.
@@ -292,17 +315,22 @@
     private boolean mBluetoothEnabled;
 
     // wifi
-    private static final int[] sWifiSignalImages = new int[] {
-            R.drawable.stat_sys_wifi_signal_1,
-            R.drawable.stat_sys_wifi_signal_2,
-            R.drawable.stat_sys_wifi_signal_3,
-            R.drawable.stat_sys_wifi_signal_4,
+    private static final int[][] sWifiSignalImages = {
+            { R.drawable.stat_sys_wifi_signal_1,
+              R.drawable.stat_sys_wifi_signal_2,
+              R.drawable.stat_sys_wifi_signal_3,
+              R.drawable.stat_sys_wifi_signal_4 },
+            { R.drawable.stat_sys_data_in_e,
+              R.drawable.stat_sys_data_in_e,
+              R.drawable.stat_sys_data_in_e,
+              R.drawable.stat_sys_data_in_e }
         };
     private static final int sWifiTemporarilyNotConnectedImage =
             R.drawable.stat_sys_wifi_signal_0;
 
     private int mLastWifiSignalLevel = -1;
     private boolean mIsWifiConnected = false;
+    private int mLastWifiInetConnectivityState = 0;
 
     // sync state
     // If sync is active the SyncActive icon is displayed. If sync is not active but
@@ -353,6 +381,10 @@
             else if (action.equals(TtyIntent.TTY_ENABLED_CHANGE_ACTION)) {
                 updateTTY(intent);
             }
+            else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+                // TODO - stop using other means to get wifi/mobile info
+                updateConnectivity(intent);
+            }
         }
     };
 
@@ -389,7 +421,7 @@
         mService.setIconVisibility("data_connection", false);
 
         // wifi
-        mService.setIcon("wifi", sWifiSignalImages[0], 0);
+        mService.setIcon("wifi", sWifiSignalImages[0][0], 0);
         mService.setIconVisibility("wifi", false);
         // wifi will get updated by the sticky intents
 
@@ -456,6 +488,7 @@
         filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION);
         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         filter.addAction(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
+        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
         mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
 
         // load config to determine if to distinguish Hspa data icon
@@ -659,6 +692,50 @@
         }
     }
 
+    private void updateConnectivity(Intent intent) {
+        NetworkInfo info = (NetworkInfo)(intent.getParcelableExtra(
+                ConnectivityManager.EXTRA_NETWORK_INFO));
+        int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
+        Slog.d(TAG, "got CONNECTIVITY_ACTION - info=" + info + ", status = " + connectionStatus);
+        if (info.isConnected() == false) return;
+
+        switch (info.getType()) {
+        case ConnectivityManager.TYPE_MOBILE:
+            if (info.isConnected()) {
+                updateDataNetType(info.getSubtype(), connectionStatus);
+                updateDataIcon();
+            }
+            break;
+        case ConnectivityManager.TYPE_WIFI:
+            if (info.isConnected()) {
+                mIsWifiConnected = true;
+                mLastWifiInetConnectivityState =
+                        (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
+                int iconId;
+                if (mLastWifiSignalLevel == -1) {
+                    iconId = sWifiSignalImages[mLastWifiInetConnectivityState][0];
+                } else {
+                    iconId = sWifiSignalImages[mLastWifiInetConnectivityState]
+                            [mLastWifiSignalLevel];
+                }
+
+                mService.setIcon("wifi", iconId, 0);
+                // Show the icon since wi-fi is connected
+                mService.setIconVisibility("wifi", true);
+            } else {
+                mLastWifiSignalLevel = -1;
+                mIsWifiConnected = false;
+                mLastWifiInetConnectivityState = 0;
+                int iconId = sWifiSignalImages[0][0];
+
+                mService.setIcon("wifi", iconId, 0);
+                // Hide the icon since we're not connected
+                mService.setIconVisibility("wifi", false);
+            }
+            break;
+        }
+    }
+
     private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
         @Override
         public void onSignalStrengthsChanged(SignalStrength signalStrength) {
@@ -686,7 +763,7 @@
         @Override
         public void onDataConnectionStateChanged(int state, int networkType) {
             mDataState = state;
-            updateDataNetType(networkType);
+            updateDataNetType(networkType, 0);
             updateDataIcon();
         }
 
@@ -848,37 +925,38 @@
         return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
     }
 
-    private final void updateDataNetType(int net) {
+    private final void updateDataNetType(int net, int inetCondition) {
+        int connected = (inetCondition > INET_CONDITION_THRESHOLD ? 1 : 0);
         switch (net) {
         case TelephonyManager.NETWORK_TYPE_EDGE:
-            mDataIconList = sDataNetType_e;
+            mDataIconList = sDataNetType_e[connected];
             break;
         case TelephonyManager.NETWORK_TYPE_UMTS:
-            mDataIconList = sDataNetType_3g;
+            mDataIconList = sDataNetType_3g[connected];
             break;
         case TelephonyManager.NETWORK_TYPE_HSDPA:
         case TelephonyManager.NETWORK_TYPE_HSUPA:
         case TelephonyManager.NETWORK_TYPE_HSPA:
             if (mHspaDataDistinguishable) {
-                mDataIconList = sDataNetType_h;
+                mDataIconList = sDataNetType_h[connected];
             } else {
-                mDataIconList = sDataNetType_3g;
+                mDataIconList = sDataNetType_3g[connected];
             }
             break;
         case TelephonyManager.NETWORK_TYPE_CDMA:
             // display 1xRTT for IS95A/B
-            mDataIconList = this.sDataNetType_1x;
+            mDataIconList = sDataNetType_1x[connected];
             break;
         case TelephonyManager.NETWORK_TYPE_1xRTT:
-            mDataIconList = this.sDataNetType_1x;
+            mDataIconList = sDataNetType_1x[connected];
             break;
         case TelephonyManager.NETWORK_TYPE_EVDO_0: //fall through
         case TelephonyManager.NETWORK_TYPE_EVDO_A:
         case TelephonyManager.NETWORK_TYPE_EVDO_B:
-            mDataIconList = sDataNetType_3g;
+            mDataIconList = sDataNetType_3g[connected];
             break;
         default:
-            mDataIconList = sDataNetType_g;
+            mDataIconList = sDataNetType_g[connected];
         break;
         }
     }
@@ -1019,34 +1097,6 @@
             if (!enabled) {
                 mService.setIconVisibility("wifi", false);
             }
-        } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
-
-            final NetworkInfo networkInfo = (NetworkInfo)
-                    intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
-
-            int iconId;
-            if (networkInfo != null && networkInfo.isConnected()) {
-                mIsWifiConnected = true;
-                if (mLastWifiSignalLevel == -1) {
-                    iconId = sWifiSignalImages[0];
-                } else {
-                    iconId = sWifiSignalImages[mLastWifiSignalLevel];
-                }
-
-                mService.setIcon("wifi", iconId, 0);
-                // Show the icon since wi-fi is connected
-                mService.setIconVisibility("wifi", true);
-
-            } else {
-                mLastWifiSignalLevel = -1;
-                mIsWifiConnected = false;
-                iconId = sWifiSignalImages[0];
-
-                mService.setIcon("wifi", iconId, 0);
-                // Hide the icon since we're not connected
-                mService.setIconVisibility("wifi", false);
-            }
-
         } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
             int iconId;
             final int newRssi = intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200);
@@ -1055,7 +1105,7 @@
             if (newSignalLevel != mLastWifiSignalLevel) {
                 mLastWifiSignalLevel = newSignalLevel;
                 if (mIsWifiConnected) {
-                    iconId = sWifiSignalImages[newSignalLevel];
+                    iconId = sWifiSignalImages[mLastWifiInetConnectivityState][newSignalLevel];
                 } else {
                     iconId = sWifiTemporarilyNotConnectedImage;
                 }
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 3db5dc1..e454c08 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -668,7 +668,7 @@
                     while (true) {
                         String packageName = in.readUTF();
                         Slog.i(TAG, "    + " + packageName);
-                        dataChanged(packageName);
+                        dataChangedImpl(packageName);
                     }
                 } catch (EOFException e) {
                     // no more data; we're done
@@ -740,7 +740,7 @@
                 int uid = mBackupParticipants.keyAt(i);
                 HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i);
                 for (ApplicationInfo app: participants) {
-                    dataChanged(app.packageName);
+                    dataChangedImpl(app.packageName);
                 }
             }
         }
@@ -896,7 +896,7 @@
                 if (!mEverStoredApps.contains(pkg.packageName)) {
                     if (DEBUG) Slog.i(TAG, "New app " + pkg.packageName
                             + " never backed up; scheduling");
-                    dataChanged(pkg.packageName);
+                    dataChangedImpl(pkg.packageName);
                 }
             }
         }
@@ -1327,7 +1327,7 @@
                 if (status != BackupConstants.TRANSPORT_OK) {
                     Slog.w(TAG, "Backup pass unsuccessful, restaging");
                     for (BackupRequest req : mQueue) {
-                        dataChanged(req.appInfo.packageName);
+                        dataChangedImpl(req.appInfo.packageName);
                     }
 
                     // We also want to reset the backup schedule based on whatever
@@ -1997,25 +1997,66 @@
         }
     }
 
+    private void dataChangedImpl(String packageName) {
+        HashSet<ApplicationInfo> targets = dataChangedTargets(packageName);
+        dataChangedImpl(packageName, targets);
+    }
 
-    // ----- IBackupManager binder interface -----
-
-    public void dataChanged(String packageName) {
+    private void dataChangedImpl(String packageName, HashSet<ApplicationInfo> targets) {
         // Record that we need a backup pass for the caller.  Since multiple callers
         // may share a uid, we need to note all candidates within that uid and schedule
         // a backup pass for each of them.
         EventLog.writeEvent(EventLogTags.BACKUP_DATA_CHANGED, packageName);
 
+        if (targets == null) {
+            Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
+                   + " uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        synchronized (mQueueLock) {
+            // Note that this client has made data changes that need to be backed up
+            for (ApplicationInfo app : targets) {
+                // validate the caller-supplied package name against the known set of
+                // packages associated with this uid
+                if (app.packageName.equals(packageName)) {
+                    // Add the caller to the set of pending backups.  If there is
+                    // one already there, then overwrite it, but no harm done.
+                    BackupRequest req = new BackupRequest(app, false);
+                    if (mPendingBackups.put(app, req) == null) {
+                        // Journal this request in case of crash.  The put()
+                        // operation returned null when this package was not already
+                        // in the set; we want to avoid touching the disk redundantly.
+                        writeToJournalLocked(packageName);
+
+                        if (DEBUG) {
+                            int numKeys = mPendingBackups.size();
+                            Slog.d(TAG, "Now awaiting backup for " + numKeys + " participants:");
+                            for (BackupRequest b : mPendingBackups.values()) {
+                                Slog.d(TAG, "    + " + b + " agent=" + b.appInfo.backupAgentName);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Note: packageName is currently unused, but may be in the future
+    private HashSet<ApplicationInfo> dataChangedTargets(String packageName) {
         // If the caller does not hold the BACKUP permission, it can only request a
         // backup of its own data.
-        HashSet<ApplicationInfo> targets;
         if ((mContext.checkPermission(android.Manifest.permission.BACKUP, Binder.getCallingPid(),
                 Binder.getCallingUid())) == PackageManager.PERMISSION_DENIED) {
-            targets = mBackupParticipants.get(Binder.getCallingUid());
-        } else {
-            // a caller with full permission can ask to back up any participating app
-            // !!! TODO: allow backup of ANY app?
-            targets = new HashSet<ApplicationInfo>();
+            synchronized (mBackupParticipants) {
+                return mBackupParticipants.get(Binder.getCallingUid());
+            }
+        }
+
+        // a caller with full permission can ask to back up any participating app
+        // !!! TODO: allow backup of ANY app?
+        HashSet<ApplicationInfo> targets = new HashSet<ApplicationInfo>();
+        synchronized (mBackupParticipants) {
             int N = mBackupParticipants.size();
             for (int i = 0; i < N; i++) {
                 HashSet<ApplicationInfo> s = mBackupParticipants.valueAt(i);
@@ -2024,37 +2065,7 @@
                 }
             }
         }
-        if (targets != null) {
-            synchronized (mQueueLock) {
-                // Note that this client has made data changes that need to be backed up
-                for (ApplicationInfo app : targets) {
-                    // validate the caller-supplied package name against the known set of
-                    // packages associated with this uid
-                    if (app.packageName.equals(packageName)) {
-                        // Add the caller to the set of pending backups.  If there is
-                        // one already there, then overwrite it, but no harm done.
-                        BackupRequest req = new BackupRequest(app, false);
-                        if (mPendingBackups.put(app, req) == null) {
-                            // Journal this request in case of crash.  The put()
-                            // operation returned null when this package was not already
-                            // in the set; we want to avoid touching the disk redundantly.
-                            writeToJournalLocked(packageName);
-
-                            if (DEBUG) {
-                                int numKeys = mPendingBackups.size();
-                                Slog.d(TAG, "Now awaiting backup for " + numKeys + " participants:");
-                                for (BackupRequest b : mPendingBackups.values()) {
-                                    Slog.d(TAG, "    + " + b + " agent=" + b.appInfo.backupAgentName);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        } else {
-            Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
-                    + " uid=" + Binder.getCallingUid());
-        }
+        return targets;
     }
 
     private void writeToJournalLocked(String str) {
@@ -2072,6 +2083,23 @@
         }
     }
 
+    // ----- IBackupManager binder interface -----
+
+    public void dataChanged(final String packageName) {
+        final HashSet<ApplicationInfo> targets = dataChangedTargets(packageName);
+        if (targets == null) {
+            Slog.w(TAG, "dataChanged but no participant pkg='" + packageName + "'"
+                   + " uid=" + Binder.getCallingUid());
+            return;
+        }
+
+        mBackupHandler.post(new Runnable() {
+                public void run() {
+                    dataChangedImpl(packageName, targets);
+                }
+            });
+    }
+
     // Clear the given package's backup data from the current transport
     public void clearBackupData(String packageName) {
         if (DEBUG) Slog.v(TAG, "clearBackupData() of " + packageName);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index c751f3d..9784d96 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -89,6 +89,11 @@
     private Context mContext;
     private int mNetworkPreference;
     private int mActiveDefaultNetwork = -1;
+    // 0 is full bad, 100 is full good
+    private int mDefaultInetCondition = 0;
+    private int mDefaultInetConditionPublished = 0;
+    private boolean mInetConditionChangeInFlight = false;
+    private int mDefaultConnectionSequence = 0;
 
     private int mNumDnsEntries;
 
@@ -1016,6 +1021,7 @@
             intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
                     info.getExtraInfo());
         }
+        intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
         sendStickyBroadcast(intent);
     }
 
@@ -1134,6 +1140,14 @@
                 }
             }
             mActiveDefaultNetwork = type;
+            // this will cause us to come up initially as unconnected and switching
+            // to connected after our normal pause unless somebody reports us as reall
+            // disconnected
+            mDefaultInetConditionPublished = 0;
+            mDefaultConnectionSequence++;
+            mInetConditionChangeInFlight = false;
+            // Don't do this - if we never sign in stay, grey
+            //reportNetworkCondition(mActiveDefaultNetwork, 100);
         }
         thisNet.setTeardownRequested(false);
         thisNet.updateNetworkSettings();
@@ -1436,6 +1450,70 @@
                     FeatureUser u = (FeatureUser)msg.obj;
                     u.expire();
                     break;
+                case NetworkStateTracker.EVENT_INET_CONDITION_CHANGE:
+                    if (DBG) {
+                        Slog.d(TAG, "Inet connectivity change, net=" +
+                                msg.arg1 + ", condition=" + msg.arg2 +
+                                ",mActiveDefaultNetwork=" + mActiveDefaultNetwork);
+                    }
+                    if (mActiveDefaultNetwork == -1) {
+                        if (DBG) Slog.d(TAG, "no active default network - aborting");
+                        break;
+                    }
+                    if (mActiveDefaultNetwork != msg.arg1) {
+                        if (DBG) Slog.d(TAG, "given net not default - aborting");
+                        break;
+                    }
+                    mDefaultInetCondition = msg.arg2;
+                    int delay;
+                    if (mInetConditionChangeInFlight == false) {
+                        if (DBG) Slog.d(TAG, "starting a change hold");
+                        // setup a new hold to debounce this
+                        if (mDefaultInetCondition > 50) {
+                            delay = Settings.Secure.getInt(mContext.getContentResolver(),
+                                    Settings.Secure.INET_CONDITION_DEBOUNCE_UP_DELAY, 500);
+                        } else {
+                            delay = Settings.Secure.getInt(mContext.getContentResolver(),
+                                    Settings.Secure.INET_CONDITION_DEBOUNCE_DOWN_DELAY, 3000);
+                        }
+                        mInetConditionChangeInFlight = true;
+                        sendMessageDelayed(obtainMessage(
+                                NetworkStateTracker.EVENT_INET_CONDITION_HOLD_END,
+                                mActiveDefaultNetwork, mDefaultConnectionSequence), delay);
+                    } else {
+                        // we've set the new condition, when this hold ends that will get
+                        // picked up
+                        if (DBG) Slog.d(TAG, "currently in hold - not setting new end evt");
+                    }
+                    break;
+                case NetworkStateTracker.EVENT_INET_CONDITION_HOLD_END:
+                    if (DBG) {
+                        Slog.d(TAG, "Inet hold end, net=" + msg.arg1 +
+                                ", condition =" + mDefaultInetCondition +
+                                ", published condition =" + mDefaultInetConditionPublished);
+                    }
+                    mInetConditionChangeInFlight = false;
+
+                    if (mActiveDefaultNetwork == -1) {
+                        if (DBG) Slog.d(TAG, "no active default network - aborting");
+                        break;
+                    }
+                    if (mDefaultConnectionSequence != msg.arg2) {
+                        if (DBG) Slog.d(TAG, "event hold for obsolete network - aborting");
+                        break;
+                    }
+                    if (mDefaultInetConditionPublished == mDefaultInetCondition) {
+                        if (DBG) Slog.d(TAG, "no change in condition - aborting");
+                        break;
+                    }
+                    NetworkInfo networkInfo = mNetTrackers[mActiveDefaultNetwork].getNetworkInfo();
+                    if (networkInfo.isConnected() == false) {
+                        if (DBG) Slog.d(TAG, "default network not connected - aborting");
+                        break;
+                    }
+                    mDefaultInetConditionPublished = mDefaultInetCondition;
+                    sendConnectedBroadcast(networkInfo);
+                    break;
             }
         }
     }
@@ -1519,4 +1597,15 @@
                 Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0);
         return tetherEnabledInSettings && mTetheringConfigValid;
     }
+
+    // 100 percent is full good, 0 is full bad.
+    public void reportInetCondition(int networkType, int percentage) {
+        if (DBG) Slog.d(TAG, "reportNetworkCondition(" + networkType + ", " + percentage + ")");
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.STATUS_BAR,
+                "ConnectivityService");
+
+        mHandler.sendMessage(mHandler.obtainMessage(
+            NetworkStateTracker.EVENT_INET_CONDITION_CHANGE, networkType, percentage));
+    }
 }
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 63325dd..0a5b72b 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -112,6 +112,10 @@
     private boolean mScreenOn = true;
     private boolean mInCall = false;
     private boolean mNotificationPulseEnabled;
+    // This is true if we have received a new notification while the screen is off
+    // (that is, if mLedNotification was set while the screen was off)
+    // This is reset to false when the screen is turned on.
+    private boolean mPendingPulseNotification;
 
     // for adb connected notifications
     private boolean mAdbNotificationShown = false;
@@ -1082,6 +1086,11 @@
             mBatteryLight.turnOff();
         }
 
+        // clear pending pulse notification if screen is on
+        if (mScreenOn || mLedNotification == null) {
+            mPendingPulseNotification = false;
+        }
+
         // handle notification lights
         if (mLedNotification == null) {
             // get next notification, if any
@@ -1089,11 +1098,14 @@
             if (n > 0) {
                 mLedNotification = mLights.get(n-1);
             }
+            if (mLedNotification != null && !mScreenOn) {
+                mPendingPulseNotification = true;
+            }
         }
 
         // we only flash if screen is off and persistent pulsing is enabled
         // and we are not currently in a call
-        if (mLedNotification == null || mScreenOn || mInCall) {
+        if (!mPendingPulseNotification || mScreenOn || mInCall) {
             mNotificationLight.turnOff();
         } else {
             int ledARGB = mLedNotification.notification.ledARGB;
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index e3480a8..1279cf7 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -9408,7 +9408,12 @@
         } catch (NoSuchAlgorithmException nsae) {
             Slog.e(TAG, "Failed to create encryption keys with exception: " + nsae);
             return null;
+        } catch (IOException ioe) {
+            Slog.e(TAG, "Failed to retrieve encryption keys with exception: "
+                      + ioe);
+            return null;
         }
+
     }
 
     /* package */ static String getTempContainerId() {
diff --git a/services/java/com/android/server/sip/SipService.java b/services/java/com/android/server/sip/SipService.java
index 563ce58..eee97c3 100644
--- a/services/java/com/android/server/sip/SipService.java
+++ b/services/java/com/android/server/sip/SipService.java
@@ -490,7 +490,7 @@
 
     private class KeepAliveProcess implements Runnable {
         private static final String TAG = "\\KEEPALIVE/";
-        private static final int INTERVAL = 15;
+        private static final int INTERVAL = 10;
         private SipSessionGroup.SipSessionImpl mSession;
 
         public KeepAliveProcess(SipSessionGroup.SipSessionImpl session) {
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index c1232e8..caec7e1 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -466,6 +466,33 @@
     }
 
     /**
+     * Hangup foreground call and resume the specific background call
+     *
+     * Note: this is noop if there is no foreground call or the heldCall is null
+     *
+     * @param heldCall to become foreground
+     * @throws CallStateException
+     */
+    public void hangupForegroundResumeBackground(Call heldCall) throws CallStateException {
+        Phone foregroundPhone = null;
+        Phone backgroundPhone = null;
+
+        if (hasActiveFgCall()) {
+            foregroundPhone = getFgPhone();
+            if (heldCall != null) {
+                backgroundPhone = heldCall.getPhone();
+                if (foregroundPhone == backgroundPhone) {
+                    getActiveFgCall().hangup();
+                } else {
+                // the call to be hangup and resumed belongs to different phones
+                    getActiveFgCall().hangup();
+                    switchHoldingAndActive(heldCall);
+                }
+            }
+        }
+    }
+
+    /**
      * Whether or not the phone can conference in the current phone
      * state--that is, one call holding and one call active.
      * @return true if the phone can conference; false otherwise.
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index bb45a9a..3433dcf 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -588,7 +588,7 @@
     // Give device socket a reasonable timeout and buffer size.
     timeval tv;
     tv.tv_sec = 0;
-    tv.tv_usec = 1000 * sampleCount / sampleRate * 1000;
+    tv.tv_usec = 1000 * sampleCount / sampleRate * 500;
     if (setsockopt(pair[0], SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) ||
         setsockopt(pair[0], SOL_SOCKET, SO_RCVBUF, &output, sizeof(output)) ||
         setsockopt(pair[1], SOL_SOCKET, SO_SNDBUF, &output, sizeof(output))) {
@@ -793,7 +793,7 @@
 
             status_t status = mRecord.obtainBuffer(&buffer, 1);
             if (status == NO_ERROR) {
-                int count = (buffer.frameCount < toRead) ?
+                int count = ((int)buffer.frameCount < toRead) ?
                         buffer.frameCount : toRead;
                 memcpy(&input[mSampleCount - toRead], buffer.i8, count * 2);
                 toRead -= count;