Merge change 5348

* changes:
  Add missing filename remap to RenamingDelegatingContext
diff --git a/api/current.xml b/api/current.xml
index 8b5f7ed..264d79f 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -24301,6 +24301,19 @@
 <parameter name="position" type="int">
 </parameter>
 </method>
+<method name="itemForPosition"
+ return="android.app.LauncherActivity.ListItem"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="position" type="int">
+</parameter>
+</method>
 <method name="makeListItems"
  return="java.util.List&lt;android.app.LauncherActivity.ListItem&gt;"
  abstract="false"
@@ -24409,6 +24422,16 @@
  visibility="public"
 >
 </field>
+<field name="resolveInfo"
+ type="android.content.pm.ResolveInfo"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="ListActivity"
  extends="android.app.Activity"
@@ -184646,7 +184669,7 @@
 <method name="startMethodTracing"
  return="void"
  abstract="false"
- native="true"
+ native="false"
  synchronized="false"
  static="true"
  final="false"
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 2f4a1c9..d8ca525 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -98,7 +98,7 @@
     LOGD("CameraService::connect E (pid %d, client %p)", callingPid,
             cameraClient->asBinder().get());
 
-    Mutex::Autolock lock(mLock);
+    Mutex::Autolock lock(mServiceLock);
     sp<Client> client;
     if (mClient != 0) {
         sp<Client> currentClient = mClient.promote();
@@ -125,13 +125,14 @@
             LOGD("New client (pid %d) connecting, old reference was dangling...",
                     callingPid);
             mClient.clear();
-            if (mUsers > 0) {
-                LOGD("Still have client, rejected");
-                return client;
-            }
         }
     }
 
+    if (mUsers > 0) {
+        LOGD("Still have client, rejected");
+        return client;
+    }
+
     // create a new Client object
     client = new Client(this, cameraClient, callingPid);
     mClient = client;
@@ -152,7 +153,7 @@
     // destructor won't be called with the lock held.
     sp<Client> client;
 
-    Mutex::Autolock lock(mLock);
+    Mutex::Autolock lock(mServiceLock);
 
     if (mClient == 0) {
         // This happens when we have already disconnected.
@@ -390,8 +391,6 @@
     // from the user directly, or called by the destructor.
     if (mHardware == 0) return;
 
-    mCameraService->removeClient(mCameraClient);
-
     LOGD("hardware teardown");
     // Before destroying mHardware, we must make sure it's in the
     // idle state.
@@ -402,6 +401,7 @@
     mHardware->release();
     mHardware.clear();
 
+    mCameraService->removeClient(mCameraClient);
     mCameraService->decUsers();
 
     LOGD("Client::disconnect() X (pid %d)", callingPid);
@@ -661,7 +661,7 @@
     sp<Client> client = 0;
     CameraService *service = static_cast<CameraService*>(user);
     if (service != NULL) {
-        Mutex::Autolock ourLock(service->mLock);
+        Mutex::Autolock ourLock(service->mServiceLock);
         if (service->mClient != 0) {
             client = service->mClient.promote();
             if (client == 0) {
@@ -1104,7 +1104,7 @@
         result.append(buffer);
         write(fd, result.string(), result.size());
     } else {
-        AutoMutex lock(&mLock);
+        AutoMutex lock(&mServiceLock);
         if (mClient != 0) {
             sp<Client> currentClient = mClient.promote();
             sprintf(buffer, "Client (%p) PID: %d\n",
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 729e539..8b8b54c 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -199,7 +199,7 @@
     virtual     void                        incUsers();
     virtual     void                        decUsers();
 
-    mutable     Mutex                       mLock;
+    mutable     Mutex                       mServiceLock;
                 wp<Client>                  mClient;
 
 #if DEBUG_HEAP_LEAKS
diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java
index 8d249da..accdda9 100644
--- a/core/java/android/app/LauncherActivity.java
+++ b/core/java/android/app/LauncherActivity.java
@@ -60,26 +60,20 @@
      * An item in the list
      */
     public static class ListItem {
+        public ResolveInfo resolveInfo;
         public CharSequence label;
-        //public CharSequence description;
         public Drawable icon;
         public String packageName;
         public String className;
         public Bundle extras;
         
         ListItem(PackageManager pm, ResolveInfo resolveInfo, IconResizer resizer) {
+            this.resolveInfo = resolveInfo;
             label = resolveInfo.loadLabel(pm);
             if (label == null && resolveInfo.activityInfo != null) {
                 label = resolveInfo.activityInfo.name;
             }
             
-            /*
-            if (resolveInfo.activityInfo != null &&
-                    resolveInfo.activityInfo.applicationInfo != null) {
-                description = resolveInfo.activityInfo.applicationInfo.loadDescription(pm);
-            }
-            */
-            
             icon = resizer.createIconThumbnail(resolveInfo.loadIcon(pm));
             packageName = resolveInfo.activityInfo.applicationInfo.packageName;
             className = resolveInfo.activityInfo.name;
@@ -122,6 +116,14 @@
             return intent;
         }
 
+        public ListItem itemForPosition(int position) {
+            if (mActivitiesList == null) {
+                return null;
+            }
+
+            return mActivitiesList.get(position);
+        }
+
         public int getCount() {
             return mActivitiesList != null ? mActivitiesList.size() : 0;
         }
@@ -354,6 +356,16 @@
     }
     
     /**
+     * Return the {@link ListItem} for a specific position in our
+     * {@link android.widget.ListView}.
+     * @param position The item to return
+     */
+    protected ListItem itemForPosition(int position) {
+        ActivityAdapter adapter = (ActivityAdapter) mAdapter;
+        return adapter.itemForPosition(position);
+    }
+    
+    /**
      * Get the base intent to use when running
      * {@link PackageManager#queryIntentActivities(Intent, int)}.
      */
diff --git a/core/java/android/backup/AbsoluteFileBackupHelper.java b/core/java/android/backup/AbsoluteFileBackupHelper.java
new file mode 100644
index 0000000..ab24675
--- /dev/null
+++ b/core/java/android/backup/AbsoluteFileBackupHelper.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.backup;
+
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileDescriptor;
+
+/**
+ * Like FileBackupHelper, but takes absolute paths for the files instead of
+ * subpaths of getFilesDir()
+ *
+ * @hide
+ */
+public class AbsoluteFileBackupHelper extends FileBackupHelperBase implements BackupHelper {
+    private static final String TAG = "AbsoluteFileBackupHelper";
+
+    Context mContext;
+    String[] mFiles;
+
+    public AbsoluteFileBackupHelper(Context context, String... files) {
+        super(context);
+
+        mContext = context;
+        mFiles = files;
+    }
+
+    /**
+     * Based on oldState, determine which of the files from the application's data directory
+     * need to be backed up, write them to the data stream, and fill in newState with the
+     * state as it exists now.
+     */
+    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+            ParcelFileDescriptor newState) {
+        // use the file paths as the keys, too
+        performBackup_checked(oldState, data, newState, mFiles, mFiles);
+    }
+
+    public void restoreEntity(BackupDataInputStream data) {
+        // TODO: turn this off before ship
+        Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size());
+        String key = data.getKey();
+        if (isKeyInList(key, mFiles)) {
+            File f = new File(key);
+            writeFile(f, data);
+        }
+    }
+}
+
diff --git a/core/java/android/backup/RestoreSet.java b/core/java/android/backup/RestoreSet.java
index 96a99ae..eeca148 100644
--- a/core/java/android/backup/RestoreSet.java
+++ b/core/java/android/backup/RestoreSet.java
@@ -43,14 +43,14 @@
      * transport.  This is guaranteed to be valid for the duration of a restore
      * session, but is meaningless once the session has ended.
      */
-    public int token;
+    public long token;
 
 
     public RestoreSet() {
         // Leave everything zero / null
     }
 
-    public RestoreSet(String _name, String _dev, int _token) {
+    public RestoreSet(String _name, String _dev, long _token) {
         name = _name;
         device = _dev;
         token = _token;
@@ -65,7 +65,7 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(name);
         out.writeString(device);
-        out.writeInt(token);
+        out.writeLong(token);
     }
 
     public static final Parcelable.Creator<RestoreSet> CREATOR
@@ -82,6 +82,6 @@
     private RestoreSet(Parcel in) {
         name = in.readString();
         device = in.readString();
-        token = in.readInt();
+        token = in.readLong();
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 33e769e..87f762d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1593,6 +1593,15 @@
     public static final String ACTION_REMOTE_INTENT =
             "android.intent.action.REMOTE_INTENT";
 
+    /**
+     * @hide
+     * TODO: This will be unhidden in a later CL.
+     * Broadcast Action: The TextToSpeech synthesizer has completed processing 
+     * all of the text in the speech queue.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED =
+            "android.intent.action.TTS_QUEUE_PROCESSING_COMPLETED";
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 680fef8..179b9bd 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -17,8 +17,15 @@
 package android.content.res;
 
 import android.content.pm.ApplicationInfo;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.Region;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
 
 /**
  * CompatibilityInfo class keeps the information about compatibility mode that the application is
@@ -27,6 +34,9 @@
  *  {@hide} 
  */
 public class CompatibilityInfo {
+    private static final boolean DBG = false;
+    private static final String TAG = "CompatibilityInfo";
+    
     /** default compatibility info object for compatible applications */
     public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo(); 
 
@@ -41,36 +51,75 @@
     public static final int DEFAULT_PORTRAIT_HEIGHT = 480;
 
     /**
+     * The x-shift mode that controls the position of the content or the window under
+     * compatibility mode.
+     * {@see getTranslator}
+     * {@see Translator#mShiftMode}
+     */
+    private static final int X_SHIFT_NONE = 0;
+    private static final int X_SHIFT_CONTENT = 1;
+    private static final int X_SHIFT_AND_CLIP_CONTENT = 2;
+    private static final int X_SHIFT_WINDOW = 3;
+
+
+    /**
+     *  A compatibility flags
+     */
+    private int compatibilityFlags;
+    
+    /**
+     * A flag mask to tell if the application needs scaling (when mApplicationScale != 1.0f)
+     * {@see compatibilityFlag}
+     */
+    private static final int SCALING_REQUIRED = 1; 
+
+    /**
+     * A flag mask to indicates that the application can expand over the original size.
+     * The flag is set to true if
+     * 1) Application declares its expandable in manifest file using <expandable /> or
+     * 2) The screen size is same as (320 x 480) * density. 
+     * {@see compatibilityFlag}
+     */
+    private static final int EXPANDABLE = 2;
+    
+    /**
+     * A flag mask to tell if the application is configured to be expandable. This differs
+     * from EXPANDABLE in that the application that is not expandable will be 
+     * marked as expandable if it runs in (320x 480) * density screen size.
+     */
+    private static final int CONFIGURED_EXPANDABLE = 4; 
+
+    private static final int SCALING_EXPANDABLE_MASK = SCALING_REQUIRED | EXPANDABLE;
+
+    /**
      * Application's scale.
      */
-    public final float mApplicationScale;
+    public final float applicationScale;
 
     /**
      * Application's inverted scale.
      */
-    public final float mApplicationInvertedScale;
-    
-    /**
-     * A boolean flag to indicates that the application can expand over the original size.
-     * The flag is set to true if
-     * 1) Application declares its expandable in manifest file using <expandable /> or
-     * 2) The screen size is same as (320 x 480) * density. 
-     */
-    public boolean mExpandable;
+    public final float applicationInvertedScale;
+
 
     /**
-     * A expandable flag in the configuration.
+     * Window size in Compatibility Mode, in real pixels. This is updated by
+     * {@link DisplayMetrics#updateMetrics}.
      */
-    public final boolean mConfiguredExpandable;
+    private int mWidth;
+    private int mHeight;
     
     /**
-     * A boolean flag to tell if the application needs scaling (when mApplicationScale != 1.0f)
+     * The x offset to center the window content. In X_SHIFT_WINDOW mode, the offset is added
+     * to the window's layout. In X_SHIFT_CONTENT/X_SHIFT_AND_CLIP_CONTENT mode, the offset
+     * is used to translate the Canvas.
      */
-    public final boolean mScalingRequired;
+    private int mXOffset;
 
     public CompatibilityInfo(ApplicationInfo appInfo) {
-        mExpandable = mConfiguredExpandable =
-            (appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0;
+        if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
+            compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
+        }
         
         float packageDensityScale = -1.0f;
         if (appInfo.supportsDensities != null) {
@@ -93,23 +142,323 @@
             }
         }
         if (packageDensityScale > 0.0f) {
-            mApplicationScale = packageDensityScale;
+            applicationScale = packageDensityScale;
         } else {
-            mApplicationScale = DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
+            applicationScale =
+                    DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
         }
-        mApplicationInvertedScale = 1.0f / mApplicationScale;
-        mScalingRequired = mApplicationScale != 1.0f;
+        applicationInvertedScale = 1.0f / applicationScale;
+        if (applicationScale != 1.0f) {
+            compatibilityFlags |= SCALING_REQUIRED;
+        }
     }
 
     private CompatibilityInfo() {
-        mApplicationScale = mApplicationInvertedScale = 1.0f;
-        mExpandable = mConfiguredExpandable = true;
-        mScalingRequired = false;
+        applicationScale = applicationInvertedScale = 1.0f;
+        compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
     }
 
+    /**
+     * Sets the application's visible rect in compatibility mode.
+     * @param xOffset the application's x offset that is added to center the content.
+     * @param widthPixels the application's width in real pixels on the screen.
+     * @param heightPixels the application's height in real pixels on the screen.
+     */
+    public void setVisibleRect(int xOffset, int widthPixels, int heightPixels) {
+        this.mXOffset = xOffset; 
+        mWidth = widthPixels;
+        mHeight = heightPixels;
+    }
+    
+    /**
+     * Sets expandable bit in the compatibility flag.
+     */
+    public void setExpandable(boolean expandable) {
+        if (expandable) {
+            compatibilityFlags |= CompatibilityInfo.EXPANDABLE;
+        } else {
+            compatibilityFlags &= ~CompatibilityInfo.EXPANDABLE;
+        }
+    }
+
+    /**
+     * @return true if the application is configured to be expandable.
+     */
+    public boolean isConfiguredExpandable() {
+        return (compatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0;
+    }
+
+    /**
+     * @return true if the scaling is required
+     */
+    public boolean isScalingRequired() {
+        return (compatibilityFlags & SCALING_REQUIRED) != 0;
+    }
+    
     @Override
     public String toString() {
-        return "CompatibilityInfo{scale=" + mApplicationScale +
-                ", expandable=" + mExpandable + "}"; 
+        return "CompatibilityInfo{scale=" + applicationScale +
+                ", compatibility flag=" + compatibilityFlags + "}"; 
     }
-}
+
+    /**
+     * Returns the translator which can translate the coordinates of the window.
+     * There are five different types of Translator.
+     * 
+     * 1) {@link CompatibilityInfo#X_SHIFT_AND_CLIP_CONTENT}
+     *   Shift and clip the content of the window at drawing time. Used for activities'
+     *   main window (with no gravity).
+     * 2) {@link CompatibilityInfo#X_SHIFT_CONTENT}
+     *   Shift the content of the window at drawing time. Used for windows that is created by
+     *   an application and expected to be aligned with the application window.
+     * 3) {@link CompatibilityInfo#X_SHIFT_WINDOW}
+     *   Create the window with adjusted x- coordinates. This is typically used 
+     *   in popup window, where it has to be placed relative to main window.
+     * 4) {@link CompatibilityInfo#X_SHIFT_NONE}
+     *   No adjustment required, such as dialog.
+     * 5) Same as X_SHIFT_WINDOW, but no scaling. This is used by {@link SurfaceView}, which
+     *  does not require scaling, but its window's location has to be adjusted.
+     * 
+     * @param params the window's parameter
+     */
+    public Translator getTranslator(WindowManager.LayoutParams params) {
+        if ( (compatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK)
+                == CompatibilityInfo.EXPANDABLE) {
+            if (DBG) Log.d(TAG, "no translation required");
+            return null;
+        }
+        
+        if ((compatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) {
+            if ((params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) {
+                if (DBG) Log.d(TAG, "translation for surface view selected");
+                return new Translator(X_SHIFT_WINDOW, false, 1.0f, 1.0f);
+            } else {
+                int shiftMode;
+                if (params.gravity == Gravity.NO_GRAVITY) {
+                    // For Regular Application window
+                    shiftMode = X_SHIFT_AND_CLIP_CONTENT;
+                    if (DBG) Log.d(TAG, "shift and clip translator");
+                } else if (params.width == WindowManager.LayoutParams.FILL_PARENT) {
+                    // For Regular Application window
+                    shiftMode = X_SHIFT_CONTENT;
+                    if (DBG) Log.d(TAG, "shift content translator");
+                } else if ((params.gravity & Gravity.LEFT) != 0 && params.x > 0) {
+                    shiftMode = X_SHIFT_WINDOW;
+                    if (DBG) Log.d(TAG, "shift window translator");
+                } else {
+                    shiftMode = X_SHIFT_NONE;
+                    if (DBG) Log.d(TAG, "no content/window translator");
+                }
+                return new Translator(shiftMode);
+            }
+        } else if (isScalingRequired()) {
+            return new Translator();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * A helper object to translate the screen and window coordinates back and forth.
+     * @hide
+     */
+    public class Translator {
+        final private int mShiftMode;
+        final public boolean scalingRequired;
+        final public float applicationScale;
+        final public float applicationInvertedScale;
+        
+        private Rect mContentInsetsBuffer = null;
+        private Rect mVisibleInsets = null;
+        
+        Translator(int shiftMode, boolean scalingRequired, float applicationScale,
+                float applicationInvertedScale) {
+            mShiftMode = shiftMode;
+            this.scalingRequired = scalingRequired;
+            this.applicationScale = applicationScale;
+            this.applicationInvertedScale = applicationInvertedScale;
+        }
+
+        Translator(int shiftMode) {
+            this(shiftMode,
+                    isScalingRequired(),
+                    CompatibilityInfo.this.applicationScale,
+                    CompatibilityInfo.this.applicationInvertedScale);
+        }
+        
+        Translator() {
+            this(X_SHIFT_NONE);
+        }
+
+        /**
+         * Translate the screen rect to the application frame.
+         */
+        public void translateRectInScreenToAppWinFrame(Rect rect) {
+            if (rect.isEmpty()) return; // skip if the window size is empty.
+            switch (mShiftMode) {
+                case X_SHIFT_AND_CLIP_CONTENT:
+                    rect.intersect(0, 0, mWidth, mHeight);
+                    break;
+                case X_SHIFT_CONTENT:
+                    rect.intersect(0, 0, mWidth + mXOffset, mHeight);
+                    break;
+                case X_SHIFT_WINDOW:
+                case X_SHIFT_NONE:
+                    break;
+            }
+            if (scalingRequired) {
+                rect.scale(applicationInvertedScale);
+            }
+        }
+
+        /**
+         * Translate the region in window to screen. 
+         */
+        public void translateRegionInWindowToScreen(Region transparentRegion) {
+            switch (mShiftMode) {
+                case X_SHIFT_AND_CLIP_CONTENT:
+                case X_SHIFT_CONTENT:
+                    transparentRegion.scale(applicationScale);
+                    transparentRegion.translate(mXOffset, 0);
+                    break;
+                case X_SHIFT_WINDOW:
+                case X_SHIFT_NONE:
+                    transparentRegion.scale(applicationScale);
+            }
+        }
+
+        /**
+         * Apply translation to the canvas that is necessary to draw the content.
+         */
+        public void translateCanvas(Canvas canvas) {
+            if (mShiftMode == X_SHIFT_CONTENT ||
+                    mShiftMode == X_SHIFT_AND_CLIP_CONTENT) {
+                // TODO: clear outside when rotation is changed.
+
+                // Translate x-offset only when the content is shifted.
+                canvas.translate(mXOffset, 0);
+            }
+            if (scalingRequired) {
+                canvas.scale(applicationScale, applicationScale);
+            }
+        }
+
+        /**
+         * Translate the motion event captured on screen to the application's window.
+         */
+        public void translateEventInScreenToAppWindow(MotionEvent event) {
+            if (mShiftMode == X_SHIFT_CONTENT ||
+                    mShiftMode == X_SHIFT_AND_CLIP_CONTENT) {
+                event.translate(-mXOffset, 0);
+            }
+            if (scalingRequired) {
+                event.scale(applicationInvertedScale);
+            }
+        }
+
+        /**
+         * Translate the window's layout parameter, from application's view to
+         * Screen's view.
+         */
+        public void translateWindowLayout(WindowManager.LayoutParams params) {
+            switch (mShiftMode) {
+                case X_SHIFT_NONE:
+                case X_SHIFT_AND_CLIP_CONTENT:
+                case X_SHIFT_CONTENT:
+                    params.scale(applicationScale);
+                    break;
+                case X_SHIFT_WINDOW:
+                    params.scale(applicationScale);
+                    params.x += mXOffset;
+                    break;
+            }
+        }
+        
+        /**
+         * Translate a Rect in application's window to screen.
+         */
+        public void translateRectInAppWindowToScreen(Rect rect) {
+            // TODO Auto-generated method stub
+            if (scalingRequired) {
+                rect.scale(applicationScale);
+            }
+            switch(mShiftMode) {
+                case X_SHIFT_NONE:
+                case X_SHIFT_WINDOW:
+                    break;
+                case X_SHIFT_CONTENT:
+                case X_SHIFT_AND_CLIP_CONTENT:
+                    rect.offset(mXOffset, 0);
+                    break;
+            }
+        }
+ 
+        /**
+         * Translate a Rect in screen coordinates into the app window's coordinates.
+         */
+        public void translateRectInScreenToAppWindow(Rect rect) {
+            switch (mShiftMode) {
+                case X_SHIFT_NONE:
+                case X_SHIFT_WINDOW:
+                    break;
+                case X_SHIFT_CONTENT: {
+                    rect.intersects(mXOffset, 0, rect.right, rect.bottom);
+                    int dx = Math.min(mXOffset, rect.left);
+                    rect.offset(-dx, 0);
+                    break;
+                }
+                case X_SHIFT_AND_CLIP_CONTENT: {
+                    rect.intersects(mXOffset, 0, mWidth + mXOffset, mHeight);
+                    int dx = Math.min(mXOffset, rect.left);
+                    rect.offset(-dx, 0);
+                    break;
+                }
+            }
+            if (scalingRequired) {
+                rect.scale(applicationInvertedScale);
+            }
+        }
+
+        /**
+         * Translate the location of the sub window.
+         * @param params
+         */
+        public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) {
+            if (scalingRequired) {
+                params.scale(applicationScale);
+            }
+            switch (mShiftMode) {
+                // the window location on these mode does not require adjustmenet.
+                case X_SHIFT_NONE:
+                case X_SHIFT_WINDOW:
+                    break;
+                case X_SHIFT_CONTENT:
+                case X_SHIFT_AND_CLIP_CONTENT:
+                    params.x += mXOffset;
+                    break;
+            }
+        }
+
+        /**
+         * Translate the content insets in application window to Screen. This uses
+         * the internal buffer for content insets to avoid extra object allocation.
+         */
+        public Rect getTranslatedContentInsets(Rect contentInsets) {
+            if (mContentInsetsBuffer == null) mContentInsetsBuffer = new Rect();
+            mContentInsetsBuffer.set(contentInsets);
+            translateRectInAppWindowToScreen(mContentInsetsBuffer);
+            return mContentInsetsBuffer;
+        }
+
+        /**
+         * Translate the visible insets in application window to Screen. This uses
+         * the internal buffer for content insets to avoid extra object allocation.
+         */
+        public Rect getTranslatedVisbileInsets(Rect visibleInsets) {
+            if (mVisibleInsets == null) mVisibleInsets = new Rect();
+            mVisibleInsets.set(visibleInsets);
+            translateRectInAppWindowToScreen(mVisibleInsets);
+            return mVisibleInsets;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 71dbd38..cb9d46e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -158,10 +158,10 @@
         }
         updateConfiguration(config, metrics);
         assets.ensureStringBlocks();
-        if (!mCompatibilityInfo.mScalingRequired) {
-            mPreloadedDrawables = sPreloadedDrawables;
-        } else {
+        if (mCompatibilityInfo.isScalingRequired()) {
             mPreloadedDrawables = emptySparseArray();
+        } else {
+            mPreloadedDrawables = sPreloadedDrawables;
         }
     }
 
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 333c7cb..1214abc 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -573,7 +573,21 @@
      * directly to a gid.
      */
     public static final native int getGidForName(String name);
-    
+
+    /**
+     * Returns a uid for a currently running process.
+     * @param pid the process id
+     * @return the uid of the process, or -1 if the process is not running.
+     * @hide pending API council review
+     */
+    public static final int getUidForPid(int pid) {
+        String[] procStatusLabels = { "Uid:" };
+        long[] procStatusValues = new long[1];
+        procStatusValues[0] = -1;
+        Process.readProcLines("/proc/" + pid + "/status", procStatusLabels, procStatusValues);
+        return (int) procStatusValues[0];
+    }
+
     /**
      * Set the priority of a thread, based on Linux priorities.
      * 
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 48dc3ae..1ed0574 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -261,6 +261,19 @@
         private Contacts()  {}
 
         /**
+         * The package name that owns this contact and all of its details. This
+         * package has control over the {@link #IS_RESTRICTED} flag, and can
+         * grant {@link RestrictionExceptions} to other packages.
+         */
+        public static final String PACKAGE = "package";
+
+        /**
+         * Flag indicating that this data entry has been restricted by the owner
+         * {@link #PACKAGE}.
+         */
+        public static final String IS_RESTRICTED = "is_restricted";
+
+        /**
          * A reference to the {@link Accounts#_ID} that this data belongs to.
          */
         public static final String ACCOUNTS_ID = "accounts_id";
@@ -332,11 +345,6 @@
 
     private interface DataColumns {
         /**
-         * The package name that defines this type of data.
-         */
-        public static final String PACKAGE = "package";
-
-        /**
          * The mime-type of the item represented by this row.
          */
         public static final String MIMETYPE = "mimetype";
@@ -361,12 +369,6 @@
         public static final String IS_SUPER_PRIMARY = "is_super_primary";
 
         /**
-         * Flag indicating that this data entry has been restricted by the owner
-         * {@link #PACKAGE}.
-         */
-        public static final String IS_RESTRICTED = "is_restricted";
-
-        /**
          * The version of this data record. This is a read-only value. The data column is
          * guaranteed to not change without the version going up. This value is monotonically
          * increasing.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ebe54fcd..483ce97 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1290,6 +1290,50 @@
         public static final String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
 
         /**
+         * CDMA only settings
+         * DTMF tone type played by the dialer when dialing.
+         *                 0 = Normal
+         *                 1 = Long
+         * @hide
+         */
+        public static final String DTMF_TONE_TYPE_WHEN_DIALING = "dtmf_tone_type";
+
+        /**
+         * CDMA only settings
+         * Emergency Tone  0 = Off
+         *                 1 = Alert
+         *                 2 = Vibrate
+         * @hide
+         */
+        public static final String EMERGENCY_TONE = "emergency_tone";
+
+        /**
+         * CDMA only settings
+         * Whether the auto retry is enabled. The value is
+         * boolean (1 or 0).
+         * @hide
+         */
+        public static final String CALL_AUTO_RETRY = "call_auto_retry";
+
+        /**
+         * Whether the hearing aid is enabled. The value is
+         * boolean (1 or 0).
+         * @hide
+         */
+        public static final String HEARING_AID = "hearing_aid";
+
+        /**
+         * CDMA only settings
+         * TTY Mode
+         * 0 = OFF
+         * 1 = FULL
+         * 2 = VCO
+         * 3 = HCO
+         * @hide
+         */
+        public static final String TTY_MODE = "tty_mode";
+
+        /**
          * Whether the sounds effects (key clicks, lid open ...) are enabled. The value is
          * boolean (1 or 0).
          */
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index a095913..d89ada0 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -106,16 +106,8 @@
      * {@hide}
      */
     public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation) {
-        if (compatibilityInfo.mScalingRequired) {
-            float invertedRatio = compatibilityInfo.mApplicationInvertedScale;
-            density *= invertedRatio;
-            scaledDensity *= invertedRatio;
-            xdpi *= invertedRatio;
-            ydpi *= invertedRatio;
-            widthPixels *= invertedRatio;
-            heightPixels *= invertedRatio;
-        }
-        if (!compatibilityInfo.mConfiguredExpandable) {
+        int xOffset = 0;
+        if (!compatibilityInfo.isConfiguredExpandable()) {
             // Note: this assume that configuration is updated before calling
             // updateMetrics method.
             int defaultWidth;
@@ -141,11 +133,13 @@
             
             if (defaultWidth == widthPixels && defaultHeight == heightPixels) {
                 // the screen size is same as expected size. make it expandable
-                compatibilityInfo.mExpandable = true;
+                compatibilityInfo.setExpandable(true);
             } else {
-                compatibilityInfo.mExpandable = false;
+                compatibilityInfo.setExpandable(false);
                 // adjust the size only when the device's screen is bigger.
                 if (defaultWidth < widthPixels) {
+                    // content/window's x offset in original pixels
+                    xOffset = ((widthPixels - defaultWidth) / 2);
                     widthPixels = defaultWidth;
                 }
                 if (defaultHeight < heightPixels) {
@@ -153,8 +147,19 @@
                 }
             }
         }
+        compatibilityInfo.setVisibleRect(xOffset, widthPixels, heightPixels);
+        if (compatibilityInfo.isScalingRequired()) {
+            float invertedRatio = compatibilityInfo.applicationInvertedScale;
+            density *= invertedRatio;
+            scaledDensity *= invertedRatio;
+            xdpi *= invertedRatio;
+            ydpi *= invertedRatio;
+            widthPixels *= invertedRatio;
+            heightPixels *= invertedRatio;
+        }
     }
 
+    @Override
     public String toString() {
         return "DisplayMetrics{density=" + density + ", width=" + widthPixels +
             ", height=" + heightPixels + ", scaledDensity=" + scaledDensity +
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 69c6a7c..0e37b26 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -270,28 +270,47 @@
     }
 
     /**
-     * Scales down the cood of this event by the given scale.
+     * Scales down the coordination of this event by the given scale.
      *
      * @hide
      */
     public void scale(float scale) {
-        if (scale != 1.0f) {
-            mX *= scale;
-            mY *= scale;
-            mRawX *= scale;
-            mRawY *= scale;
-            mSize *= scale;
-            mXPrecision *= scale;
-            mYPrecision *= scale;
-            if (mHistory != null) {
-                float[] history = mHistory;
-                int length = history.length;
-                for (int i = 0; i < length; i += 4) {
-                    history[i] *= scale;        // X
-                                                // history[i + 2] == pressure
-                    history[i + 1] *= scale;    // Y
-                    history[i + 3] *= scale;    // Size, TODO: square this?
-                }
+        mX *= scale;
+        mY *= scale;
+        mRawX *= scale;
+        mRawY *= scale;
+        mSize *= scale;
+        mXPrecision *= scale;
+        mYPrecision *= scale;
+        if (mHistory != null) {
+            float[] history = mHistory;
+            int length = history.length;
+            for (int i = 0; i < length; i += 4) {
+                history[i] *= scale;        // X
+                history[i + 1] *= scale;    // Y
+                // no need to scale pressure ([i+2])
+                history[i + 3] *= scale;    // Size, TODO: square this?
+            }
+        }
+    }
+
+    /**
+     * Translate the coordination of the event by given x and y.
+     *
+     * @hide
+     */
+    public void translate(float dx, float dy) {
+        mX += dx;
+        mY += dy;
+        mRawX += dx;
+        mRawY += dx;
+        if (mHistory != null) {
+            float[] history = mHistory;
+            int length = history.length;
+            for (int i = 0; i < length; i += 4) {
+                history[i] += dx;        // X
+                history[i + 1] += dy;    // Y
+                // no need to translate pressure (i+2) and size (i+3) 
             }
         }
     }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6519852..1e2bc1f 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.CompatibilityInfo;
+import android.content.res.CompatibilityInfo.Translator;
 import android.graphics.Canvas;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
@@ -139,24 +140,21 @@
     int mFormat = -1;
     int mType = -1;
     final Rect mSurfaceFrame = new Rect();
-    private final CompatibilityInfo mCompatibilityInfo;
+    private Translator mTranslator;
 
     public SurfaceView(Context context) {
         super(context);
         setWillNotDraw(true);
-        mCompatibilityInfo = context.getResources().getCompatibilityInfo();
     }
     
     public SurfaceView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setWillNotDraw(true);
-        mCompatibilityInfo = context.getResources().getCompatibilityInfo();
     }
 
     public SurfaceView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         setWillNotDraw(true);
-        mCompatibilityInfo = context.getResources().getCompatibilityInfo();
     }
     
     /**
@@ -259,9 +257,9 @@
     public boolean dispatchTouchEvent(MotionEvent event) {
         // SurfaceView uses pre-scaled size unless fixed size is requested. This hook
         // scales the event back to the pre-scaled coordinates for such surface.
-        if (mRequestedWidth < 0 && mCompatibilityInfo.mScalingRequired) {
+        if (mRequestedWidth < 0 && mTranslator != null) {
             MotionEvent scaledBack = MotionEvent.obtain(event);
-            scaledBack.scale(mCompatibilityInfo.mApplicationScale);
+            scaledBack.scale(mTranslator.applicationScale);
             try {
                 return super.dispatchTouchEvent(scaledBack);
             } finally {
@@ -298,15 +296,18 @@
         if (!mHaveFrame) {
             return;
         }
-        float appScale = mCompatibilityInfo.mApplicationScale;
+        mTranslator = ((ViewRoot)getRootView().getParent()).mTranslator;
+
+        float appScale = mTranslator == null ? 1.0f : mTranslator.applicationScale;
         
         int myWidth = mRequestedWidth;
         if (myWidth <= 0) myWidth = getWidth();
         int myHeight = mRequestedHeight;
         if (myHeight <= 0) myHeight = getHeight();
 
-        // Use original size for surface unless fixed size is requested.
-        if (mRequestedWidth <= 0 && mCompatibilityInfo.mScalingRequired) {
+        // Use original size if the app specified the size of the view,
+        // and let the flinger to scale up.
+        if (mRequestedWidth <= 0 && mTranslator != null && mTranslator.scalingRequired) {
             myWidth *= appScale;
             myHeight *= appScale;
         }
@@ -326,7 +327,7 @@
                     + " visible=" + visibleChanged
                     + " left=" + (mLeft != mLocation[0])
                     + " top=" + (mTop != mLocation[1]));
-            
+
             try {
                 final boolean visible = mVisible = mRequestedVisible;
                 mLeft = mLocation[0];
@@ -336,16 +337,23 @@
                 mFormat = mRequestedFormat;
                 mType = mRequestedType;
 
-                // Scaling window's layout here because mLayout is not used elsewhere.
-                mLayout.x = (int) (mLeft * appScale);
-                mLayout.y = (int) (mTop * appScale);
-                mLayout.width = (int) (getWidth() * appScale);
-                mLayout.height = (int) (getHeight() * appScale);
+                // Scaling/Translate window's layout here because mLayout is not used elsewhere.
+                
+                // Places the window relative
+                mLayout.x = mLeft;
+                mLayout.y = mTop;
+                mLayout.width = getWidth();
+                mLayout.height = getHeight();
+                if (mTranslator != null) {
+                    mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);
+                }
+                
                 mLayout.format = mRequestedFormat;
                 mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                               | WindowManager.LayoutParams.FLAG_SCALED
                               | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                               | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                              | WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING
                               ;
 
                 mLayout.memoryType = mRequestedType;
@@ -372,13 +380,6 @@
                         visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
                         mVisibleInsets, mSurface);
 
-                if (mCompatibilityInfo.mScalingRequired) {
-                    float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
-                    mContentInsets.scale(invertedScale);
-                    mVisibleInsets.scale(invertedScale);
-                    mWinFrame.scale(invertedScale);
-                }
-
                 if (localLOGV) Log.i(TAG, "New surface: " + mSurface
                         + ", vis=" + visible + ", frame=" + mWinFrame);
                 mSurfaceFrame.left = 0;
@@ -447,24 +448,14 @@
 
     private static class MyWindow extends IWindow.Stub {
         private final WeakReference<SurfaceView> mSurfaceView;
-        private final CompatibilityInfo mCompatibilityInfo;
 
         public MyWindow(SurfaceView surfaceView) {
             mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
-            mCompatibilityInfo = surfaceView.getContext().getResources().getCompatibilityInfo();
         }
 
         public void resized(int w, int h, Rect coveredInsets,
                 Rect visibleInsets, boolean reportDraw) {
             SurfaceView surfaceView = mSurfaceView.get();
-            if (mCompatibilityInfo.mScalingRequired) {
-                float scale = mCompatibilityInfo.mApplicationInvertedScale;
-                w *= scale;
-                h *= scale;
-                coveredInsets.scale(scale);
-                visibleInsets.scale(scale);
-            }
-
             if (surfaceView != null) {
                 if (localLOGV) Log.v(
                         "SurfaceView", surfaceView + " got resized: w=" +
@@ -627,9 +618,6 @@
             Canvas c = null;
             if (!mDrawingStopped && mWindow != null) {
                 Rect frame = dirty != null ? dirty : mSurfaceFrame;
-                if (mCompatibilityInfo.mScalingRequired) {
-                    frame.scale(mCompatibilityInfo.mApplicationScale);
-                }
                 try {
                     c = mSurface.lockCanvas(frame);
                 } catch (Exception e) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f17f0e4..3bfdde8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6543,7 +6543,7 @@
         boolean changed = false;
 
         if (DBG) {
-            System.out.println(this + " View.setFrame(" + left + "," + top + ","
+            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
                     + right + "," + bottom + ")");
         }
 
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index fe5edc2..a12b14a 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -131,13 +131,12 @@
     Rect mDirty; // will be a graphics.Region soon
     boolean mIsAnimating;
 
-    private CompatibilityInfo mCompatibilityInfo;
+    CompatibilityInfo.Translator mTranslator;
 
     final View.AttachInfo mAttachInfo;
 
     final Rect mTempRect; // used in the transaction to not thrash the heap.
     final Rect mVisRect; // used to retrieve visible rect of focused view.
-    final Point mVisPoint; // used to retrieve global offset of focused view.
 
     boolean mTraversalScheduled;
     boolean mWillDrawSoon;
@@ -225,7 +224,6 @@
         mDirty = new Rect();
         mTempRect = new Rect();
         mVisRect = new Rect();
-        mVisPoint = new Point();
         mWinFrame = new Rect();
         mWindow = new W(this, context);
         mInputMethodCallback = new InputMethodCallback(this);
@@ -394,20 +392,25 @@
             if (mView == null) {
                 mView = view;
                 mWindowAttributes.copyFrom(attrs);
-                mCompatibilityInfo = mView.getContext().getResources().getCompatibilityInfo();
+
+                CompatibilityInfo compatibilityInfo =
+                        mView.getContext().getResources().getCompatibilityInfo();
+                mTranslator = compatibilityInfo.getTranslator(attrs);
                 boolean restore = false;
-                if (mCompatibilityInfo.mScalingRequired || !mCompatibilityInfo.mExpandable) {
+                if (attrs != null && mTranslator != null) {
                     restore = true;
-                    mWindowAttributes.backup();
+                    attrs.backup();
+                    mTranslator.translateWindowLayout(attrs);
                 }
-                if (!mCompatibilityInfo.mExpandable) {
-                    adjustWindowAttributesForCompatibleMode(mWindowAttributes);
-                }
+                if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
+
                 mSoftInputMode = attrs.softInputMode;
                 mWindowAttributesChanged = true;
                 mAttachInfo.mRootView = view;
-                mAttachInfo.mScalingRequired = mCompatibilityInfo.mScalingRequired;
-                mAttachInfo.mApplicationScale = mCompatibilityInfo.mApplicationScale;
+                mAttachInfo.mScalingRequired =
+                        mTranslator == null ? false : mTranslator.scalingRequired;
+                mAttachInfo.mApplicationScale =
+                        mTranslator == null ? 1.0f : mTranslator.applicationScale;
                 if (panelParentView != null) {
                     mAttachInfo.mPanelParentWindowToken
                             = panelParentView.getApplicationWindowToken();
@@ -428,15 +431,14 @@
                     mAttachInfo.mRootView = null;
                     unscheduleTraversals();
                     throw new RuntimeException("Adding window failed", e);
+                } finally {
+                    if (restore) {
+                        attrs.restore();
+                    }
                 }
 
-                if (restore) {
-                    mWindowAttributes.restore();
-                }
-
-                if (mCompatibilityInfo.mScalingRequired) {
-                    mAttachInfo.mContentInsets.scale(
-                            mCompatibilityInfo.mApplicationInvertedScale);
+                if (mTranslator != null) {
+                    mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
                 }
                 mPendingContentInsets.set(mAttachInfo.mContentInsets);
                 mPendingVisibleInsets.set(0, 0, 0, 0);
@@ -548,14 +550,14 @@
 
     public void invalidateChild(View child, Rect dirty) {
         checkThread();
-        if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty);
-        if (mCurScrollY != 0 || mCompatibilityInfo.mScalingRequired) {
+        if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty);
+        if (mCurScrollY != 0 || mTranslator != null) {
             mTempRect.set(dirty);
             if (mCurScrollY != 0) {
                mTempRect.offset(0, -mCurScrollY);
             }
-            if (mCompatibilityInfo.mScalingRequired) {
-                mTempRect.scale(mCompatibilityInfo.mApplicationScale);
+            if (mTranslator != null) {
+                mTranslator.translateRectInAppWindowToScreen(mTempRect);
             }
             dirty = mTempRect;
         }
@@ -574,7 +576,7 @@
         return null;
     }
 
-     public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
+    public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
         if (child != mView) {
             throw new RuntimeException("child is not mine, honest!");
         }
@@ -635,14 +637,14 @@
         boolean viewVisibilityChanged = mViewVisibility != viewVisibility
                 || mNewSurfaceNeeded;
 
-        float appScale = mCompatibilityInfo.mApplicationScale;
+        float appScale = mAttachInfo.mApplicationScale;
 
         WindowManager.LayoutParams params = null;
         if (mWindowAttributesChanged) {
             mWindowAttributesChanged = false;
             params = lp;
         }
-
+        Rect frame = mWinFrame;
         if (mFirst) {
             fullRedrawNeeded = true;
             mLayoutRequested = true;
@@ -667,11 +669,11 @@
             //Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);
 
         } else {
-            desiredWindowWidth = mWinFrame.width();
-            desiredWindowHeight = mWinFrame.height();
+            desiredWindowWidth = frame.width();
+            desiredWindowHeight = frame.height();
             if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
                 if (DEBUG_ORIENTATION) Log.v("ViewRoot",
-                        "View " + host + " resized to: " + mWinFrame);
+                        "View " + host + " resized to: " + frame);
                 fullRedrawNeeded = true;
                 mLayoutRequested = true;
                 windowResizesToFitContent = true;
@@ -817,7 +819,6 @@
                 }
             }
 
-            final Rect frame = mWinFrame;
             boolean initialized = false;
             boolean contentInsetsChanged = false;
             boolean visibleInsetsChanged;
@@ -890,7 +891,7 @@
             } catch (RemoteException e) {
             }
             if (DEBUG_ORIENTATION) Log.v(
-                    "ViewRoot", "Relayout returned: frame=" + mWinFrame + ", surface=" + mSurface);
+                    "ViewRoot", "Relayout returned: frame=" + frame + ", surface=" + mSurface);
 
             attachInfo.mWindowLeft = frame.left;
             attachInfo.mWindowTop = frame.top;
@@ -965,7 +966,6 @@
             if (Config.DEBUG && ViewDebug.profileLayout) {
                 startTime = SystemClock.elapsedRealtime();
             }
-
             host.layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight);
 
             if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
@@ -992,7 +992,10 @@
                         mTmpLocation[1] + host.mBottom - host.mTop);
 
                 host.gatherTransparentRegion(mTransparentRegion);
-                mTransparentRegion.scale(appScale);
+                if (mTranslator != null) {
+                    mTranslator.translateRegionInWindowToScreen(mTransparentRegion);
+                }
+
                 if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
                     mPreviousTransparentRegion.set(mTransparentRegion);
                     // reconfigure window manager
@@ -1023,15 +1026,17 @@
                     = givenContent.bottom = givenVisible.left = givenVisible.top
                     = givenVisible.right = givenVisible.bottom = 0;
             attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
-            if (mCompatibilityInfo.mScalingRequired) {
-                insets.contentInsets.scale(appScale);
-                insets.visibleInsets.scale(appScale);
+            Rect contentInsets = insets.contentInsets;
+            Rect visibleInsets = insets.visibleInsets;
+            if (mTranslator != null) {
+                contentInsets = mTranslator.getTranslatedContentInsets(contentInsets);
+                visibleInsets = mTranslator.getTranslatedVisbileInsets(visibleInsets);
             }
             if (insetsPending || !mLastGivenInsets.equals(insets)) {
                 mLastGivenInsets.set(insets);
                 try {
                     sWindowSession.setInsets(mWindow, insets.mTouchableInsets,
-                            insets.contentInsets, insets.visibleInsets);
+                            contentInsets, visibleInsets);
                 } catch (RemoteException e) {
                 }
             }
@@ -1174,8 +1179,8 @@
             mCurScrollY = yoff;
             fullRedrawNeeded = true;
         }
-        float appScale = mCompatibilityInfo.mApplicationScale;
-        boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
+        float appScale = mAttachInfo.mApplicationScale;
+        boolean scalingRequired = mAttachInfo.mScalingRequired;
 
         Rect dirty = mDirty;
         if (mUseGL) {
@@ -1194,8 +1199,8 @@
                     int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
                     try {
                         canvas.translate(0, -yoff);
-                        if (scalingRequired) {
-                            canvas.scale(appScale, appScale);
+                        if (mTranslator != null) {
+                            mTranslator.translateCanvas(canvas);
                         }
                         mView.draw(canvas);
                         if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
@@ -1246,7 +1251,6 @@
             int top = dirty.top;
             int right = dirty.right;
             int bottom = dirty.bottom;
-
             canvas = surface.lockCanvas(dirty);
 
             if (left != dirty.left || top != dirty.top || right != dirty.right ||
@@ -1302,8 +1306,8 @@
                 int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
                 try {
                     canvas.translate(0, -yoff);
-                    if (scalingRequired) {
-                        canvas.scale(appScale, appScale);
+                    if (mTranslator != null) {
+                        mTranslator.translateCanvas(canvas);
                     }
                     mView.draw(canvas);
                 } finally {
@@ -1616,10 +1620,9 @@
             } else {
                 didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
             }
-            if (event != null && mCompatibilityInfo.mScalingRequired) {
-                event.scale(mCompatibilityInfo.mApplicationInvertedScale);
+            if (event != null && mTranslator != null) {
+                mTranslator.translateEventInScreenToAppWindow(event);
             }
-
             try {
                 boolean handled;
                 if (mView != null && mAdded && event != null) {
@@ -1711,6 +1714,7 @@
         case RESIZED:
             Rect coveredInsets = ((Rect[])msg.obj)[0];
             Rect visibleInsets = ((Rect[])msg.obj)[1];
+
             if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
                     && mPendingContentInsets.equals(coveredInsets)
                     && mPendingVisibleInsets.equals(visibleInsets)) {
@@ -1745,7 +1749,7 @@
                         if (mGlWanted && !mUseGL) {
                             initializeGL();
                             if (mGlCanvas != null) {
-                                float appScale = mCompatibilityInfo.mApplicationScale;
+                                float appScale = mAttachInfo.mApplicationScale;
                                 mGlCanvas.setViewport(
                                         (int) (mWidth * appScale), (int) (mHeight * appScale));
                             }
@@ -2379,18 +2383,16 @@
 
     private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
             boolean insetsPending) throws RemoteException {
+
+        float appScale = mAttachInfo.mApplicationScale;
         boolean restore = false;
-        float appScale = mCompatibilityInfo.mApplicationScale;
-        boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
-        if (params != null && !mCompatibilityInfo.mExpandable) {
+        if (params != null && mTranslator != null) {
             restore = true;
             params.backup();
-            adjustWindowAttributesForCompatibleMode(params);
+            mTranslator.translateWindowLayout(params);
         }
-        if (params != null && scalingRequired) {
-            if (!restore) params.backup();
-            restore = true;
-            params.scale(appScale);
+        if (params != null) {
+            if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params);
         }
         int relayoutResult = sWindowSession.relayout(
                 mWindow, params,
@@ -2401,44 +2403,16 @@
         if (restore) {
             params.restore();
         }
-        if (scalingRequired) {
-            float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
-            mPendingContentInsets.scale(invertedScale);
-            mPendingVisibleInsets.scale(invertedScale);
-            mWinFrame.scale(invertedScale);
+        
+        if (mTranslator != null) {
+            mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
+            mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
+            mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
         }
         return relayoutResult;
     }
 
     /**
-     * Adjust the window's layout parameter for compatibility mode. It replaces FILL_PARENT
-     * with the default window size, and centers if the window wanted to fill
-     * horizontally.
-     *
-     * @param attrs the window's layout params to adjust
-     */
-    private void adjustWindowAttributesForCompatibleMode(WindowManager.LayoutParams attrs) {
-        // fix app windows only
-        if (attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
-            DisplayMetrics metrics = mView.getContext().getResources().getDisplayMetrics();
-            // TODO: improve gravity logic
-            if (attrs.width == ViewGroup.LayoutParams.FILL_PARENT) {
-                attrs.width = metrics.widthPixels;
-                attrs.gravity |= Gravity.CENTER_HORIZONTAL;
-                mWindowAttributesChanged = attrs == mWindowAttributes;
-            }
-            if (attrs.height == ViewGroup.LayoutParams.FILL_PARENT) {
-                attrs.height = metrics.heightPixels;
-                attrs.gravity |= Gravity.TOP;
-                mWindowAttributesChanged = attrs == mWindowAttributes;
-            }
-            if (DEBUG_LAYOUT) {
-                Log.d(TAG, "Adjusted Attributes for compatibility : " + attrs);
-            }
-        }
-    }
-
-    /**
      * {@inheritDoc}
      */
     public void playSoundEffect(int effectId) {
@@ -2541,16 +2515,14 @@
                 + " visibleInsets=" + visibleInsets.toShortString()
                 + " reportDraw=" + reportDraw);
         Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED);
-        if (mCompatibilityInfo.mScalingRequired) {
-            float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
-            coveredInsets.scale(invertedScale);
-            visibleInsets.scale(invertedScale);
-            msg.arg1 = (int) (w * invertedScale);
-            msg.arg2 = (int) (h * invertedScale);
-        } else {
-            msg.arg1 = w;
-            msg.arg2 = h;
+        if (mTranslator != null) {
+            mTranslator.translateRectInScreenToAppWindow(coveredInsets);
+            mTranslator.translateRectInScreenToAppWindow(visibleInsets);
+            w *= mTranslator.applicationInvertedScale;
+            h *= mTranslator.applicationInvertedScale;
         }
+        msg.arg1 = w;
+        msg.arg2 = h;
         msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
         sendMessage(msg);
     }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e295d15..bdb86d7 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -483,6 +483,12 @@
          * {@hide} */
         public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
 
+        /** Window flag: special flag to let a window ignore the compatibility scaling.
+         * This is used by SurfaceView to create a window that does not scale the content.
+         *
+         * {@hide} */
+        public static final int FLAG_NO_COMPATIBILITY_SCALING = 0x00100000;
+
         /** Window flag: a special option intended for system dialogs.  When
          * this flag is set, the window will demand focus unconditionally when
          * it is created.
@@ -978,8 +984,9 @@
 
         /**
          * Scale the layout params' coordinates and size.
+         * @hide
          */
-        void scale(float scale) {
+        public void scale(float scale) {
             x *= scale;
             y *= scale;
             if (width > 0) {
@@ -997,14 +1004,13 @@
         void backup() {
             int[] backup = mCompatibilityParamsBackup;
             if (backup == null) {
-                // we backup 5 elements, x, y, width, height and gravity.
-                backup = mCompatibilityParamsBackup = new int[5];
+                // we backup 4 elements, x, y, width, height
+                backup = mCompatibilityParamsBackup = new int[4];
             }
             backup[0] = x;
             backup[1] = y;
             backup[2] = width;
             backup[3] = height;
-            backup[4] = gravity;
         }
 
         /**
@@ -1018,7 +1024,6 @@
                 y = backup[1];
                 width = backup[2];
                 height = backup[3];
-                gravity = backup[4];
             }
         }
 
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index bd6edfb..0c2cd55 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -990,7 +990,7 @@
         
         int bottomEdge = displayFrame.bottom;
         if (ignoreBottomDecorations) {
-            bottomEdge = WindowManagerImpl.getDefault().getDefaultDisplay().getHeight();
+            bottomEdge = anchor.getContext().getResources().getDisplayMetrics().heightPixels;
         }
         final int distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset;
         final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9479f9e..d8ed4f0 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3681,12 +3681,13 @@
 
     @Override
     protected boolean isPaddingOffsetRequired() {
-        return mShadowRadius != 0;
+        return mShadowRadius != 0 || mDrawables != null;
     }
 
     @Override
     protected int getLeftPaddingOffset() {
-        return (int) Math.min(0, mShadowDx - mShadowRadius);
+        return getCompoundPaddingLeft() - mPaddingLeft +
+                (int) Math.min(0, mShadowDx - mShadowRadius);
     }
 
     @Override
@@ -3701,7 +3702,8 @@
 
     @Override
     protected int getRightPaddingOffset() {
-        return (int) Math.max(0, mShadowDx + mShadowRadius);
+        return -(getCompoundPaddingRight() - mPaddingRight) +
+                (int) Math.max(0, mShadowDx + mShadowRadius);
     }
 
     @Override
@@ -6665,9 +6667,10 @@
             } else if (getLineCount() == 1) {
                 switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                     case Gravity.LEFT:
-                        return (mLayout.getLineRight(0) - mScrollX - (mRight - mLeft) -
-                                getCompoundPaddingLeft() - getCompoundPaddingRight()) /
-                                getHorizontalFadingEdgeLength();
+                        final int textWidth = (mRight - mLeft) - getCompoundPaddingLeft() -
+                                getCompoundPaddingRight();
+                        final float lineWidth = mLayout.getLineWidth(0);
+                        return (lineWidth - textWidth) / getHorizontalFadingEdgeLength();
                     case Gravity.RIGHT:
                         return 0.0f;
                     case Gravity.CENTER_HORIZONTAL:
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index 84ed729..ec63528 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -54,63 +54,70 @@
     long requestBackupTime();
 
     /**
-     * Establish a connection to the back-end data repository, if necessary.  If the transport
-     * needs to initialize state that is not tied to individual applications' backup operations,
-     * this is where it should be done.
-     *
-     * @return Zero on success; a nonzero error code on failure.
-     */
-    int startSession();
-
-    /**
-     * Send one application's data to the backup destination.
+     * Send one application's data to the backup destination.  The transport may send
+     * the data immediately, or may buffer it.  After this is called, {@link #finishBackup}
+     * must be called to ensure the data is sent and recorded successfully.
      *
      * @param packageInfo The identity of the application whose data is being backed up.
      *   This specifically includes the signature list for the package.
      * @param data The data stream that resulted from invoking the application's
      *   BackupService.doBackup() method.  This may be a pipe rather than a file on
      *   persistent media, so it may not be seekable.
-     * @return Zero on success; a nonzero error code on failure.
+     * @return false if errors occurred (the backup should be aborted and rescheduled),
+     *   true if everything is OK so far (but {@link #finishBackup} must be called).
      */
-    int performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor data);
+    boolean performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd);
+
+    /**
+     * Finish sending application data to the backup destination.  This must be
+     * called after {@link #performBackup} to ensure that all data is sent.  Only
+     * when this method returns true can the backup be assumed to have succeeded.
+     *
+     * @return false if errors occurred (the backup should be aborted and rescheduled),
+     *   true if everything is OK so far (but {@link #finishBackup} must be called).
+     */
+    boolean finishBackup();
 
     /**
      * Get the set of backups currently available over this transport.
      *
-     * @return Descriptions of the set of restore images available for this device.
+     * @return Descriptions of the set of restore images available for this device,
+     *   or null if an error occurred (the attempt should be rescheduled).
      **/
     RestoreSet[] getAvailableRestoreSets();
 
     /**
-     * Get the set of applications from a given restore image.
+     * Start restoring application data from backup.  After calling this function,
+     * alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData}
+     * to walk through the actual application data.
      *
      * @param token A backup token as returned by {@link #getAvailableRestoreSets}.
-     * @return An array of PackageInfo objects describing all of the applications
-     *   available for restore from this restore image.  This should include the list
-     *   of signatures for each package so that the Backup Manager can filter using that
-     *   information.
+     * @param packages List of applications to restore (if data is available).
+     *   Application data will be restored in the order given.
+     * @return false if errors occurred (the restore should be aborted and rescheduled),
+     *   true if everything is OK so far (go ahead and call {@link #nextRestorePackage}).
      */
-    PackageInfo[] getAppSet(int token);
+    boolean startRestore(long token, in PackageInfo[] packages);
 
     /**
-     * Retrieve one application's data from the backing store.
-     *
-     * @param token The backup record from which a restore is being requested.
-     * @param packageInfo The identity of the application whose data is being restored.
-     *   This must include the signature list for the package; it is up to the transport
-     *   to verify that the requested app's signatures match the saved backup record
-     *   because the transport cannot necessarily trust the client device.
-     * @param data An open, writable file into which the backup image should be stored.
-     * @return Zero on success; a nonzero error code on failure.
+     * Get the package name of the next application with data in the backup store.
+     * @return The name of one of the packages supplied to {@link #startRestore},
+     *   or "" (the empty string) if no more backup data is available,
+     *   or null if an error occurred (the restore should be aborted and rescheduled).
      */
-    int getRestoreData(int token, in PackageInfo packageInfo, in ParcelFileDescriptor data);
+    String nextRestorePackage();
 
     /**
-     * Terminate the backup session, closing files, freeing memory, and cleaning up whatever
-     * other state the transport required.
-     *
-     * @return Zero on success; a nonzero error code on failure.  Even on failure, the session
-     *         is torn down and must be restarted if another backup is attempted.
+     * Get the data for the application returned by {@link #nextRestorePackage}.
+     * @param data An open, writable file into which the backup data should be stored.
+     * @return false if errors occurred (the restore should be aborted and rescheduled),
+     *   true if everything is OK so far (go ahead and call {@link #nextRestorePackage}).
      */
-    int endSession();
+    boolean getRestoreData(in ParcelFileDescriptor outFd);
+
+    /**
+     * End a restore session (aborting any in-process data transfer as necessary),
+     * freeing any resources and connections used during the restore process.
+     */
+    void finishRestore();
 }
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 3dd71f3..0fbbb3f 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -33,11 +33,8 @@
     private Context mContext;
     private PackageManager mPackageManager;
     private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup");
-    private FileFilter mDirFileFilter = new FileFilter() {
-        public boolean accept(File f) {
-            return f.isDirectory();
-        }
-    };
+    private PackageInfo[] mRestorePackages = null;
+    private int mRestorePackage = -1;  // Index into mRestorePackages
 
 
     public LocalTransport(Context context) {
@@ -51,21 +48,9 @@
         return 0;
     }
 
-    public int startSession() throws RemoteException {
-        if (DEBUG) Log.v(TAG, "session started");
-        mDataDir.mkdirs();
-        return 0;
-    }
-
-    public int endSession() throws RemoteException {
-        if (DEBUG) Log.v(TAG, "session ended");
-        return 0;
-    }
-
-    public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data)
+    public boolean performBackup(PackageInfo packageInfo, ParcelFileDescriptor data)
             throws RemoteException {
         if (DEBUG) Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName);
-        int err = 0;
 
         File packageDir = new File(mDataDir, packageInfo.packageName);
         packageDir.mkdirs();
@@ -101,9 +86,8 @@
                     try {
                         entity.write(buf, 0, dataSize);
                     } catch (IOException e) {
-                        Log.e(TAG, "Unable to update key file "
-                                + entityFile.getAbsolutePath());
-                        err = -1;
+                        Log.e(TAG, "Unable to update key file " + entityFile.getAbsolutePath());
+                        return false;
                     } finally {
                         entity.close();
                     }
@@ -111,14 +95,17 @@
                     entityFile.delete();
                 }
             }
+            return true;
         } catch (IOException e) {
             // oops, something went wrong.  abort the operation and return error.
-            Log.v(TAG, "Exception reading backup input:");
-            e.printStackTrace();
-            err = -1;
+            Log.v(TAG, "Exception reading backup input:", e);
+            return false;
         }
+    }
 
-        return err;
+    public boolean finishBackup() throws RemoteException {
+        if (DEBUG) Log.v(TAG, "finishBackup()");
+        return true;
     }
 
     // Restore handling
@@ -129,72 +116,66 @@
         return array;
     }
 
-    public PackageInfo[] getAppSet(int token) throws android.os.RemoteException {
-        if (DEBUG) Log.v(TAG, "getting app set " + token);
-        // the available packages are the extant subdirs of mDatadir
-        File[] packageDirs = mDataDir.listFiles(mDirFileFilter);
-        ArrayList<PackageInfo> packages = new ArrayList<PackageInfo>();
-        for (File dir : packageDirs) {
-            try {
-                PackageInfo pkg = mPackageManager.getPackageInfo(dir.getName(),
-                        PackageManager.GET_SIGNATURES);
-                if (pkg != null) {
-                    packages.add(pkg);
-                }
-            } catch (NameNotFoundException e) {
-                // restore set contains data for a package not installed on the
-                // phone -- just ignore it.
-            }
-        }
-
-        if (DEBUG) {
-            Log.v(TAG, "Built app set of " + packages.size() + " entries:");
-            for (PackageInfo p : packages) {
-                Log.v(TAG, "    + " + p.packageName);
-            }
-        }
-
-        PackageInfo[] result = new PackageInfo[packages.size()];
-        return packages.toArray(result);
+    public boolean startRestore(long token, PackageInfo[] packages) {
+        if (DEBUG) Log.v(TAG, "start restore " + token);
+        mRestorePackages = packages;
+        mRestorePackage = -1;
+        return true;
     }
 
-    public int getRestoreData(int token, PackageInfo packageInfo, ParcelFileDescriptor outFd)
-            throws android.os.RemoteException {
-        if (DEBUG) Log.v(TAG, "getting restore data " + token + " : " + packageInfo.packageName);
-        // we only support one hardcoded restore set
-        if (token != 0) return -1;
+    public String nextRestorePackage() {
+        if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");
+        while (++mRestorePackage < mRestorePackages.length) {
+            String name = mRestorePackages[mRestorePackage].packageName;
+            if (new File(mDataDir, name).isDirectory()) {
+                if (DEBUG) Log.v(TAG, "  nextRestorePackage() = " + name);
+                return name;
+            }
+        }
 
-        // the data for a given package is at a known location
-        File packageDir = new File(mDataDir, packageInfo.packageName);
+        if (DEBUG) Log.v(TAG, "  no more packages to restore");
+        return "";
+    }
+
+    public boolean getRestoreData(ParcelFileDescriptor outFd) {
+        if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");
+        if (mRestorePackage < 0) throw new IllegalStateException("nextRestorePackage not called");
+        File packageDir = new File(mDataDir, mRestorePackages[mRestorePackage].packageName);
 
         // The restore set is the concatenation of the individual record blobs,
         // each of which is a file in the package's directory
         File[] blobs = packageDir.listFiles();
-        if (DEBUG) Log.v(TAG, "   found " + blobs.length + " key files");
-        int err = 0;
-        if (blobs != null && blobs.length > 0) {
-            BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor());
-            try {
-                for (File f : blobs) {
-                    copyToRestoreData(f, out);
-                }
-            } catch (Exception e) {
-                Log.e(TAG, "Unable to read backup records");
-                err = -1;
-            }
+        if (blobs == null) {
+            Log.e(TAG, "Error listing directory: " + packageDir);
+            return false;  // nextRestorePackage() ensures the dir exists, so this is an error
         }
-        return err;
+
+        // We expect at least some data if the directory exists in the first place
+        if (DEBUG) Log.v(TAG, "  getRestoreData() found " + blobs.length + " key files");
+        BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor());
+        try {
+            for (File f : blobs) {
+                FileInputStream in = new FileInputStream(f);
+                try {
+                    int size = (int) f.length();
+                    byte[] buf = new byte[size];
+                    in.read(buf);
+                    String key = new String(Base64.decode(f.getName()));
+                    if (DEBUG) Log.v(TAG, "    ... key=" + key + " size=" + size);
+                    out.writeEntityHeader(key, size);
+                    out.writeEntityData(buf, size);
+                } finally {
+                    in.close();
+                }
+            }
+            return true;
+        } catch (IOException e) {
+            Log.e(TAG, "Unable to read backup records", e);
+            return false;
+        }
     }
 
-    private void copyToRestoreData(File f, BackupDataOutput out) throws IOException {
-        FileInputStream in = new FileInputStream(f);
-        int size = (int) f.length();
-        byte[] buf = new byte[size];
-        in.read(buf);
-        String key = new String(Base64.decode(f.getName()));
-        if (DEBUG) Log.v(TAG, "   ... copy to stream: key=" + key
-                + " size=" + size);
-        out.writeEntityHeader(key, size);
-        out.writeEntityData(buf, size);
+    public void finishRestore() {
+        if (DEBUG) Log.v(TAG, "finishRestore()");
     }
 }
diff --git a/core/java/com/android/internal/backup/SystemBackupAgent.java b/core/java/com/android/internal/backup/SystemBackupAgent.java
new file mode 100644
index 0000000..6b396d7
--- /dev/null
+++ b/core/java/com/android/internal/backup/SystemBackupAgent.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.backup;
+
+import android.backup.AbsoluteFileBackupHelper;
+import android.backup.BackupHelperAgent;
+
+/**
+ * Backup agent for various system-managed data
+ */
+public class SystemBackupAgent extends BackupHelperAgent {
+    // the set of files that we back up whole, as absolute paths
+    String[] mFiles = {
+            /* WallpaperService.WALLPAPER_FILE */
+            "/data/data/com.android.settings/files/wallpaper",
+            };
+
+    public void onCreate() {
+        addHelper("system_files", new AbsoluteFileBackupHelper(this, mFiles));
+    }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index fc4a9c4..a03802d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -2836,14 +2836,12 @@
      * @param name process name
      * @return the statistics object for the process
      */
-    public Uid.Proc getProcessStatsLocked(String name) {
+    public Uid.Proc getProcessStatsLocked(String name, int pid) {
         int uid;
         if (mUidCache.containsKey(name)) {
             uid = mUidCache.get(name);
         } else {
-            // TODO: Find the actual uid from /proc/pid/status. For now use the hashcode of the
-            // process name
-            uid = name.hashCode();
+            uid = Process.getUidForPid(pid);
             mUidCache.put(name, uid);
         }
         Uid u = getUidStatsLocked(uid);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0c90769..db31818 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1000,6 +1000,7 @@
                  android:hasCode="false"
                  android:label="@string/android_system_label"
                  android:allowClearUserData="false"
+                 android:backupAgent="com.android.internal.backup.SystemBackupAgent"
                  android:icon="@drawable/ic_launcher_android">
         <activity android:name="com.android.internal.app.ChooserActivity"
                 android:theme="@style/Theme.Dialog.Alert"
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index f861400..d2721f1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -592,6 +592,21 @@
         loadIntegerSetting(stmt, Settings.System.SCREEN_OFF_TIMEOUT,
                 R.integer.def_screen_off_timeout);
 
+        // Set default cdma emergency tone
+        loadSetting(stmt, Settings.System.EMERGENCY_TONE, 0);
+
+        // Set default cdma call auto retry
+        loadSetting(stmt, Settings.System.CALL_AUTO_RETRY, 0);
+
+        // Set default cdma DTMF type
+        loadSetting(stmt, Settings.System.DTMF_TONE_TYPE_WHEN_DIALING, 0);
+
+        // Set default hearing aid
+        loadSetting(stmt, Settings.System.HEARING_AID, 0);
+
+        // Set default tty mode
+        loadSetting(stmt, Settings.System.TTY_MODE, 0);
+
         loadBooleanSetting(stmt, Settings.System.AIRPLANE_MODE_ON,
                 R.bool.def_airplane_mode_on);
 
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 197404e..efa6179 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -76,8 +76,7 @@
     private static final boolean DEBUG = true;
 
     // Default time to wait after data changes before we back up the data
-    private static final long COLLECTION_INTERVAL = 1000;
-    //private static final long COLLECTION_INTERVAL = 3 * 60 * 1000;
+    private static final long COLLECTION_INTERVAL = 3 * 60 * 1000;
 
     private static final int MSG_RUN_BACKUP = 1;
     private static final int MSG_RUN_FULL_BACKUP = 2;
@@ -351,28 +350,29 @@
     void addPackageParticipantsLocked(String packageName) {
         // Look for apps that define the android:backupAgent attribute
         if (DEBUG) Log.v(TAG, "addPackageParticipantsLocked: " + packageName);
-        List<ApplicationInfo> targetApps = allAgentApps();
+        List<PackageInfo> targetApps = allAgentPackages();
         addPackageParticipantsLockedInner(packageName, targetApps);
     }
 
     private void addPackageParticipantsLockedInner(String packageName,
-            List<ApplicationInfo> targetApps) {
+            List<PackageInfo> targetPkgs) {
         if (DEBUG) {
-            Log.v(TAG, "Adding " + targetApps.size() + " backup participants:");
-            for (ApplicationInfo a : targetApps) {
-                Log.v(TAG, "    " + a + " agent=" + a.backupAgentName);
+            Log.v(TAG, "Adding " + targetPkgs.size() + " backup participants:");
+            for (PackageInfo p : targetPkgs) {
+                Log.v(TAG, "    " + p + " agent=" + p.applicationInfo.backupAgentName
+                        + " uid=" + p.applicationInfo.uid);
             }
         }
 
-        for (ApplicationInfo app : targetApps) {
-            if (packageName == null || app.packageName.equals(packageName)) {
-                int uid = app.uid;
+        for (PackageInfo pkg : targetPkgs) {
+            if (packageName == null || pkg.packageName.equals(packageName)) {
+                int uid = pkg.applicationInfo.uid;
                 HashSet<ApplicationInfo> set = mBackupParticipants.get(uid);
                 if (set == null) {
                     set = new HashSet<ApplicationInfo>();
                     mBackupParticipants.put(uid, set);
                 }
-                set.add(app);
+                set.add(pkg.applicationInfo);
                 backUpPackageManagerData();
             }
         }
@@ -382,67 +382,67 @@
     // 'packageName' is null, *all* participating apps will be removed.
     void removePackageParticipantsLocked(String packageName) {
         if (DEBUG) Log.v(TAG, "removePackageParticipantsLocked: " + packageName);
-        List<ApplicationInfo> allApps = null;
+        List<PackageInfo> allApps = null;
         if (packageName != null) {
-            allApps = new ArrayList<ApplicationInfo>();
+            allApps = new ArrayList<PackageInfo>();
             try {
-                ApplicationInfo app = mPackageManager.getApplicationInfo(packageName, 0);
-                allApps.add(app);
+                int flags = PackageManager.GET_SIGNATURES;
+                allApps.add(mPackageManager.getPackageInfo(packageName, flags));
             } catch (Exception e) {
-                // just skip it
+                // just skip it (???)
             }
         } else {
             // all apps with agents
-            allApps = allAgentApps();
+            allApps = allAgentPackages();
         }
         removePackageParticipantsLockedInner(packageName, allApps);
     }
 
     private void removePackageParticipantsLockedInner(String packageName,
-            List<ApplicationInfo> agents) {
+            List<PackageInfo> agents) {
         if (DEBUG) {
             Log.v(TAG, "removePackageParticipantsLockedInner (" + packageName
                     + ") removing " + agents.size() + " entries");
-            for (ApplicationInfo a : agents) {
-                Log.v(TAG, "    - " + a);
+            for (PackageInfo p : agents) {
+                Log.v(TAG, "    - " + p);
             }
         }
-        for (ApplicationInfo app : agents) {
-            if (packageName == null || app.packageName.equals(packageName)) {
-                int uid = app.uid;
+        for (PackageInfo pkg : agents) {
+            if (packageName == null || pkg.packageName.equals(packageName)) {
+                int uid = pkg.applicationInfo.uid;
                 HashSet<ApplicationInfo> set = mBackupParticipants.get(uid);
                 if (set != null) {
                     // Find the existing entry with the same package name, and remove it.
                     // We can't just remove(app) because the instances are different.
                     for (ApplicationInfo entry: set) {
-                        if (entry.packageName.equals(app.packageName)) {
+                        if (entry.packageName.equals(pkg.packageName)) {
                             set.remove(entry);
                             backUpPackageManagerData();
                             break;
                         }
                     }
                     if (set.size() == 0) {
-                        mBackupParticipants.delete(uid);                    }
+                        mBackupParticipants.delete(uid);
+                    }
                 }
             }
         }
     }
 
     // Returns the set of all applications that define an android:backupAgent attribute
-    private List<ApplicationInfo> allAgentApps() {
+    private List<PackageInfo> allAgentPackages() {
         // !!! TODO: cache this and regenerate only when necessary
-        List<ApplicationInfo> allApps = mPackageManager.getInstalledApplications(0);
-        int N = allApps.size();
-        if (N > 0) {
-            for (int a = N-1; a >= 0; a--) {
-                ApplicationInfo app = allApps.get(a);
-                if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
-                        || app.backupAgentName == null) {
-                    allApps.remove(a);
-                }
+        int flags = PackageManager.GET_SIGNATURES;
+        List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags);
+        int N = packages.size();
+        for (int a = N-1; a >= 0; a--) {
+            ApplicationInfo app = packages.get(a).applicationInfo;
+            if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
+                    || app.backupAgentName == null) {
+                packages.remove(a);
             }
         }
-        return allApps;
+        return packages;
     }
 
     // Reset the given package's known backup participants.  Unlike add/remove, the update
@@ -455,7 +455,7 @@
         if (DEBUG) Log.v(TAG, "updatePackageParticipantsLocked: " + packageName);
 
         // brute force but small code size
-        List<ApplicationInfo> allApps = allAgentApps();
+        List<PackageInfo> allApps = allAgentPackages();
         removePackageParticipantsLockedInner(packageName, allApps);
         addPackageParticipantsLockedInner(packageName, allApps);
     }
@@ -578,17 +578,7 @@
         public void run() {
             if (DEBUG) Log.v(TAG, "Beginning backup of " + mQueue.size() + " targets");
 
-            // start up the transport
-            try {
-                mTransport.startSession();
-            } catch (Exception e) {
-                Log.e(TAG, "Error session transport");
-                e.printStackTrace();
-                return;
-            }
-
-            // The transport is up and running.  First, back up the package manager
-            // metadata if necessary
+            // First, back up the package manager metadata if necessary
             boolean doPackageManager;
             synchronized (BackupManagerService.this) {
                 doPackageManager = mDoPackageManager;
@@ -601,7 +591,7 @@
                 if (DEBUG) Log.i(TAG, "Running PM backup pass as well");
 
                 PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
-                        mPackageManager, allAgentApps());
+                        mPackageManager, allAgentPackages());
                 BackupRequest pmRequest = new BackupRequest(new ApplicationInfo(), false);
                 pmRequest.appInfo.packageName = PACKAGE_MANAGER_SENTINEL;
                 processOneBackup(pmRequest,
@@ -614,10 +604,12 @@
 
             // Finally, tear down the transport
             try {
-                mTransport.endSession();
-            } catch (Exception e) {
-                Log.e(TAG, "Error ending transport");
-                e.printStackTrace();
+                if (!mTransport.finishBackup()) {
+                    // STOPSHIP TODO: handle errors
+                    Log.e(TAG, "Backup failure in finishBackup()");
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error in finishBackup()", e);
             }
 
             if (!mJournal.delete()) {
@@ -712,24 +704,18 @@
                     if (DEBUG) Log.v(TAG, "doBackup() success; calling transport");
                     backupData =
                         ParcelFileDescriptor.open(backupDataName, ParcelFileDescriptor.MODE_READ_ONLY);
-                    int error = transport.performBackup(packInfo, backupData);
+                    if (!transport.performBackup(packInfo, backupData)) {
+                        // STOPSHIP TODO: handle errors
+                        Log.e(TAG, "Backup failure in performBackup()");
+                    }
 
                     // !!! TODO: After successful transport, delete the now-stale data
                     // and juggle the files so that next time the new state is passed
                     //backupDataName.delete();
                     newStateName.renameTo(savedStateName);
                 }
-            } catch (NameNotFoundException e) {
-                Log.e(TAG, "Package not found on backup: " + packageName);
-            } catch (FileNotFoundException fnf) {
-                Log.w(TAG, "File not found on backup: ");
-                fnf.printStackTrace();
-            } catch (RemoteException e) {
-                Log.d(TAG, "Remote target " + request.appInfo.packageName + " threw during backup:");
-                e.printStackTrace();
             } catch (Exception e) {
-                Log.w(TAG, "Final exception guard in backup: ");
-                e.printStackTrace();
+                Log.e(TAG, "Error backing up " + packageName, e);
             }
         }
     }
@@ -737,25 +723,6 @@
 
     // ----- Restore handling -----
 
-    // Is the given package restorable on this device?  Returns the on-device app's
-    // ApplicationInfo struct if it is; null if not.
-    //
-    // !!! TODO: also consider signatures
-    PackageInfo isRestorable(PackageInfo packageInfo) {
-        if (packageInfo.packageName != null) {
-            try {
-                PackageInfo app = mPackageManager.getPackageInfo(packageInfo.packageName,
-                        PackageManager.GET_SIGNATURES);
-                if ((app.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0) {
-                    return app;
-                }
-            } catch (Exception e) {
-                // doesn't exist on this device, or other error -- just ignore it.
-            }
-        }
-        return null;
-    }
-
     private boolean signaturesMatch(Signature[] storedSigs, Signature[] deviceSigs) {
         // Allow unsigned apps, but not signed on one device and unsigned on the other
         // !!! TODO: is this the right policy?
@@ -816,130 +783,141 @@
             /**
              * Restore sequence:
              *
-             * 1. start up the transport session
-             * 2. get the restore set description for our identity
-             * 3. for each app in the restore set:
+             * 1. get the restore set description for our identity
+             * 2. for each app in the restore set:
              *    3.a. if it's restorable on this device, add it to the restore queue
-             * 4. for each app in the restore queue:
-             *    4.a. clear the app data
-             *    4.b. get the restore data for the app from the transport
-             *    4.c. launch the backup agent for the app
-             *    4.d. agent.doRestore() with the data from the server
-             *    4.e. unbind the agent [and kill the app?]
-             * 5. shut down the transport
+             * 3. for each app in the restore queue:
+             *    3.a. clear the app data
+             *    3.b. get the restore data for the app from the transport
+             *    3.c. launch the backup agent for the app
+             *    3.d. agent.doRestore() with the data from the server
+             *    3.e. unbind the agent [and kill the app?]
+             * 4. shut down the transport
              */
 
-            int err = -1;
+            // build the set of apps to restore
             try {
-                err = mTransport.startSession();
-            } catch (Exception e) {
-                Log.e(TAG, "Error starting transport for restore");
-                e.printStackTrace();
-            }
+                RestoreSet[] images = mTransport.getAvailableRestoreSets();
+                if (images == null) {
+                    // STOPSHIP TODO: Handle the failure somehow?
+                    Log.e(TAG, "Error getting restore sets");
+                    return;
+                }
 
-            if (err == 0) {
-                // build the set of apps to restore
-                try {
-                    RestoreSet[] images = mTransport.getAvailableRestoreSets();
-                    if (images.length > 0) {
-                        // !!! TODO: pick out the set for this token
-                        mImage = images[0];
+                if (images.length == 0) {
+                    Log.i(TAG, "No restore sets available");
+                    return;
+                }
 
-                        // Pull the Package Manager metadata from the restore set first
-                        PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
-                                mPackageManager, allAgentApps());
-                        PackageInfo pmApp = new PackageInfo();
-                        pmApp.packageName = PACKAGE_MANAGER_SENTINEL;
-                        // !!! TODO: version currently ignored when 'restoring' the PM metadata
-                        processOneRestore(pmApp, 0,
-                                IBackupAgent.Stub.asInterface(pmAgent.onBind()));
+                mImage = images[0];
 
-                        // build the set of apps we will attempt to restore
-                        PackageInfo[] packages = mTransport.getAppSet(mImage.token);
-                        HashSet<RestoreRequest> appsToRestore = new HashSet<RestoreRequest>();
-                        for (PackageInfo pkg: packages) {
-                            // get the real PackageManager idea of the package
-                            PackageInfo app = isRestorable(pkg);
-                            if (app != null) {
-                                // Validate against the backed-up signature block, too
-                                Metadata info = pmAgent.getRestoredMetadata(app.packageName);
-                                if (info != null) {
-                                    if (app.versionCode >= info.versionCode) {
-                                        if (DEBUG) Log.v(TAG, "Restore version "
-                                                + info.versionCode
-                                                + " compatible with app version "
-                                                + app.versionCode);
-                                        if (signaturesMatch(info.signatures, app.signatures)) {
-                                            appsToRestore.add(
-                                                    new RestoreRequest(app, info.versionCode));
-                                        } else {
-                                            Log.w(TAG, "Sig mismatch restoring "
-                                                    + app.packageName);
-                                        }
-                                    } else {
-                                        Log.i(TAG, "Restore set for " + app.packageName
-                                                + " is too new [" + info.versionCode
-                                                + "] for installed app version "
-                                                + app.versionCode);
-                                    }
-                                } else {
-                                    Log.d(TAG, "Unable to get metadata for "
-                                            + app.packageName);
-                                }
-                            }
-                        }
+                // Get the list of all packages which have backup enabled.
+                // (Include the Package Manager metadata pseudo-package first.)
+                ArrayList<PackageInfo> restorePackages = new ArrayList<PackageInfo>();
+                PackageInfo omPackage = new PackageInfo();
+                omPackage.packageName = PACKAGE_MANAGER_SENTINEL;
+                restorePackages.add(omPackage);
 
-                        // now run the restore queue
-                        doQueuedRestores(appsToRestore);
+                List<PackageInfo> agentPackages = allAgentPackages();
+                restorePackages.addAll(agentPackages);
+
+                // STOPSHIP TODO: pick out the set for this token (instead of images[0])
+                long token = images[0].token;
+                if (!mTransport.startRestore(token, restorePackages.toArray(new PackageInfo[0]))) {
+                    // STOPSHIP TODO: Handle the failure somehow?
+                    Log.e(TAG, "Error starting restore operation");
+                    return;
+                }
+
+                String packageName = mTransport.nextRestorePackage();
+                if (packageName == null) {
+                    // STOPSHIP TODO: Handle the failure somehow?
+                    Log.e(TAG, "Error getting first restore package");
+                    return;
+                } else if (packageName.equals("")) {
+                    Log.i(TAG, "No restore data available");
+                    return;
+                } else if (!packageName.equals(PACKAGE_MANAGER_SENTINEL)) {
+                    Log.e(TAG, "Expected restore data for \"" + PACKAGE_MANAGER_SENTINEL
+                          + "\", found only \"" + packageName + "\"");
+                    return;
+                }
+
+                // Pull the Package Manager metadata from the restore set first
+                PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
+                        mPackageManager, agentPackages);
+                processOneRestore(omPackage, 0, IBackupAgent.Stub.asInterface(pmAgent.onBind()));
+
+                for (;;) {
+                    packageName = mTransport.nextRestorePackage();
+                    if (packageName == null) {
+                        // STOPSHIP TODO: Handle the failure somehow?
+                        Log.e(TAG, "Error getting next restore package");
+                        return;
+                    } else if (packageName.equals("")) {
+                        break;
                     }
-                } catch (RemoteException e) {
-                    // can't happen; transports run locally
-                }
 
-                // done; shut down the transport
-                try {
-                    mTransport.endSession();
-                } catch (Exception e) {
-                    Log.e(TAG, "Error ending transport for restore");
-                    e.printStackTrace();
-                }
-            }
+                    Metadata metaInfo = pmAgent.getRestoredMetadata(packageName);
+                    if (metaInfo == null) {
+                        Log.e(TAG, "Missing metadata for " + packageName);
+                        continue;
+                    }
 
-            // even if the initial session startup failed, report that we're done here
-        }
+                    int flags = PackageManager.GET_SIGNATURES;
+                    PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, flags);
+                    if (metaInfo.versionCode > packageInfo.versionCode) {
+                        Log.w(TAG, "Package " + packageName
+                                + " restore version [" + metaInfo.versionCode
+                                + "] is too new for installed version ["
+                                + packageInfo.versionCode + "]");
+                        continue;
+                    }
 
-        // restore each app in the queue
-        void doQueuedRestores(HashSet<RestoreRequest> appsToRestore) {
-            for (RestoreRequest req : appsToRestore) {
-                PackageInfo app = req.app;
-                Log.d(TAG, "starting agent for restore of " + app);
+                    if (!signaturesMatch(metaInfo.signatures, packageInfo.signatures)) {
+                        Log.w(TAG, "Signature mismatch restoring " + packageName);
+                        continue;
+                    }
 
-                try {
-                    // Remove the app's data first
-                    clearApplicationDataSynchronous(app.packageName);
+                    if (DEBUG) Log.v(TAG, "Package " + packageName
+                            + " restore version [" + metaInfo.versionCode
+                            + "] is compatible with installed version ["
+                            + packageInfo.versionCode + "]");
 
-                    // Now perform the restore into the clean app
-                    IBackupAgent agent = bindToAgentSynchronous(app.applicationInfo,
+                    // Now perform the actual restore
+                    clearApplicationDataSynchronous(packageName);
+                    IBackupAgent agent = bindToAgentSynchronous(
+                            packageInfo.applicationInfo,
                             IApplicationThread.BACKUP_MODE_RESTORE);
-                    if (agent != null) {
-                        processOneRestore(app, req.storedAppVersion, agent);
+                    if (agent == null) {
+                        Log.w(TAG, "Can't find backup agent for " + packageName);
+                        continue;
                     }
 
-                    // unbind even on timeout, just in case
-                    mActivityManager.unbindBackupAgent(app.applicationInfo);
-                } catch (SecurityException ex) {
-                    // Try for the next one.
-                    Log.d(TAG, "error in bind", ex);
-                } catch (RemoteException e) {
-                    // can't happen
+                    try {
+                        processOneRestore(packageInfo, metaInfo.versionCode, agent);
+                    } finally {
+                        // unbind even on timeout or failure, just in case
+                        mActivityManager.unbindBackupAgent(packageInfo.applicationInfo);
+                    }
                 }
-
+            } catch (NameNotFoundException e) {
+                // STOPSHIP TODO: Handle the failure somehow?
+                Log.e(TAG, "Invalid paackage restoring data", e);
+            } catch (RemoteException e) {
+                // STOPSHIP TODO: Handle the failure somehow?
+                Log.e(TAG, "Error restoring data", e);
+            } finally {
+                try {
+                    mTransport.finishRestore();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error finishing restore", e);
+                }
             }
         }
 
-        // Do the guts of a restore of one application, derived from the 'mImage'
-        // restore set via the 'mTransport' transport.
-        void processOneRestore(PackageInfo app, int storedAppVersion, IBackupAgent agent) {
+        // Do the guts of a restore of one application, using mTransport.getRestoreData().
+        void processOneRestore(PackageInfo app, int appVersionCode, IBackupAgent agent) {
             // !!! TODO: actually run the restore through mTransport
             final String packageName = app.packageName;
 
@@ -954,11 +932,12 @@
 
                 // Run the transport's restore pass
                 // Run the target's backup pass
-                int err = -1;
                 try {
-                    err = mTransport.getRestoreData(mImage.token, app, backupData);
-                } catch (RemoteException e) {
-                    // can't happen
+                    if (!mTransport.getRestoreData(backupData)) {
+                        // STOPSHIP TODO: Handle this error somehow?
+                        Log.e(TAG, "Error getting restore data for " + packageName);
+                        return;
+                    }
                 } finally {
                     backupData.close();
                 }
@@ -973,30 +952,18 @@
                 backupData = ParcelFileDescriptor.open(backupDataName,
                             ParcelFileDescriptor.MODE_READ_ONLY);
 
-                boolean success = false;
                 try {
-                    agent.doRestore(backupData, storedAppVersion, newState);
-                    success = true;
-                } catch (Exception e) {
-                    Log.e(TAG, "Restore failed for " + packageName);
-                    e.printStackTrace();
+                    agent.doRestore(backupData, appVersionCode, newState);
                 } finally {
                     newState.close();
                     backupData.close();
                 }
 
                 // if everything went okay, remember the recorded state now
-                if (success) {
-                    File savedStateName = new File(mStateDir, packageName);
-                    newStateName.renameTo(savedStateName);
-                }
-            } catch (FileNotFoundException fnfe) {
-                Log.v(TAG, "Couldn't open file for restore: " + fnfe);
-            } catch (IOException ioe) {
-                Log.e(TAG, "Unable to process restore file: " + ioe);
+                File savedStateName = new File(mStateDir, packageName);
+                newStateName.renameTo(savedStateName);
             } catch (Exception e) {
-                Log.e(TAG, "Final exception guard in restore:");
-                e.printStackTrace();
+                Log.e(TAG, "Error restoring data for " + packageName, e);
             }
         }
     }
@@ -1206,7 +1173,7 @@
             mContext.enforceCallingPermission("android.permission.BACKUP",
                     "endRestoreSession");
 
-            mRestoreTransport.endSession();
+            mRestoreTransport.finishRestore();
             mRestoreTransport = null;
             synchronized(BackupManagerService.this) {
                 if (BackupManagerService.this.mActiveRestoreSession == this) {
diff --git a/services/java/com/android/server/PackageManagerBackupAgent.java b/services/java/com/android/server/PackageManagerBackupAgent.java
index d620eb1..66fb86d 100644
--- a/services/java/com/android/server/PackageManagerBackupAgent.java
+++ b/services/java/com/android/server/PackageManagerBackupAgent.java
@@ -57,7 +57,7 @@
     // is stored using the package name as a key)
     private static final String GLOBAL_METADATA_KEY = "@meta@";
 
-    private List<ApplicationInfo> mAllApps;
+    private List<PackageInfo> mAllPackages;
     private PackageManager mPackageManager;
     private HashMap<String, Metadata> mRestoredSignatures;
 
@@ -73,9 +73,9 @@
 
     // We're constructed with the set of applications that are participating
     // in backup.  This set changes as apps are installed & removed.
-    PackageManagerBackupAgent(PackageManager packageMgr, List<ApplicationInfo> apps) {
+    PackageManagerBackupAgent(PackageManager packageMgr, List<PackageInfo> packages) {
         mPackageManager = packageMgr;
-        mAllApps = apps;
+        mAllPackages = packages;
         mRestoredSignatures = null;
     }
 
@@ -118,8 +118,8 @@
 
             // For each app we have on device, see if we've backed it up yet.  If not,
             // write its signature block to the output, keyed on the package name.
-            for (ApplicationInfo app : mAllApps) {
-                String packName = app.packageName;
+            for (PackageInfo pkg : mAllPackages) {
+                String packName = pkg.packageName;
                 if (!existing.contains(packName)) {
                     // We haven't stored this app's signatures yet, so we do that now
                     try {
@@ -186,7 +186,7 @@
         }
 
         // Finally, write the new state blob -- just the list of all apps we handled
-        writeStateFile(mAllApps, newState);
+        writeStateFile(mAllPackages, newState);
     }
 
     // "Restore" here is a misnomer.  What we're really doing is reading back the
@@ -327,7 +327,7 @@
     }
 
     // Util: write out our new backup state file
-    private void writeStateFile(List<ApplicationInfo> apps, ParcelFileDescriptor stateFile) {
+    private void writeStateFile(List<PackageInfo> pkgs, ParcelFileDescriptor stateFile) {
         FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor());
         DataOutputStream out = new DataOutputStream(outstream);
 
@@ -338,8 +338,8 @@
             out.write(metaNameBuf);
 
             // now write all the app names too
-            for (ApplicationInfo app : apps) {
-                byte[] pkgNameBuf = app.packageName.getBytes();
+            for (PackageInfo pkg : pkgs) {
+                byte[] pkgNameBuf = pkg.packageName.getBytes();
                 out.writeInt(pkgNameBuf.length);
                 out.write(pkgNameBuf);
             }
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index d2e5555..857bfaa 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -968,35 +968,7 @@
 
             if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
             if (a != null && mSettings.isEnabledLP(a.info, flags)) {
-                ActivityInfo ainfo = PackageParser.generateActivityInfo(a, flags);
-                if (ainfo != null) {
-                    ApplicationInfo appInfo = getApplicationInfo(component.getPackageName(),
-                            PackageManager.GET_SUPPORTS_DENSITIES);
-                    if (appInfo != null &&
-                            (appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) == 0) {
-                        // Check if the screen size is same as what the application expect.
-                        CompatibilityInfo info = new CompatibilityInfo(appInfo);
-                        DisplayMetrics metrics = new DisplayMetrics();
-                        metrics.setTo(mMetrics);
-                        int orientation = mMetrics.widthPixels > mMetrics.heightPixels ?
-                                Configuration.ORIENTATION_LANDSCAPE :
-                                Configuration.ORIENTATION_PORTRAIT;
-                        metrics.updateMetrics(info, orientation);
-                        if (!info.mExpandable) {
-                            // Don't allow an app that cannot expand to handle rotation.
-                            ainfo.configChanges &= ~ ActivityInfo.CONFIG_ORIENTATION;
-                        } else {
-                            appInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
-                        }
-                        if (DEBUG_SETTINGS) {
-                            Log.d(TAG, "component=" + component +
-                                    ", expandable:" +
-                                    ((appInfo.flags &
-                                            ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0));
-                        }
-                    }
-                }
-                return ainfo;
+                return PackageParser.generateActivityInfo(a, flags);
             }
             if (mResolveComponentName.equals(component)) {
                 return mResolveActivity;
diff --git a/services/java/com/android/server/WallpaperService.java b/services/java/com/android/server/WallpaperService.java
index 5532894..d921baf 100644
--- a/services/java/com/android/server/WallpaperService.java
+++ b/services/java/com/android/server/WallpaperService.java
@@ -18,8 +18,10 @@
 
 import static android.os.FileObserver.*;
 import static android.os.ParcelFileDescriptor.*;
+
 import android.app.IWallpaperService;
 import android.app.IWallpaperServiceCallback;
+import android.backup.BackupManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
@@ -154,7 +156,16 @@
     public ParcelFileDescriptor setWallpaper() {
         checkPermission(android.Manifest.permission.SET_WALLPAPER);
         try {
-            return ParcelFileDescriptor.open(WALLPAPER_FILE, MODE_CREATE|MODE_READ_WRITE);
+            ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE,
+                    MODE_CREATE|MODE_READ_WRITE);
+
+            // changing the wallpaper means we'll need to back up the new one
+            long origId = Binder.clearCallingIdentity();
+            BackupManager bm = new BackupManager(mContext);
+            bm.dataChanged();
+            Binder.restoreCallingIdentity(origId);
+
+            return fd;
         } catch (FileNotFoundException e) {
             if (Config.LOGD) Log.d(TAG, "Error setting wallpaper", e);
         }
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 5236a91..8cdc1dc 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -1524,8 +1524,7 @@
                 }
             }
             
-            final BatteryStatsImpl bstats =
-                    (BatteryStatsImpl) mBatteryStatsService.getActiveStatistics();
+            final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
             synchronized(bstats) {
                 synchronized(mPidsSelfLocked) {
                     if (haveNewCpuStats) {
@@ -1540,7 +1539,7 @@
                                     ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
                                 } else {
                                     BatteryStatsImpl.Uid.Proc ps =
-                                            bstats.getProcessStatsLocked(st.name);
+                                            bstats.getProcessStatsLocked(st.name, st.pid);
                                     if (ps != null) {
                                         ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
                                     }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a79eb3a..bf5df88 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -612,6 +612,21 @@
     }
 
     /**
+     * Returns the voice mail count.
+     * <p>
+     * Requires Permission:
+     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * @hide
+     */
+    public int getVoiceMessageCount() {
+        try {
+            return getITelephony().getVoiceMessageCount();
+        } catch (RemoteException ex) {
+        }
+        return 0;
+    }
+
+    /**
      * Retrieves the alphabetic identifier associated with the voice
      * mail number.
      * <p>
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 6e6f64c..d83b135 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -241,7 +241,7 @@
     /**
       * Returns the unread count of voicemails
       */
-    int getCountVoiceMessages();
+    int getVoiceMessageCount();
 
 }
 
diff --git a/telephony/java/com/android/internal/telephony/IccRecords.java b/telephony/java/com/android/internal/telephony/IccRecords.java
index 114094b..ea24c25 100644
--- a/telephony/java/com/android/internal/telephony/IccRecords.java
+++ b/telephony/java/com/android/internal/telephony/IccRecords.java
@@ -196,7 +196,7 @@
      * If not available (eg, on an older CPHS SIM) -1 is returned if
      * getVoiceMessageWaiting() is true
      */
-    public int getCountVoiceMessages() {
+    public int getVoiceMessageCount() {
         return countVoiceMessages;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index cdbfd61..c8d384d 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -831,7 +831,7 @@
      * Returns unread voicemail count. This count is shown when the  voicemail
      * notification is expanded.<p>
      */
-    int getCountVoiceMessages();
+    int getVoiceMessageCount();
 
     /**
      * Returns the alpha tag associated with the voice mail number.
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index c34f26e..f6665aa 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -651,6 +651,11 @@
         mNotifier.notifyDataActivity(this);
     }
 
+    public void notifyMessageWaitingIndicator() {
+        // This function is added to send the notification to DefaultPhoneNotifier.
+        mNotifier.notifyMessageWaitingChanged(this);
+    }
+
     public void notifyDataConnection(String reason) {
         mNotifier.notifyDataConnection(this, reason);
     }
@@ -658,7 +663,7 @@
     public abstract String getPhoneName();
 
     /** @hide */
-    public int getCountVoiceMessages(){
+    public int getVoiceMessageCount(){
         return 0;
     }
 
diff --git a/telephony/java/com/android/internal/telephony/PhoneProxy.java b/telephony/java/com/android/internal/telephony/PhoneProxy.java
index 4bb24dc..5b3c8dd 100644
--- a/telephony/java/com/android/internal/telephony/PhoneProxy.java
+++ b/telephony/java/com/android/internal/telephony/PhoneProxy.java
@@ -435,8 +435,8 @@
     }
 
      /** @hide */
-    public int getCountVoiceMessages(){
-        return mActivePhone.getCountVoiceMessages();
+    public int getVoiceMessageCount(){
+        return mActivePhone.getVoiceMessageCount();
     }
 
     public String getVoiceMailAlphaTag() {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 9aa7eab..3362de8 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -19,6 +19,7 @@
 import android.app.ActivityManagerNative;
 import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Looper;
@@ -26,6 +27,7 @@
 import android.os.Registrant;
 import android.os.RegistrantList;
 import android.os.SystemProperties;
+import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.telephony.CellLocation;
 import android.telephony.PhoneNumberUtils;
@@ -40,6 +42,7 @@
 import com.android.internal.telephony.Connection;
 import com.android.internal.telephony.DataConnection;
 import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccException;
 import com.android.internal.telephony.IccFileHandler;
 import com.android.internal.telephony.IccPhoneBookInterfaceManager;
 import com.android.internal.telephony.IccSmsInterfaceManager;
@@ -65,6 +68,9 @@
 
     // Default Emergency Callback Mode exit timer
     private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 30000;
+    static final String VM_COUNT_CDMA = "vm_count_key_cdma";
+    private static final String VM_NUMBER_CDMA = "vm_number_key_cdma";
+    private String mVmNumber = null;
 
     //***** Instance Variables
     CdmaCallTracker mCT;
@@ -147,6 +153,9 @@
         // This is needed to handle phone process crashes
         String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
         mIsPhoneInECMState = inEcm.equals("true");
+
+        // Notify voicemails.
+        notifier.notifyMessageWaitingChanged(this);
     }
 
     public void dispose() {
@@ -300,7 +309,7 @@
 
     public boolean
     getMessageWaitingIndicator() {
-        return mRuimRecords.getVoiceMessageWaiting();
+        return (getVoiceMessageCount() > 0);
     }
 
     public List<? extends MmiCode>
@@ -678,22 +687,33 @@
     public void setVoiceMailNumber(String alphaTag,
                                    String voiceMailNumber,
                                    Message onComplete) {
-        //mSIMRecords.setVoiceMailNumber(alphaTag, voiceMailNumber, onComplete);
-        //TODO: Where do we have to store this value has to be clarified with QC
+        Message resp;
+        mVmNumber = voiceMailNumber;
+        resp = h.obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
+        mRuimRecords.setVoiceMailNumber(alphaTag, mVmNumber, resp);
     }
 
     public String getVoiceMailNumber() {
-        //TODO: Where can we get this value has to be clarified with QC
-        //return mSIMRecords.getVoiceMailNumber();
-//      throw new RuntimeException();
-        return "*86";
+        String number = null;
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+        // TODO(Moto): The default value of voicemail number should be read from a system property
+        number = sp.getString(VM_NUMBER_CDMA, "*86");
+        return number;
     }
 
     /* Returns Number of Voicemails
      * @hide
      */
-    public int getCountVoiceMessages() {
-        return mRuimRecords.getCountVoiceMessages();
+    public int getVoiceMessageCount() {
+        int voicemailCount =  mRuimRecords.getVoiceMessageCount();
+        // If mRuimRecords.getVoiceMessageCount returns zero, then there is possibility
+        // that phone was power cycled and would have lost the voicemail count.
+        // So get the count from preferences.
+        if (voicemailCount == 0) {
+            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+            voicemailCount = sp.getInt(VM_COUNT_CDMA, 0);
+        }
+        return voicemailCount;
     }
 
     public String getVoiceMailAlphaTag() {
@@ -820,9 +840,10 @@
         mRuimRecords.setVoiceMessageWaiting(1, mwi ? -1 : 0);
     }
 
-    public void
-    notifyMessageWaitingIndicator() {
-        mNotifier.notifyMessageWaitingChanged(this);
+    /* This function is overloaded to send number of voicemails instead of sending true/false */
+    /*package*/ void
+    updateMessageWaitingIndicator(int mwi) {
+        mRuimRecords.setVoiceMessageWaiting(1, mwi);
     }
 
     /**
@@ -984,6 +1005,19 @@
                 }
                 break;
 
+                case EVENT_SET_VM_NUMBER_DONE:{
+                    ar = (AsyncResult)msg.obj;
+                    if (IccException.class.isInstance(ar.exception)) {
+                        storeVoiceMailNumber(mVmNumber);
+                        ar.exception = null;
+                    }
+                    onComplete = (Message) ar.userObj;
+                    if (onComplete != null) {
+                        AsyncResult.forMessage(onComplete, ar.result, ar.exception);
+                        onComplete.sendToTarget();
+                    }
+                }
+
                 default:{
                     throw new RuntimeException("unexpected event not handled");
                 }
@@ -1198,4 +1232,16 @@
         int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
         return mEriManager.getCdmaEriText(roamInd, defRoamInd);
     }
+
+    /**
+     * Store the voicemail number in preferences
+     */
+    private void storeVoiceMailNumber(String number) {
+        // Update the preference value of voicemail number
+        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
+        SharedPreferences.Editor editor = sp.edit();
+        editor.putString(VM_NUMBER_CDMA, number);
+        editor.commit();
+    }
+
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index da9fd0c4..ed2ea90 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -253,11 +253,7 @@
             // Always unmute when answering a new call
             setMute(false);
             cm.acceptCall(obtainCompleteMessage());
-        } else if ((foregroundCall.connections.size() > 0) &&
-                   (ringingCall.getState() == CdmaCall.State.WAITING)) {
-            // TODO(Moto): jsh asks, "Is this check necessary? I don't think it should be
-            // possible to have no fg connection and a WAITING call, but if we should hit
-            // this situation, is a CallStateExcetion appropriate?"
+        } else if (ringingCall.getState() == CdmaCall.State.WAITING) {
             CdmaConnection cwConn = (CdmaConnection)(ringingCall.getLatestConnection());
 
             // Since there is no network response for supplimentary
@@ -530,10 +526,6 @@
                         CdmaConnection cn = (CdmaConnection)foregroundCall.connections.get(n);
                         droppedDuringPoll.add(cn);
                     }
-                    // TODO(Moto): jsh asks, "Are we sure we don't need to do this for
-                    // ringingCall as well? What if there's a WAITING call (ie, UI timer
-                    // hasn't expired, moving it to DISCONNECTED)? How/when will it
-                    // transition to DISCONNECTED?"
                 }
                 foregroundCall.setGeneric(false);
                 // Dropped connections are removed from the CallTracker
@@ -681,8 +673,12 @@
             // set the ringing call state to IDLE here to avoid a race condition
             // where a new call waiting could get a hang up from an old call
             // waiting ringingCall.
-            // TODO(Moto): jsh asks, "Should we call conn.ondisconnect() here or Somewhere?"
-            ringingCall.detach(conn);
+            //
+            // PhoneApp does the call log itself since only PhoneApp knows
+            // the hangup reason is user ignoring or timing out. So conn.onDisconnect()
+            // is not called here. Instead, conn.onLocalDisconnect() is called.
+            conn.onLocalDisconnect();
+            phone.notifyCallStateChanged();
             return;
         } else {
             try {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
index 588bdf0..025382d 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -452,12 +452,7 @@
         this.cause = cause;
 
         if (!disconnected) {
-            index = -1;
-
-            disconnectTime = System.currentTimeMillis();
-            duration = SystemClock.elapsedRealtime() - connectTimeReal;
-            disconnected = true;
-
+            doDisconnect();
             if (Config.LOGD) Log.d(LOG_TAG,
                     "[CDMAConn] onDisconnect: cause=" + cause);
 
@@ -470,6 +465,21 @@
         releaseWakeLock();
     }
 
+    /** Called when the call waiting connection has been hung up */
+    /*package*/ void
+    onLocalDisconnect() {
+        if (!disconnected) {
+            doDisconnect();
+            if (Config.LOGD) Log.d(LOG_TAG,
+                    "[CDMAConn] onLoalDisconnect" );
+
+            if (parent != null) {
+                parent.detach(this);
+            }
+        }
+        releaseWakeLock();
+    }
+
     // Returns true if state has changed, false if nothing changed
     /*package*/ boolean
     update (DriverCall dc) {
@@ -587,6 +597,14 @@
     }
 
     private void
+    doDisconnect() {
+       index = -1;
+       disconnectTime = System.currentTimeMillis();
+       duration = SystemClock.elapsedRealtime() - connectTimeReal;
+       disconnected = true;
+    }
+
+    private void
     onStartedHolding() {
         holdingStartTime = SystemClock.elapsedRealtime();
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
index 2b4a700..8a0070d 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaSMSDispatcher.java
@@ -20,11 +20,13 @@
 import android.app.Activity;
 import android.app.PendingIntent;
 import android.content.ContentValues;
+import android.content.SharedPreferences;
 import android.database.Cursor;
 import android.database.SQLException;
 import android.os.AsyncResult;
 import android.os.Message;
 import android.provider.Telephony.Sms.Intents;
+import android.preference.PreferenceManager;
 import android.util.Config;
 import android.util.Log;
 
@@ -83,27 +85,6 @@
         int teleService = sms.getTeleService();
         boolean handled = false;
 
-        // Teleservices W(E)MT and VMN are handled together:
-        if ((teleService == SmsEnvelope.TELESERVICE_WMT)
-                || (teleService == SmsEnvelope.TELESERVICE_WEMT)
-                || (teleService == SmsEnvelope.TELESERVICE_VMN)) {
-            // From here on we need decoded BD.
-            // Special case the message waiting indicator messages
-            if (sms.isMWISetMessage()) {
-                mCdmaPhone.updateMessageWaitingIndicator(true);
-                handled |= sms.isMwiDontStore();
-                if (Config.LOGD) {
-                    Log.d(TAG, "Received voice mail indicator set SMS shouldStore=" + !handled);
-                }
-            } else if (sms.isMWIClearMessage()) {
-                mCdmaPhone.updateMessageWaitingIndicator(false);
-                handled |= sms.isMwiDontStore();
-                if (Config.LOGD) {
-                    Log.d(TAG, "Received voice mail indicator clear SMS shouldStore=" + !handled);
-                }
-            }
-        }
-
         if (sms.getUserData() == null) {
             if (Config.LOGD) {
                 Log.d(TAG, "Received SMS without user data");
@@ -116,6 +97,18 @@
         if (SmsEnvelope.TELESERVICE_WAP == teleService){
             processCdmaWapPdu(sms.getUserData(), sms.messageRef, sms.getOriginatingAddress());
             return;
+        } else if (SmsEnvelope.TELESERVICE_VMN == teleService) {
+            // handling Voicemail
+            int voicemailCount = sms.getNumOfVoicemails();
+            Log.d(TAG, "Voicemail count=" + voicemailCount);
+            // Store the voicemail count in preferences.
+            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(
+                    ((CDMAPhone) mPhone).getContext());
+            SharedPreferences.Editor editor = sp.edit();
+            editor.putInt(CDMAPhone.VM_COUNT_CDMA, voicemailCount);
+            editor.commit();
+            ((CDMAPhone) mPhone).updateMessageWaitingIndicator(voicemailCount);
+            return;
         }
 
         /**
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 63d2c47..3a92064 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -773,6 +773,12 @@
         return asciiDigit;
     }
 
+    /** This function  shall be called to get the number of voicemails.
+     * @hide
+     */
+    /*package*/ int getNumOfVoicemails() {
+        return mBearerData.numberOfMessages;
+    }
 
 
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index 70d71fc..d1e4b4f 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -448,11 +448,6 @@
     }
 
     public void
-    notifyMessageWaitingIndicator() {
-        mNotifier.notifyMessageWaitingChanged(this);
-    }
-
-    public void
     notifyCallForwardingIndicator() {
         mNotifier.notifyCallForwardingChanged(this);
     }
diff --git a/tools/localize/Perforce.cpp b/tools/localize/Perforce.cpp
index a7f301e..ae11231 100644
--- a/tools/localize/Perforce.cpp
+++ b/tools/localize/Perforce.cpp
@@ -1,6 +1,7 @@
 #include "Perforce.h"
 #include "log.h"
 #include <string.h>
+#include <cstdio>
 #include <stdlib.h>
 #include <sstream>
 #include <sys/types.h>
diff --git a/tools/localize/SourcePos.cpp b/tools/localize/SourcePos.cpp
index dd54f3a..184bfe0a 100644
--- a/tools/localize/SourcePos.cpp
+++ b/tools/localize/SourcePos.cpp
@@ -1,6 +1,7 @@
 #include "SourcePos.h"
 
 #include <stdarg.h>
+#include <cstdio>
 #include <set>
 #include <cstdio>
 
diff --git a/tools/localize/file_utils.cpp b/tools/localize/file_utils.cpp
index 84081f5..775ce2f 100644
--- a/tools/localize/file_utils.cpp
+++ b/tools/localize/file_utils.cpp
@@ -1,4 +1,5 @@
 #include <string.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include "file_utils.h"
diff --git a/tools/localize/localize_test.cpp b/tools/localize/localize_test.cpp
index 931ea95..1d0ac9a 100644
--- a/tools/localize/localize_test.cpp
+++ b/tools/localize/localize_test.cpp
@@ -2,6 +2,7 @@
 #include "XLIFFFile.h"
 #include "ValuesFile.h"
 #include "localize.h"
+#include <stdio.h>
 
 int pseudolocalize_xliff(XLIFFFile* xliff, bool expand);
 
diff --git a/tools/localize/merge_res_and_xliff.cpp b/tools/localize/merge_res_and_xliff.cpp
index 58a6554..1fdaa0e 100644
--- a/tools/localize/merge_res_and_xliff.cpp
+++ b/tools/localize/merge_res_and_xliff.cpp
@@ -3,6 +3,7 @@
 #include "file_utils.h"
 #include "Perforce.h"
 #include "log.h"
+#include <stdio.h>
 
 static set<StringResource>::const_iterator
 find_id(const set<StringResource>& s, const string& id, int index)
diff --git a/tools/localize/merge_res_and_xliff_test.cpp b/tools/localize/merge_res_and_xliff_test.cpp
index f638a74..6fe2629 100644
--- a/tools/localize/merge_res_and_xliff_test.cpp
+++ b/tools/localize/merge_res_and_xliff_test.cpp
@@ -1,6 +1,6 @@
 #include <cstdio>
 #include "merge_res_and_xliff.h"
-
+#include <stdio.h>
 
 int
 merge_test()
diff --git a/tools/localize/xmb.cpp b/tools/localize/xmb.cpp
index 236705f..d8f6ff0 100644
--- a/tools/localize/xmb.cpp
+++ b/tools/localize/xmb.cpp
@@ -7,6 +7,7 @@
 #include "XLIFFFile.h"
 
 #include <map>
+#include <cstdio>
 
 using namespace std;