Merge "Document RS element and type and add validity checking to type creation."
diff --git a/api/current.xml b/api/current.xml
index 2fe910c..ed1d929 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1949,7 +1949,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843553"
+ value="16843555"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1960,7 +1960,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843552"
+ value="16843554"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1971,7 +1971,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843554"
+ value="16843556"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2363,6 +2363,17 @@
  visibility="public"
 >
 </field>
+<field name="autoAdvanceViewId"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843552"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="autoCompleteTextViewStyle"
  type="int"
  transient="false"
@@ -9385,7 +9396,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843556"
+ value="16843558"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9396,7 +9407,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843555"
+ value="16843557"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9414,6 +9425,17 @@
  visibility="public"
 >
 </field>
+<field name="textIsSelectable"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843559"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="textLineHeight"
  type="int"
  transient="false"
@@ -9887,6 +9909,17 @@
  visibility="public"
 >
 </field>
+<field name="useIntrinsicSizeAsMinimum"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843553"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="useLevel"
  type="int"
  transient="false"
@@ -10338,6 +10371,17 @@
  visibility="public"
 >
 </field>
+<field name="windowEnableSplitTouch"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843560"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="windowEnterAnimation"
  type="int"
  transient="false"
@@ -14513,6 +14557,17 @@
  visibility="public"
 >
 </field>
+<field name="Theme_Holo_DialogWhenLarge"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973954"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Theme_Holo_Dialog_Alert"
  type="int"
  transient="false"
@@ -27359,6 +27414,17 @@
  visibility="public"
 >
 </method>
+<method name="getResources"
+ return="android.content.res.Resources"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getRetainInstance"
  return="boolean"
  abstract="false"
@@ -27370,6 +27436,34 @@
  visibility="public"
 >
 </method>
+<method name="getString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
+<method name="getString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+<parameter name="formatArgs" type="java.lang.Object...">
+</parameter>
+</method>
 <method name="getTag"
  return="java.lang.String"
  abstract="false"
@@ -27403,6 +27497,19 @@
  visibility="public"
 >
 </method>
+<method name="getText"
+ return="java.lang.CharSequence"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="resId" type="int">
+</parameter>
+</method>
 <method name="getView"
  return="android.view.View"
  abstract="false"
@@ -34296,6 +34403,17 @@
  visibility="public"
 >
 </field>
+<field name="USES_POLICY_EXPIRE_PASSWORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="USES_POLICY_FORCE_LOCK"
  type="int"
  transient="false"
@@ -34465,6 +34583,21 @@
 <parameter name="intent" type="android.content.Intent">
 </parameter>
 </method>
+<method name="onPasswordExpiring"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="intent" type="android.content.Intent">
+</parameter>
+</method>
 <method name="onPasswordFailed"
  return="void"
  abstract="false"
@@ -34554,6 +34687,17 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_PASSWORD_EXPIRING"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.app.action.ACTION_PASSWORD_EXPIRING&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="ACTION_PASSWORD_FAILED"
  type="java.lang.String"
  transient="false"
@@ -34666,6 +34810,32 @@
 <parameter name="admin" type="android.content.ComponentName">
 </parameter>
 </method>
+<method name="getPasswordExpiration"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
+<method name="getPasswordExpirationTimeout"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
 <method name="getPasswordHistoryLength"
  return="int"
  abstract="false"
@@ -34906,6 +35076,21 @@
 <parameter name="timeMs" type="long">
 </parameter>
 </method>
+<method name="setPasswordExpirationTimeout"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="timeout" type="long">
+</parameter>
+</method>
 <method name="setPasswordHistoryLength"
  return="void"
  abstract="false"
@@ -36517,6 +36702,16 @@
  visibility="public"
 >
 </field>
+<field name="autoAdvanceViewId"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="configure"
  type="android.content.ComponentName"
  transient="false"
@@ -39726,7 +39921,18 @@
  type="int"
  transient="false"
  volatile="false"
- value="10"
+ value="12"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATE_AUDIO_CONNECTING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="11"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -39737,7 +39943,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="11"
+ value="10"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -195619,6 +195825,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_AVR_INPUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="182"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_AVR_POWER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="181"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_B"
  type="int"
  transient="false"
@@ -195652,6 +195880,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_BOOKMARK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="174"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_BREAK"
  type="int"
  transient="false"
@@ -195872,6 +196111,39 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_CAPTIONS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="175"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_CHANNEL_DOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="167"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_CHANNEL_UP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="166"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_CLEAR"
  type="int"
  transient="false"
@@ -195993,6 +196265,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_DVR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="173"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_E"
  type="int"
  transient="false"
@@ -196279,6 +196562,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_GUIDE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="172"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_H"
  type="int"
  transient="false"
@@ -196323,6 +196617,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_INFO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="165"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_INSERT"
  type="int"
  transient="false"
@@ -196950,6 +197255,50 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_PROG_BLUE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="186"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_PROG_GREEN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="184"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_PROG_RED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="183"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_PROG_YELLOW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="185"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_Q"
  type="int"
  transient="false"
@@ -197027,6 +197376,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_SETTINGS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="176"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_SHIFT_LEFT"
  type="int"
  transient="false"
@@ -197104,6 +197464,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_STB_INPUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="180"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_STB_POWER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="179"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_SWITCH_CHARSET"
  type="int"
  transient="false"
@@ -197159,6 +197541,39 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_TV"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="170"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_TV_INPUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="178"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_TV_POWER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="177"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_U"
  type="int"
  transient="false"
@@ -197236,6 +197651,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_WINDOW"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="171"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_X"
  type="int"
  transient="false"
@@ -197269,6 +197695,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_ZOOM_IN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="168"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_ZOOM_OUT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="169"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MAX_KEYCODE"
  type="int"
  transient="false"
@@ -227411,6 +227859,17 @@
 <parameter name="attrs" type="android.util.AttributeSet">
 </parameter>
 </constructor>
+<method name="advance"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getAdapter"
  return="android.widget.Adapter"
  abstract="false"
@@ -227666,6 +228125,17 @@
  visibility="public"
 >
 </method>
+<method name="willBeAdvancedByHost"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 </class>
 <class name="AdapterViewFlipper"
  extends="android.widget.AdapterViewAnimator"
@@ -243088,6 +243558,17 @@
  visibility="public"
 >
 </method>
+<method name="isTextSelectable"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="length"
  return="int"
  abstract="false"
@@ -244135,6 +244616,19 @@
 <parameter name="colors" type="android.content.res.ColorStateList">
 </parameter>
 </method>
+<method name="setTextIsSelectable"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="selectable" type="boolean">
+</parameter>
+</method>
 <method name="setTextKeepState"
  return="void"
  abstract="false"
@@ -363942,7 +364436,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="string" type="java.lang.String">
+<parameter name="comment" type="java.lang.String">
 </parameter>
 </method>
 <method name="setCompressedSize"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 174b6da..70e11df 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3001,7 +3001,7 @@
 
         Resources.updateSystemConfiguration(config, dm);
 
-        ContextImpl.ApplicationPackageManager.configurationChanged();
+        ApplicationPackageManager.configurationChanged();
         //Slog.i(TAG, "Configuration changed in " + currentPackageName());
         
         Iterator<WeakReference<Resources>> it =
@@ -3138,7 +3138,7 @@
                 mResourcePackages.remove(packages[i]);
             }
         }
-        ContextImpl.ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
+        ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
                 hasPkgInfo);
     }
         
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
new file mode 100644
index 0000000..ce9501a
--- /dev/null
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -0,0 +1,1113 @@
+/*
+ * Copyright (C) 2010 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.app;
+
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.IPackageDataObserver;
+import android.content.pm.IPackageDeleteObserver;
+import android.content.pm.IPackageInstallObserver;
+import android.content.pm.IPackageManager;
+import android.content.pm.IPackageMoveObserver;
+import android.content.pm.IPackageStatsObserver;
+import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Process;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/*package*/
+final class ApplicationPackageManager extends PackageManager {
+    private static final String TAG = "ApplicationPackageManager";
+    private final static boolean DEBUG = false;
+    private final static boolean DEBUG_ICONS = false;
+
+    @Override
+    public PackageInfo getPackageInfo(String packageName, int flags)
+            throws NameNotFoundException {
+        try {
+            PackageInfo pi = mPM.getPackageInfo(packageName, flags);
+            if (pi != null) {
+                return pi;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(packageName);
+    }
+
+    @Override
+    public String[] currentToCanonicalPackageNames(String[] names) {
+        try {
+            return mPM.currentToCanonicalPackageNames(names);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public String[] canonicalToCurrentPackageNames(String[] names) {
+        try {
+            return mPM.canonicalToCurrentPackageNames(names);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public Intent getLaunchIntentForPackage(String packageName) {
+        // First see if the package has an INFO activity; the existence of
+        // such an activity is implied to be the desired front-door for the
+        // overall package (such as if it has multiple launcher entries).
+        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+        intentToResolve.addCategory(Intent.CATEGORY_INFO);
+        intentToResolve.setPackage(packageName);
+        ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
+
+        // Otherwise, try to find a main launcher activity.
+        if (resolveInfo == null) {
+            // reuse the intent instance
+            intentToResolve.removeCategory(Intent.CATEGORY_INFO);
+            intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
+            intentToResolve.setPackage(packageName);
+            resolveInfo = resolveActivity(intentToResolve, 0);
+        }
+        if (resolveInfo == null) {
+            return null;
+        }
+        Intent intent = new Intent(intentToResolve);
+        intent.setClassName(resolveInfo.activityInfo.applicationInfo.packageName,
+                            resolveInfo.activityInfo.name);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return intent;
+    }
+
+    @Override
+    public int[] getPackageGids(String packageName)
+            throws NameNotFoundException {
+        try {
+            int[] gids = mPM.getPackageGids(packageName);
+            if (gids == null || gids.length > 0) {
+                return gids;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(packageName);
+    }
+
+    @Override
+    public PermissionInfo getPermissionInfo(String name, int flags)
+            throws NameNotFoundException {
+        try {
+            PermissionInfo pi = mPM.getPermissionInfo(name, flags);
+            if (pi != null) {
+                return pi;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(name);
+    }
+
+    @Override
+    public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
+            throws NameNotFoundException {
+        try {
+            List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
+            if (pi != null) {
+                return pi;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(group);
+    }
+
+    @Override
+    public PermissionGroupInfo getPermissionGroupInfo(String name,
+                                                      int flags) throws NameNotFoundException {
+        try {
+            PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
+            if (pgi != null) {
+                return pgi;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(name);
+    }
+
+    @Override
+    public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
+        try {
+            return mPM.getAllPermissionGroups(flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public ApplicationInfo getApplicationInfo(String packageName, int flags)
+            throws NameNotFoundException {
+        try {
+            ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
+            if (ai != null) {
+                return ai;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(packageName);
+    }
+
+    @Override
+    public ActivityInfo getActivityInfo(ComponentName className, int flags)
+            throws NameNotFoundException {
+        try {
+            ActivityInfo ai = mPM.getActivityInfo(className, flags);
+            if (ai != null) {
+                return ai;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(className.toString());
+    }
+
+    @Override
+    public ActivityInfo getReceiverInfo(ComponentName className, int flags)
+            throws NameNotFoundException {
+        try {
+            ActivityInfo ai = mPM.getReceiverInfo(className, flags);
+            if (ai != null) {
+                return ai;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(className.toString());
+    }
+
+    @Override
+    public ServiceInfo getServiceInfo(ComponentName className, int flags)
+            throws NameNotFoundException {
+        try {
+            ServiceInfo si = mPM.getServiceInfo(className, flags);
+            if (si != null) {
+                return si;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(className.toString());
+    }
+
+    @Override
+    public ProviderInfo getProviderInfo(ComponentName className, int flags)
+            throws NameNotFoundException {
+        try {
+            ProviderInfo pi = mPM.getProviderInfo(className, flags);
+            if (pi != null) {
+                return pi;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(className.toString());
+    }
+
+    @Override
+    public String[] getSystemSharedLibraryNames() {
+        try {
+            return mPM.getSystemSharedLibraryNames();
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public FeatureInfo[] getSystemAvailableFeatures() {
+        try {
+            return mPM.getSystemAvailableFeatures();
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public boolean hasSystemFeature(String name) {
+        try {
+            return mPM.hasSystemFeature(name);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public int checkPermission(String permName, String pkgName) {
+        try {
+            return mPM.checkPermission(permName, pkgName);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public boolean addPermission(PermissionInfo info) {
+        try {
+            return mPM.addPermission(info);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public boolean addPermissionAsync(PermissionInfo info) {
+        try {
+            return mPM.addPermissionAsync(info);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public void removePermission(String name) {
+        try {
+            mPM.removePermission(name);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public int checkSignatures(String pkg1, String pkg2) {
+        try {
+            return mPM.checkSignatures(pkg1, pkg2);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public int checkSignatures(int uid1, int uid2) {
+        try {
+            return mPM.checkUidSignatures(uid1, uid2);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public String[] getPackagesForUid(int uid) {
+        try {
+            return mPM.getPackagesForUid(uid);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public String getNameForUid(int uid) {
+        try {
+            return mPM.getNameForUid(uid);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public int getUidForSharedUser(String sharedUserName)
+            throws NameNotFoundException {
+        try {
+            int uid = mPM.getUidForSharedUser(sharedUserName);
+            if(uid != -1) {
+                return uid;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+        throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
+    }
+
+    @Override
+    public List<PackageInfo> getInstalledPackages(int flags) {
+        try {
+            return mPM.getInstalledPackages(flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public List<ApplicationInfo> getInstalledApplications(int flags) {
+        try {
+            return mPM.getInstalledApplications(flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public ResolveInfo resolveActivity(Intent intent, int flags) {
+        try {
+            return mPM.resolveIntent(
+                intent,
+                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public List<ResolveInfo> queryIntentActivities(Intent intent,
+                                                   int flags) {
+        try {
+            return mPM.queryIntentActivities(
+                intent,
+                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public List<ResolveInfo> queryIntentActivityOptions(
+        ComponentName caller, Intent[] specifics, Intent intent,
+        int flags) {
+        final ContentResolver resolver = mContext.getContentResolver();
+
+        String[] specificTypes = null;
+        if (specifics != null) {
+            final int N = specifics.length;
+            for (int i=0; i<N; i++) {
+                Intent sp = specifics[i];
+                if (sp != null) {
+                    String t = sp.resolveTypeIfNeeded(resolver);
+                    if (t != null) {
+                        if (specificTypes == null) {
+                            specificTypes = new String[N];
+                        }
+                        specificTypes[i] = t;
+                    }
+                }
+            }
+        }
+
+        try {
+            return mPM.queryIntentActivityOptions(caller, specifics,
+                                                  specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
+                                                  flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
+        try {
+            return mPM.queryIntentReceivers(
+                intent,
+                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public ResolveInfo resolveService(Intent intent, int flags) {
+        try {
+            return mPM.resolveService(
+                intent,
+                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
+        try {
+            return mPM.queryIntentServices(
+                intent,
+                intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public ProviderInfo resolveContentProvider(String name,
+                                               int flags) {
+        try {
+            return mPM.resolveContentProvider(name, flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public List<ProviderInfo> queryContentProviders(String processName,
+                                                    int uid, int flags) {
+        try {
+            return mPM.queryContentProviders(processName, uid, flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override
+    public InstrumentationInfo getInstrumentationInfo(
+        ComponentName className, int flags)
+            throws NameNotFoundException {
+        try {
+            InstrumentationInfo ii = mPM.getInstrumentationInfo(
+                className, flags);
+            if (ii != null) {
+                return ii;
+            }
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+
+        throw new NameNotFoundException(className.toString());
+    }
+
+    @Override
+    public List<InstrumentationInfo> queryInstrumentation(
+        String targetPackage, int flags) {
+        try {
+            return mPM.queryInstrumentation(targetPackage, flags);
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    @Override public Drawable getDrawable(String packageName, int resid,
+                                          ApplicationInfo appInfo) {
+        ResourceName name = new ResourceName(packageName, resid);
+        Drawable dr = getCachedIcon(name);
+        if (dr != null) {
+            return dr;
+        }
+        if (appInfo == null) {
+            try {
+                appInfo = getApplicationInfo(packageName, 0);
+            } catch (NameNotFoundException e) {
+                return null;
+            }
+        }
+        try {
+            Resources r = getResourcesForApplication(appInfo);
+            dr = r.getDrawable(resid);
+            if (false) {
+                RuntimeException e = new RuntimeException("here");
+                e.fillInStackTrace();
+                Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
+                      + " from package " + packageName
+                      + ": app scale=" + r.getCompatibilityInfo().applicationScale
+                      + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
+                      e);
+            }
+            if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
+                                   + Integer.toHexString(resid) + " from " + r
+                                   + ": " + dr);
+            putCachedIcon(name, dr);
+            return dr;
+        } catch (NameNotFoundException e) {
+            Log.w("PackageManager", "Failure retrieving resources for"
+                  + appInfo.packageName);
+        } catch (RuntimeException e) {
+            // If an exception was thrown, fall through to return
+            // default icon.
+            Log.w("PackageManager", "Failure retrieving icon 0x"
+                  + Integer.toHexString(resid) + " in package "
+                  + packageName, e);
+        }
+        return null;
+    }
+
+    @Override public Drawable getActivityIcon(ComponentName activityName)
+            throws NameNotFoundException {
+        return getActivityInfo(activityName, 0).loadIcon(this);
+    }
+
+    @Override public Drawable getActivityIcon(Intent intent)
+            throws NameNotFoundException {
+        if (intent.getComponent() != null) {
+            return getActivityIcon(intent.getComponent());
+        }
+
+        ResolveInfo info = resolveActivity(
+            intent, PackageManager.MATCH_DEFAULT_ONLY);
+        if (info != null) {
+            return info.activityInfo.loadIcon(this);
+        }
+
+        throw new NameNotFoundException(intent.toURI());
+    }
+
+    @Override public Drawable getDefaultActivityIcon() {
+        return Resources.getSystem().getDrawable(
+            com.android.internal.R.drawable.sym_def_app_icon);
+    }
+
+    @Override public Drawable getApplicationIcon(ApplicationInfo info) {
+        return info.loadIcon(this);
+    }
+
+    @Override public Drawable getApplicationIcon(String packageName)
+            throws NameNotFoundException {
+        return getApplicationIcon(getApplicationInfo(packageName, 0));
+    }
+
+    @Override
+    public Drawable getActivityLogo(ComponentName activityName)
+            throws NameNotFoundException {
+        return getActivityInfo(activityName, 0).loadLogo(this);
+    }
+
+    @Override
+    public Drawable getActivityLogo(Intent intent)
+            throws NameNotFoundException {
+        if (intent.getComponent() != null) {
+            return getActivityLogo(intent.getComponent());
+        }
+
+        ResolveInfo info = resolveActivity(
+            intent, PackageManager.MATCH_DEFAULT_ONLY);
+        if (info != null) {
+            return info.activityInfo.loadLogo(this);
+        }
+
+        throw new NameNotFoundException(intent.toUri(0));
+    }
+
+    @Override
+    public Drawable getApplicationLogo(ApplicationInfo info) {
+        return info.loadLogo(this);
+    }
+
+    @Override
+    public Drawable getApplicationLogo(String packageName)
+            throws NameNotFoundException {
+        return getApplicationLogo(getApplicationInfo(packageName, 0));
+    }
+
+    @Override public Resources getResourcesForActivity(
+        ComponentName activityName) throws NameNotFoundException {
+        return getResourcesForApplication(
+            getActivityInfo(activityName, 0).applicationInfo);
+    }
+
+    @Override public Resources getResourcesForApplication(
+        ApplicationInfo app) throws NameNotFoundException {
+        if (app.packageName.equals("system")) {
+            return mContext.mMainThread.getSystemContext().getResources();
+        }
+        Resources r = mContext.mMainThread.getTopLevelResources(
+            app.uid == Process.myUid() ? app.sourceDir
+            : app.publicSourceDir, mContext.mPackageInfo);
+        if (r != null) {
+            return r;
+        }
+        throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
+    }
+
+    @Override public Resources getResourcesForApplication(
+        String appPackageName) throws NameNotFoundException {
+        return getResourcesForApplication(
+            getApplicationInfo(appPackageName, 0));
+    }
+
+    int mCachedSafeMode = -1;
+    @Override public boolean isSafeMode() {
+        try {
+            if (mCachedSafeMode < 0) {
+                mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
+            }
+            return mCachedSafeMode != 0;
+        } catch (RemoteException e) {
+            throw new RuntimeException("Package manager has died", e);
+        }
+    }
+
+    static void configurationChanged() {
+        synchronized (sSync) {
+            sIconCache.clear();
+            sStringCache.clear();
+        }
+    }
+
+    ApplicationPackageManager(ContextImpl context,
+                              IPackageManager pm) {
+        mContext = context;
+        mPM = pm;
+    }
+
+    private Drawable getCachedIcon(ResourceName name) {
+        synchronized (sSync) {
+            WeakReference<Drawable> wr = sIconCache.get(name);
+            if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
+                                   + name + ": " + wr);
+            if (wr != null) {   // we have the activity
+                Drawable dr = wr.get();
+                if (dr != null) {
+                    if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
+                                           + name + ": " + dr);
+                    return dr;
+                }
+                // our entry has been purged
+                sIconCache.remove(name);
+            }
+        }
+        return null;
+    }
+
+    private void putCachedIcon(ResourceName name, Drawable dr) {
+        synchronized (sSync) {
+            sIconCache.put(name, new WeakReference<Drawable>(dr));
+            if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
+                                   + name + ": " + dr);
+        }
+    }
+
+    static final void handlePackageBroadcast(int cmd, String[] pkgList,
+                                             boolean hasPkgInfo) {
+        boolean immediateGc = false;
+        if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
+            immediateGc = true;
+        }
+        if (pkgList != null && (pkgList.length > 0)) {
+            boolean needCleanup = false;
+            for (String ssp : pkgList) {
+                synchronized (sSync) {
+                    if (sIconCache.size() > 0) {
+                        Iterator<ResourceName> it = sIconCache.keySet().iterator();
+                        while (it.hasNext()) {
+                            ResourceName nm = it.next();
+                            if (nm.packageName.equals(ssp)) {
+                                //Log.i(TAG, "Removing cached drawable for " + nm);
+                                it.remove();
+                                needCleanup = true;
+                            }
+                        }
+                    }
+                    if (sStringCache.size() > 0) {
+                        Iterator<ResourceName> it = sStringCache.keySet().iterator();
+                        while (it.hasNext()) {
+                            ResourceName nm = it.next();
+                            if (nm.packageName.equals(ssp)) {
+                                //Log.i(TAG, "Removing cached string for " + nm);
+                                it.remove();
+                                needCleanup = true;
+                            }
+                        }
+                    }
+                }
+            }
+            if (needCleanup || hasPkgInfo) {
+                if (immediateGc) {
+                    // Schedule an immediate gc.
+                    Runtime.getRuntime().gc();
+                } else {
+                    ActivityThread.currentActivityThread().scheduleGcIdler();
+                }
+            }
+        }
+    }
+
+    private static final class ResourceName {
+        final String packageName;
+        final int iconId;
+
+        ResourceName(String _packageName, int _iconId) {
+            packageName = _packageName;
+            iconId = _iconId;
+        }
+
+        ResourceName(ApplicationInfo aInfo, int _iconId) {
+            this(aInfo.packageName, _iconId);
+        }
+
+        ResourceName(ComponentInfo cInfo, int _iconId) {
+            this(cInfo.applicationInfo.packageName, _iconId);
+        }
+
+        ResourceName(ResolveInfo rInfo, int _iconId) {
+            this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            ResourceName that = (ResourceName) o;
+
+            if (iconId != that.iconId) return false;
+            return !(packageName != null ?
+                     !packageName.equals(that.packageName) : that.packageName != null);
+
+        }
+
+        @Override
+        public int hashCode() {
+            int result;
+            result = packageName.hashCode();
+            result = 31 * result + iconId;
+            return result;
+        }
+
+        @Override
+        public String toString() {
+            return "{ResourceName " + packageName + " / " + iconId + "}";
+        }
+    }
+
+    private CharSequence getCachedString(ResourceName name) {
+        synchronized (sSync) {
+            WeakReference<CharSequence> wr = sStringCache.get(name);
+            if (wr != null) {   // we have the activity
+                CharSequence cs = wr.get();
+                if (cs != null) {
+                    return cs;
+                }
+                // our entry has been purged
+                sStringCache.remove(name);
+            }
+        }
+        return null;
+    }
+
+    private void putCachedString(ResourceName name, CharSequence cs) {
+        synchronized (sSync) {
+            sStringCache.put(name, new WeakReference<CharSequence>(cs));
+        }
+    }
+
+    @Override
+    public CharSequence getText(String packageName, int resid,
+                                ApplicationInfo appInfo) {
+        ResourceName name = new ResourceName(packageName, resid);
+        CharSequence text = getCachedString(name);
+        if (text != null) {
+            return text;
+        }
+        if (appInfo == null) {
+            try {
+                appInfo = getApplicationInfo(packageName, 0);
+            } catch (NameNotFoundException e) {
+                return null;
+            }
+        }
+        try {
+            Resources r = getResourcesForApplication(appInfo);
+            text = r.getText(resid);
+            putCachedString(name, text);
+            return text;
+        } catch (NameNotFoundException e) {
+            Log.w("PackageManager", "Failure retrieving resources for"
+                  + appInfo.packageName);
+        } catch (RuntimeException e) {
+            // If an exception was thrown, fall through to return
+            // default icon.
+            Log.w("PackageManager", "Failure retrieving text 0x"
+                  + Integer.toHexString(resid) + " in package "
+                  + packageName, e);
+        }
+        return null;
+    }
+
+    @Override
+    public XmlResourceParser getXml(String packageName, int resid,
+                                    ApplicationInfo appInfo) {
+        if (appInfo == null) {
+            try {
+                appInfo = getApplicationInfo(packageName, 0);
+            } catch (NameNotFoundException e) {
+                return null;
+            }
+        }
+        try {
+            Resources r = getResourcesForApplication(appInfo);
+            return r.getXml(resid);
+        } catch (RuntimeException e) {
+            // If an exception was thrown, fall through to return
+            // default icon.
+            Log.w("PackageManager", "Failure retrieving xml 0x"
+                  + Integer.toHexString(resid) + " in package "
+                  + packageName, e);
+        } catch (NameNotFoundException e) {
+            Log.w("PackageManager", "Failure retrieving resources for "
+                  + appInfo.packageName);
+        }
+        return null;
+    }
+
+    @Override
+    public CharSequence getApplicationLabel(ApplicationInfo info) {
+        return info.loadLabel(this);
+    }
+
+    @Override
+    public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
+                               String installerPackageName) {
+        try {
+            mPM.installPackage(packageURI, observer, flags, installerPackageName);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
+        try {
+            mPM.movePackage(packageName, observer, flags);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public String getInstallerPackageName(String packageName) {
+        try {
+            return mPM.getInstallerPackageName(packageName);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+        return null;
+    }
+
+    @Override
+    public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
+        try {
+            mPM.deletePackage(packageName, observer, flags);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+    @Override
+    public void clearApplicationUserData(String packageName,
+                                         IPackageDataObserver observer) {
+        try {
+            mPM.clearApplicationUserData(packageName, observer);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+    @Override
+    public void deleteApplicationCacheFiles(String packageName,
+                                            IPackageDataObserver observer) {
+        try {
+            mPM.deleteApplicationCacheFiles(packageName, observer);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+    @Override
+    public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
+        try {
+            mPM.freeStorageAndNotify(idealStorageSize, observer);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public void freeStorage(long freeStorageSize, IntentSender pi) {
+        try {
+            mPM.freeStorage(freeStorageSize, pi);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public void getPackageSizeInfo(String packageName,
+                                   IPackageStatsObserver observer) {
+        try {
+            mPM.getPackageSizeInfo(packageName, observer);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+    @Override
+    public void addPackageToPreferred(String packageName) {
+        try {
+            mPM.addPackageToPreferred(packageName);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public void removePackageFromPreferred(String packageName) {
+        try {
+            mPM.removePackageFromPreferred(packageName);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public List<PackageInfo> getPreferredPackages(int flags) {
+        try {
+            return mPM.getPreferredPackages(flags);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+        return new ArrayList<PackageInfo>();
+    }
+
+    @Override
+    public void addPreferredActivity(IntentFilter filter,
+                                     int match, ComponentName[] set, ComponentName activity) {
+        try {
+            mPM.addPreferredActivity(filter, match, set, activity);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public void replacePreferredActivity(IntentFilter filter,
+                                         int match, ComponentName[] set, ComponentName activity) {
+        try {
+            mPM.replacePreferredActivity(filter, match, set, activity);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public void clearPackagePreferredActivities(String packageName) {
+        try {
+            mPM.clearPackagePreferredActivities(packageName);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public int getPreferredActivities(List<IntentFilter> outFilters,
+                                      List<ComponentName> outActivities, String packageName) {
+        try {
+            return mPM.getPreferredActivities(outFilters, outActivities, packageName);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+        return 0;
+    }
+
+    @Override
+    public void setComponentEnabledSetting(ComponentName componentName,
+                                           int newState, int flags) {
+        try {
+            mPM.setComponentEnabledSetting(componentName, newState, flags);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public int getComponentEnabledSetting(ComponentName componentName) {
+        try {
+            return mPM.getComponentEnabledSetting(componentName);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+    }
+
+    @Override
+    public void setApplicationEnabledSetting(String packageName,
+                                             int newState, int flags) {
+        try {
+            mPM.setApplicationEnabledSetting(packageName, newState, flags);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    @Override
+    public int getApplicationEnabledSetting(String packageName) {
+        try {
+            return mPM.getApplicationEnabledSetting(packageName);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+        return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+    }
+
+    @Override
+    public void setPackageObbPath(String packageName, String path) {
+        try {
+            mPM.setPackageObbPath(packageName, path);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+    }
+
+    private final ContextImpl mContext;
+    private final IPackageManager mPM;
+
+    private static final Object sSync = new Object();
+    private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
+            = new HashMap<ResourceName, WeakReference<Drawable> >();
+    private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
+            = new HashMap<ResourceName, WeakReference<CharSequence> >();
+}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index ba301e9..129c29d 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -18,7 +18,6 @@
 
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.util.XmlUtils;
-import com.google.android.collect.Maps;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -35,7 +34,6 @@
 import android.content.ReceiverCallNotAllowedException;
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
-import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ComponentInfo;
 import android.content.pm.FeatureInfo;
@@ -45,17 +43,9 @@
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageManager;
 import android.content.pm.IPackageStatsObserver;
-import android.content.pm.InstrumentationInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
-import android.content.res.XmlResourceParser;
 import android.database.DatabaseErrorHandler;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteDatabase.CursorFactory;
@@ -111,14 +101,10 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.CountDownLatch;
@@ -162,7 +148,6 @@
 class ContextImpl extends Context {
     private final static String TAG = "ApplicationContext";
     private final static boolean DEBUG = false;
-    private final static boolean DEBUG_ICONS = false;
 
     private static final Object sSync = new Object();
     private static AlarmManager sAlarmManager;
@@ -315,7 +300,7 @@
         throw new RuntimeException("Not supported in system context");
     }
 
-    private static File makeBackupFile(File prefsFile) {
+    static File makeBackupFile(File prefsFile) {
         return new File(prefsFile.getPath() + ".bak");
     }
 
@@ -363,7 +348,7 @@
                     FileInputStream str = new FileInputStream(prefsFile);
                     map = XmlUtils.readMapXml(str);
                     str.close();
-                } catch (org.xmlpull.v1.XmlPullParserException e) {
+                } catch (XmlPullParserException e) {
                     Log.w(TAG, "getSharedPreferences", e);
                 } catch (FileNotFoundException e) {
                     Log.w(TAG, "getSharedPreferences", e);
@@ -1593,7 +1578,7 @@
         return mActivityToken;
     }
 
-    private static void setFilePermissionsFromMode(String name, int mode,
+    static void setFilePermissionsFromMode(String name, int mode,
             int extraPermissions) {
         int perms = FileUtils.S_IRUSR|FileUtils.S_IWUSR
             |FileUtils.S_IRGRP|FileUtils.S_IWGRP
@@ -1669,1540 +1654,4 @@
 
         private final ActivityThread mMainThread;
     }
-
-    // ----------------------------------------------------------------------
-    // ----------------------------------------------------------------------
-    // ----------------------------------------------------------------------
-
-    /*package*/
-    static final class ApplicationPackageManager extends PackageManager {
-        @Override
-        public PackageInfo getPackageInfo(String packageName, int flags)
-                throws NameNotFoundException {
-            try {
-                PackageInfo pi = mPM.getPackageInfo(packageName, flags);
-                if (pi != null) {
-                    return pi;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(packageName);
-        }
-
-        @Override
-        public String[] currentToCanonicalPackageNames(String[] names) {
-            try {
-                return mPM.currentToCanonicalPackageNames(names);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public String[] canonicalToCurrentPackageNames(String[] names) {
-            try {
-                return mPM.canonicalToCurrentPackageNames(names);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public Intent getLaunchIntentForPackage(String packageName) {
-            // First see if the package has an INFO activity; the existence of
-            // such an activity is implied to be the desired front-door for the
-            // overall package (such as if it has multiple launcher entries).
-            Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
-            intentToResolve.addCategory(Intent.CATEGORY_INFO);
-            intentToResolve.setPackage(packageName);
-            ResolveInfo resolveInfo = resolveActivity(intentToResolve, 0);
-
-            // Otherwise, try to find a main launcher activity.
-            if (resolveInfo == null) {
-                // reuse the intent instance
-                intentToResolve.removeCategory(Intent.CATEGORY_INFO);
-                intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER);
-                intentToResolve.setPackage(packageName);
-                resolveInfo = resolveActivity(intentToResolve, 0);
-            }
-            if (resolveInfo == null) {
-                return null;
-            }
-            Intent intent = new Intent(intentToResolve);
-            intent.setClassName(resolveInfo.activityInfo.applicationInfo.packageName,
-                                resolveInfo.activityInfo.name);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            return intent;
-        }
-
-        @Override
-        public int[] getPackageGids(String packageName)
-            throws NameNotFoundException {
-            try {
-                int[] gids = mPM.getPackageGids(packageName);
-                if (gids == null || gids.length > 0) {
-                    return gids;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(packageName);
-        }
-
-        @Override
-        public PermissionInfo getPermissionInfo(String name, int flags)
-            throws NameNotFoundException {
-            try {
-                PermissionInfo pi = mPM.getPermissionInfo(name, flags);
-                if (pi != null) {
-                    return pi;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(name);
-        }
-
-        @Override
-        public List<PermissionInfo> queryPermissionsByGroup(String group, int flags)
-                throws NameNotFoundException {
-            try {
-                List<PermissionInfo> pi = mPM.queryPermissionsByGroup(group, flags);
-                if (pi != null) {
-                    return pi;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(group);
-        }
-
-        @Override
-        public PermissionGroupInfo getPermissionGroupInfo(String name,
-                int flags) throws NameNotFoundException {
-            try {
-                PermissionGroupInfo pgi = mPM.getPermissionGroupInfo(name, flags);
-                if (pgi != null) {
-                    return pgi;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(name);
-        }
-
-        @Override
-        public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
-            try {
-                return mPM.getAllPermissionGroups(flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public ApplicationInfo getApplicationInfo(String packageName, int flags)
-            throws NameNotFoundException {
-            try {
-                ApplicationInfo ai = mPM.getApplicationInfo(packageName, flags);
-                if (ai != null) {
-                    return ai;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(packageName);
-        }
-
-        @Override
-        public ActivityInfo getActivityInfo(ComponentName className, int flags)
-            throws NameNotFoundException {
-            try {
-                ActivityInfo ai = mPM.getActivityInfo(className, flags);
-                if (ai != null) {
-                    return ai;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(className.toString());
-        }
-
-        @Override
-        public ActivityInfo getReceiverInfo(ComponentName className, int flags)
-            throws NameNotFoundException {
-            try {
-                ActivityInfo ai = mPM.getReceiverInfo(className, flags);
-                if (ai != null) {
-                    return ai;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(className.toString());
-        }
-
-        @Override
-        public ServiceInfo getServiceInfo(ComponentName className, int flags)
-            throws NameNotFoundException {
-            try {
-                ServiceInfo si = mPM.getServiceInfo(className, flags);
-                if (si != null) {
-                    return si;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(className.toString());
-        }
-
-        @Override
-        public ProviderInfo getProviderInfo(ComponentName className, int flags)
-            throws NameNotFoundException {
-            try {
-                ProviderInfo pi = mPM.getProviderInfo(className, flags);
-                if (pi != null) {
-                    return pi;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(className.toString());
-        }
-
-        @Override
-        public String[] getSystemSharedLibraryNames() {
-             try {
-                 return mPM.getSystemSharedLibraryNames();
-             } catch (RemoteException e) {
-                 throw new RuntimeException("Package manager has died", e);
-             }
-        }
-
-        @Override
-        public FeatureInfo[] getSystemAvailableFeatures() {
-            try {
-                return mPM.getSystemAvailableFeatures();
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public boolean hasSystemFeature(String name) {
-            try {
-                return mPM.hasSystemFeature(name);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public int checkPermission(String permName, String pkgName) {
-            try {
-                return mPM.checkPermission(permName, pkgName);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public boolean addPermission(PermissionInfo info) {
-            try {
-                return mPM.addPermission(info);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public boolean addPermissionAsync(PermissionInfo info) {
-            try {
-                return mPM.addPermissionAsync(info);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public void removePermission(String name) {
-            try {
-                mPM.removePermission(name);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public int checkSignatures(String pkg1, String pkg2) {
-            try {
-                return mPM.checkSignatures(pkg1, pkg2);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public int checkSignatures(int uid1, int uid2) {
-            try {
-                return mPM.checkUidSignatures(uid1, uid2);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public String[] getPackagesForUid(int uid) {
-            try {
-                return mPM.getPackagesForUid(uid);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public String getNameForUid(int uid) {
-            try {
-                return mPM.getNameForUid(uid);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public int getUidForSharedUser(String sharedUserName)
-                throws NameNotFoundException {
-            try {
-                int uid = mPM.getUidForSharedUser(sharedUserName);
-                if(uid != -1) {
-                    return uid;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-            throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
-        }
-
-        @Override
-        public List<PackageInfo> getInstalledPackages(int flags) {
-            try {
-                return mPM.getInstalledPackages(flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public List<ApplicationInfo> getInstalledApplications(int flags) {
-            try {
-                return mPM.getInstalledApplications(flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public ResolveInfo resolveActivity(Intent intent, int flags) {
-            try {
-                return mPM.resolveIntent(
-                    intent,
-                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public List<ResolveInfo> queryIntentActivities(Intent intent,
-                int flags) {
-            try {
-                return mPM.queryIntentActivities(
-                    intent,
-                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public List<ResolveInfo> queryIntentActivityOptions(
-                ComponentName caller, Intent[] specifics, Intent intent,
-                int flags) {
-            final ContentResolver resolver = mContext.getContentResolver();
-
-            String[] specificTypes = null;
-            if (specifics != null) {
-                final int N = specifics.length;
-                for (int i=0; i<N; i++) {
-                    Intent sp = specifics[i];
-                    if (sp != null) {
-                        String t = sp.resolveTypeIfNeeded(resolver);
-                        if (t != null) {
-                            if (specificTypes == null) {
-                                specificTypes = new String[N];
-                            }
-                            specificTypes[i] = t;
-                        }
-                    }
-                }
-            }
-
-            try {
-                return mPM.queryIntentActivityOptions(caller, specifics,
-                    specificTypes, intent, intent.resolveTypeIfNeeded(resolver),
-                    flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
-            try {
-                return mPM.queryIntentReceivers(
-                    intent,
-                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public ResolveInfo resolveService(Intent intent, int flags) {
-            try {
-                return mPM.resolveService(
-                    intent,
-                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public List<ResolveInfo> queryIntentServices(Intent intent, int flags) {
-            try {
-                return mPM.queryIntentServices(
-                    intent,
-                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public ProviderInfo resolveContentProvider(String name,
-                int flags) {
-            try {
-                return mPM.resolveContentProvider(name, flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public List<ProviderInfo> queryContentProviders(String processName,
-                int uid, int flags) {
-            try {
-                return mPM.queryContentProviders(processName, uid, flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override
-        public InstrumentationInfo getInstrumentationInfo(
-                ComponentName className, int flags)
-                throws NameNotFoundException {
-            try {
-                InstrumentationInfo ii = mPM.getInstrumentationInfo(
-                        className, flags);
-                if (ii != null) {
-                    return ii;
-                }
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-
-            throw new NameNotFoundException(className.toString());
-        }
-
-        @Override
-        public List<InstrumentationInfo> queryInstrumentation(
-                String targetPackage, int flags) {
-            try {
-                return mPM.queryInstrumentation(targetPackage, flags);
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        @Override public Drawable getDrawable(String packageName, int resid,
-                ApplicationInfo appInfo) {
-            ResourceName name = new ResourceName(packageName, resid);
-            Drawable dr = getCachedIcon(name);
-            if (dr != null) {
-                return dr;
-            }
-            if (appInfo == null) {
-                try {
-                    appInfo = getApplicationInfo(packageName, 0);
-                } catch (NameNotFoundException e) {
-                    return null;
-                }
-            }
-            try {
-                Resources r = getResourcesForApplication(appInfo);
-                dr = r.getDrawable(resid);
-                if (false) {
-                    RuntimeException e = new RuntimeException("here");
-                    e.fillInStackTrace();
-                    Log.w(TAG, "Getting drawable 0x" + Integer.toHexString(resid)
-                            + " from package " + packageName
-                            + ": app scale=" + r.getCompatibilityInfo().applicationScale
-                            + ", caller scale=" + mContext.getResources().getCompatibilityInfo().applicationScale,
-                            e);
-                }
-                if (DEBUG_ICONS) Log.v(TAG, "Getting drawable 0x"
-                        + Integer.toHexString(resid) + " from " + r
-                        + ": " + dr);
-                putCachedIcon(name, dr);
-                return dr;
-            } catch (NameNotFoundException e) {
-                Log.w("PackageManager", "Failure retrieving resources for"
-                        + appInfo.packageName);
-            } catch (RuntimeException e) {
-                // If an exception was thrown, fall through to return
-                // default icon.
-                Log.w("PackageManager", "Failure retrieving icon 0x"
-                        + Integer.toHexString(resid) + " in package "
-                        + packageName, e);
-            }
-            return null;
-        }
-
-        @Override public Drawable getActivityIcon(ComponentName activityName)
-                throws NameNotFoundException {
-            return getActivityInfo(activityName, 0).loadIcon(this);
-        }
-
-        @Override public Drawable getActivityIcon(Intent intent)
-                throws NameNotFoundException {
-            if (intent.getComponent() != null) {
-                return getActivityIcon(intent.getComponent());
-            }
-
-            ResolveInfo info = resolveActivity(
-                intent, PackageManager.MATCH_DEFAULT_ONLY);
-            if (info != null) {
-                return info.activityInfo.loadIcon(this);
-            }
-
-            throw new NameNotFoundException(intent.toURI());
-        }
-
-        @Override public Drawable getDefaultActivityIcon() {
-            return Resources.getSystem().getDrawable(
-                com.android.internal.R.drawable.sym_def_app_icon);
-        }
-
-        @Override public Drawable getApplicationIcon(ApplicationInfo info) {
-            return info.loadIcon(this);
-        }
-
-        @Override public Drawable getApplicationIcon(String packageName)
-                throws NameNotFoundException {
-            return getApplicationIcon(getApplicationInfo(packageName, 0));
-        }
-        
-        @Override 
-        public Drawable getActivityLogo(ComponentName activityName)
-                throws NameNotFoundException {
-            return getActivityInfo(activityName, 0).loadLogo(this);
-        }
-
-        @Override
-        public Drawable getActivityLogo(Intent intent)
-                throws NameNotFoundException {
-            if (intent.getComponent() != null) {
-                return getActivityLogo(intent.getComponent());
-            }
-
-            ResolveInfo info = resolveActivity(
-                    intent, PackageManager.MATCH_DEFAULT_ONLY);
-            if (info != null) {
-                return info.activityInfo.loadLogo(this);
-            }
-
-            throw new NameNotFoundException(intent.toUri(0));
-        }
-
-        @Override
-        public Drawable getApplicationLogo(ApplicationInfo info) {
-            return info.loadLogo(this);
-        }
-
-        @Override
-        public Drawable getApplicationLogo(String packageName)
-                throws NameNotFoundException {
-            return getApplicationLogo(getApplicationInfo(packageName, 0));
-        }
-
-        @Override public Resources getResourcesForActivity(
-                ComponentName activityName) throws NameNotFoundException {
-            return getResourcesForApplication(
-                getActivityInfo(activityName, 0).applicationInfo);
-        }
-
-        @Override public Resources getResourcesForApplication(
-                ApplicationInfo app) throws NameNotFoundException {
-            if (app.packageName.equals("system")) {
-                return mContext.mMainThread.getSystemContext().getResources();
-            }
-            Resources r = mContext.mMainThread.getTopLevelResources(
-                    app.uid == Process.myUid() ? app.sourceDir
-                    : app.publicSourceDir, mContext.mPackageInfo);
-            if (r != null) {
-                return r;
-            }
-            throw new NameNotFoundException("Unable to open " + app.publicSourceDir);
-        }
-
-        @Override public Resources getResourcesForApplication(
-                String appPackageName) throws NameNotFoundException {
-            return getResourcesForApplication(
-                getApplicationInfo(appPackageName, 0));
-        }
-
-        int mCachedSafeMode = -1;
-        @Override public boolean isSafeMode() {
-            try {
-                if (mCachedSafeMode < 0) {
-                    mCachedSafeMode = mPM.isSafeMode() ? 1 : 0;
-                }
-                return mCachedSafeMode != 0;
-            } catch (RemoteException e) {
-                throw new RuntimeException("Package manager has died", e);
-            }
-        }
-
-        static void configurationChanged() {
-            synchronized (sSync) {
-                sIconCache.clear();
-                sStringCache.clear();
-            }
-        }
-
-        ApplicationPackageManager(ContextImpl context,
-                IPackageManager pm) {
-            mContext = context;
-            mPM = pm;
-        }
-
-        private Drawable getCachedIcon(ResourceName name) {
-            synchronized (sSync) {
-                WeakReference<Drawable> wr = sIconCache.get(name);
-                if (DEBUG_ICONS) Log.v(TAG, "Get cached weak drawable ref for "
-                        + name + ": " + wr);
-                if (wr != null) {   // we have the activity
-                    Drawable dr = wr.get();
-                    if (dr != null) {
-                        if (DEBUG_ICONS) Log.v(TAG, "Get cached drawable for "
-                                + name + ": " + dr);
-                        return dr;
-                    }
-                    // our entry has been purged
-                    sIconCache.remove(name);
-                }
-            }
-            return null;
-        }
-
-        private void putCachedIcon(ResourceName name, Drawable dr) {
-            synchronized (sSync) {
-                sIconCache.put(name, new WeakReference<Drawable>(dr));
-                if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
-                        + name + ": " + dr);
-            }
-        }
-
-        static final void handlePackageBroadcast(int cmd, String[] pkgList,
-                boolean hasPkgInfo) {
-            boolean immediateGc = false;
-            if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
-                immediateGc = true;
-            }
-            if (pkgList != null && (pkgList.length > 0)) {
-                boolean needCleanup = false;
-                for (String ssp : pkgList) {
-                    synchronized (sSync) {
-                        if (sIconCache.size() > 0) {
-                            Iterator<ResourceName> it = sIconCache.keySet().iterator();
-                            while (it.hasNext()) {
-                                ResourceName nm = it.next();
-                                if (nm.packageName.equals(ssp)) {
-                                    //Log.i(TAG, "Removing cached drawable for " + nm);
-                                    it.remove();
-                                    needCleanup = true;
-                                }
-                            }
-                        }
-                        if (sStringCache.size() > 0) {
-                            Iterator<ResourceName> it = sStringCache.keySet().iterator();
-                            while (it.hasNext()) {
-                                ResourceName nm = it.next();
-                                if (nm.packageName.equals(ssp)) {
-                                    //Log.i(TAG, "Removing cached string for " + nm);
-                                    it.remove();
-                                    needCleanup = true;
-                                }
-                            }
-                        }
-                    }
-                }
-                if (needCleanup || hasPkgInfo) {
-                    if (immediateGc) {
-                        // Schedule an immediate gc.
-                        Runtime.getRuntime().gc();
-                    } else {
-                        ActivityThread.currentActivityThread().scheduleGcIdler();
-                    }
-                }
-            }
-        }
-
-        private static final class ResourceName {
-            final String packageName;
-            final int iconId;
-
-            ResourceName(String _packageName, int _iconId) {
-                packageName = _packageName;
-                iconId = _iconId;
-            }
-
-            ResourceName(ApplicationInfo aInfo, int _iconId) {
-                this(aInfo.packageName, _iconId);
-            }
-
-            ResourceName(ComponentInfo cInfo, int _iconId) {
-                this(cInfo.applicationInfo.packageName, _iconId);
-            }
-
-            ResourceName(ResolveInfo rInfo, int _iconId) {
-                this(rInfo.activityInfo.applicationInfo.packageName, _iconId);
-            }
-
-            @Override
-            public boolean equals(Object o) {
-                if (this == o) return true;
-                if (o == null || getClass() != o.getClass()) return false;
-
-                ResourceName that = (ResourceName) o;
-
-                if (iconId != that.iconId) return false;
-                return !(packageName != null ?
-                        !packageName.equals(that.packageName) : that.packageName != null);
-
-            }
-
-            @Override
-            public int hashCode() {
-                int result;
-                result = packageName.hashCode();
-                result = 31 * result + iconId;
-                return result;
-            }
-
-            @Override
-            public String toString() {
-                return "{ResourceName " + packageName + " / " + iconId + "}";
-            }
-        }
-
-        private CharSequence getCachedString(ResourceName name) {
-            synchronized (sSync) {
-                WeakReference<CharSequence> wr = sStringCache.get(name);
-                if (wr != null) {   // we have the activity
-                    CharSequence cs = wr.get();
-                    if (cs != null) {
-                        return cs;
-                    }
-                    // our entry has been purged
-                    sStringCache.remove(name);
-                }
-            }
-            return null;
-        }
-
-        private void putCachedString(ResourceName name, CharSequence cs) {
-            synchronized (sSync) {
-                sStringCache.put(name, new WeakReference<CharSequence>(cs));
-            }
-        }
-
-        @Override
-        public CharSequence getText(String packageName, int resid,
-                ApplicationInfo appInfo) {
-            ResourceName name = new ResourceName(packageName, resid);
-            CharSequence text = getCachedString(name);
-            if (text != null) {
-                return text;
-            }
-            if (appInfo == null) {
-                try {
-                    appInfo = getApplicationInfo(packageName, 0);
-                } catch (NameNotFoundException e) {
-                    return null;
-                }
-            }
-            try {
-                Resources r = getResourcesForApplication(appInfo);
-                text = r.getText(resid);
-                putCachedString(name, text);
-                return text;
-            } catch (NameNotFoundException e) {
-                Log.w("PackageManager", "Failure retrieving resources for"
-                        + appInfo.packageName);
-            } catch (RuntimeException e) {
-                // If an exception was thrown, fall through to return
-                // default icon.
-                Log.w("PackageManager", "Failure retrieving text 0x"
-                        + Integer.toHexString(resid) + " in package "
-                        + packageName, e);
-            }
-            return null;
-        }
-
-        @Override
-        public XmlResourceParser getXml(String packageName, int resid,
-                ApplicationInfo appInfo) {
-            if (appInfo == null) {
-                try {
-                    appInfo = getApplicationInfo(packageName, 0);
-                } catch (NameNotFoundException e) {
-                    return null;
-                }
-            }
-            try {
-                Resources r = getResourcesForApplication(appInfo);
-                return r.getXml(resid);
-            } catch (RuntimeException e) {
-                // If an exception was thrown, fall through to return
-                // default icon.
-                Log.w("PackageManager", "Failure retrieving xml 0x"
-                        + Integer.toHexString(resid) + " in package "
-                        + packageName, e);
-            } catch (NameNotFoundException e) {
-                Log.w("PackageManager", "Failure retrieving resources for"
-                        + appInfo.packageName);
-            }
-            return null;
-        }
-
-        @Override
-        public CharSequence getApplicationLabel(ApplicationInfo info) {
-            return info.loadLabel(this);
-        }
-
-        @Override
-        public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
-                String installerPackageName) {
-            try {
-                mPM.installPackage(packageURI, observer, flags, installerPackageName);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public void movePackage(String packageName, IPackageMoveObserver observer, int flags) {
-            try {
-                mPM.movePackage(packageName, observer, flags);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public String getInstallerPackageName(String packageName) {
-            try {
-                return mPM.getInstallerPackageName(packageName);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-            return null;
-        }
-
-        @Override
-        public void deletePackage(String packageName, IPackageDeleteObserver observer, int flags) {
-            try {
-                mPM.deletePackage(packageName, observer, flags);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-        @Override
-        public void clearApplicationUserData(String packageName,
-                IPackageDataObserver observer) {
-            try {
-                mPM.clearApplicationUserData(packageName, observer);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-        @Override
-        public void deleteApplicationCacheFiles(String packageName,
-                IPackageDataObserver observer) {
-            try {
-                mPM.deleteApplicationCacheFiles(packageName, observer);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-        @Override
-        public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) {
-            try {
-                mPM.freeStorageAndNotify(idealStorageSize, observer);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public void freeStorage(long freeStorageSize, IntentSender pi) {
-            try {
-                mPM.freeStorage(freeStorageSize, pi);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public void getPackageSizeInfo(String packageName,
-                IPackageStatsObserver observer) {
-            try {
-                mPM.getPackageSizeInfo(packageName, observer);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-        @Override
-        public void addPackageToPreferred(String packageName) {
-            try {
-                mPM.addPackageToPreferred(packageName);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public void removePackageFromPreferred(String packageName) {
-            try {
-                mPM.removePackageFromPreferred(packageName);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public List<PackageInfo> getPreferredPackages(int flags) {
-            try {
-                return mPM.getPreferredPackages(flags);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-            return new ArrayList<PackageInfo>();
-        }
-
-        @Override
-        public void addPreferredActivity(IntentFilter filter,
-                int match, ComponentName[] set, ComponentName activity) {
-            try {
-                mPM.addPreferredActivity(filter, match, set, activity);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public void replacePreferredActivity(IntentFilter filter,
-                int match, ComponentName[] set, ComponentName activity) {
-            try {
-                mPM.replacePreferredActivity(filter, match, set, activity);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public void clearPackagePreferredActivities(String packageName) {
-            try {
-                mPM.clearPackagePreferredActivities(packageName);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public int getPreferredActivities(List<IntentFilter> outFilters,
-                List<ComponentName> outActivities, String packageName) {
-            try {
-                return mPM.getPreferredActivities(outFilters, outActivities, packageName);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-            return 0;
-        }
-
-        @Override
-        public void setComponentEnabledSetting(ComponentName componentName,
-                int newState, int flags) {
-            try {
-                mPM.setComponentEnabledSetting(componentName, newState, flags);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public int getComponentEnabledSetting(ComponentName componentName) {
-            try {
-                return mPM.getComponentEnabledSetting(componentName);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-            return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-        }
-
-        @Override
-        public void setApplicationEnabledSetting(String packageName,
-                int newState, int flags) {
-            try {
-                mPM.setApplicationEnabledSetting(packageName, newState, flags);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        @Override
-        public int getApplicationEnabledSetting(String packageName) {
-            try {
-                return mPM.getApplicationEnabledSetting(packageName);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-            return PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-        }
-
-        @Override
-        public void setPackageObbPath(String packageName, String path) {
-            try {
-                mPM.setPackageObbPath(packageName, path);
-            } catch (RemoteException e) {
-                // Should never happen!
-            }
-        }
-
-        private final ContextImpl mContext;
-        private final IPackageManager mPM;
-
-        private static final Object sSync = new Object();
-        private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
-                = new HashMap<ResourceName, WeakReference<Drawable> >();
-        private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
-                = new HashMap<ResourceName, WeakReference<CharSequence> >();
-    }
-
-    // ----------------------------------------------------------------------
-    // ----------------------------------------------------------------------
-    // ----------------------------------------------------------------------
-
-    private static final class SharedPreferencesImpl implements SharedPreferences {
-
-        // Lock ordering rules:
-        //  - acquire SharedPreferencesImpl.this before EditorImpl.this
-        //  - acquire mWritingToDiskLock before EditorImpl.this
-
-        private final File mFile;
-        private final File mBackupFile;
-        private final int mMode;
-
-        private Map<String, Object> mMap;     // guarded by 'this'
-        private int mDiskWritesInFlight = 0;  // guarded by 'this'
-        private boolean mLoaded = false;      // guarded by 'this'
-        private long mStatTimestamp;          // guarded by 'this'
-        private long mStatSize;               // guarded by 'this'
-
-        private final Object mWritingToDiskLock = new Object();
-        private static final Object mContent = new Object();
-        private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
-
-        SharedPreferencesImpl(
-            File file, int mode, Map initialContents) {
-            mFile = file;
-            mBackupFile = makeBackupFile(file);
-            mMode = mode;
-            mLoaded = initialContents != null;
-            mMap = initialContents != null ? initialContents : new HashMap<String, Object>();
-            FileStatus stat = new FileStatus();
-            if (FileUtils.getFileStatus(file.getPath(), stat)) {
-                mStatTimestamp = stat.mtime;
-            }
-            mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
-        }
-
-        // Has this SharedPreferences ever had values assigned to it?
-        boolean isLoaded() {
-            synchronized (this) {
-                return mLoaded;
-            }
-        }
-
-        // Has the file changed out from under us?  i.e. writes that
-        // we didn't instigate.
-        public boolean hasFileChangedUnexpectedly() {
-            synchronized (this) {
-                if (mDiskWritesInFlight > 0) {
-                    // If we know we caused it, it's not unexpected.
-                    if (DEBUG) Log.d(TAG, "disk write in flight, not unexpected.");
-                    return false;
-                }
-            }
-            FileStatus stat = new FileStatus();
-            if (!FileUtils.getFileStatus(mFile.getPath(), stat)) {
-                return true;
-            }
-            synchronized (this) {
-                return mStatTimestamp != stat.mtime || mStatSize != stat.size;
-            }
-        }
-
-        public void replace(Map newContents) {
-            synchronized (this) {
-                mLoaded = true;
-                if (newContents != null) {
-                    mMap = newContents;
-                }
-            }
-        }
-
-        public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
-            synchronized(this) {
-                mListeners.put(listener, mContent);
-            }
-        }
-
-        public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
-            synchronized(this) {
-                mListeners.remove(listener);
-            }
-        }
-
-        public Map<String, ?> getAll() {
-            synchronized(this) {
-                //noinspection unchecked
-                return new HashMap<String, Object>(mMap);
-            }
-        }
-
-        public String getString(String key, String defValue) {
-            synchronized (this) {
-                String v = (String)mMap.get(key);
-                return v != null ? v : defValue;
-            }
-        }
-        
-        public Set<String> getStringSet(String key, Set<String> defValues) {
-            synchronized (this) {
-                Set<String> v = (Set<String>) mMap.get(key);
-                return v != null ? v : defValues;
-            }
-        }
-
-        public int getInt(String key, int defValue) {
-            synchronized (this) {
-                Integer v = (Integer)mMap.get(key);
-                return v != null ? v : defValue;
-            }
-        }
-        public long getLong(String key, long defValue) {
-            synchronized (this) {
-                Long v = (Long)mMap.get(key);
-                return v != null ? v : defValue;
-            }
-        }
-        public float getFloat(String key, float defValue) {
-            synchronized (this) {
-                Float v = (Float)mMap.get(key);
-                return v != null ? v : defValue;
-            }
-        }
-        public boolean getBoolean(String key, boolean defValue) {
-            synchronized (this) {
-                Boolean v = (Boolean)mMap.get(key);
-                return v != null ? v : defValue;
-            }
-        }
-
-        public boolean contains(String key) {
-            synchronized (this) {
-                return mMap.containsKey(key);
-            }
-        }
-
-        public Editor edit() {
-            return new EditorImpl();
-        }
-
-        // Return value from EditorImpl#commitToMemory()
-        private static class MemoryCommitResult {
-            public boolean changesMade;  // any keys different?
-            public List<String> keysModified;  // may be null
-            public Set<OnSharedPreferenceChangeListener> listeners;  // may be null
-            public Map<?, ?> mapToWriteToDisk;
-            public final CountDownLatch writtenToDiskLatch = new CountDownLatch(1);
-            public volatile boolean writeToDiskResult = false;
-
-            public void setDiskWriteResult(boolean result) {
-                writeToDiskResult = result;
-                writtenToDiskLatch.countDown();
-            }
-        }
-
-        public final class EditorImpl implements Editor {
-            private final Map<String, Object> mModified = Maps.newHashMap();
-            private boolean mClear = false;
-
-            public Editor putString(String key, String value) {
-                synchronized (this) {
-                    mModified.put(key, value);
-                    return this;
-                }
-            }
-            public Editor putStringSet(String key, Set<String> values) {
-                synchronized (this) {
-                    mModified.put(key, values);
-                    return this;
-                }
-            }
-            public Editor putInt(String key, int value) {
-                synchronized (this) {
-                    mModified.put(key, value);
-                    return this;
-                }
-            }
-            public Editor putLong(String key, long value) {
-                synchronized (this) {
-                    mModified.put(key, value);
-                    return this;
-                }
-            }
-            public Editor putFloat(String key, float value) {
-                synchronized (this) {
-                    mModified.put(key, value);
-                    return this;
-                }
-            }
-            public Editor putBoolean(String key, boolean value) {
-                synchronized (this) {
-                    mModified.put(key, value);
-                    return this;
-                }
-            }
-
-            public Editor remove(String key) {
-                synchronized (this) {
-                    mModified.put(key, this);
-                    return this;
-                }
-            }
-
-            public Editor clear() {
-                synchronized (this) {
-                    mClear = true;
-                    return this;
-                }
-            }
-
-            public void apply() {
-                final MemoryCommitResult mcr = commitToMemory();
-                final Runnable awaitCommit = new Runnable() {
-                        public void run() {
-                            try {
-                                mcr.writtenToDiskLatch.await();
-                            } catch (InterruptedException ignored) {
-                            }
-                        }
-                    };
-
-                QueuedWork.add(awaitCommit);
-
-                Runnable postWriteRunnable = new Runnable() {
-                        public void run() {
-                            awaitCommit.run();
-                            QueuedWork.remove(awaitCommit);
-                        }
-                    };
-
-                SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);
-
-                // Okay to notify the listeners before it's hit disk
-                // because the listeners should always get the same
-                // SharedPreferences instance back, which has the
-                // changes reflected in memory.
-                notifyListeners(mcr);
-            }
-
-            // Returns true if any changes were made
-            private MemoryCommitResult commitToMemory() {
-                MemoryCommitResult mcr = new MemoryCommitResult();
-                synchronized (SharedPreferencesImpl.this) {
-                    // We optimistically don't make a deep copy until
-                    // a memory commit comes in when we're already
-                    // writing to disk.
-                    if (mDiskWritesInFlight > 0) {
-                        // We can't modify our mMap as a currently
-                        // in-flight write owns it.  Clone it before
-                        // modifying it.
-                        // noinspection unchecked
-                        mMap = new HashMap<String, Object>(mMap);
-                    }
-                    mcr.mapToWriteToDisk = mMap;
-                    mDiskWritesInFlight++;
-
-                    boolean hasListeners = mListeners.size() > 0;
-                    if (hasListeners) {
-                        mcr.keysModified = new ArrayList<String>();
-                        mcr.listeners =
-                            new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
-                    }
-
-                    synchronized (this) {
-                        if (mClear) {
-                            if (!mMap.isEmpty()) {
-                                mcr.changesMade = true;
-                                mMap.clear();
-                            }
-                            mClear = false;
-                        }
-
-                        for (Entry<String, Object> e : mModified.entrySet()) {
-                            String k = e.getKey();
-                            Object v = e.getValue();
-                            if (v == this) {  // magic value for a removal mutation
-                                if (!mMap.containsKey(k)) {
-                                    continue;
-                                }
-                                mMap.remove(k);
-                            } else {
-                                boolean isSame = false;
-                                if (mMap.containsKey(k)) {
-                                    Object existingValue = mMap.get(k);
-                                    if (existingValue != null && existingValue.equals(v)) {
-                                        continue;
-                                    }
-                                }
-                                mMap.put(k, v);
-                            }
-
-                            mcr.changesMade = true;
-                            if (hasListeners) {
-                                mcr.keysModified.add(k);
-                            }
-                        }
-
-                        mModified.clear();
-                    }
-                }
-                return mcr;
-            }
-
-            public boolean commit() {
-                MemoryCommitResult mcr = commitToMemory();
-                SharedPreferencesImpl.this.enqueueDiskWrite(
-                    mcr, null /* sync write on this thread okay */);
-                try {
-                    mcr.writtenToDiskLatch.await();
-                } catch (InterruptedException e) {
-                    return false;
-                }
-                notifyListeners(mcr);
-                return mcr.writeToDiskResult;
-            }
-
-            private void notifyListeners(final MemoryCommitResult mcr) {
-                if (mcr.listeners == null || mcr.keysModified == null ||
-                    mcr.keysModified.size() == 0) {
-                    return;
-                }
-                if (Looper.myLooper() == Looper.getMainLooper()) {
-                    for (int i = mcr.keysModified.size() - 1; i >= 0; i--) {
-                        final String key = mcr.keysModified.get(i);
-                        for (OnSharedPreferenceChangeListener listener : mcr.listeners) {
-                            if (listener != null) {
-                                listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
-                            }
-                        }
-                    }
-                } else {
-                    // Run this function on the main thread.
-                    ActivityThread.sMainThreadHandler.post(new Runnable() {
-                            public void run() {
-                                notifyListeners(mcr);
-                            }
-                        });
-                }
-            }
-        }
-
-        /**
-         * Enqueue an already-committed-to-memory result to be written
-         * to disk.
-         *
-         * They will be written to disk one-at-a-time in the order
-         * that they're enqueued.
-         *
-         * @param postWriteRunnable if non-null, we're being called
-         *   from apply() and this is the runnable to run after
-         *   the write proceeds.  if null (from a regular commit()),
-         *   then we're allowed to do this disk write on the main
-         *   thread (which in addition to reducing allocations and
-         *   creating a background thread, this has the advantage that
-         *   we catch them in userdebug StrictMode reports to convert
-         *   them where possible to apply() ...)
-         */
-        private void enqueueDiskWrite(final MemoryCommitResult mcr,
-                                      final Runnable postWriteRunnable) {
-            final Runnable writeToDiskRunnable = new Runnable() {
-                    public void run() {
-                        synchronized (mWritingToDiskLock) {
-                            writeToFile(mcr);
-                        }
-                        synchronized (SharedPreferencesImpl.this) {
-                            mDiskWritesInFlight--;
-                        }
-                        if (postWriteRunnable != null) {
-                            postWriteRunnable.run();
-                        }
-                    }
-                };
-
-            final boolean isFromSyncCommit = (postWriteRunnable == null);
-
-            // Typical #commit() path with fewer allocations, doing a write on
-            // the current thread.
-            if (isFromSyncCommit) {
-                boolean wasEmpty = false;
-                synchronized (SharedPreferencesImpl.this) {
-                    wasEmpty = mDiskWritesInFlight == 1;
-                }
-                if (wasEmpty) {
-                    writeToDiskRunnable.run();
-                    return;
-                }
-            }
-
-            QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
-        }
-
-        private static FileOutputStream createFileOutputStream(File file) {
-            FileOutputStream str = null;
-            try {
-                str = new FileOutputStream(file);
-            } catch (FileNotFoundException e) {
-                File parent = file.getParentFile();
-                if (!parent.mkdir()) {
-                    Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
-                    return null;
-                }
-                FileUtils.setPermissions(
-                    parent.getPath(),
-                    FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
-                    -1, -1);
-                try {
-                    str = new FileOutputStream(file);
-                } catch (FileNotFoundException e2) {
-                    Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
-                }
-            }
-            return str;
-        }
-
-        // Note: must hold mWritingToDiskLock
-        private void writeToFile(MemoryCommitResult mcr) {
-            // Rename the current file so it may be used as a backup during the next read
-            if (mFile.exists()) {
-                if (!mcr.changesMade) {
-                    // If the file already exists, but no changes were
-                    // made to the underlying map, it's wasteful to
-                    // re-write the file.  Return as if we wrote it
-                    // out.
-                    mcr.setDiskWriteResult(true);
-                    return;
-                }
-                if (!mBackupFile.exists()) {
-                    if (!mFile.renameTo(mBackupFile)) {
-                        Log.e(TAG, "Couldn't rename file " + mFile
-                                + " to backup file " + mBackupFile);
-                        mcr.setDiskWriteResult(false);
-                        return;
-                    }
-                } else {
-                    mFile.delete();
-                }
-            }
-
-            // Attempt to write the file, delete the backup and return true as atomically as
-            // possible.  If any exception occurs, delete the new file; next time we will restore
-            // from the backup.
-            try {
-                FileOutputStream str = createFileOutputStream(mFile);
-                if (str == null) {
-                    mcr.setDiskWriteResult(false);
-                    return;
-                }
-                XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
-                FileUtils.sync(str);
-                str.close();
-                setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
-                FileStatus stat = new FileStatus();
-                if (FileUtils.getFileStatus(mFile.getPath(), stat)) {
-                    synchronized (this) {
-                        mStatTimestamp = stat.mtime;
-                        mStatSize = stat.size;
-                    }
-                }
-                // Writing was successful, delete the backup file if there is one.
-                mBackupFile.delete();
-                mcr.setDiskWriteResult(true);
-                return;
-            } catch (XmlPullParserException e) {
-                Log.w(TAG, "writeToFile: Got exception:", e);
-            } catch (IOException e) {
-                Log.w(TAG, "writeToFile: Got exception:", e);
-            }
-            // Clean up an unsuccessfully written file
-            if (mFile.exists()) {
-                if (!mFile.delete()) {
-                    Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
-                }
-            }
-            mcr.setDiskWriteResult(false);
-        }
-    }
 }
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index eaf1aee..b103385 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -619,6 +620,46 @@
     }
     
     /**
+     * Return <code>getActivity().getResources()</code>.
+     */
+    final public Resources getResources() {
+        return mActivity.getResources();
+    }
+    
+    /**
+     * Return a localized, styled CharSequence from the application's package's
+     * default string table.
+     *
+     * @param resId Resource id for the CharSequence text
+     */
+    public final CharSequence getText(int resId) {
+        return getResources().getText(resId);
+    }
+
+    /**
+     * Return a localized string from the application's package's
+     * default string table.
+     *
+     * @param resId Resource id for the string
+     */
+    public final String getString(int resId) {
+        return getResources().getString(resId);
+    }
+
+    /**
+     * Return a localized formatted string from the application's package's
+     * default string table, substituting the format arguments as defined in
+     * {@link java.util.Formatter} and {@link java.lang.String#format}.
+     *
+     * @param resId Resource id for the format string
+     * @param formatArgs The format arguments that will be used for substitution.
+     */
+
+    public final String getString(int resId, Object... formatArgs) {
+        return getResources().getString(resId, formatArgs);
+    }
+
+    /**
      * Return the FragmentManager for interacting with fragments associated
      * with this fragment's activity.  Note that this will be non-null slightly
      * before {@link #getActivity()}, during the time from when the fragment is
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index dc4acbe..5aec348 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -76,7 +76,7 @@
     public abstract FragmentTransaction hide(Fragment fragment);
     
     /**
-     * Hides a previously hidden fragment.  This is only relevant for fragments whose
+     * Shows a previously hidden fragment.  This is only relevant for fragments whose
      * views have been added to a container, as this will cause the view to
      * be shown.
      * 
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
new file mode 100644
index 0000000..2096a78
--- /dev/null
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -0,0 +1,518 @@
+/*
+ * Copyright (C) 2010 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.app;
+
+import android.content.SharedPreferences;
+import android.os.FileUtils.FileStatus;
+import android.os.FileUtils;
+import android.os.Looper;
+import android.util.Log;
+
+import com.google.android.collect.Maps;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+
+final class SharedPreferencesImpl implements SharedPreferences {
+    private static final String TAG = "SharedPreferencesImpl";
+    private static final boolean DEBUG = false;
+
+    // Lock ordering rules:
+    //  - acquire SharedPreferencesImpl.this before EditorImpl.this
+    //  - acquire mWritingToDiskLock before EditorImpl.this
+
+    private final File mFile;
+    private final File mBackupFile;
+    private final int mMode;
+
+    private Map<String, Object> mMap;     // guarded by 'this'
+    private int mDiskWritesInFlight = 0;  // guarded by 'this'
+    private boolean mLoaded = false;      // guarded by 'this'
+    private long mStatTimestamp;          // guarded by 'this'
+    private long mStatSize;               // guarded by 'this'
+
+    private final Object mWritingToDiskLock = new Object();
+    private static final Object mContent = new Object();
+    private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
+
+    SharedPreferencesImpl(
+        File file, int mode, Map initialContents) {
+        mFile = file;
+        mBackupFile = ContextImpl.makeBackupFile(file);
+        mMode = mode;
+        mLoaded = initialContents != null;
+        mMap = initialContents != null ? initialContents : new HashMap<String, Object>();
+        FileStatus stat = new FileStatus();
+        if (FileUtils.getFileStatus(file.getPath(), stat)) {
+            mStatTimestamp = stat.mtime;
+        }
+        mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
+    }
+
+    // Has this SharedPreferences ever had values assigned to it?
+    boolean isLoaded() {
+        synchronized (this) {
+            return mLoaded;
+        }
+    }
+
+    // Has the file changed out from under us?  i.e. writes that
+    // we didn't instigate.
+    public boolean hasFileChangedUnexpectedly() {
+        synchronized (this) {
+            if (mDiskWritesInFlight > 0) {
+                // If we know we caused it, it's not unexpected.
+                if (DEBUG) Log.d(TAG, "disk write in flight, not unexpected.");
+                return false;
+            }
+        }
+        FileStatus stat = new FileStatus();
+        if (!FileUtils.getFileStatus(mFile.getPath(), stat)) {
+            return true;
+        }
+        synchronized (this) {
+            return mStatTimestamp != stat.mtime || mStatSize != stat.size;
+        }
+    }
+
+    public void replace(Map newContents) {
+        synchronized (this) {
+            mLoaded = true;
+            if (newContents != null) {
+                mMap = newContents;
+            }
+        }
+    }
+
+    public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
+        synchronized(this) {
+            mListeners.put(listener, mContent);
+        }
+    }
+
+    public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
+        synchronized(this) {
+            mListeners.remove(listener);
+        }
+    }
+
+    public Map<String, ?> getAll() {
+        synchronized(this) {
+            //noinspection unchecked
+            return new HashMap<String, Object>(mMap);
+        }
+    }
+
+    public String getString(String key, String defValue) {
+        synchronized (this) {
+            String v = (String)mMap.get(key);
+            return v != null ? v : defValue;
+        }
+    }
+
+    public Set<String> getStringSet(String key, Set<String> defValues) {
+        synchronized (this) {
+            Set<String> v = (Set<String>) mMap.get(key);
+            return v != null ? v : defValues;
+        }
+    }
+
+    public int getInt(String key, int defValue) {
+        synchronized (this) {
+            Integer v = (Integer)mMap.get(key);
+            return v != null ? v : defValue;
+        }
+    }
+    public long getLong(String key, long defValue) {
+        synchronized (this) {
+            Long v = (Long)mMap.get(key);
+            return v != null ? v : defValue;
+        }
+    }
+    public float getFloat(String key, float defValue) {
+        synchronized (this) {
+            Float v = (Float)mMap.get(key);
+            return v != null ? v : defValue;
+        }
+    }
+    public boolean getBoolean(String key, boolean defValue) {
+        synchronized (this) {
+            Boolean v = (Boolean)mMap.get(key);
+            return v != null ? v : defValue;
+        }
+    }
+
+    public boolean contains(String key) {
+        synchronized (this) {
+            return mMap.containsKey(key);
+        }
+    }
+
+    public Editor edit() {
+        return new EditorImpl();
+    }
+
+    // Return value from EditorImpl#commitToMemory()
+    private static class MemoryCommitResult {
+        public boolean changesMade;  // any keys different?
+        public List<String> keysModified;  // may be null
+        public Set<OnSharedPreferenceChangeListener> listeners;  // may be null
+        public Map<?, ?> mapToWriteToDisk;
+        public final CountDownLatch writtenToDiskLatch = new CountDownLatch(1);
+        public volatile boolean writeToDiskResult = false;
+
+        public void setDiskWriteResult(boolean result) {
+            writeToDiskResult = result;
+            writtenToDiskLatch.countDown();
+        }
+    }
+
+    public final class EditorImpl implements Editor {
+        private final Map<String, Object> mModified = Maps.newHashMap();
+        private boolean mClear = false;
+
+        public Editor putString(String key, String value) {
+            synchronized (this) {
+                mModified.put(key, value);
+                return this;
+            }
+        }
+        public Editor putStringSet(String key, Set<String> values) {
+            synchronized (this) {
+                mModified.put(key, values);
+                return this;
+            }
+        }
+        public Editor putInt(String key, int value) {
+            synchronized (this) {
+                mModified.put(key, value);
+                return this;
+            }
+        }
+        public Editor putLong(String key, long value) {
+            synchronized (this) {
+                mModified.put(key, value);
+                return this;
+            }
+        }
+        public Editor putFloat(String key, float value) {
+            synchronized (this) {
+                mModified.put(key, value);
+                return this;
+            }
+        }
+        public Editor putBoolean(String key, boolean value) {
+            synchronized (this) {
+                mModified.put(key, value);
+                return this;
+            }
+        }
+
+        public Editor remove(String key) {
+            synchronized (this) {
+                mModified.put(key, this);
+                return this;
+            }
+        }
+
+        public Editor clear() {
+            synchronized (this) {
+                mClear = true;
+                return this;
+            }
+        }
+
+        public void apply() {
+            final MemoryCommitResult mcr = commitToMemory();
+            final Runnable awaitCommit = new Runnable() {
+                    public void run() {
+                        try {
+                            mcr.writtenToDiskLatch.await();
+                        } catch (InterruptedException ignored) {
+                        }
+                    }
+                };
+
+            QueuedWork.add(awaitCommit);
+
+            Runnable postWriteRunnable = new Runnable() {
+                    public void run() {
+                        awaitCommit.run();
+                        QueuedWork.remove(awaitCommit);
+                    }
+                };
+
+            SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);
+
+            // Okay to notify the listeners before it's hit disk
+            // because the listeners should always get the same
+            // SharedPreferences instance back, which has the
+            // changes reflected in memory.
+            notifyListeners(mcr);
+        }
+
+        // Returns true if any changes were made
+        private MemoryCommitResult commitToMemory() {
+            MemoryCommitResult mcr = new MemoryCommitResult();
+            synchronized (SharedPreferencesImpl.this) {
+                // We optimistically don't make a deep copy until
+                // a memory commit comes in when we're already
+                // writing to disk.
+                if (mDiskWritesInFlight > 0) {
+                    // We can't modify our mMap as a currently
+                    // in-flight write owns it.  Clone it before
+                    // modifying it.
+                    // noinspection unchecked
+                    mMap = new HashMap<String, Object>(mMap);
+                }
+                mcr.mapToWriteToDisk = mMap;
+                mDiskWritesInFlight++;
+
+                boolean hasListeners = mListeners.size() > 0;
+                if (hasListeners) {
+                    mcr.keysModified = new ArrayList<String>();
+                    mcr.listeners =
+                            new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
+                }
+
+                synchronized (this) {
+                    if (mClear) {
+                        if (!mMap.isEmpty()) {
+                            mcr.changesMade = true;
+                            mMap.clear();
+                        }
+                        mClear = false;
+                    }
+
+                    for (Map.Entry<String, Object> e : mModified.entrySet()) {
+                        String k = e.getKey();
+                        Object v = e.getValue();
+                        if (v == this) {  // magic value for a removal mutation
+                            if (!mMap.containsKey(k)) {
+                                continue;
+                            }
+                            mMap.remove(k);
+                        } else {
+                            boolean isSame = false;
+                            if (mMap.containsKey(k)) {
+                                Object existingValue = mMap.get(k);
+                                if (existingValue != null && existingValue.equals(v)) {
+                                    continue;
+                                }
+                            }
+                            mMap.put(k, v);
+                        }
+
+                        mcr.changesMade = true;
+                        if (hasListeners) {
+                            mcr.keysModified.add(k);
+                        }
+                    }
+
+                    mModified.clear();
+                }
+            }
+            return mcr;
+        }
+
+        public boolean commit() {
+            MemoryCommitResult mcr = commitToMemory();
+            SharedPreferencesImpl.this.enqueueDiskWrite(
+                mcr, null /* sync write on this thread okay */);
+            try {
+                mcr.writtenToDiskLatch.await();
+            } catch (InterruptedException e) {
+                return false;
+            }
+            notifyListeners(mcr);
+            return mcr.writeToDiskResult;
+        }
+
+        private void notifyListeners(final MemoryCommitResult mcr) {
+            if (mcr.listeners == null || mcr.keysModified == null ||
+                mcr.keysModified.size() == 0) {
+                return;
+            }
+            if (Looper.myLooper() == Looper.getMainLooper()) {
+                for (int i = mcr.keysModified.size() - 1; i >= 0; i--) {
+                    final String key = mcr.keysModified.get(i);
+                    for (OnSharedPreferenceChangeListener listener : mcr.listeners) {
+                        if (listener != null) {
+                            listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
+                        }
+                    }
+                }
+            } else {
+                // Run this function on the main thread.
+                ActivityThread.sMainThreadHandler.post(new Runnable() {
+                        public void run() {
+                            notifyListeners(mcr);
+                        }
+                    });
+            }
+        }
+    }
+
+    /**
+     * Enqueue an already-committed-to-memory result to be written
+     * to disk.
+     *
+     * They will be written to disk one-at-a-time in the order
+     * that they're enqueued.
+     *
+     * @param postWriteRunnable if non-null, we're being called
+     *   from apply() and this is the runnable to run after
+     *   the write proceeds.  if null (from a regular commit()),
+     *   then we're allowed to do this disk write on the main
+     *   thread (which in addition to reducing allocations and
+     *   creating a background thread, this has the advantage that
+     *   we catch them in userdebug StrictMode reports to convert
+     *   them where possible to apply() ...)
+     */
+    private void enqueueDiskWrite(final MemoryCommitResult mcr,
+                                  final Runnable postWriteRunnable) {
+        final Runnable writeToDiskRunnable = new Runnable() {
+                public void run() {
+                    synchronized (mWritingToDiskLock) {
+                        writeToFile(mcr);
+                    }
+                    synchronized (SharedPreferencesImpl.this) {
+                        mDiskWritesInFlight--;
+                    }
+                    if (postWriteRunnable != null) {
+                        postWriteRunnable.run();
+                    }
+                }
+            };
+
+        final boolean isFromSyncCommit = (postWriteRunnable == null);
+
+        // Typical #commit() path with fewer allocations, doing a write on
+        // the current thread.
+        if (isFromSyncCommit) {
+            boolean wasEmpty = false;
+            synchronized (SharedPreferencesImpl.this) {
+                wasEmpty = mDiskWritesInFlight == 1;
+            }
+            if (wasEmpty) {
+                writeToDiskRunnable.run();
+                return;
+            }
+        }
+
+        QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
+    }
+
+    private static FileOutputStream createFileOutputStream(File file) {
+        FileOutputStream str = null;
+        try {
+            str = new FileOutputStream(file);
+        } catch (FileNotFoundException e) {
+            File parent = file.getParentFile();
+            if (!parent.mkdir()) {
+                Log.e(TAG, "Couldn't create directory for SharedPreferences file " + file);
+                return null;
+            }
+            FileUtils.setPermissions(
+                parent.getPath(),
+                FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
+                -1, -1);
+            try {
+                str = new FileOutputStream(file);
+            } catch (FileNotFoundException e2) {
+                Log.e(TAG, "Couldn't create SharedPreferences file " + file, e2);
+            }
+        }
+        return str;
+    }
+
+    // Note: must hold mWritingToDiskLock
+    private void writeToFile(MemoryCommitResult mcr) {
+        // Rename the current file so it may be used as a backup during the next read
+        if (mFile.exists()) {
+            if (!mcr.changesMade) {
+                // If the file already exists, but no changes were
+                // made to the underlying map, it's wasteful to
+                // re-write the file.  Return as if we wrote it
+                // out.
+                mcr.setDiskWriteResult(true);
+                return;
+            }
+            if (!mBackupFile.exists()) {
+                if (!mFile.renameTo(mBackupFile)) {
+                    Log.e(TAG, "Couldn't rename file " + mFile
+                          + " to backup file " + mBackupFile);
+                    mcr.setDiskWriteResult(false);
+                    return;
+                }
+            } else {
+                mFile.delete();
+            }
+        }
+
+        // Attempt to write the file, delete the backup and return true as atomically as
+        // possible.  If any exception occurs, delete the new file; next time we will restore
+        // from the backup.
+        try {
+            FileOutputStream str = createFileOutputStream(mFile);
+            if (str == null) {
+                mcr.setDiskWriteResult(false);
+                return;
+            }
+            XmlUtils.writeMapXml(mcr.mapToWriteToDisk, str);
+            FileUtils.sync(str);
+            str.close();
+            ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
+            FileStatus stat = new FileStatus();
+            if (FileUtils.getFileStatus(mFile.getPath(), stat)) {
+                synchronized (this) {
+                    mStatTimestamp = stat.mtime;
+                    mStatSize = stat.size;
+                }
+            }
+            // Writing was successful, delete the backup file if there is one.
+            mBackupFile.delete();
+            mcr.setDiskWriteResult(true);
+            return;
+        } catch (XmlPullParserException e) {
+            Log.w(TAG, "writeToFile: Got exception:", e);
+        } catch (IOException e) {
+            Log.w(TAG, "writeToFile: Got exception:", e);
+        }
+        // Clean up an unsuccessfully written file
+        if (mFile.exists()) {
+            if (!mFile.delete()) {
+                Log.e(TAG, "Couldn't clean up partially-written file " + mFile);
+            }
+        }
+        mcr.setDiskWriteResult(false);
+    }
+}
diff --git a/core/java/android/app/admin/DeviceAdminInfo.java b/core/java/android/app/admin/DeviceAdminInfo.java
index 2237c82..2bb0e33 100644
--- a/core/java/android/app/admin/DeviceAdminInfo.java
+++ b/core/java/android/app/admin/DeviceAdminInfo.java
@@ -112,6 +112,15 @@
      */
     public static final int USES_POLICY_SETS_GLOBAL_PROXY = 5;
 
+    /**
+     * A type of policy that this device admin can use: force the user to
+     * change their password after an administrator-defined time limit.
+     *
+     * <p>To control this policy, the device admin must have an "expire-password"
+     * tag in the "uses-policies" section of its meta-data.
+     */
+    public static final int USES_POLICY_EXPIRE_PASSWORD = 6;
+
     /** @hide */
     public static class PolicyInfo {
         public final int ident;
@@ -150,7 +159,10 @@
         sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_SETS_GLOBAL_PROXY, "set-global-proxy",
                 com.android.internal.R.string.policylab_setGlobalProxy,
                 com.android.internal.R.string.policydesc_setGlobalProxy));
-        
+        sPoliciesDisplayOrder.add(new PolicyInfo(USES_POLICY_EXPIRE_PASSWORD, "expire-password",
+                com.android.internal.R.string.policylab_expirePassword,
+                com.android.internal.R.string.policydesc_expirePassword));
+
         for (int i=0; i<sPoliciesDisplayOrder.size(); i++) {
             PolicyInfo pi = sPoliciesDisplayOrder.get(i);
             sRevKnownPolicies.put(pi.ident, pi);
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index b4dd9e7..eccd7c9 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -145,7 +145,19 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_PASSWORD_SUCCEEDED
             = "android.app.action.ACTION_PASSWORD_SUCCEEDED";
-    
+
+    /**
+     * Action periodically sent to a device administrator when the device password
+     * is expiring. 
+     *
+     * <p>The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to receive
+     * this broadcast.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_PASSWORD_EXPIRING
+            = "android.app.action.ACTION_PASSWORD_EXPIRING";
+
     /**
      * Name under which an DevicePolicy component publishes information
      * about itself.  This meta-data must reference an XML resource containing
@@ -251,7 +263,28 @@
      */
     public void onPasswordSucceeded(Context context, Intent intent) {
     }
-    
+
+    /**
+     * Called periodically when the password is about to expire or has expired.  It will typically
+     * be called on device boot, once per day before the password expires and at the time when it
+     * expires.
+     *
+     * <p>If the password is not updated by the user, this method will continue to be called
+     * once per day until the password is changed or the device admin disables password expiration.
+     *
+     * <p>The admin will typically post a notification requesting the user to change their password
+     * in response to this call. The actual password expiration time can be obtained by calling
+     * {@link DevicePolicyManager#getPasswordExpiration(ComponentName) }
+     *
+     * <p>The admin should be sure to take down any notifications it posted in response to this call
+     * when it receives {@link DeviceAdminReceiver#onPasswordChanged(Context, Intent) }.
+     *
+     * @param context The running context as per {@link #onReceive}.
+     * @param intent The received intent as per {@link #onReceive}.
+     */
+    public void onPasswordExpiring(Context context, Intent intent) {
+    }
+
     /**
      * Intercept standard device administrator broadcasts.  Implementations
      * should not override this method; it is better to implement the
@@ -276,6 +309,8 @@
             }
         } else if (ACTION_DEVICE_ADMIN_DISABLED.equals(action)) {
             onDisabled(context, intent);
+        } else if (ACTION_PASSWORD_EXPIRING.equals(action)) {
+            onPasswordExpiring(context, intent);
         }
     }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index ca27010..a18fdac 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -681,6 +681,73 @@
     }
 
     /**
+     * Called by a device admin to set the password expiration timeout. Calling this method
+     * will restart the countdown for password expiration for the given admin, as will changing
+     * the device password (for all admins).
+     *
+     * <p>The provided timeout is the time delta in ms and will be added to the current time.
+     * For example, to have the password expire 5 days from now, timeout would be
+     * 5 * 86400 * 1000 = 432000000 ms for timeout.
+     *
+     * <p>To disable password expiration, a value of 0 may be used for timeout.
+     *
+     * <p>Timeout must be at least 1 day or IllegalArgumentException will be thrown.
+     *
+     * <p>The calling device admin must have requested
+     * {@link DeviceAdminInfo#USES_POLICY_EXPIRE_PASSWORD} to be able to call this
+     * method; if it has not, a security exception will be thrown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param timeout The limit (in ms) that a password can remain in effect. A value of 0
+     *        means there is no restriction (unlimited).
+     */
+    public void setPasswordExpirationTimeout(ComponentName admin, long timeout) {
+        if (mService != null) {
+            try {
+                mService.setPasswordExpirationTimeout(admin, timeout);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Get the current password expiration timeout for the given admin or the aggregate
+     * of all admins if admin is null.
+     *
+     * @param admin The name of the admin component to check, or null to aggregate all admins.
+     * @return The timeout for the given admin or the minimum of all timeouts
+     */
+    public long getPasswordExpirationTimeout(ComponentName admin) {
+        if (mService != null) {
+            try {
+                return mService.getPasswordExpirationTimeout(admin);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return 0;
+    }
+
+    /**
+     * Get the current password expiration time for the given admin or an aggregate of
+     * all admins if admin is null.
+     *
+     * @param admin The name of the admin component to check, or null to aggregate all admins.
+     * @return The password expiration time, in ms.
+     */
+    public long getPasswordExpiration(ComponentName admin) {
+        if (mService != null) {
+            try {
+                return mService.getPasswordExpiration(admin);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return 0;
+    }
+
+    /**
      * Retrieve the current password history length for all admins
      * or a particular one.
      * @param admin The name of the admin component to check, or null to aggregate
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 3fcd6fc..7acc83e 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -52,6 +52,11 @@
     void setPasswordHistoryLength(in ComponentName who, int length);
     int getPasswordHistoryLength(in ComponentName who);
 
+    void setPasswordExpirationTimeout(in ComponentName who, long expiration);
+    long getPasswordExpirationTimeout(in ComponentName who);
+
+    long getPasswordExpiration(in ComponentName who);
+
     boolean isActivePasswordSufficient();
     int getCurrentFailedPasswordAttempts();
     
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 396e92d..a3db01d 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -98,8 +98,7 @@
      * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
      */
     public int icon;
-    
-    
+
     /**
      * The previous name, if any, of the app widget receiver. If not supplied, it will be
      * ignored.
@@ -110,7 +109,12 @@
      * @hide Pending API approval
      */
     public String oldName;
-    
+
+    /**
+     * The view id of the AppWidget subview which should be auto-advanced by the widget's host.
+     */
+    public int autoAdvanceViewId;
+
     /**
      * A preview of what the AppWidget will look like after it's configured.
      * If not supplied, the AppWidget's icon will be used.
@@ -142,9 +146,9 @@
         this.label = in.readString();
         this.icon = in.readInt();
         this.previewImage = in.readInt();
+        this.autoAdvanceViewId = in.readInt();
     }
 
-
     public void writeToParcel(android.os.Parcel out, int flags) {
         if (this.provider != null) {
             out.writeInt(1);
@@ -165,6 +169,7 @@
         out.writeString(this.label);
         out.writeInt(this.icon);
         out.writeInt(this.previewImage);
+        out.writeInt(this.autoAdvanceViewId);
     }
 
     public int describeContents() {
@@ -192,5 +197,3 @@
         return "AppWidgetProviderInfo(provider=" + this.provider + ")";
     }
 }
-
-
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index f63a5c5..d5b0042 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -184,29 +184,29 @@
             "android.bluetooth.headset.intent.category.companyid";
 
     /**
-     * Headset state when SCO audio is connected
+     * Headset state when SCO audio is not connected
      * This state can be one of
      * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
      * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
      */
-    public static final int STATE_AUDIO_CONNECTED = 10;
+    public static final int STATE_AUDIO_DISCONNECTED = 10;
 
     /**
      * Headset state when SCO audio is connecting
      * This state can be one of
      * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
      * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
-     * @hide
      */
-    public static final int STATE_AUDIO_CONNECTING = 12;
+    public static final int STATE_AUDIO_CONNECTING = 11;
 
     /**
-     * Headset state when SCO audio is not connected
+     * Headset state when SCO audio is connected
      * This state can be one of
      * {@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} of
      * {@link #ACTION_AUDIO_STATE_CHANGED} intent.
      */
-    public static final int STATE_AUDIO_DISCONNECTED = 11;
+    public static final int STATE_AUDIO_CONNECTED = 12;
+
 
     private Context mContext;
     private ServiceListener mServiceListener;
@@ -377,11 +377,15 @@
      * audio connection.
      *
      * <p> Users can listen to {@link #ACTION_AUDIO_STATE_CHANGED}.
-     * {@link #EXTRA_STATE} will be set to {@link #STATE_AUDIO_CONNECTED}
-     * when the audio connection is established,
-     * and to {@link #STATE_AUDIO_DISCONNECTED} in case of failure.
+     * If this function returns true, this intent will be broadcasted with
+     * {@link #EXTRA_STATE} set to {@link #STATE_AUDIO_CONNECTING}.
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
+     * <p> {@link #EXTRA_STATE} will transition from
+     * {@link #STATE_AUDIO_CONNECTING} to {@link #STATE_AUDIO_CONNECTED} when
+     * audio connection is established and to {@link #STATE_AUDIO_DISCONNECTED}
+     * in case of failure to establish the audio connection.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
      *
      * @param device Bluetooth headset
      * @return false if there is no headset connected of if the
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 34bd386..221fe23 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -705,6 +705,14 @@
         }
     }
 
+    private void clearBackoffSetting(SyncOperation op) {
+        mSyncStorageEngine.setBackoff(op.account, op.authority,
+                SyncStorageEngine.NOT_IN_BACKOFF_MODE, SyncStorageEngine.NOT_IN_BACKOFF_MODE);
+        synchronized (mSyncQueue) {
+            mSyncQueue.onBackoffChanged(op.account, op.authority, 0);
+        }
+    }
+
     private void increaseBackoffSetting(SyncOperation op) {
         final long now = SystemClock.elapsedRealtime();
 
@@ -1854,6 +1862,7 @@
                     // TODO: set these correctly when the SyncResult is extended to include it
                     downstreamActivity = 0;
                     upstreamActivity = 0;
+                    clearBackoffSetting(syncOperation);
                 } else {
                     Log.d(TAG, "failed sync operation " + syncOperation + ", " + syncResult);
                     // the operation failed so increase the backoff time
diff --git a/core/java/android/content/pm/RegisteredServicesCache.java b/core/java/android/content/pm/RegisteredServicesCache.java
index dce3963..06095d1 100644
--- a/core/java/android/content/pm/RegisteredServicesCache.java
+++ b/core/java/android/content/pm/RegisteredServicesCache.java
@@ -271,17 +271,11 @@
         }
 
         synchronized (mServicesLock) {
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.d(TAG, "generateServicesMap: " + mInterfaceName);
-            }
             if (mPersistentServices == null) {
                 readPersistentServicesLocked();
             }
             mServices = Maps.newHashMap();
-            boolean changed = false;
-            if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                Log.d(TAG, "found " + serviceInfos.size() + " services");
-            }
+            StringBuilder changes = new StringBuilder();
             for (ServiceInfo<V> info : serviceInfos) {
                 // four cases:
                 // - doesn't exist yet
@@ -294,10 +288,7 @@
                 //   - add, notify user that it was added
                 Integer previousUid = mPersistentServices.get(info.type);
                 if (previousUid == null) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.d(TAG, "encountered new type: " + info);
-                    }
-                    changed = true;
+                    changes.append("  New service added: ").append(info).append("\n");
                     mServices.put(info.type, info);
                     mPersistentServices.put(info.type, info.uid);
                     if (!mPersistentServicesFileDidNotExist) {
@@ -305,29 +296,25 @@
                     }
                 } else if (previousUid == info.uid) {
                     if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.d(TAG, "encountered existing type with the same uid: " + info);
+                        changes.append("  Existing service (nop): ").append(info).append("\n");
                     }
                     mServices.put(info.type, info);
                 } else if (inSystemImage(info.uid)
                         || !containsTypeAndUid(serviceInfos, info.type, previousUid)) {
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        if (inSystemImage(info.uid)) {
-                            Log.d(TAG, "encountered existing type with a new uid but from"
-                                    + " the system: " + info);
-                        } else {
-                            Log.d(TAG, "encountered existing type with a new uid but existing was"
-                                    + " removed: " + info);
-                        }
+                    if (inSystemImage(info.uid)) {
+                        changes.append("  System service replacing existing: ").append(info)
+                                .append("\n");
+                    } else {
+                        changes.append("  Existing service replacing a removed service: ")
+                                .append(info).append("\n");
                     }
-                    changed = true;
                     mServices.put(info.type, info);
                     mPersistentServices.put(info.type, info.uid);
                     notifyListener(info.type, false /* removed */);
                 } else {
                     // ignore
-                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                        Log.d(TAG, "encountered existing type with a new uid, ignoring: " + info);
-                    }
+                    changes.append("  Existing service with new uid ignored: ").append(info)
+                            .append("\n");
                 }
             }
 
@@ -339,18 +326,16 @@
             }
             for (V v1 : toBeRemoved) {
                 mPersistentServices.remove(v1);
-                changed = true;
+                changes.append("  Service removed: ").append(v1).append("\n");
                 notifyListener(v1, true /* removed */);
             }
-            if (changed) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.d(TAG, "writing updated list of persistent services");
-                }
+            if (changes.length() > 0) {
+                Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
+                        serviceInfos.size() + " services:\n" + changes);
                 writePersistentServicesLocked();
             } else {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.d(TAG, "persistent services did not change, so not writing anything");
-                }
+                Log.d(TAG, "generateServicesMap(" + mInterfaceName + "): " +
+                        serviceInfos.size() + " services unchanged");
             }
             mPersistentServicesFileDidNotExist = false;
         }
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 25d868f..22876c0 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -112,6 +112,9 @@
     // Only show an annoying dialog at most every 30 seconds
     private static final long MIN_DIALOG_INTERVAL_MS = 30000;
 
+    // How many Span tags (e.g. animations) to report.
+    private static final int MAX_SPAN_TAGS = 20;
+
     // How many offending stacks to keep track of (and time) per loop
     // of the Looper.
     private static final int MAX_OFFENSES_PER_LOOP = 10;
@@ -1217,6 +1220,140 @@
     }
 
     /**
+     * A tracked, critical time span.  (e.g. during an animation.)
+     *
+     * The object itself is a linked list node, to avoid any allocations
+     * during rapid span entries and exits.
+     *
+     * @hide
+     */
+    public static class Span {
+        private String mName;
+        private long mCreateMillis;
+        private Span mNext;
+        private Span mPrev;  // not used when in freeList, only active
+        private final ThreadSpanState mContainerState;
+
+        Span(ThreadSpanState threadState) {
+            mContainerState = threadState;
+        }
+
+        /**
+         * To be called when the critical span is complete (i.e. the
+         * animation is done animating).  This can be called on any
+         * thread (even a different one from where the animation was
+         * taking place), but that's only a defensive implementation
+         * measure.  It really makes no sense for you to call this on
+         * thread other than that where you created it.
+         *
+         * @hide
+         */
+        public void finish() {
+            ThreadSpanState state = mContainerState;
+            synchronized (state) {
+                if (mName == null) {
+                    // Duplicate finish call.  Ignore.
+                    return;
+                }
+
+                // Remove ourselves from the active list.
+                if (mPrev != null) {
+                    mPrev.mNext = mNext;
+                }
+                if (mNext != null) {
+                    mNext.mPrev = mPrev;
+                }
+                if (state.mActiveHead == this) {
+                    state.mActiveHead = mNext;
+                }
+
+                this.mCreateMillis = -1;
+                this.mName = null;
+                this.mPrev = null;
+                this.mNext = null;
+                state.mActiveSize--;
+
+                // Add ourselves to the freeList, if it's not already
+                // too big.
+                if (state.mFreeListSize < 5) {
+                    this.mNext = state.mFreeListHead;
+                    state.mFreeListHead = this;
+                    state.mFreeListSize++;
+                }
+            }
+        }
+    }
+
+    /**
+     * Linked lists of active spans and a freelist.
+     *
+     * Locking notes: there's one of these structures per thread and
+     * all members of this structure (as well as the Span nodes under
+     * it) are guarded by the ThreadSpanState object instance.  While
+     * in theory there'd be no locking required because it's all local
+     * per-thread, the finish() method above is defensive against
+     * people calling it on a different thread from where they created
+     * the Span, hence the locking.
+     */
+    private static class ThreadSpanState {
+        public Span mActiveHead;    // doubly-linked list.
+        public int mActiveSize;
+        public Span mFreeListHead;  // singly-linked list.  only changes at head.
+        public int mFreeListSize;
+    }
+
+    private static final ThreadLocal<ThreadSpanState> sThisThreadSpanState =
+            new ThreadLocal<ThreadSpanState>() {
+        @Override protected ThreadSpanState initialValue() {
+            return new ThreadSpanState();
+        }
+    };
+
+    /**
+     * Enter a named critical span (e.g. an animation)
+     *
+     * <p>The name is an arbitary label (or tag) that will be applied
+     * to any strictmode violation that happens while this span is
+     * active.  You must call finish() on the span when done.
+     *
+     * <p>This will never return null, but on devices without debugging
+     * enabled, this may return a dummy object on which the finish()
+     * method is a no-op.
+     *
+     * <p>TODO: add CloseGuard to this, verifying callers call finish.
+     *
+     * @hide
+     */
+    public static Span enterCriticalSpan(String name) {
+        if (name == null || name.isEmpty()) {
+            throw new IllegalArgumentException("name must be non-null and non-empty");
+        }
+        ThreadSpanState state = sThisThreadSpanState.get();
+        Span span = null;
+        synchronized (state) {
+            if (state.mFreeListHead != null) {
+                span = state.mFreeListHead;
+                state.mFreeListHead = span.mNext;
+                state.mFreeListSize--;
+            } else {
+                // Shouldn't have to do this often.
+                span = new Span(state);
+            }
+            span.mName = name;
+            span.mCreateMillis = SystemClock.uptimeMillis();
+            span.mNext = state.mActiveHead;
+            span.mPrev = null;
+            state.mActiveHead = span;
+            state.mActiveSize++;
+            if (span.mNext != null) {
+                span.mNext.mPrev = span;
+            }
+        }
+        return span;
+    }
+
+
+    /**
      * Parcelable that gets sent in Binder call headers back to callers
      * to report violations that happened during a cross-process call.
      *
@@ -1245,6 +1382,12 @@
         public int numAnimationsRunning = 0;
 
         /**
+         * List of tags from active Span instances during this
+         * violation, or null for none.
+         */
+        public String[] tags;
+
+        /**
          * Which violation number this was (1-based) since the last Looper loop,
          * from the perspective of the root caller (if it crossed any processes
          * via Binder calls).  The value is 0 if the root caller wasn't on a Looper
@@ -1284,6 +1427,23 @@
             if (broadcastIntent != null) {
                 broadcastIntentAction = broadcastIntent.getAction();
             }
+            ThreadSpanState state = sThisThreadSpanState.get();
+            synchronized (state) {
+                int spanActiveCount = state.mActiveSize;
+                if (spanActiveCount > MAX_SPAN_TAGS) {
+                    spanActiveCount = MAX_SPAN_TAGS;
+                }
+                if (spanActiveCount != 0) {
+                    this.tags = new String[spanActiveCount];
+                    Span iter = state.mActiveHead;
+                    int index = 0;
+                    while (iter != null && index < spanActiveCount) {
+                        this.tags[index] = iter.mName;
+                        index++;
+                        iter = iter.mNext;
+                    }
+                }
+            }
         }
 
         /**
@@ -1312,6 +1472,7 @@
             numAnimationsRunning = in.readInt();
             violationUptimeMillis = in.readLong();
             broadcastIntentAction = in.readString();
+            tags = in.readStringArray();
         }
 
         /**
@@ -1325,6 +1486,7 @@
             dest.writeInt(numAnimationsRunning);
             dest.writeLong(violationUptimeMillis);
             dest.writeString(broadcastIntentAction);
+            dest.writeStringArray(tags);
         }
 
 
@@ -1347,6 +1509,12 @@
             if (broadcastIntentAction != null) {
                 pw.println(prefix + "broadcastIntentAction: " + broadcastIntentAction);
             }
+            if (tags != null) {
+                int index = 0;
+                for (String tag : tags) {
+                    pw.println(prefix + "tag[" + (index++) + "]: " + tag);
+                }
+            }
         }
 
     }
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index bbad2b6..45c8174 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -322,7 +322,7 @@
     private void requestInputMethod(Dialog dialog) {
         Window window = dialog.getWindow();
         window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE |
-                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
+                WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
     }
 
     /**
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 65adef9..ff769ad 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -375,6 +375,13 @@
          */
         public static final String COLUMN_MEDIA_SCANNED = "scanned";
 
+        /**
+         * The column with errorMsg for a failed downloaded.
+         * Used only for debugging purposes.
+         * <P>Type: TEXT</P>
+         */
+        public static final String COLUMN_ERROR_MSG = "errorMsg";
+
         /*
          * Lists the destinations that an application can specify for a download.
          */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ddfcb06..1fe2c5a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2396,6 +2396,14 @@
                 "selected_input_method_subtype";
 
         /**
+         * Setting to record the history of input method subtype, holding the pair of ID of IME
+         * and its last used subtype.
+         * @hide
+         */
+        public static final String INPUT_METHODS_SUBTYPE_HISTORY =
+                "input_methods_subtype_history";
+
+        /**
          * Whether the device has been provisioned (0 = false, 1 = true)
          */
         public static final String DEVICE_PROVISIONED = "device_provisioned";
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 4f56281..56ab6bf 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -287,8 +287,6 @@
                 mBluetoothService.setIsDiscovering(true);
                 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
             } else {
-                // Stop the discovery.
-                mBluetoothService.cancelDiscovery();
                 mBluetoothService.setIsDiscovering(false);
                 intent = new Intent(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
             }
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index ec8f031..01a6b94 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -2508,44 +2508,42 @@
         // dump
         pw.println("\n--Headset Service--");
         if (mBluetoothHeadset != null) {
-           List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
-           if (deviceList.size() == 0) {
-              pw.println("\n--No headsets connected--");
-           }
-           BluetoothDevice device = deviceList.get(0);
+            List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
+            if (deviceList.size() == 0) {
+                pw.println("\n--No headsets connected--");
+            } else {
+                BluetoothDevice device = deviceList.get(0);
+                pw.println("\ngetConnectedDevices[0] = " + device);
 
-            switch (mBluetoothHeadset.getConnectionState(device)) {
-                case BluetoothHeadset.STATE_DISCONNECTED:
-                    pw.println("getConnectionState() = STATE_DISCONNECTED");
-                    break;
-                case BluetoothHeadset.STATE_CONNECTING:
-                    pw.println("getConnectionState() = STATE_CONNECTING");
-                    break;
-                case BluetoothHeadset.STATE_CONNECTED:
-                    pw.println("getConnectionState() = STATE_CONNECTED");
-                    break;
-                case BluetoothHeadset.STATE_DISCONNECTING:
-                    pw.println("getConnectionState() = STATE_DISCONNECTING");
-                    break;
-                case BluetoothHeadset.STATE_AUDIO_CONNECTED:
-                    pw.println("getConnectionState() = STATE_AUDIO_CONNECTED");
-                    break;
+                switch (mBluetoothHeadset.getConnectionState(device)) {
+                    case BluetoothHeadset.STATE_CONNECTING:
+                        pw.println("getConnectionState() = STATE_CONNECTING");
+                        break;
+                    case BluetoothHeadset.STATE_CONNECTED:
+                        pw.println("getConnectionState() = STATE_CONNECTED");
+                        break;
+                    case BluetoothHeadset.STATE_DISCONNECTING:
+                        pw.println("getConnectionState() = STATE_DISCONNECTING");
+                        break;
+                    case BluetoothHeadset.STATE_AUDIO_CONNECTED:
+                        pw.println("getConnectionState() = STATE_AUDIO_CONNECTED");
+                        break;
+                }
+                pw.println("getBatteryUsageHint() = " +
+                             mBluetoothHeadset.getBatteryUsageHint(device));
             }
 
             deviceList.clear();
             deviceList = mBluetoothHeadset.getDevicesMatchingConnectionStates(new int[] {
                      BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
             pw.println("\n--Connected and Disconnected Headsets");
-            for (BluetoothDevice dev: deviceList) {
+            for (BluetoothDevice device: deviceList) {
                 pw.println(device);
                 if (mBluetoothHeadset.isAudioConnected(device)) {
                     pw.println("SCO audio connected to device:" + device);
                 }
             }
 
-            pw.println("\ngetCurrentHeadset() = " + device);
-            pw.println("getBatteryUsageHint() = " +
-                       mBluetoothHeadset.getBatteryUsageHint(device));
             mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
         }
 
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index e7a16a2..63c1137 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -463,8 +463,73 @@
      * This key should normally be implemented as a toggle such that the first press
      * mutes the speaker and the second press restores the original volume. */
     public static final int KEYCODE_VOLUME_MUTE     = 164;
+    /** Key code constant: Info key.
+     * Common on TV remotes to show additional information related to what is
+     * currently being viewed. */
+    public static final int KEYCODE_INFO            = 165;
+    /** Key code constant: Channel up key.
+     * On TV remotes, increments the television channel. */
+    public static final int KEYCODE_CHANNEL_UP      = 166;
+    /** Key code constant: Channel down key.
+     * On TV remotes, decrements the television channel. */
+    public static final int KEYCODE_CHANNEL_DOWN    = 167;
+    /** Key code constant: Zoom in key. */
+    public static final int KEYCODE_ZOOM_IN         = 168;
+    /** Key code constant: Zoom out key. */
+    public static final int KEYCODE_ZOOM_OUT        = 169;
+    /** Key code constant: TV key.
+     * On TV remotes, switches to viewing live TV. */
+    public static final int KEYCODE_TV              = 170;
+    /** Key code constant: Window key.
+     * On TV remotes, toggles picture-in-picture mode or other windowing functions. */
+    public static final int KEYCODE_WINDOW          = 171;
+    /** Key code constant: Guide key.
+     * On TV remotes, shows a programming guide. */
+    public static final int KEYCODE_GUIDE           = 172;
+    /** Key code constant: DVR key.
+     * On some TV remotes, switches to a DVR mode for recorded shows. */
+    public static final int KEYCODE_DVR             = 173;
+    /** Key code constant: Bookmark key.
+     * On some TV remotes, bookmarks content or web pages. */
+    public static final int KEYCODE_BOOKMARK        = 174;
+    /** Key code constant: Toggle captions key.
+     * Switches the mode for closed-captioning text, for example during television shows. */
+    public static final int KEYCODE_CAPTIONS        = 175;
+    /** Key code constant: Settings key.
+     * Starts the system settings activity. */
+    public static final int KEYCODE_SETTINGS        = 176;
+    /** Key code constant: TV power key.
+     * On TV remotes, toggles the power on a television screen. */
+    public static final int KEYCODE_TV_POWER        = 177;
+    /** Key code constant: TV input key.
+     * On TV remotes, switches the input on a television screen. */
+    public static final int KEYCODE_TV_INPUT        = 178;
+    /** Key code constant: Set-top-box power key.
+     * On TV remotes, toggles the power on an external Set-top-box. */
+    public static final int KEYCODE_STB_POWER       = 179;
+    /** Key code constant: Set-top-box input key.
+     * On TV remotes, switches the input mode on an external Set-top-box. */
+    public static final int KEYCODE_STB_INPUT       = 180;
+    /** Key code constant: A/V Receiver power key.
+     * On TV remotes, toggles the power on an external A/V Receiver. */
+    public static final int KEYCODE_AVR_POWER       = 181;
+    /** Key code constant: A/V Receiver input key.
+     * On TV remotes, switches the input mode on an external A/V Receiver. */
+    public static final int KEYCODE_AVR_INPUT       = 182;
+    /** Key code constant: Red "programmable" key.
+     * On TV remotes, acts as a contextual/programmable key. */
+    public static final int KEYCODE_PROG_RED        = 183;
+    /** Key code constant: Green "programmable" key.
+     * On TV remotes, actsas a contextual/programmable key. */
+    public static final int KEYCODE_PROG_GREEN      = 184;
+    /** Key code constant: Yellow "programmable" key.
+     * On TV remotes, acts as a contextual/programmable key. */
+    public static final int KEYCODE_PROG_YELLOW     = 185;
+    /** Key code constant: Blue "programmable" key.
+     * On TV remotes, acts as a contextual/programmable key. */
+    public static final int KEYCODE_PROG_BLUE       = 186;
 
-    private static final int LAST_KEYCODE           = KEYCODE_VOLUME_MUTE;
+    private static final int LAST_KEYCODE           = KEYCODE_PROG_BLUE;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
@@ -649,6 +714,28 @@
         "KEYCODE_NUMPAD_LEFT_PAREN",
         "KEYCODE_NUMPAD_RIGHT_PAREN",
         "KEYCODE_VOLUME_MUTE",
+        "KEYCODE_INFO",
+        "KEYCODE_CHANNEL_UP",
+        "KEYCODE_CHANNEL_DOWN",
+        "KEYCODE_ZOOM_IN",
+        "KEYCODE_ZOOM_OUT",
+        "KEYCODE_TV",
+        "KEYCODE_WINDOW",
+        "KEYCODE_GUIDE",
+        "KEYCODE_DVR",
+        "KEYCODE_BOOKMARK",
+        "KEYCODE_CAPTIONS",
+        "KEYCODE_SETTINGS",
+        "KEYCODE_TV_POWER",
+        "KEYCODE_TV_INPUT",
+        "KEYCODE_STB_INPUT",
+        "KEYCODE_STB_POWER",
+        "KEYCODE_AVR_POWER",
+        "KEYCODE_AVR_INPUT",
+        "KEYCODE_PROG_RED",
+        "KEYCODE_PROG_GREEN",
+        "KEYCODE_PROG_YELLOW",
+        "KEYCODE_PROG_BLUE",
     };
 
     // Symbolic names of all metakeys in bit order from least significant to most significant.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 454ef4d..026f1a0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8637,7 +8637,6 @@
     public void setBackgroundColor(int color) {
         if (mBGDrawable instanceof ColorDrawable) {
             ((ColorDrawable) mBGDrawable).setColor(color);
-            invalidate();
         } else {
             setBackgroundDrawable(new ColorDrawable(color));
         }
diff --git a/core/java/android/webkit/DebugFlags.java b/core/java/android/webkit/DebugFlags.java
index 8e25395..3cb5e24 100644
--- a/core/java/android/webkit/DebugFlags.java
+++ b/core/java/android/webkit/DebugFlags.java
@@ -45,5 +45,9 @@
     public static final boolean WEB_TEXT_VIEW = false;
     public static final boolean WEB_VIEW = false;
     public static final boolean WEB_VIEW_CORE = false;
-
+    /*
+     * Set to true to allow the WebTextView to draw on top of the web page in a
+     * different color so that you can see how the two line up.
+     */
+    public static final boolean DRAW_WEBTEXTVIEW = false;
 }
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 1538bd0..f477f8f 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -36,6 +36,7 @@
 import android.text.method.MovementMethod;
 import android.text.method.Touch;
 import android.util.Log;
+import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
@@ -54,6 +55,8 @@
 
 import java.util.ArrayList;
 
+import junit.framework.Assert;
+
 /**
  * WebTextView is a specialized version of EditText used by WebView
  * to overlay html textfields (and textareas) to use our standard
@@ -144,6 +147,19 @@
         mWebView = webView;
         mMaxLength = -1;
         setAutoFillable(autoFillQueryId);
+        // Turn on subpixel text, and turn off kerning, so it better matches
+        // the text in webkit.
+        TextPaint paint = getPaint();
+        int flags = paint.getFlags() & ~Paint.DEV_KERN_TEXT_FLAG
+                | Paint.SUBPIXEL_TEXT_FLAG | Paint.DITHER_FLAG;
+        paint.setFlags(flags);
+
+        // Set the text color to black, regardless of the theme.  This ensures
+        // that other applications that use embedded WebViews will properly
+        // display the text in password textfields.
+        setTextColor(DebugFlags.DRAW_WEBTEXTVIEW ? Color.RED : Color.BLACK);
+        // This helps to align the text better with the text in the web page.
+        setIncludeFontPadding(false);
     }
 
     public void setAutoFillable(int queryId) {
@@ -388,8 +404,9 @@
         // onDraw should only be called for password fields.  If WebTextView is
         // still drawing, but is no longer corresponding to a password field,
         // remove it.
-        if (mWebView == null || !mWebView.nativeFocusCandidateIsPassword()
-                || !isSameTextField(mWebView.nativeFocusCandidatePointer())) {
+        if (!DebugFlags.DRAW_WEBTEXTVIEW && (mWebView == null
+                || !mWebView.nativeFocusCandidateIsPassword()
+                || !isSameTextField(mWebView.nativeFocusCandidatePointer()))) {
             // Although calling remove() would seem to make more sense here,
             // changing it to not be a password field will make it not draw.
             // Other code will make sure that it is removed completely, but this
@@ -803,7 +820,9 @@
         }
         // For password fields, draw the WebTextView.  For others, just show
         // webkit's drawing.
-        setWillNotDraw(!inPassword);
+        if (!DebugFlags.DRAW_WEBTEXTVIEW) {
+            setWillNotDraw(!inPassword);
+        }
         setBackgroundDrawable(inPassword ? mBackground : null);
     }
 
@@ -845,16 +864,6 @@
         mBackground = new OutlineDrawable();
 
         setGravity(Gravity.CENTER_VERTICAL);
-        // Turn on subpixel text, and turn off kerning, so it better matches
-        // the text in webkit.
-        TextPaint paint = getPaint();
-        int flags = paint.getFlags() | Paint.SUBPIXEL_TEXT_FLAG |
-                Paint.ANTI_ALIAS_FLAG & ~Paint.DEV_KERN_TEXT_FLAG;
-        paint.setFlags(flags);
-        // Set the text color to black, regardless of the theme.  This ensures
-        // that other applications that use embedded WebViews will properly
-        // display the text in password textfields.
-        setTextColor(Color.BLACK);
     }
 
     @Override
@@ -928,6 +937,20 @@
     }
 
     /**
+     * Update the text size according to the size of the focus candidate's text
+     * size in mWebView.  Should only be called from mWebView.
+     */
+    /* package */ void updateTextSize() {
+        Assert.assertNotNull("updateTextSize should only be called from "
+                + "mWebView, so mWebView should never be null!", mWebView);
+        // Note that this is approximately WebView.contentToViewDimension,
+        // without being rounded.
+        float size = mWebView.nativeFocusCandidateTextSize()
+                * mWebView.getScale();
+        setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
+    }
+
+    /**
      * Set the text to the new string, but use the old selection, making sure
      * to keep it within the new string.
      * @param   text    The new text to place in the textfield.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index fb760ac7..14dbfe2 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -54,7 +54,6 @@
 import android.util.AttributeSet;
 import android.util.EventLog;
 import android.util.Log;
-import android.util.TypedValue;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -3585,7 +3584,17 @@
      */
     private SelectActionModeCallback mSelectCallback;
 
-    private boolean didUpdateTextViewBounds(boolean allowIntersect) {
+    /**
+     * Check to see if the focused textfield/textarea is still on screen.  If it
+     * is, update the the dimensions and location of WebTextView.  Otherwise,
+     * remove the WebTextView.  Should be called when the zoom level changes.
+     * @param allowIntersect Whether to consider the textfield/textarea on
+     *         screen if it only intersects the screen (as opposed to being
+     *         completely on screen).
+     * @return boolean True if the textfield/textarea is still on screen and the
+     *         dimensions/location of WebTextView have been updated.
+     */
+    private boolean didUpdateWebTextViewDimensions(boolean allowIntersect) {
         Rect contentBounds = nativeFocusCandidateNodeBounds();
         Rect vBox = contentToViewRect(contentBounds);
         Rect visibleRect = new Rect();
@@ -3597,9 +3606,8 @@
                 : visibleRect.contains(vBox)) {
             mWebTextView.setRect(vBox.left, vBox.top, vBox.width(),
                     vBox.height());
-            mWebTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
-                    contentToViewDimension(
-                    nativeFocusCandidateTextSize()));
+            mWebTextView.updateTextSize();
+            updateWebTextViewPadding();
             return true;
         } else {
             // The textfield is now off screen.  The user probably
@@ -3632,7 +3640,8 @@
 
     private void onZoomAnimationEnd() {
         // adjust the edit text view if needed
-        if (inEditingMode() && didUpdateTextViewBounds(false) && nativeFocusCandidateIsPassword()) {
+        if (inEditingMode() && didUpdateWebTextViewDimensions(false)
+                && nativeFocusCandidateIsPassword()) {
             // If it is a password field, start drawing the WebTextView once
             // again.
             mWebTextView.setInPassword(true);
@@ -3765,7 +3774,7 @@
             // finishes.  We also do not need to do this unless the WebTextView
             // is showing.
             if (!animateZoom && inEditingMode()) {
-                didUpdateTextViewBounds(true);
+                didUpdateWebTextViewDimensions(true);
             }
         }
     }
@@ -3870,7 +3879,7 @@
             if (inEditingMode()) {
                 imm.showSoftInput(mWebTextView, 0);
                 if (zoom) {
-                    didUpdateTextViewBounds(true);
+                    didUpdateWebTextViewDimensions(true);
                 }
                 return;
             }
@@ -3918,8 +3927,7 @@
             // Initialize our generation number.
             mTextGeneration = 0;
         }
-        mWebTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
-                contentToViewDimension(nativeFocusCandidateTextSize()));
+        mWebTextView.updateTextSize();
         Rect visibleRect = new Rect();
         calcOurContentVisibleRect(visibleRect);
         // Note that sendOurVisibleRect calls viewToContent, so the coordinates
@@ -3951,16 +3959,7 @@
             // requestFormData, and it needs to have the correct nodePointer.
             mWebTextView.setNodePointer(nodePointer);
             mWebTextView.setType(nativeFocusCandidateType());
-            Rect paddingRect = nativeFocusCandidatePaddingRect();
-            if (paddingRect != null) {
-                // Use contentToViewDimension since these are the dimensions of
-                // the padding.
-                mWebTextView.setPadding(
-                        contentToViewDimension(paddingRect.left),
-                        contentToViewDimension(paddingRect.top),
-                        contentToViewDimension(paddingRect.right),
-                        contentToViewDimension(paddingRect.bottom));
-            }
+            updateWebTextViewPadding();
             if (null == text) {
                 if (DebugFlags.WEB_VIEW) {
                     Log.v(LOGTAG, "rebuildWebTextView null == text");
@@ -3979,6 +3978,22 @@
     }
 
     /**
+     * Update the padding of mWebTextView based on the native textfield/textarea
+     */
+    void updateWebTextViewPadding() {
+        Rect paddingRect = nativeFocusCandidatePaddingRect();
+        if (paddingRect != null) {
+            // Use contentToViewDimension since these are the dimensions of
+            // the padding.
+            mWebTextView.setPadding(
+                    contentToViewDimension(paddingRect.left),
+                    contentToViewDimension(paddingRect.top),
+                    contentToViewDimension(paddingRect.right),
+                    contentToViewDimension(paddingRect.bottom));
+        }
+    }
+
+    /**
      * Tell webkit to put the cursor on screen.
      */
     /* package */ void revealSelection() {
@@ -6529,8 +6544,11 @@
                         // If the text entry has created more events, ignore
                         // this one.
                         } else if (msg.arg2 == mTextGeneration) {
-                            mWebTextView.setTextAndKeepSelection(
-                                    (String) msg.obj);
+                            String text = (String) msg.obj;
+                            if (null == text) {
+                                text = "";
+                            }
+                            mWebTextView.setTextAndKeepSelection(text);
                         }
                     }
                     break;
@@ -7463,7 +7481,7 @@
     private native Rect     nativeFocusCandidatePaddingRect();
     /* package */ native int      nativeFocusCandidatePointer();
     private native String   nativeFocusCandidateText();
-    private native int      nativeFocusCandidateTextSize();
+    /* package */ native float    nativeFocusCandidateTextSize();
     /**
      * Returns an integer corresponding to WebView.cpp::type.
      * See WebTextView.setType()
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 6e927a6..0fcd26c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1803,6 +1803,8 @@
                 } else {
                     width = Math.max(w, mViewportWidth);
                 }
+            } else if (mSettings.getUseFixedViewport()) {
+                width = mWebView.getViewWidth();
             } else {
                 width = textwrapWidth;
             }
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index d0ed23f..ab5ff3d 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -3856,12 +3856,23 @@
                 // Update this first, since setNextSelectedPositionInt inspects it
                 mNeedSync = false;
 
-                if (mTranscriptMode == TRANSCRIPT_MODE_ALWAYS_SCROLL ||
-                        (mTranscriptMode == TRANSCRIPT_MODE_NORMAL &&
-                                mFirstPosition + getChildCount() >= mOldItemCount)) {
+                if (mTranscriptMode == TRANSCRIPT_MODE_ALWAYS_SCROLL) {
                     mLayoutMode = LAYOUT_FORCE_BOTTOM;
                     return;
                 }
+                if (mTranscriptMode == TRANSCRIPT_MODE_NORMAL) {
+                    final int childCount = getChildCount();
+                    final int listBottom = getBottom() - getPaddingBottom();
+                    final View lastChild = getChildAt(childCount - 1);
+                    final int lastBottom = lastChild != null ? lastChild.getBottom() : listBottom;
+                    if (mFirstPosition + childCount >= mOldItemCount && lastBottom <= listBottom) {
+                        mLayoutMode = LAYOUT_FORCE_BOTTOM;
+                        return;
+                    }
+                    // Something new came in and we didn't scroll; give the user a clue that
+                    // there's something new.
+                    awakenScrollBars();
+                }
 
                 switch (mSyncMode) {
                 case SYNC_SELECTED_POSITION:
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 1f98c88..695ea6b 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -24,7 +24,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.TypedArray;
-import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Parcel;
@@ -45,7 +44,7 @@
  * @attr ref android.R.styleable#AdapterViewAnimator_loopViews
  */
 public abstract class AdapterViewAnimator extends AdapterView<Adapter>
-        implements RemoteViewsAdapter.RemoteAdapterConnectionCallback {
+        implements RemoteViewsAdapter.RemoteAdapterConnectionCallback, Advanceable {
     private static final String TAG = "RemoteViewAnimator";
 
     /**
@@ -965,4 +964,11 @@
             setAdapter(mRemoteViewsAdapter);
         }
     }
+
+    public void advance() {
+        showNext();
+    }
+
+    public void willBeAdvancedByHost() {
+    }
 }
diff --git a/core/java/android/widget/AdapterViewFlipper.java b/core/java/android/widget/AdapterViewFlipper.java
index b09ade7..7721688 100644
--- a/core/java/android/widget/AdapterViewFlipper.java
+++ b/core/java/android/widget/AdapterViewFlipper.java
@@ -52,6 +52,7 @@
     private boolean mStarted = false;
     private boolean mVisible = false;
     private boolean mUserPresent = true;
+    private boolean mAdvancedByHost = false;
 
     public AdapterViewFlipper(Context context) {
         super(context);
@@ -203,7 +204,8 @@
      *            true.
      */
     private void updateRunning(boolean flipNow) {
-        boolean running = mVisible && mStarted && mUserPresent && mAdapter != null;
+        boolean running = !mAdvancedByHost && mVisible && mStarted && mUserPresent
+                && mAdapter != null;
         if (running != mRunning) {
             if (running) {
                 showOnly(mWhichChild, flipNow);
@@ -255,4 +257,10 @@
             }
         }
     };
+
+    @Override
+    public void willBeAdvancedByHost() {
+        mAdvancedByHost = true;
+        updateRunning(false);
+    }
 }
diff --git a/core/java/android/widget/Advanceable.java b/core/java/android/widget/Advanceable.java
new file mode 100644
index 0000000..bb162de
--- /dev/null
+++ b/core/java/android/widget/Advanceable.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2010 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.widget;
+
+/**
+ * This interface can be implemented by any collection-type view which has a notion of
+ * progressing through its set of children. The interface exists to give AppWidgetHosts a way of
+ * taking responsibility for automatically advancing such collections.
+ *
+ * @hide
+ */
+public interface Advanceable {
+
+    /**
+     * Advances this collection, eg. shows the next view.
+     */
+    public void advance();
+
+    /**
+     * Called by the AppWidgetHost once before it begins to call advance(), allowing the
+     * collection to do any required setup.
+     */
+    public void willBeAdvancedByHost();
+}
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 27a6ad3..690164c 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -298,7 +298,8 @@
             p.y = anchorpos[1] + mAnchor.getHeight() - p.height;
             p.format = PixelFormat.TRANSLUCENT;
             p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
-            p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+            p.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
             p.token = null;
             p.windowAnimations = 0; // android.R.style.DropDownAnimationDown;
             mWindowManager.addView(mDecor, p);
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 95678c6..0f61cd4 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -25,6 +25,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
+import android.os.Build;
 import android.os.IBinder;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
@@ -87,7 +88,7 @@
     private boolean mTouchable = true;
     private boolean mOutsideTouchable = false;
     private boolean mClippingEnabled = true;
-    private boolean mSplitTouchEnabled;
+    private int mSplitTouchEnabled = -1;
     private boolean mLayoutInScreen;
     private boolean mClipToScreen;
 
@@ -602,14 +603,17 @@
      * @hide
      */
     public boolean isSplitTouchEnabled() {
-        return mSplitTouchEnabled;
+        if (mSplitTouchEnabled < 0 && mContext != null) {
+            return mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB;
+        }
+        return mSplitTouchEnabled == 1;
     }
 
     /**
      * <p>Allows the popup window to split touches across other windows that also
-     * support split touch.  When this flag is not set, the first pointer
+     * support split touch.  When this flag is false, the first pointer
      * that goes down determines the window to which all subsequent touches
-     * go until all pointers go up.  When this flag is set, each pointer
+     * go until all pointers go up.  When this flag is true, each pointer
      * (not necessarily the first) that goes down determines the window
      * to which all subsequent touches of that pointer will go until that
      * pointer goes up thereby enabling touches with multiple pointers
@@ -620,7 +624,7 @@
      * @hide
      */
     public void setSplitTouchEnabled(boolean enabled) {
-        mSplitTouchEnabled = enabled;
+        mSplitTouchEnabled = enabled ? 1 : 0;
     }
 
     /**
@@ -993,7 +997,7 @@
         if (!mClippingEnabled) {
             curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
         }
-        if (mSplitTouchEnabled) {
+        if (isSplitTouchEnabled()) {
             curFlags |= WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
         }
         if (mLayoutInScreen) {
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index a27e1cc..7c38714 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -122,7 +122,7 @@
     private boolean mFirstLayoutHappened = false;
     private int mStackMode;
     private int mFramePadding;
-    private final Rect invalidateRect = new Rect();
+    private final Rect stackInvalidateRect = new Rect();
 
     public StackView(Context context) {
         super(context);
@@ -243,6 +243,7 @@
     @Override
     @android.view.RemotableViewMethod
     public void showNext() {
+        if (mSwipeGestureType != GESTURE_NONE) return;
         if (!mTransitionIsSetup) {
             View v = getViewAtRelativeIndex(1);
             if (v != null) {
@@ -257,6 +258,7 @@
     @Override
     @android.view.RemotableViewMethod
     public void showPrevious() {
+        if (mSwipeGestureType != GESTURE_NONE) return;
         if (!mTransitionIsSetup) {
             View v = getViewAtRelativeIndex(0);
             if (v != null) {
@@ -301,8 +303,11 @@
         // Here we need to make sure that the z-order of the children is correct
         for (int i = mCurrentWindowEnd; i >= mCurrentWindowStart; i--) {
             int index = modulo(i, getWindowSize());
-            View v = mViewsMap.get(index).view;
-            if (v != null) v.bringToFront();
+            ViewAndIndex vi = mViewsMap.get(index);
+            if (vi != null) {
+                View v = mViewsMap.get(index).view;
+                if (v != null) v.bringToFront();
+            }
         }
         mTransitionIsSetup = false;
     }
@@ -331,16 +336,15 @@
 
     @Override
     protected void dispatchDraw(Canvas canvas) {
-        canvas.getClipBounds(invalidateRect);
+        canvas.getClipBounds(stackInvalidateRect);
         final int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             LayoutParams lp = (LayoutParams) getChildAt(i).getLayoutParams();
-            invalidateRect.union(lp.getInvalidateRect());
+            stackInvalidateRect.union(lp.getInvalidateRect());
             lp.resetInvalidateRect();
         }
-
         canvas.save(Canvas.CLIP_SAVE_FLAG);
-        canvas.clipRect(invalidateRect, Region.Op.UNION);
+        canvas.clipRect(stackInvalidateRect, Region.Op.UNION);
         super.dispatchDraw(canvas);
         canvas.restore();
     }
@@ -553,6 +557,10 @@
 
         if (deltaY > mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_DOWN
                 && mStackSlider.mMode == StackSlider.NORMAL_MODE) {
+            // We reset the gesture variable, because otherwise we will ignore showPrevious() /
+            // showNext();
+            mSwipeGestureType = GESTURE_NONE;
+
             // Swipe threshold exceeded, swipe down
             if (mStackMode == ITEMS_SLIDE_UP) {
                 showPrevious();
@@ -562,6 +570,10 @@
             mHighlight.bringToFront();
         } else if (deltaY < -mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_UP
                 && mStackSlider.mMode == StackSlider.NORMAL_MODE) {
+            // We reset the gesture variable, because otherwise we will ignore showPrevious() /
+            // showNext();
+            mSwipeGestureType = GESTURE_NONE;
+
             // Swipe threshold exceeded, swipe up
             if (mStackMode == ITEMS_SLIDE_UP) {
                 showNext();
@@ -674,6 +686,8 @@
             r = Math.max(0, r);
 
             mYProgress = r;
+            if (mView == null) return;
+
             final LayoutParams viewLp = (LayoutParams) mView.getLayoutParams();
             final LayoutParams highlightLp = (LayoutParams) mHighlight.getLayoutParams();
 
@@ -722,6 +736,7 @@
 
             mXProgress = r;
 
+            if (mView == null) return;
             final LayoutParams viewLp = (LayoutParams) mView.getLayoutParams();
             final LayoutParams highlightLp = (LayoutParams) mHighlight.getLayoutParams();
 
@@ -894,7 +909,6 @@
         int horizontalOffset;
         int verticalOffset;
         View mView;
-        int left, top, right, bottom;
         private final Rect parentRect = new Rect();
         private final Rect invalidateRect = new Rect();
         private final RectF invalidateRectf = new RectF();
@@ -949,44 +963,32 @@
         }
 
         void resetInvalidateRect() {
-           invalidateRect.set(0, 0, 0, 0);
+            invalidateRect.set(0, 0, 0, 0);
         }
 
         // This is public so that ObjectAnimator can access it
         public void setVerticalOffset(int newVerticalOffset) {
-            int offsetDelta = newVerticalOffset - verticalOffset;
+            setOffsets(horizontalOffset, newVerticalOffset);
+        }
+
+        public void setHorizontalOffset(int newHorizontalOffset) {
+            setOffsets(newHorizontalOffset, verticalOffset);
+        }
+
+        public void setOffsets(int newHorizontalOffset, int newVerticalOffset) {
+            int horizontalOffsetDelta = newHorizontalOffset - horizontalOffset;
+            horizontalOffset = newHorizontalOffset;
+            int verticalOffsetDelta = newVerticalOffset - verticalOffset;
             verticalOffset = newVerticalOffset;
 
             if (mView != null) {
                 mView.requestLayout();
-                int top = Math.min(mView.getTop() + offsetDelta, mView.getTop());
-                int bottom = Math.max(mView.getBottom() + offsetDelta, mView.getBottom());
+                int left = Math.min(mView.getLeft() + horizontalOffsetDelta, mView.getLeft());
+                int right = Math.max(mView.getRight() + horizontalOffsetDelta, mView.getRight());
+                int top = Math.min(mView.getTop() + verticalOffsetDelta, mView.getTop());
+                int bottom = Math.max(mView.getBottom() + verticalOffsetDelta, mView.getBottom());
 
-                invalidateRectf.set(mView.getLeft(), top, mView.getRight(), bottom);
-
-                float xoffset = -invalidateRectf.left;
-                float yoffset = -invalidateRectf.top;
-                invalidateRectf.offset(xoffset, yoffset);
-                mView.getMatrix().mapRect(invalidateRectf);
-                invalidateRectf.offset(-xoffset, -yoffset);
-                invalidateRect.union((int) Math.floor(invalidateRectf.left),
-                        (int) Math.floor(invalidateRectf.top),
-                        (int) Math.ceil(invalidateRectf.right),
-                        (int) Math.ceil(invalidateRectf.bottom));
-
-                invalidateGlobalRegion(mView, invalidateRect);
-            }
-        }
-
-        public void setHorizontalOffset(int newHorizontalOffset) {
-            int offsetDelta = newHorizontalOffset - horizontalOffset;
-            horizontalOffset = newHorizontalOffset;
-
-            if (mView != null) {
-                mView.requestLayout();
-                int left = Math.min(mView.getLeft() + offsetDelta, mView.getLeft());
-                int right = Math.max(mView.getRight() + offsetDelta, mView.getRight());
-                invalidateRectf.set(left,  mView.getTop(), right, mView.getBottom());
+                invalidateRectf.set(left, top, right, bottom);
 
                 float xoffset = -invalidateRectf.left;
                 float yoffset = -invalidateRectf.top;
@@ -994,7 +996,7 @@
                 mView.getMatrix().mapRect(invalidateRectf);
                 invalidateRectf.offset(-xoffset, -yoffset);
 
-                invalidateRect.union((int) Math.floor(invalidateRectf.left),
+                invalidateRect.set((int) Math.floor(invalidateRectf.left),
                         (int) Math.floor(invalidateRectf.top),
                         (int) Math.ceil(invalidateRectf.right),
                         (int) Math.ceil(invalidateRectf.bottom));
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3838a02..5320b10 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -23,6 +23,7 @@
 
 import android.R;
 import android.content.ClipData;
+import android.content.ClipData.Item;
 import android.content.ClipboardManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -65,6 +66,7 @@
 import android.text.TextPaint;
 import android.text.TextUtils;
 import android.text.TextWatcher;
+import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.DateKeyListener;
 import android.text.method.DateTimeKeyListener;
 import android.text.method.DialerKeyListener;
@@ -88,6 +90,7 @@
 import android.util.TypedValue;
 import android.view.ActionMode;
 import android.view.ContextMenu;
+import android.view.DragEvent;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
@@ -753,12 +756,24 @@
                 if (lineHeight != 0) {
                     setLineHeight(lineHeight);
                 }
+                break;
+
+            case com.android.internal.R.styleable.TextView_textIsSelectable:
+                mTextIsSelectable = a.getBoolean(attr, false);
+                break;
             }
         }
         a.recycle();
 
         BufferType bufferType = BufferType.EDITABLE;
 
+        final int variation =
+                inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
+        final boolean passwordInputType = variation
+                == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD);
+        final boolean webPasswordInputType = variation
+                == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD);
+
         if (inputMethod != null) {
             Class<?> c;
 
@@ -835,6 +850,14 @@
 
             mInput = TextKeyListener.getInstance(autotext, cap);
             mInputType = inputType;
+        } else if (mTextIsSelectable) {
+            // Prevent text changes from keyboard.
+            mInputType = EditorInfo.TYPE_NULL;
+            mInput = null;
+            bufferType = BufferType.SPANNABLE;
+            setFocusableInTouchMode(true);
+            // So that selection can be changed using arrow keys and touch is handled.
+            setMovementMethod(ArrowKeyMovementMethod.getInstance());
         } else if (editable) {
             mInput = TextKeyListener.getInstance();
             mInputType = EditorInfo.TYPE_CLASS_TEXT;
@@ -854,19 +877,18 @@
             }
         }
 
-        if (password) {
-            // Caller used the deprecated xml attribute "password".  Ensure that
-            // the inputType is correct.
-            boolean normalText = (mInputType & EditorInfo.TYPE_MASK_CLASS)
-                    == EditorInfo.TYPE_CLASS_TEXT;
-            if (normalText && !isPasswordInputType(mInputType)) {
+        // mInputType has been set from inputType, possibly modified by mInputMethod.
+        // Specialize mInputType to [web]password if we have a text class and the original input
+        // type was a password.
+        if ((mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
+            if (password || passwordInputType) {
                 mInputType = (mInputType & ~(EditorInfo.TYPE_MASK_VARIATION))
-                    | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD;
+                        | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD;
             }
-        } else if (isPasswordInputType(mInputType)) {
-            // Caller did not use the deprecated xml attribute "password", but
-            // did set the input properly.  Set password to true.
-            password = true;
+            if (webPasswordInputType) {
+                mInputType = (mInputType & ~(EditorInfo.TYPE_MASK_VARIATION))
+                        | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD;
+            }
         }
 
         if (selectallonfocus) {
@@ -880,7 +902,10 @@
             drawableLeft, drawableTop, drawableRight, drawableBottom);
         setCompoundDrawablePadding(drawablePadding);
 
-        setSingleLine(singleLine);
+        // Same as setSingleLine, but make sure the transformation method is unchanged.
+        setInputTypeSingleLine(singleLine);
+        applySingleLine(singleLine, false);
+
         if (singleLine && mInput == null && ellipsize < 0) {
                 ellipsize = 3; // END
         }
@@ -909,13 +934,11 @@
         }
         setRawTextSize(textSize);
 
-        if (password) {
+        if (password || passwordInputType || webPasswordInputType) {
             setTransformationMethod(PasswordTransformationMethod.getInstance());
             typefaceIndex = MONOSPACE;
-        } else if ((mInputType&(EditorInfo.TYPE_MASK_CLASS
-                |EditorInfo.TYPE_MASK_VARIATION))
-                == (EditorInfo.TYPE_CLASS_TEXT
-                        |EditorInfo.TYPE_TEXT_VARIATION_PASSWORD)) {
+        } else if ((mInputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION))
+                == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD)) {
             typefaceIndex = MONOSPACE;
         }
 
@@ -1089,6 +1112,8 @@
      * within the text can cause individual lines to be taller or shorter
      * than this height, and the layout may contain additional first-
      * or last-line padding.
+     *
+     * @attr ref android.R.styleable#TextView_textLineHeight
      */
     public int getLineHeight() {
         if (mLineHeight != 0) {
@@ -1146,7 +1171,9 @@
             } catch (IncompatibleClassChangeError e) {
                 mInputType = EditorInfo.TYPE_CLASS_TEXT;
             }
-            setSingleLine(mSingleLine);
+            // Change inputType, without affecting transformation.
+            // No need to applySingleLine since mSingleLine is unchanged.
+            setInputTypeSingleLine(mSingleLine);
         } else {
             mInputType = EditorInfo.TYPE_NULL;
         }
@@ -3049,21 +3076,19 @@
     }
 
     private boolean isPasswordInputType(int inputType) {
-        final int variation = inputType & (EditorInfo.TYPE_MASK_CLASS
-                | EditorInfo.TYPE_MASK_VARIATION);
+        final int variation =
+                inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
         return variation
-                == (EditorInfo.TYPE_CLASS_TEXT
-                        | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD)
-                        || variation == (EditorInfo.TYPE_CLASS_TEXT
-                        | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD);
+                == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_PASSWORD)
+                || variation
+                == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_WEB_PASSWORD);
     }
 
     private boolean isVisiblePasswordInputType(int inputType) {
-        final int variation = inputType & (EditorInfo.TYPE_MASK_CLASS
-                | EditorInfo.TYPE_MASK_VARIATION);
+        final int variation =
+                inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
         return variation
-                == (EditorInfo.TYPE_CLASS_TEXT
-                        | EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
+                == (EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
     }
 
     /**
@@ -4019,6 +4044,71 @@
         return false;
     }
 
+    /**
+     * When a TextView is used to display a useful piece of information to the user (such as a
+     * contact's address), it should be made selectable, so that the user can select and copy this
+     * content.
+     *
+     * Use {@link #setTextIsSelectable(boolean)} or the
+     * {@link android.R.styleable#TextView_textIsSelectable} XML attribute to make this TextView
+     * selectable (the text is not selectable by default). Note that the content of an EditText is
+     * always selectable.
+     *
+     * @return True if the text displayed in this TextView can be selected by the user.
+     *
+     * @attr ref android.R.styleable#TextView_textIsSelectable
+     */
+    public boolean isTextSelectable() {
+        return mTextIsSelectable;
+    }
+
+    /**
+     * Sets whether or not (default) the content of this view is selectable by the user.
+     *
+     * See {@link #isTextSelectable} for details.
+     *
+     * @param selectable Whether or not the content of this TextView should be selectable.
+     */
+    public void setTextIsSelectable(boolean selectable) {
+        if (mTextIsSelectable == selectable) return;
+
+        mTextIsSelectable = selectable;
+
+        setFocusableInTouchMode(selectable);
+        setFocusable(selectable);
+        setClickable(selectable);
+        setLongClickable(selectable);
+
+        // mInputType is already EditorInfo.TYPE_NULL and mInput is null;
+
+        setMovementMethod(selectable ? ArrowKeyMovementMethod.getInstance() : null);
+        setText(getText(), selectable ? BufferType.SPANNABLE : BufferType.NORMAL);
+
+        // Called by setText above, but safer in case of future code changes
+        prepareCursorControllers();
+    }
+
+    @Override
+    protected int[] onCreateDrawableState(int extraSpace) {
+        final int[] drawableState = super.onCreateDrawableState(extraSpace);
+        if (mTextIsSelectable) {
+            // Disable pressed state, which was introduced when TextView was made clickable.
+            // Prevents text color change.
+            // setClickable(false) would have a similar effect, but it also disables focus changes
+            // and long press actions, which are both needed by text selection.
+            final int length = drawableState.length;
+            for (int i = 0; i < length; i++) {
+                if (drawableState[i] == R.attr.state_pressed) {
+                    final int[] nonPressedState = new int[length - 1];
+                    System.arraycopy(drawableState, 0, nonPressedState, 0, i);
+                    System.arraycopy(drawableState, i + 1, nonPressedState, i, length - i - 1);
+                    return nonPressedState;
+                }
+            }
+        }
+        return drawableState;
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         if (mCurrentAlpha <= ViewConfiguration.ALPHA_THRESHOLD_INT) return;
@@ -4181,12 +4271,13 @@
             selStart = getSelectionStart();
             selEnd = getSelectionEnd();
 
-            if (mCursorVisible && selStart >= 0 && isEnabled()) {
+            if ((mCursorVisible || mTextIsSelectable) && selStart >= 0 && isEnabled()) {
                 if (mHighlightPath == null)
                     mHighlightPath = new Path();
 
                 if (selStart == selEnd) {
-                    if ((SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK) {
+                    if (!mTextIsSelectable &&
+                            (SystemClock.uptimeMillis() - mShowCursor) % (2 * BLINK) < BLINK) {
                         if (mHighlightPathBogus) {
                             mHighlightPath.reset();
                             mLayout.getCursorPath(selStart, mHighlightPath, mText);
@@ -6073,6 +6164,15 @@
      */
     @android.view.RemotableViewMethod
     public void setSingleLine(boolean singleLine) {
+        setInputTypeSingleLine(singleLine);
+        applySingleLine(singleLine, true);
+    }
+
+    /**
+     * Adds or remove the EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE on the mInputType.
+     * @param singleLine
+     */
+    private void setInputTypeSingleLine(boolean singleLine) {
         if ((mInputType & EditorInfo.TYPE_MASK_CLASS) == EditorInfo.TYPE_CLASS_TEXT) {
             if (singleLine) {
                 mInputType &= ~EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
@@ -6080,7 +6180,6 @@
                 mInputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE;
             }
         }
-        applySingleLine(singleLine, true);
     }
 
     private void applySingleLine(boolean singleLine, boolean applyTransformation) {
@@ -6731,10 +6830,6 @@
                     mMovement.onTakeFocus(this, (Spannable) mText, direction);
                 }
 
-                if (mSelectAllOnFocus) {
-                    Selection.setSelection((Spannable) mText, 0, mText.length());
-                }
-
                 // The DecorView does not have focus when the 'Done' ExtractEditText button is
                 // pressed. Since it is the ViewRoot's mView, it requests focus before
                 // ExtractEditText clears focus, which gives focus to the ExtractEditText.
@@ -6753,6 +6848,11 @@
                      */
                     Selection.setSelection((Spannable) mText, selStart, selEnd);
                 }
+
+                if (mSelectAllOnFocus) {
+                    Selection.setSelection((Spannable) mText, 0, mText.length());
+                }
+
                 mTouchFocusSelected = true;
             }
 
@@ -6993,9 +7093,9 @@
                         mSelectionModifierCursorController.updatePosition();
                     }
                 }
-                if (action == MotionEvent.ACTION_UP && isFocused() && !mScrolled) {
+                if (action == MotionEvent.ACTION_UP && !mScrolled && isFocused()) {
                     InputMethodManager imm = (InputMethodManager)
-                          getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 
                     CommitSelectionReceiver csr = null;
                     if (getSelectionStart() != oldSelStart || getSelectionEnd() != oldSelEnd ||
@@ -7029,12 +7129,13 @@
                     || windowParams.type > WindowManager.LayoutParams.LAST_SUB_WINDOW;
         }
 
-        // TODO Add an extra android:cursorController flag to disable the controller?
-        if (windowSupportsHandles && mCursorVisible && mLayout != null) {
+        if (windowSupportsHandles && isTextEditable() && mCursorVisible && mLayout != null &&
+                !mTextIsSelectable) {
             if (mInsertionPointCursorController == null) {
                 mInsertionPointCursorController = new InsertionPointCursorController();
             }
         } else {
+            hideInsertionPointCursorController();
             mInsertionPointCursorController = null;
         }
 
@@ -7044,16 +7145,20 @@
             }
         } else {
             // Stop selection mode if the controller becomes unavailable.
-            stopSelectionActionMode();
+            if (mSelectionModifierCursorController != null) {
+                stopSelectionActionMode();
+            }
             mSelectionModifierCursorController = null;
         }
     }
 
     /**
-     * @return True iff this TextView contains a text that can be edited.
+     * @return True iff this TextView contains a text that can be edited, or if this is
+     * a selectable TextView.
      */
     private boolean isTextEditable() {
-        return mText instanceof Editable && onCheckIsTextEditor();
+        return (mText instanceof Editable && onCheckIsTextEditor() && isEnabled())
+                || mTextIsSelectable;
     }
 
     /**
@@ -7300,9 +7405,7 @@
         // prepareCursorController() relies on this method.
         // If you change this condition, make sure prepareCursorController is called anywhere
         // the value of this condition might be changed.
-        return (mText instanceof Spannable &&
-                mMovement != null &&
-                mMovement.canSelectArbitrarily());
+        return (mText instanceof Spannable && mMovement != null && mMovement.canSelectArbitrarily());
     }
 
     private boolean canCut() {
@@ -7684,13 +7787,53 @@
         return packRangeInLong(min, max);
     }
 
+    private DragThumbnailBuilder getTextThumbnailBuilder(CharSequence text) {
+        TextView thumbnail = (TextView) inflate(mContext,
+                com.android.internal.R.layout.text_drag_thumbnail, null);
+
+        if (thumbnail == null) {
+            throw new IllegalArgumentException("Unable to inflate text drag thumbnail");
+        }
+
+        if (text.length() > DRAG_THUMBNAIL_MAX_TEXT_LENGTH) {
+            text = text.subSequence(0, DRAG_THUMBNAIL_MAX_TEXT_LENGTH);
+        }
+        thumbnail.setText(text);
+        thumbnail.setTextColor(getTextColors());
+
+        thumbnail.setTextAppearance(mContext, R.styleable.Theme_textAppearanceLarge);
+        thumbnail.setGravity(Gravity.CENTER);
+
+        thumbnail.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT));
+
+        final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
+        thumbnail.measure(size, size);
+
+        thumbnail.layout(0, 0, thumbnail.getMeasuredWidth(), thumbnail.getMeasuredHeight());
+        thumbnail.invalidate();
+        return new DragThumbnailBuilder(thumbnail);
+    }
+
     @Override
     public boolean performLongClick() {
         if (super.performLongClick()) {
             mEatTouchRelease = true;
             return true;
         }
-        
+
+        if (mSelectionActionMode != null && touchPositionIsInSelection()) {
+            final int start = getSelectionStart();
+            final int end = getSelectionEnd();
+            CharSequence selectedText = mTransformed.subSequence(start, end);
+            ClipData data = ClipData.newPlainText(null, null, selectedText);
+            startDrag(data, getTextThumbnailBuilder(selectedText), false);
+            stopSelectionActionMode();
+            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+            mEatTouchRelease = true;
+            return true;
+        }
+
         if (startSelectionActionMode()) {
             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
             mEatTouchRelease = true;
@@ -7830,6 +7973,8 @@
                 if (hasPasswordTransformationMethod()) {
                     // selectCurrentWord is not available on a password field and would return an
                     // arbitrary 10-charater selection around pressed position. Select all instead.
+                    // Note that cut/copy menu entries are not available for passwords.
+                    // This is however useful to delete or paste to replace the entire content.
                     Selection.setSelection((Spannable) mText, 0, mText.length());
                 } else {
                     selectCurrentWord();
@@ -8728,6 +8873,46 @@
         return getOffsetForHorizontal(line, x);
     }
 
+    @Override
+    public boolean onDragEvent(DragEvent event) {
+        switch (event.getAction()) {
+            case DragEvent.ACTION_DRAG_STARTED:
+                return mInsertionPointCursorController != null;
+
+            case DragEvent.ACTION_DRAG_ENTERED:
+                TextView.this.requestFocus();
+                return true;
+
+            case DragEvent.ACTION_DRAG_LOCATION: {
+                final int offset = getOffset((int)event.getX(), (int)event.getY());
+                Selection.setSelection((Spannable)mText, offset);
+                return true;
+            }
+
+            case DragEvent.ACTION_DROP: {
+                StringBuilder content = new StringBuilder("");
+                ClipData clipData = event.getClipData();
+                final int itemCount = clipData.getItemCount();
+                for (int i=0; i < itemCount; i++) {
+                    Item item = clipData.getItem(i);
+                    content.append(item.coerceToText(TextView.this.mContext));
+                }
+                final int offset = getOffset((int) event.getX(), (int) event.getY());
+                long minMax = prepareSpacesAroundPaste(offset, offset, content);
+                int min = extractRangeStartFromLong(minMax);
+                int max = extractRangeEndFromLong(minMax);
+                Selection.setSelection((Spannable) mText, max);
+                ((Editable) mText).replace(min, max, content);
+                return true;
+            }
+
+            case DragEvent.ACTION_DRAG_EXITED:
+            case DragEvent.ACTION_DRAG_ENDED:
+            default:
+                return true;
+        }
+    }
+
 
     @ViewDebug.ExportedProperty(category = "text")
     private CharSequence            mText;
@@ -8781,6 +8966,7 @@
     private float                   mSpacingMult = 1;
     private float                   mSpacingAdd = 0;
     private int                     mLineHeight = 0;
+    private boolean                 mTextIsSelectable = false;
 
     private static final int        LINES = 1;
     private static final int        EMS = LINES;
@@ -8822,4 +9008,5 @@
     private static final InputFilter[] NO_FILTERS = new InputFilter[0];
     private InputFilter[] mFilters = NO_FILTERS;
     private static final Spanned EMPTY_SPANNED = new SpannedString("");
+    private static int DRAG_THUMBNAIL_MAX_TEXT_LENGTH = 20;
 }
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 7cf369f..cd1cae6 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -616,7 +616,7 @@
     public int getSelectedNavigationIndex() {
         switch (mActionView.getNavigationMode()) {
             case NAVIGATION_MODE_TABS:
-                return mSelectedTab.getPosition();
+                return mSelectedTab != null ? mSelectedTab.getPosition() : -1;
             case NAVIGATION_MODE_LIST:
                 return mActionView.getDropdownSelectedPosition();
             default:
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index b535fc1..5bfa1b2 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -17,11 +17,38 @@
 package com.android.internal.backup;
 
 import android.app.backup.RestoreSet;
+import android.content.Intent;
 import android.content.pm.PackageInfo;
 import android.os.ParcelFileDescriptor;
 
 /** {@hide} */
 interface IBackupTransport {
+	/**
+	 * Ask the transport for an Intent that can be used to launch any internal
+	 * configuration Activity that it wishes to present.  For example, the transport
+	 * may offer a UI for allowing the user to supply login credentials for the
+	 * transport's off-device backend.
+	 *
+	 * If the transport does not supply any user-facing configuration UI, it should
+	 * return null from this method.
+	 *
+	 * @return An Intent that can be passed to Context.startActivity() in order to
+	 *         launch the transport's configuration UI.  This method will return null
+	 *         if the transport does not offer any user-facing configuration UI.
+	 */
+	Intent configurationIntent();
+
+	/**
+	 * On demand, supply a one-line string that can be shown to the user that
+	 * describes the current backend destination.  For example, a transport that
+	 * can potentially associate backup data with arbitrary user accounts should
+	 * include the name of the currently-active account here.
+	 *
+	 * @return A string describing the destination to which the transport is currently
+	 *         sending data.  This method should not return null.
+	 */
+	String currentDestinationString();
+
     /**
      * Ask the transport where, on local device storage, to keep backup state blobs.
      * This is per-transport so that mock transports used for testing can coexist with
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index b436363..45f8599 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -20,6 +20,7 @@
 import android.app.backup.BackupDataOutput;
 import android.app.backup.RestoreSet;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -49,11 +50,13 @@
     private static final String TRANSPORT_DIR_NAME
             = "com.android.internal.backup.LocalTransport";
 
+    private static final String TRANSPORT_DESTINATION_STRING
+            = "Backing up to debug-only private cache";
+
     // The single hardcoded restore set always has the same (nonzero!) token
     private static final long RESTORE_TOKEN = 1;
 
     private Context mContext;
-    private PackageManager mPackageManager;
     private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup");
     private PackageInfo[] mRestorePackages = null;
     private int mRestorePackage = -1;  // Index into mRestorePackages
@@ -61,9 +64,16 @@
 
     public LocalTransport(Context context) {
         mContext = context;
-        mPackageManager = context.getPackageManager();
     }
 
+    public Intent configurationIntent() {
+        // The local transport is not user-configurable
+        return null;
+    }
+
+    public String currentDestinationString() {
+        return TRANSPORT_DESTINATION_STRING;
+    }
 
     public String transportDirName() {
         return TRANSPORT_DIR_NAME;
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 127ed68..99a6843 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -47,6 +47,15 @@
     public static final String POWER_CPU_IDLE = "cpu.idle";
 
     /**
+     * Power consumption when CPU is awake (when a wake lock is held).  This
+     * should be 0 on devices that can go into full CPU power collapse even
+     * when a wake lock is held.  Otherwise, this is the power consumption in
+     * addition to POWERR_CPU_IDLE due to a wake lock being held but with no
+     * CPU activity.
+     */
+    public static final String POWER_CPU_AWAKE = "cpu.awake";
+
+    /**
      * Power consumption when CPU is in power collapse mode.
      */
     public static final String POWER_CPU_ACTIVE = "cpu.active";
diff --git a/core/java/com/android/internal/os/SamplingProfilerIntegration.java b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
index 6d2bcae..c930c57c 100644
--- a/core/java/com/android/internal/os/SamplingProfilerIntegration.java
+++ b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
@@ -53,7 +53,10 @@
 
     static {
         samplingProfilerHz = SystemProperties.getInt("persist.sys.profiler_hz", 0);
-        if (samplingProfilerHz > 0) {
+        // Disabling this for now, as it crashes when enabled server-side.  So adding
+        // a new property ("REALLY") for those wanting to test and fix it.
+        boolean really = SystemProperties.getInt("persist.sys.profiler_hz_REALLY", 0) > 0;
+        if (samplingProfilerHz > 0 && really) {
             snapshotWriter = Executors.newSingleThreadExecutor();
             enabled = true;
             Log.i(TAG, "Profiler is enabled. Sampling Profiler Hz: " + samplingProfilerHz);
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index c947824..1d103ed 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -24,6 +24,7 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.View.MeasureSpec;
+import android.view.ViewTreeObserver;
 import android.widget.AdapterView;
 import android.widget.ListPopupWindow;
 import android.widget.PopupWindow;
@@ -33,7 +34,8 @@
 /**
  * @hide
  */
-public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener {
+public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener,
+        ViewTreeObserver.OnGlobalLayoutListener {
     private static final String TAG = "MenuPopupHelper";
 
     private Context mContext;
@@ -42,6 +44,7 @@
     private int mPopupMaxWidth;
     private WeakReference<View> mAnchorView;
     private boolean mOverflowOnly;
+    private ViewTreeObserver mTreeObserver;
 
     private PopupWindow.OnDismissListener mDismissListener = new PopupWindow.OnDismissListener() {
         public void onDismiss() {
@@ -82,12 +85,18 @@
         mPopup.setAdapter(adapter);
         mPopup.setModal(true);
 
-        if (mAnchorView != null) {
-            mPopup.setAnchorView(mAnchorView.get());
-        } else if (mMenu instanceof SubMenuBuilder) {
+        View anchor = mAnchorView != null ? mAnchorView.get() : null;
+        if (anchor == null && mMenu instanceof SubMenuBuilder) {
             SubMenuBuilder subMenu = (SubMenuBuilder) mMenu;
             final MenuItemImpl itemImpl = (MenuItemImpl) subMenu.getItem();
-            mPopup.setAnchorView(itemImpl.getItemView(MenuBuilder.TYPE_ACTION_BUTTON, null));
+            anchor = itemImpl.getItemView(MenuBuilder.TYPE_ACTION_BUTTON, null);
+            mAnchorView = new WeakReference<View>(anchor);
+        }
+
+        if (anchor != null) {
+            mTreeObserver = anchor.getViewTreeObserver();
+            mTreeObserver.addOnGlobalLayoutListener(this);
+            mPopup.setAnchorView(anchor);
         } else {
             throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor");
         }
@@ -101,6 +110,8 @@
         if (isShowing()) {
             mPopup.dismiss();
         }
+        mTreeObserver.removeGlobalOnLayoutListener(this);
+        mTreeObserver = null;
     }
 
     public boolean isShowing() {
@@ -115,7 +126,7 @@
             item = mMenu.getItem(position);
         }
         mMenu.performItemAction(item, 0);
-        mPopup.dismiss();
+        dismiss();
     }
 
     public boolean onKey(View v, int keyCode, KeyEvent event) {
@@ -142,4 +153,17 @@
         }
         return width;
     }
+
+    @Override
+    public void onGlobalLayout() {
+        if (!isShowing()) {
+            mTreeObserver.removeGlobalOnLayoutListener(this);
+            mTreeObserver = null;
+        } else {
+            final View anchor = mAnchorView != null ? mAnchorView.get() : null;
+            if (anchor != null && !anchor.isShown()) {
+                dismiss();
+            }
+        }
+    }
 }
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index be6a57a..7a64da0 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -330,6 +330,7 @@
         mSubtitle = subtitle;
         if (mSubtitleView != null) {
             mSubtitleView.setText(subtitle);
+            mSubtitleView.setVisibility(subtitle != null ? VISIBLE : GONE);
         }
     }
 
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index abe33f4..90c4dd4 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -36,7 +36,7 @@
     static void finalizer(JNIEnv* env, jobject clazz, SkPath* obj) {
 #ifdef USE_OPENGL_RENDERER
         if (android::uirenderer::Caches::hasInstance()) {
-            android::uirenderer::Caches::getInstance().pathCache.remove(obj);
+            android::uirenderer::Caches::getInstance().pathCache.removeDeferred(obj);
         }
 #endif
         delete obj;
diff --git a/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png
new file mode 100644
index 0000000..192df6d2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progress_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png
new file mode 100644
index 0000000..223416d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progress_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png
new file mode 100644
index 0000000..1a59124
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progress_primary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png
new file mode 100644
index 0000000..f119c6a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progress_primary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png
new file mode 100644
index 0000000..3c6c5ed
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progress_secondary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png
new file mode 100644
index 0000000..cab3888
--- /dev/null
+++ b/core/res/res/drawable-hdpi/progress_secondary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png
new file mode 100644
index 0000000..316af64
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progress_bg_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png b/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png
new file mode 100644
index 0000000..e286136
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progress_bg_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png
new file mode 100644
index 0000000..0502669
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progress_primary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png b/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png
new file mode 100644
index 0000000..1ba9e34
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progress_primary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png b/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png
new file mode 100644
index 0000000..a2fe2b3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progress_secondary_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png b/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png
new file mode 100644
index 0000000..3b264ab
--- /dev/null
+++ b/core/res/res/drawable-mdpi/progress_secondary_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable/item_background_holo_dark.xml b/core/res/res/drawable/item_background_holo_dark.xml
index f119ec0..2d4f20a 100644
--- a/core/res/res/drawable/item_background_holo_dark.xml
+++ b/core/res/res/drawable/item_background_holo_dark.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          android:exitFadeDuration="@android:integer/config_mediumAnimTime">
 
     <item android:state_window_focused="false" android:drawable="@color/transparent" />
 
diff --git a/core/res/res/drawable/item_background_holo_light.xml b/core/res/res/drawable/item_background_holo_light.xml
index d3d278a..c616d86 100644
--- a/core/res/res/drawable/item_background_holo_light.xml
+++ b/core/res/res/drawable/item_background_holo_light.xml
@@ -14,7 +14,8 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
+<selector xmlns:android="http://schemas.android.com/apk/res/android"
+          android:exitFadeDuration="@android:integer/config_mediumAnimTime">
 
     <item android:state_window_focused="false" android:drawable="@color/transparent" />
 
diff --git a/core/res/res/drawable/progress_horizontal_holo_dark.xml b/core/res/res/drawable/progress_horizontal_holo_dark.xml
new file mode 100644
index 0000000..ff270b3
--- /dev/null
+++ b/core/res/res/drawable/progress_horizontal_holo_dark.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:id="@android:id/background"
+          android:drawable="@android:drawable/progress_bg_holo_dark" />
+
+    <item android:id="@android:id/secondaryProgress">
+        <scale android:scaleWidth="100%"
+               android:drawable="@android:drawable/progress_secondary_holo_dark" />
+    </item>
+
+    <item android:id="@android:id/progress">
+        <scale android:scaleWidth="100%"
+               android:drawable="@android:drawable/progress_primary_holo_dark" />
+    </item>
+
+</layer-list>
diff --git a/core/res/res/drawable/progress_horizontal_holo_light.xml b/core/res/res/drawable/progress_horizontal_holo_light.xml
new file mode 100644
index 0000000..4935185
--- /dev/null
+++ b/core/res/res/drawable/progress_horizontal_holo_light.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <item android:id="@android:id/background"
+          android:drawable="@android:drawable/progress_bg_holo_light" />
+
+    <item android:id="@android:id/secondaryProgress">
+        <scale android:scaleWidth="100%"
+               android:drawable="@android:drawable/progress_secondary_holo_light" />
+    </item>
+
+    <item android:id="@android:id/progress">
+        <scale android:scaleWidth="100%"
+               android:drawable="@android:drawable/progress_primary_holo_light" />
+    </item>
+
+</layer-list>
diff --git a/core/res/res/layout/text_drag_thumbnail.xml b/core/res/res/layout/text_drag_thumbnail.xml
new file mode 100644
index 0000000..63d2c05
--- /dev/null
+++ b/core/res/res/layout/text_drag_thumbnail.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* apps/common/assets/default/default/skins/StatusBar.xml
+**
+** Copyright 2010, 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.
+*/
+-->
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:textAppearance="@android:style/TextAppearance.Large"
+    android:gravity="center"
+    />
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 7e892a4..0aa4247 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Umožňuje aplikaci zobrazit konfiguraci místního telefonu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"ovládat technologii NFC"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Umožňuje aplikaci komunikovat se štítky, kartami a čtečkami s podporou technologie NFC."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"vypnutí zámku kláves"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Umožňuje aplikaci vypnout zámek kláves a související zabezpečení heslem. Příkladem oprávněného použití této funkce je vypnutí zámku klávesnice při příchozím hovoru a jeho opětovné zapnutí po skončení hovoru."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"čtení nastavení synchronizace"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Umožňuje aplikaci načíst nastavení synchronizace, např. zda má být povolena synchronizace kontaktů."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 0dbf3b7..e0be775 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Tillader, at et program viser konfigurationen af den lokale Bluetooth-telefon samt opretter og accepterer forbindelse med parrede enheder."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"kontrollere Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Tillader, at et program kommunikerer med tags, kort og læsere i Near Field Communication (NFC)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"deaktiver tastaturlås"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Tillader, at et program deaktiverer tastaturlåsen og al associeret adgangskodesikkerhed. Et legitimt eksempel på dette er, at telefonen deaktiverer tastaturlåsen, når der modtages et indgående telefonopkald, og genaktiverer tastaturlåsen, når opkaldet er afsluttet."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"læs indstillinger for synkronisering"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Tillader, at et program læser synkroniseringsindstillingerne, f.eks. om kontakter skal synkroniseres."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 0db7b0a..1566b1b 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Ermöglicht einer Anwendung, die Konfiguration des lokalen Bluetooth-Telefons einzusehen und Verbindungen mit Partnergeräten herzustellen und zu akzeptieren."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"Nahfeldkommunikation steuern"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Ermöglicht einer Anwendung die Kommunikation mit Tags für die Nahfeldkommunikation, Karten und Readern."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"Tastensperre deaktivieren"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Ermöglicht einer Anwendung, die Tastensperre sowie den damit verbundenen Passwortschutz zu deaktivieren. So wird die Tastensperre vom Telefon deaktiviert, wenn ein Anruf eingeht, und nach Beendigung des Anrufs wieder aktiviert."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Synchronisierungseinstellungen lesen"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Ermöglicht einer Anwendung, die Synchronisierungseinstellungen zu lesen, etwa ob die Synchronisierung für Kontakte aktiviert ist oder nicht."</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index dc3d747..bd86221 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Επιτρέπει σε μια εφαρμογή να προβάλει τη διαμόρφωση του τοπικού τηλεφώνου Bluetooth και επίσης να πραγματοποιεί και να αποδέχεται συνδέσεις με συζευγμένες συσκευές."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"έλεγχος Επικοινωνίας κοντινού πεδίου (Near Field Communication)"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Επιτρέπει σε μια εφαρμογή την επικοινωνία με ετικέτες, τις κάρτες και τους αναγνώστες της Επικοινωνίας κοντινού πεδίου (NFC)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"απενεργοποίηση κλειδώματος πληκτρολογίου"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Επιτρέπει σε μια εφαρμογή την απενεργοποίηση του κλειδώματος πληκτρολογίου και άλλης σχετικής ασφάλειας με κωδικό πρόσβασης. Για παράδειγμα, η απενεργοποίηση του κλειδώματος πληκτρολογίου όταν λαμβάνεται εισερχόμενη τηλεφωνική κλήση και η επανενεργοποίηση του κλειδώματος πληκτρολογίου όταν η κλήση τερματιστεί."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ανάγνωση ρυθμίσεων συγχρονισμού"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Επιτρέπει σε μια εφαρμογή την ανάγνωση των ρυθμίσεων συγχρονισμού, όπως π.χ. εάν ο συγχρονισμός είναι ενεργοποιημένος για τις Επαφές."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index b518c46..e303707 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -439,6 +439,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Admite una aplicación que ve la configuración del teléfono Bluetooth local, y realiza y acepta conexiones con dispositivos vinculados."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"controlar la Transmisión de datos en proximidad"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Permite que una aplicación se comunique con etiquetas, tarjetas y lectores de Transmisión de datos en proximidad (NFC)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"desactivar el bloqueo"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Admite una aplicación que desactiva el bloqueo y cualquier seguridad con contraseña relacionada. Un ejemplo legítimo de esto es el bloqueo desactivado por el teléfono cuando recibe una llamada telefónica entrante, y luego la reactivación del bloqueo cuando finaliza la llamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Admite una aplicación que lee la configuración de sincronización, como si está activada la sincronización para los Contactos."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 75e5dc1..452eefd 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Permite que una aplicación vea la configuración del teléfono Bluetooth local, y cree y acepte conexiones con los dispositivos sincronizados."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"controlar Comunicación de campo cercano (NFC)"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Permite que la aplicación se comunique con lectores, tarjetas y etiquetas de Comunicación de campo cercano (NFC)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"inhabilitar bloqueo del teclado"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite que una aplicación inhabilite el bloqueo del teclado y cualquier protección con contraseña asociada. Un ejemplo legítimo de este permiso es la inhabilitación por parte del teléfono del bloqueo del teclado cuando recibe una llamada telefónica entrante y su posterior habilitación cuando finaliza la llamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"leer la configuración de sincronización"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Permite que una aplicación lea la configuración de sincronización como, por ejemplo, si la sincronización está habilitada para el menú \"Contactos\"."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 0a944b9..a802350 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Permet à une application d\'obtenir la configuration du téléphone Bluetooth local et de créer et accepter des connexions à des appareils associés."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"contrôler la communication en champ proche"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Autorise une application à communiquer avec des tags, cartes et lecteurs prenant en charge la communication en champ proche (NFC)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"Désactivation du verrouillage des touches"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permet à une application de désactiver le verrouillage des touches et toute sécurité par mot de passe. Exemple : Votre téléphone désactive le verrouillage du clavier lorsque vous recevez un appel, puis le réactive lorsque vous raccrochez."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"Lecture des paramètres de synchronisation"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Permet à une application de lire les paramètres de synchronisation (par ex. savoir si la synchronisation est activée pour les Contacts)."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index ba71e53..6e5987e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Consente a un\'applicazione di visualizzare la configurazione del telefono Bluetooth locale e di stabilire e accettare connessioni con dispositivi associati."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"controllo Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Consente a un\'applicazione di comunicare con tag, schede e lettori NFC (Near Field Communication)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"disattivazione blocco tastiera"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Consente la disattivazione da parte di un\'applicazione del blocco tastiera e di eventuali protezioni tramite password associate. Un valido esempio è la disattivazione da parte del telefono del blocco tastiera quando riceve una telefonata in entrata, e la successiva riattivazione del blocco al termine della chiamata."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lettura impostazioni di sincronizz."</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Consente a un\'applicazione di leggere le impostazioni di sincronizzazione, come l\'attivazione o meno della sincronizzazione per Contatti."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 748f8a7..12cb290 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"このBluetooth端末の設定表示、および別の端末をペアとして設定し接続を承認することをアプリケーションに許可します。"</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"NFCの管理"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"NFCタグ、カード、リーダーとの通信をアプリケーションに許可します。"</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"キーロックを無効にする"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"キーロックや関連するパスワードセキュリティを無効にすることをアプリケーションに許可します。正当な利用の例では、かかってきた電話を受信する際にキーロックを無効にし、通話の終了時にキーロックを有効にし直します。"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"同期設定の読み取り"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"連絡先の同期の有効/無効など、同期設定の読み取りをアプリケーションに許可します。"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 5951045..36e5134 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"애플리케이션이 로컬 Bluetooth 전화의 구성을 보고 페어링된 장치에 연결하며 연결을 수락할 수 있도록 합니다."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"NFC(Near Field Communication) 제어"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"애플리케이션에서 NFC(Near Field Communication) 태그, 카드 및 리더와 통신할 수 있습니다."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"키 잠금 사용 중지"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"애플리케이션이 키 잠금 및 관련 비밀번호 보안을 사용 중지할 수 있도록 합니다. 예를 들어, 휴대전화가 수신전화를 받을 때 키 잠금을 사용 중지했다가 통화가 끝나면 키 잠금을 다시 사용할 수 있습니다."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"동기화 설정 읽기"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"애플리케이션이 주소록에 동기화를 사용할지 여부와 같은 동기화 설정을 읽을 수 있도록 합니다."</string>
diff --git a/core/res/res/values-large/themes.xml b/core/res/res/values-large/themes.xml
new file mode 100644
index 0000000..cdf58fe
--- /dev/null
+++ b/core/res/res/values-large/themes.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2010, 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.
+*/
+-->
+<resources>
+    <style name="Theme.Holo.DialogWhenLarge" parent="@android:style/Theme.Holo.Dialog">
+    </style>
+</resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index d97e803..e43aabd 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Lar applikasjonen se konfigurasjonen til den lokale Bluetooth-telefonen, og å opprette og godta tilkoblinger med parede enheter."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"kontroller overføring av data med NFC-teknologi"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Tillater programmet å kommunisere data via koder, kort og lesere for NFC-teknologi."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"slå av tastaturlås"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Lar applikasjonen slå av tastaturlåsen og enhver tilknyttet passordsikkerhet. Et legitimt eksempel på dette er at telefonen slår av tastaturlåsen når den mottar et innkommende anrop, og så slår den på igjen når samtalen er over."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"lese synkroniseringsinnstillinger"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Lar applikasjonen lese synkroniseringsinnstillingene, som for eksempel om kontakter blir synkronisert."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 483b236..d66b694 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Hiermee kan een toepassing de configuratie van een lokale Bluetooth-telefoon bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"Near Field Communication regelen"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Hiermee kan een toepassing communiceren met NFC-tags (Near Field Communication), kaarten en lezers."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"toetsvergrendeling uitschakelen"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Hiermee kan een toepassing de toetsvergrendeling en bijbehorende wachtwoordbeveiliging uitschakelen. Een voorbeeld: de telefoon schakelt de toetsvergrendeling uit als er een oproep binnenkomt en schakelt de toetsvergrendeling weer in als de oproep is beëindigd."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"synchronisatie-instellingen lezen"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Hiermee kan een toepassing de synchronisatie-instellingen lezen, bijvoorbeeld of de synchronisatie van contacten is ingeschakeld."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index d2f345e..66a7160 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Pozwala aplikacji na wyświetlanie konfiguracji lokalnego telefonu Bluetooth oraz na tworzenie i akceptowanie połączeń ze sparowanymi urządzeniami."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"kontrolowanie łączności Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Zezwala aplikacji na komunikowanie się z użyciem tagów, kart i czytników Near Field Communication (NFC)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"wyłączanie blokady klawiatury"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Pozwala aplikacji na wyłączenie blokady klawiatury i wszystkich związanych z tym haseł zabezpieczających. Typowym przykładem takiego działania jest wyłączanie blokady klawiatury, gdy pojawia się połączenie przychodzące, a następnie ponowne jej włączanie po zakończeniu połączenia."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"czytanie ustawień synchronizowania"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Pozwala aplikacji na czytanie ustawień synchronizacji, takich jak informacje, czy synchronizacja kontaktów jest włączona."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 3252911..990d630 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Permite a uma aplicação ver a configuração do telefone Bluetooth local, bem como efectuar e aceitar ligações com dispositivos emparelhados."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"controlo Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Permite que uma aplicação comunique com etiquetas, cartões e leitores Near Field Communication (NFC)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"desactivar bloqueio de teclas"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite a uma aplicação desactivar o bloqueio de teclas e qualquer segurança por palavra-passe associada. Um exemplo legítimo é a desactivação do bloqueio de teclas pelo telefone ao receber uma chamada, reactivando, em seguida, o bloqueio de teclas ao terminar a chamada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler definições de sincronização"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Permite a uma aplicação ler as definições de sincronização como, por exemplo, se a sincronização está activada para Contactos."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 28d7bf6..ce106db 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Permite que um aplicativo veja a configuração do telefone Bluetooth local e que possa fazer e aceitar conexões com dispositivos pareados."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"controlar a comunicação a curta distância"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Permite que um aplicativo se comunique com tags, cartões e leitores de comunicação a curta distância (NFC)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"desativar o bloqueio de teclas"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permite que um aplicativo desative o bloqueio de teclas e qualquer segurança por senha associada. Um exemplo legítimo disso é a desativação do bloqueio de teclas pelo telefone ao receber uma chamada e a reativação do bloqueio quando a chamada é finalizada."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"ler as configurações de sincronização"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Permite que um aplicativo leia as configurações de sincronização, como se a sincronização está ativada para Contatos."</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 3feba6a..bbd61bd 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -444,6 +444,7 @@
     <skip />
     <!-- no translation found for permdesc_nfc (9171401851954407226) -->
     <skip />
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"deactivar la bloccaziun da la tastatura"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Permetta ad ina applicaziun da deactivar la bloccaziun da la tastatura e la protecziun cun il pled-clav associada. In exempel dad ina utilisaziun legitima: La bloccaziun da la tastatura vegn deactivada sche Vus retschavais in clom ed ella vegn reactivada sche Vus finis il telefon."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"leger ils parameters da sincronisaziun"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Permetta ad ina applicaziun da leger ils parameters da sincronisaziun (per exempel per savair sche la sincronisaziun da contacts è activà u betg)."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 38ae2aa..4babb3bd 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Позволяет приложению просматривать конфигурацию локального телефона Bluetooth, создавать подключения с сопряженными устройствами."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"управлять радиосвязью ближнего действия"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Позволяет приложению обмениваться данными с метками, картами и считывателями через радиосвязь ближнего действия (NFC)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"отключать блокировку клавиатуры"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Позволяет приложению отключить блокировку клавиатуры и другие функции защиты паролем. Примером допустимого использования этой функции является отключение блокировки клавиатуры при получении входящего вызова и включение блокировки после завершения разговора."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"считывать настройки синхронизации"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Позволяет приложению считывать настройки синхронизации, такие как включение синхронизации Контактов."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index dd05ecb..102a08d16 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Tillåter att ett program ser den lokala Bluetooth-telefonens konfiguration, och skapar och accepterar anslutningar med parkopplade enheter."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"kontrollera närfältskommunikationen"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Tillåter att en app kommunicerar med taggar, kort och läsare för närfältskommunikation (NFC)."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"inaktivera tangentlås"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Tillåter att ett program inaktiverar tangentlåset och tillhörande lösenordsskydd. Ett exempel på detta är att telefonen inaktiverar tangentlåset vid inkommande samtal och sedan aktiverar det igen när samtalet är avslutat."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"läsa synkroniseringsinställningar"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Tillåter att ett program läser synkroniseringsinställningarna, till exempel om synkronisering har aktiverats för kontakter."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 1545d7a..a6bfbf6 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"Uygulamaların yerel Bluetooth telefonunun yapılandırmasını görüntülemesine ve eşleşilmiş cihazlar ile bağlantı kurup kabul etmesine izin verir."</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"Yakın Alan İletişimini denetle"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"Bir uyg\'nın Yakın Alan İletişimi etiketleri, kartları ve okuyclr ile iletşm kurmasına izin verir."</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"tuş kilidini devre dışı bırak"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"Uygulamaların tuş kilidini ve ilgili şifreli güvenlik önlemini devre dışı bırakmasına izin verir. Bunun geçerli bir örneği gelen bir çağrı alındığında tuş kilidinin devre dışı bırakılması, sonra çağrı bittiğinde kilidin yeniden devreye sokulmasıdır."</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"senk. ayarlarını oku"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"Uygulamanın, senkronizasyon işlevinin Kişiler için devrede olup olmadığı gibi senkronizasyon ayarlarını okumasına izin verir."</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 76690dd..4fd5161 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"允许应用程序查看本地蓝牙手机的配置,以及建立或接受与配对设备的连接。"</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"控制近距离通信"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"允许应用程序与近距离通信 (NFC) 标签、卡和读卡器进行通信。"</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"停用键锁"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"允许应用程序停用键锁和任何关联的密码安全设置。例如,在手机上接听电话时停用键锁,在通话结束后重新启用键锁。"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"读取同步设置"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"允许应用程序读取同步设置,例如是否为“联系人”启用同步。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 5fb0998..6d5c4d4 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -440,6 +440,7 @@
     <string name="permdesc_bluetooth" product="default" msgid="762515380679392945">"允許應用程式檢視本機藍牙電話設定,並與其他配對裝置連線。"</string>
     <string name="permlab_nfc" msgid="4423351274757876953">"控制近距離無線通訊"</string>
     <string name="permdesc_nfc" msgid="9171401851954407226">"允許應用程式使用近距離無線通訊 (NFC) 標記、卡片及讀取程式進行通訊。"</string>
+    <string name="permlab_disableKeyguard" msgid="4977406164311535092">"停用按鍵鎖定"</string>
     <string name="permdesc_disableKeyguard" msgid="3189763479326302017">"允許應用程式停用按鍵鎖定以及其他相關的密碼安全性。例如:收到來電時解除按鍵鎖定,通話結束後重新啟動按鍵鎖定。"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"讀取同步處理設定"</string>
     <string name="permdesc_readSyncSettings" msgid="5315925706353341823">"允許應用程式讀取同步處理設定,例如:是否同步處理 [聯絡人]。"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2a942b8..d6684fe 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -345,6 +345,18 @@
              because there will be no such interaction coming. -->
         <attr name="windowNoDisplay" format="boolean" />
 
+        <!-- Flag indicating that this window should allow touches to be split
+             across other windows that also support split touch.
+             The default value is true for applications with a targetSdkVersion
+             of Honeycomb or newer; false otherwise.
+             When this flag is false, the first pointer that goes down determines
+             the window to which all subsequent touches go until all pointers go up.
+             When this flag is true, each pointer (not necessarily the first) that
+             goes down determines the window to which all subsequent touches of that
+             pointer will go until that pointers go up thereby enabling touches
+             with multiple pointers to be split across multiple windows. -->
+        <attr name="windowEnableSplitTouch" format="boolean" />
+
         <!-- ============ -->
         <!-- Alert Dialog styles -->
         <!-- ============ -->
@@ -635,6 +647,10 @@
     <!-- Height of a line of text. -->
     <attr name="textLineHeight" format="dimension" />
 
+    <!-- Indicates that the content of a non-editable TextView can be selected.
+     Default value is false. EditText content is always selectable. -->
+    <attr name="textIsSelectable" format="boolean" />
+
     <!-- Where to ellipsize text. -->
     <attr name="ellipsize">
         <enum name="none" value="0" />
@@ -1170,6 +1186,28 @@
         <enum name="KEYCODE_NUMPAD_LEFT_PAREN" value="162" />
         <enum name="KEYCODE_NUMPAD_RIGHT_PAREN" value="163" />
         <enum name="KEYCODE_VOLUME_MUTE" value="164" />
+        <enum name="KEYCODE_INFO" value="165" />
+        <enum name="KEYCODE_CHANNEL_UP" value="166" />
+        <enum name="KEYCODE_CHANNEL_DOWN" value="167" />
+        <enum name="KEYCODE_ZOOM_IN" value="168" />
+        <enum name="KEYCODE_ZOOM_OUT" value="169" />
+        <enum name="KEYCODE_TV" value="170" />
+        <enum name="KEYCODE_WINDOW" value="171" />
+        <enum name="KEYCODE_GUIDE" value="172" />
+        <enum name="KEYCODE_DVR" value="173" />
+        <enum name="KEYCODE_BOOKMARK" value="174" />
+        <enum name="KEYCODE_CAPTIONS" value="175" />
+        <enum name="KEYCODE_SETTINGS" value="176" />
+        <enum name="KEYCODE_TV_POWER" value="177" />
+        <enum name="KEYCODE_TV_INPUT" value="178" />
+        <enum name="KEYCODE_STB_POWER" value="179" />
+        <enum name="KEYCODE_STB_INPUT" value="180" />
+        <enum name="KEYCODE_AVR_POWER" value="181" />
+        <enum name="KEYCODE_AVR_INPUT" value="182" />
+        <enum name="KEYCODE_PROG_GRED" value="183" />
+        <enum name="KEYCODE_PROG_GREEN" value="184" />
+        <enum name="KEYCODE_PROG_YELLOW" value="185" />
+        <enum name="KEYCODE_PROG_BLUE" value="186" />
     </attr>
 
     <!-- ***************************************************************** -->
@@ -1201,6 +1239,7 @@
         <attr name="windowActionBar" />
         <attr name="windowActionModeOverlay" />
         <attr name="windowActionBarOverlay" />
+        <attr name="windowEnableSplitTouch" />
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -2455,6 +2494,9 @@
 
         <!-- Height of a line of text. -->
         <attr name="textLineHeight" />
+        <!-- Indicates that a non-editable text can be selected. -->
+        <attr name="textIsSelectable" />
+
     </declare-styleable>
     <!-- An <code>input-extras</code> is a container for extra data to supply to
          an input method.  Contains
@@ -3021,6 +3063,10 @@
         </attr>
         <!-- Reference to a drawable resource to draw with the specified scale. -->
         <attr name="drawable" />
+        <!-- Use the drawable's intrinsic width and height as minimum size values.
+             Useful if the target drawable is a 9-patch or otherwise should not be scaled
+             down beyond a minimum size. -->
+        <attr name="useIntrinsicSizeAsMinimum" format="boolean" />
     </declare-styleable>
 
     <declare-styleable name="ClipDrawable">
@@ -4048,6 +4094,9 @@
         <!-- A preview of what the AppWidget will look like after it's configured.
        	     If not supplied, the AppWidget's icon will be used. -->
         <attr name="previewImage" format="reference" />
+        <!-- The view id of the AppWidget subview which should be auto-advanced.
+             by the widget's host. -->
+        <attr name="autoAdvanceViewId" format="reference" />
     </declare-styleable>
 
     <!-- =============================== -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ef609a2..28df995 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1363,6 +1363,15 @@
   <public type="attr" name="enterFadeDuration" />
   <public type="attr" name="exitFadeDuration" />
   <public type="attr" name="selectableItemBackground" />
+  <public type="attr" name="autoAdvanceViewId" />
+  <public type="attr" name="useIntrinsicSizeAsMinimum" />
+  <public type="attr" name="actionModeCutDrawable" />
+  <public type="attr" name="actionModeCopyDrawable" />
+  <public type="attr" name="actionModePasteDrawable" />
+  <public type="attr" name="textEditPasteWindowLayout" />
+  <public type="attr" name="textEditNoPasteWindowLayout" />
+  <public type="attr" name="textIsSelectable" />
+  <public type="attr" name="windowEnableSplitTouch" />
 
   <public type="anim" name="animator_fade_in" />
   <public type="anim" name="animator_fade_out" />
@@ -1429,11 +1438,7 @@
   <public type="style" name="TextAppearance.Widget.PopupMenu.Small" />
   <public type="style" name="Widget.FragmentBreadCrumbs" />
 
+  <public type="style" name="Theme.Holo.DialogWhenLarge" />
+  
   <public type="string" name="selectTextMode" />
-
-  <public type="attr" name="actionModeCutDrawable" />
-  <public type="attr" name="actionModeCopyDrawable" />
-  <public type="attr" name="actionModePasteDrawable" />
-  <public type="attr" name="textEditPasteWindowLayout" />
-  <public type="attr" name="textEditNoPasteWindowLayout" />
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3b01890..64cd00a 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1396,6 +1396,11 @@
     <string name="policydesc_setGlobalProxy">Set the device global proxy
         to be used while policy is enabled. Only the first device admin
         sets the effective global proxy.</string>
+    <!-- Title of policy access to enforce password expiration [CHAR LIMIT=30]-->
+    <string name="policylab_expirePassword">Set password expiration</string>
+    <!-- Description of policy access to enforce password expiration [CHAR LIMIT=110]-->
+    <string name="policydesc_expirePassword">Control how long before lockscreen password needs to be
+    changed</string>
 
     <!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
     <!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index f63805b..457175b4 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1359,6 +1359,9 @@
     </style>
 
     <style name="Widget.Holo.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
+        <item name="android:progressDrawable">@android:drawable/progress_horizontal_holo_dark</item>
+        <item name="android:minHeight">16dip</item>
+        <item name="android:maxHeight">16dip</item>
     </style>
 
     <style name="Widget.Holo.ProgressBar.Small" parent="Widget.ProgressBar.Horizontal">
@@ -1383,8 +1386,8 @@
         <item name="android:indeterminateOnly">false</item>
         <item name="android:progressDrawable">@android:drawable/scrubber_progress_horizontal_holo_dark</item>
         <item name="android:indeterminateDrawable">@android:drawable/scrubber_progress_horizontal_holo_dark</item>
-        <item name="android:minHeight">16dip</item>
-        <item name="android:maxHeight">16dip</item>
+        <item name="android:minHeight">6dip</item>
+        <item name="android:maxHeight">6dip</item>
         <item name="android:thumb">@android:drawable/scrubber_control_holo</item>
         <item name="android:thumbOffset">16dip</item>
         <item name="android:focusable">true</item>
@@ -1646,6 +1649,7 @@
     </style>
 
     <style name="Widget.Holo.Light.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
+        <item name="android:progressDrawable">@android:drawable/progress_horizontal_holo_light</item>
     </style>
 
     <style name="Widget.Holo.Light.ProgressBar.Small" parent="Widget.ProgressBar.Small">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index b4e3c6f..c8cce81 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -1187,6 +1187,12 @@
         <item name="windowContentOverlay">@null</item>
     </style>
 
+    <!-- Theme for a window that will be displayed either full-screen on
+         smaller screens (small, normal) or as a dialog on larger screens
+         (large, xlarge) -->
+    <style name="Theme.Holo.DialogWhenLarge" parent="@android:style/Theme.Holo">
+    </style>
+    
     <!-- Light holo dialog themes -->
 
     <!-- Holo light theme for dialog windows and activities, which is used by the
diff --git a/docs/html/images/sdk_manager_packages.png b/docs/html/images/sdk_manager_packages.png
index 463be8f..027cce7 100755
--- a/docs/html/images/sdk_manager_packages.png
+++ b/docs/html/images/sdk_manager_packages.png
Binary files differ
diff --git a/docs/html/sdk/adding-components.jd b/docs/html/sdk/adding-components.jd
index 05be0d6..d2e55d8 100644
--- a/docs/html/sdk/adding-components.jd
+++ b/docs/html/sdk/adding-components.jd
@@ -98,20 +98,20 @@
   This will reveal all of the components that are currently available for download
   from the SDK repository.</li>
   <li>Select the component(s) you'd like to install and click <strong>Install
-  Selected</strong>. If you aren't sure which packages to select, read <a
-  href="installing.html#which">Recommended Components</a>.</li>
-  <li>Verify and accept the components you want and click <strong>Install
-  Accepted</strong>. The components will now be installed into your existing
-  Android SDK directories.</li>
+  Selected</strong>. (If you aren't sure which packages to select, read <a
+  href="installing.html#which">Recommended Components</a>.)</li>
+  <li>Verify and accept the components you want (ensure each one is selected with a green
+checkmark) and click <strong>Install</strong>. The components will now be installed into
+your existing Android SDK directories.</li>
 </ol>
 
 <p>New platforms are automatically saved into the
-<code>&lt;<em>sdk</em>&gt;/platforms/</code> directory of your SDK;
-new add-ons are saved in the <code>&lt;<em>sdk</em>&gt;/add-ons/</code>
+<code>&lt;sdk&gt;/platforms/</code> directory of your SDK;
+new add-ons are saved in the <code>&lt;sdk&gt;/add-ons/</code>
 directory; samples are saved in the
-<code>&lt;<em>sdk</em>&gt;/samples/android-&lt;<em>level</em>&gt;/</code>;
+<code>&lt;sdk&gt;/samples/android-&lt;level&gt;/</code>;
 and new documentation is saved in the existing
-<code>&lt;<em>sdk</em>&gt;/docs/</code> directory (old docs are replaced).</p>
+<code>&lt;sdk&gt;/docs/</code> directory (old docs are replaced).</p>
 
 
 <h2 id="UpdatingComponents">Updating SDK Components</h2>
@@ -150,27 +150,32 @@
 
 <p>For example, there may be a dependency between the ADT Plugin for Eclipse and
 the SDK Tools component. When you install the SDK Tools
-component, you would then need to upgrade to the required version of ADT (if you
-are developing in Eclipse). In this case, you would find dependencies listed in
-"Revisions" section of the <a href="{@docRoot}sdk/eclipse-adt.html#notes">ADT
-Plugin Notes</a> and <a href="{@docRoot}sdk/tools-notes.html#notes">SDK Tools
-Notes</a> documents. </p>
+component, you should also upgrade to the required version of ADT (if you
+are developing in Eclipse). In this case,  the major version number for your ADT plugin should
+always match the revision number of your SDK Tools (for example, ADT 8.x requires SDK Tools r8).
+</p>
 
-<p>Additionally, the development tools will notify you with debug warnings
-if there is dependency that you need to address. </p>
+<p>Also make sure that, each time you install a new version of the Android platform, you have
+the latest version of the SDK Platform-tools component. The SDK Platform-tools contain
+tools that are backward compatible with all versions of the Android platform and are
+often updated to support new features in the latest version of the Android platform.</p>
+
+<p>The development tools will notify you with debug warnings if there is dependency that you need to
+address. The SDK and AVD Manager also enforces dependencies by requiring that you download any
+components that are needed by those you have selected.</p>
 
 
 <h2 id="AddingSites">Adding New Sites</h2>
 
-<p>By default, <strong>Available Packages</strong> only shows the default
-repository site, which offers platforms, SDK tools, documentation, the
-Google APIs Add-on, and other components. You can add other sites that host
+<p>By default, <strong>Available Packages</strong> displays components available from the
+<em>Android Repository</em> and <em>Third party Add-ons</em>. You can add other sites that host
 their own Android SDK add-ons, then download the SDK add-ons
 from those sites.</p>
 
 <p>For example, a mobile carrier or device manufacturer might offer additional
 API libraries that are supported by their own Android-powered devices. In order
-to develop using their libraries, you must install their Android SDK add-on. </p>
+to develop using their libraries, you must install their Android SDK add-on, if it's not already
+available under <em>Third party Add-ons</em>. </p>
 
 <p>If a carrier or device manufacturer has hosted an SDK add-on repository file
 on their web site, follow these steps to add their site to the SDK and AVD
@@ -178,11 +183,12 @@
 
 <ol>
   <li>Select <strong>Available Packages</strong> in the left panel.</li>
-  <li>Click <strong>Add Site</strong> and enter the URL of the
+  <li>Click <strong>Add Add-on Site</strong> and enter the URL of the
 {@code repository.xml} file. Click <strong>OK</strong>.</li>
 </ol>
-<p>Any SDK components available from the site will now be listed under
-<strong>Available Packages</strong>.</p>
+<p>Any SDK components available from the site will now be listed under a new item named
+<strong>User Add-ons</strong>.</p>
+
 
 <h2 id="troubleshooting">Troubleshooting</h2>
 
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 3dda5ee..8b77303 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -23,7 +23,8 @@
 
 <ol>
   <li>Prepare your development computer and ensure it meets the system requirements.</li>
-  <li>Install the SDK starter package from the table above.</li>
+  <li>Install the SDK starter package from the table above. (If you're on Windows, download the
+installer for help with the initial setup.)</li>
   <li>Install the ADT Plugin for Eclipse (if you'll be developing in Eclipse).</li>
   <li>Add Android platforms and other components to your SDK.</li>
   <li>Explore the contents of the Android SDK (optional).</li>
diff --git a/docs/html/sdk/installing.jd b/docs/html/sdk/installing.jd
index 2f19181..4cb1bb2 100644
--- a/docs/html/sdk/installing.jd
+++ b/docs/html/sdk/installing.jd
@@ -56,6 +56,7 @@
     <li><a href="#InstallingADT">3. Installing the ADT Plugin for Eclipse</a></li>
     <li><a href="#components">4. Adding Platforms and Other Components</a>
       <ol>
+        <li><a href="#components">Available Components</a></li>
         <li><a href="#which">Recommended Components</a></li>
       </ol></li>
     <li><a href="#sdkContents">5. Exploring the SDK (Optional)</a></li>
@@ -119,52 +120,14 @@
 it to a safe location on your machine. By default, the SDK files are unpacked
 into a directory named <code>android-sdk-&lt;machine-platform&gt;</code>.</p>
 
-<p>Make a note of the name and
-location of the unpacked SDK directory on your system&mdash;you will need to
+<p>If you downloaded the Windows installer ({@code .exe} file), run it now and it will check
+whether the proper Java SE Development Kit (JDK) is installed (installing it, if necessary), then
+install the SDK Tools into a default location (which you can modify).</p>
+
+<p>Make a note of the name and location of the SDK directory on your system&mdash;you will need to
 refer to the SDK directory later, when setting up the ADT plugin and when using
 the SDK tools from command line.</p>
 
-<p>Optionally, you might want to add the location of the SDK's
-<code>tools/</code> directory and {@code platform-tools/} directory  to your system
-<code>PATH</code>. Both tool directories are located at the root of the SDK folder.
-
-
-<div class="toggleable closed">
-  <a href="#" onclick="return toggleDiv(this)">
-        <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
-width="9px" />
-        How to update your PATH</a>
-  <div class="toggleme">
-
-<p>Adding
-<code>tools/</code> and {@code platform-tools/} to your path lets you run Android Debug Bridge (adb)
-and the other command line <a
-href="{@docRoot}guide/developing/tools/index.html">tools</a> without needing to
-supply the full path to the tool directories. </p>
-
-<ul>
-    <li>On Linux, edit your <code>~/.bash_profile</code> or <code>~/.bashrc</code> file. Look
-    for a line that sets the PATH environment variable and add the
-    full path to the <code>tools/</code> and {@code platform-tools/} directories to it. If you don't
-    see a line setting the path, you can add one:
-
-    <pre>export PATH=${PATH}:&lt;your_sdk_dir&gt;/tools:&lt;your_sdk_dir&gt;/platform-tools</pre>
-    </li>
-
-    <li>On a Mac OS X, look in your home directory for <code>.bash_profile</code> and
-    proceed as for Linux. You can create the <code>.bash_profile</code> if
-    you haven't already set one up on your machine. </li>
-
-    <li>On Windows, right-click on My Computer, and select Properties.
-  Under the Advanced tab, hit the Environment Variables button, and in the
-  dialog that comes up, double-click on Path (under System Variables). Add the full path to the
-  <code>tools/</code> and {@code platform-tools/} directories to the path. </li>
-  </ul>
-
-</div><!-- end toggleme -->
-</div><!-- end toggleable -->
-
-
 
 <h2 id="InstallingADT">Step 3. Installing the ADT Plugin for Eclipse</h2>
 
@@ -204,28 +167,40 @@
 (tools that the latest platform depend upon). However, downloading
 additional components is highly recommended.</p>
 
+<p>If you used the Windows installer, when you complete the installation wizard, it will launch the
+Android SDK and AVD Manager with a default set of platforms and other components selected
+for you to install. Simply click <strong>Install</strong> to accept the recommended set of
+components and install them. You can then skip to <a href="#sdkContents">Step 5</a>, but we
+recommend you first read the section about the <a href="#components">Available Components</a> to
+better understand the components available from the Android SDK and AVD Manager.</p>
+
 <p>You can launch the Android SDK and AVD Manager in one of the following ways:</p>
 <ul>
   <li>From within Eclipse, select <strong>Window &gt; Android SDK and AVD Manager</strong>.</li>
   <li>On Windows, double-click the <code>SDK Manager.ext</code> file at the root of the Android
 SDK directory.</li>
   <li>On Mac or Linux, open a terminal and navigate to the <code>tools/</code> directory in the
-Android SDK, then execute: <pre>android update sdk</pre> <p>This will automatically select
-the required and recommended components for you to install.</p></li>
+Android SDK, then execute: <pre>android</pre> </li>
 </ul>
 
 <p>To download components, use the graphical UI of the Android SDK and AVD
 Manager, shown in Figure 1, to browse the SDK repository and select new or updated
 components. The Android SDK and AVD Manager will install the selected components in
 your SDK environment. For information about which components you should download, see the following
-section about <a href="#which">Recommended Components</a></p>
+section about <a href="#which">Recommended Components</a>.</p>
 
 <img src="/images/sdk_manager_packages.png" />
 <p class="img-caption"><strong>Figure 1.</strong> The Android SDK and AVD Manager's
 <strong>Available Packages</strong> panel, which shows the SDK components that are
 available for you to download into your environment.</p>
 
-<p>The SDK repository offers these types of components:</p>
+
+<h3 id="components">Available Components</h3>
+
+<p>By default, there are two repositories of components for your SDK: <em>Android
+Repository</em> and <em>Third party Add-ons</em>.</p>
+
+<p>The <em>Android Repository</em> offers these types of components:</p>
 
 <ul>
 <li><strong>SDK Tools</strong> (pre-installed in the Android SDK starter
@@ -249,20 +224,14 @@
 detailed information about each platform, see the overview documents available
 under the section "Downloadable SDK Components," at left. </li>
 
-<li><strong>SDK Add-Ons</strong> &mdash; SDK add-ons provide a development
-environment for specific Android external
-library or a customized (but fully compliant) Android system image.  The Android
-SDK repository offers the Google APIs Add-On, which gives your application
-access to powerful mapping capabilities through the
-<code>com.google.android.maps</code> library. You can also add additional
-repositories, so that you can download other SDK add-ons, where available. </li>
-
-<li><strong>USB Driver for Windows</strong> &mdash; Contains driver files
+<li><strong>USB Driver for Windows</strong> (Windows only) &mdash; Contains driver files
 that you can install on your Windows computer, so that you can run and debug
 your applications on an actual device. You <em>do not</em> need the USB driver unless
 you plan to debug your application on an actual Android-powered device. If you
 develop on Mac OS X or Linux, you do not need a special driver to debug
-your application on an Android-powered device.</li>
+your application on an Android-powered device. (See <a
+href="{@docRoot}guide/developing/device.html">Developing on a Device</a> for more information
+about developing on a real device.)</li>
 
 <li><strong>Samples</strong> &mdash; Contains the sample code and apps available
 for each Android development platform. If you are just getting started with
@@ -275,6 +244,11 @@
 multiversion documentation for the Android framework API. </li>
 </ul>
 
+<p>The <em>Third party Add-ons</em> provide components that allow you to create a development
+environment using a specific Android external library (such as the Google Maps library) or a
+customized (but fully compliant) Android system image. You can add additional Add-on repositories,
+by clicking <strong>Add Add-on Site</strong>.</p>
+
 
 <h3 id="which">Recommended Components</h3>
 
@@ -496,6 +470,47 @@
 
 </table>
 
+
+<p>Optionally, you might want to add the location of the SDK's <code>tools/</code> and
+<code>platform-tools</code> to your <code>PATH</code> environment variable, to provide easy
+access to the tools.</p>
+
+
+<div class="toggleable closed">
+  <a href="#" onclick="return toggleDiv(this)">
+        <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-img" height="9px"
+width="9px" />
+        How to update your PATH</a>
+  <div class="toggleme">
+
+<p>Adding both <code>tools/</code> and <code>platform-tools/</code> to your PATH lets you run
+command line <a href="{@docRoot}guide/developing/tools/index.html">tools</a> without needing to
+supply the full path to the tool directories. Depending on your operating system, you can
+include these directories in your PATH in the following way:</p>
+
+<ul>
+
+  <li>On Windows, right-click on My Computer, and select Properties.
+  Under the Advanced tab, hit the Environment Variables button, and in the
+  dialog that comes up, double-click on Path (under System Variables). Add the full path to the
+  <code>tools/</code> and <code>platform-tools/</code> directories to the path. </li>
+
+  <li>On Linux, edit your <code>~/.bash_profile</code> or <code>~/.bashrc</code> file. Look
+  for a line that sets the PATH environment variable and add the
+  full path to the <code>tools/</code> and <code>platform-tools</code> directories to it. If you
+  don't see a line setting the path, you can add one:
+  <pre>export PATH=${PATH}:&lt;sdk&gt;/tools:&lt;sdk&gt;/platform-tools</pre>
+  </li>
+
+  <li>On a Mac OS X, look in your home directory for <code>.bash_profile</code> and
+  proceed as for Linux. You can create the <code>.bash_profile</code> if
+  you don't already have one. </li>
+</ul>
+
+</div><!-- end toggleme -->
+</div><!-- end toggleable -->
+
+
 <h2 id="NextSteps">Next Steps</h2>
 <p>Once you have completed installation, you are ready to
 begin developing applications. Here are a few ways you can get started: </p>
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 32111e8..032244f 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -174,11 +174,14 @@
     }
     
     private void setBitmap(Bitmap bitmap) {
-        mBitmap = bitmap;
-        if (bitmap != null) {
-            computeBitmapSize();
-        } else {
-            mBitmapWidth = mBitmapHeight = -1;
+        if (bitmap != mBitmap) {
+            mBitmap = bitmap;
+            if (bitmap != null) {
+                computeBitmapSize();
+            } else {
+                mBitmapWidth = mBitmapHeight = -1;
+            }
+            invalidateSelf();
         }
     }
 
@@ -205,10 +208,7 @@
      * @see android.graphics.Bitmap#getDensity()
      */
     public void setTargetDensity(DisplayMetrics metrics) {
-        mTargetDensity = metrics.densityDpi;
-        if (mBitmap != null) {
-            computeBitmapSize();
-        }
+        setTargetDensity(metrics.densityDpi);
     }
 
     /**
@@ -220,9 +220,12 @@
      * @see android.graphics.Bitmap#getDensity()
      */
     public void setTargetDensity(int density) {
-        mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
-        if (mBitmap != null) {
-            computeBitmapSize();
+        if (mTargetDensity != density) {
+            mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
+            if (mBitmap != null) {
+                computeBitmapSize();
+            }
+            invalidateSelf();
         }
     }
 
@@ -239,22 +242,28 @@
      * @param gravity the gravity
      */
     public void setGravity(int gravity) {
-        mBitmapState.mGravity = gravity;
-        mApplyGravity = true;
+        if (mBitmapState.mGravity != gravity) {
+            mBitmapState.mGravity = gravity;
+            mApplyGravity = true;
+            invalidateSelf();
+        }
     }
 
     public void setAntiAlias(boolean aa) {
         mBitmapState.mPaint.setAntiAlias(aa);
+        invalidateSelf();
     }
     
     @Override
     public void setFilterBitmap(boolean filter) {
         mBitmapState.mPaint.setFilterBitmap(filter);
+        invalidateSelf();
     }
 
     @Override
     public void setDither(boolean dither) {
         mBitmapState.mPaint.setDither(dither);
+        invalidateSelf();
     }
 
     public Shader.TileMode getTileModeX() {
@@ -280,6 +289,7 @@
             state.mTileModeX = xmode;
             state.mTileModeY = ymode;
             mRebuildShader = true;
+            invalidateSelf();
         }
     }
 
@@ -336,11 +346,13 @@
     @Override
     public void setAlpha(int alpha) {
         mBitmapState.mPaint.setAlpha(alpha);
+        invalidateSelf();
     }
 
     @Override
     public void setColorFilter(ColorFilter cf) {
         mBitmapState.mPaint.setColorFilter(cf);
+        invalidateSelf();
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 289348a..4d560be 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -87,7 +87,10 @@
      * @param color The color to draw.
      */
     public void setColor(int color) {
-        mState.mBaseColor = mState.mUseColor = color;
+        if (mState.mBaseColor != color || mState.mUseColor != color) {
+            invalidateSelf();
+            mState.mBaseColor = mState.mUseColor = color;
+        }
     }
 
     /**
@@ -109,6 +112,7 @@
         int baseAlpha = mState.mBaseColor >>> 24;
         int useAlpha = baseAlpha * alpha >> 8;
         mState.mUseColor = (mState.mBaseColor << 8 >>> 8) | (useAlpha << 24);
+        invalidateSelf();
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index baa9d62..2f13bef 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -488,7 +488,10 @@
      */
     public boolean setVisible(boolean visible, boolean restart) {
         boolean changed = mVisible != visible;
-        mVisible = visible;
+        if (changed) {
+            mVisible = visible;
+            invalidateSelf();
+        }
         return changed;
     }
 
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index c558632..da8bb1b 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -180,6 +180,7 @@
     public void setCornerRadii(float[] radii) {
         mGradientState.setCornerRadii(radii);
         mPathIsDirty = true;
+        invalidateSelf();
     }
     
     /**
@@ -189,6 +190,7 @@
     public void setCornerRadius(float radius) {
         mGradientState.setCornerRadius(radius);
         mPathIsDirty = true;
+        invalidateSelf();
     }
     
     /**
@@ -214,34 +216,41 @@
             e = new DashPathEffect(new float[] { dashWidth, dashGap }, 0);
         }
         mStrokePaint.setPathEffect(e);
+        invalidateSelf();
     }
     
     public void setSize(int width, int height) {
         mGradientState.setSize(width, height);
         mPathIsDirty = true;
+        invalidateSelf();
     }
     
     public void setShape(int shape) {
         mRingPath = null;
         mPathIsDirty = true;
         mGradientState.setShape(shape);
+        invalidateSelf();
     }
 
     public void setGradientType(int gradient) {
         mGradientState.setGradientType(gradient);
         mRectIsDirty = true;
+        invalidateSelf();
     }
 
     public void setGradientCenter(float x, float y) {
         mGradientState.setGradientCenter(x, y);
+        invalidateSelf();
     }
 
     public void setGradientRadius(float gradientRadius) {
         mGradientState.setGradientRadius(gradientRadius);
+        invalidateSelf();
     }
 
     public void setUseLevel(boolean useLevel) {
         mGradientState.mUseLevel = useLevel;
+        invalidateSelf();
     }
     
     private int modulateAlpha(int alpha) {
@@ -433,6 +442,7 @@
     public void setColor(int argb) {
         mGradientState.setSolidColor(argb);
         mFillPaint.setColor(argb);
+        invalidateSelf();
     }
 
     @Override
@@ -443,17 +453,26 @@
     
     @Override
     public void setAlpha(int alpha) {
-        mAlpha = alpha;
+        if (alpha != mAlpha) {
+            mAlpha = alpha;
+            invalidateSelf();
+        }
     }
 
     @Override
     public void setDither(boolean dither) {
-        mDither = dither;
+        if (dither != mDither) {
+            mDither = dither;
+            invalidateSelf();
+        }
     }
 
     @Override
     public void setColorFilter(ColorFilter cf) {
-        mColorFilter = cf;
+        if (cf != mColorFilter) {
+            mColorFilter = cf;
+            invalidateSelf();
+        }
     }
 
     @Override
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 501cca9..b6cce7e 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -21,7 +21,10 @@
 
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.graphics.*;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
 
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 50b4b75..35b8319 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -132,10 +132,7 @@
      * @see android.graphics.Bitmap#getDensity()
      */
     public void setTargetDensity(DisplayMetrics metrics) {
-        mTargetDensity = metrics.densityDpi;
-        if (mNinePatch != null) {
-            computeBitmapSize();
-        }
+        setTargetDensity(metrics.densityDpi);
     }
 
     /**
@@ -147,9 +144,12 @@
      * @see android.graphics.Bitmap#getDensity()
      */
     public void setTargetDensity(int density) {
-        mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
-        if (mNinePatch != null) {
-            computeBitmapSize();
+        if (density != mTargetDensity) {
+            mTargetDensity = density == 0 ? DisplayMetrics.DENSITY_DEFAULT : density;
+            if (mNinePatch != null) {
+                computeBitmapSize();
+            }
+            invalidateSelf();
         }
     }
 
@@ -197,16 +197,19 @@
     @Override
     public void setAlpha(int alpha) {
         getPaint().setAlpha(alpha);
+        invalidateSelf();
     }
     
     @Override
     public void setColorFilter(ColorFilter cf) {
         getPaint().setColorFilter(cf);
+        invalidateSelf();
     }
 
     @Override
     public void setDither(boolean dither) {
         getPaint().setDither(dither);
+        invalidateSelf();
     }
 
     @Override
diff --git a/graphics/java/android/graphics/drawable/PaintDrawable.java b/graphics/java/android/graphics/drawable/PaintDrawable.java
index c86fc46..c71cda1 100644
--- a/graphics/java/android/graphics/drawable/PaintDrawable.java
+++ b/graphics/java/android/graphics/drawable/PaintDrawable.java
@@ -66,6 +66,7 @@
         } else {
             setShape(new RoundRectShape(radii, null, null));
         }
+        invalidateSelf();
     }
 
     @Override
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index b623d80..dcaf20b 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -95,6 +95,8 @@
         float sw = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleWidth);
         float sh = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleHeight);
         int g = a.getInt(com.android.internal.R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT);
+        boolean min = a.getBoolean(
+                com.android.internal.R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false);
         Drawable dr = a.getDrawable(com.android.internal.R.styleable.ScaleDrawable_drawable);
 
         a.recycle();
@@ -116,6 +118,7 @@
         mScaleState.mScaleWidth = sw;
         mScaleState.mScaleHeight = sh;
         mScaleState.mGravity = g;
+        mScaleState.mUseIntrinsicSizeAsMin = min;
         if (dr != null) {
             dr.setCallback(this);
         }
@@ -206,15 +209,16 @@
     @Override
     protected void onBoundsChange(Rect bounds) {
         final Rect r = mTmpRect;
+        final boolean min = mScaleState.mUseIntrinsicSizeAsMin;
         int level = getLevel();
         int w = bounds.width();
-        final int iw = 0; //mScaleState.mDrawable.getIntrinsicWidth();
         if (mScaleState.mScaleWidth > 0) {
+            final int iw = min ? mScaleState.mDrawable.getIntrinsicWidth() : 0;
             w -= (int) ((w - iw) * (10000 - level) * mScaleState.mScaleWidth / 10000);
         }
         int h = bounds.height();
-        final int ih = 0; //mScaleState.mDrawable.getIntrinsicHeight();
         if (mScaleState.mScaleHeight > 0) {
+            final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0;
             h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000);
         }
         Gravity.apply(mScaleState.mGravity, w, h, bounds, r);
@@ -258,6 +262,7 @@
         float mScaleWidth;
         float mScaleHeight;
         int mGravity;
+        boolean mUseIntrinsicSizeAsMin;
 
         private boolean mCheckedConstantState;
         private boolean mCanConstantState;
@@ -273,6 +278,7 @@
                 mScaleWidth = orig.mScaleWidth;
                 mScaleHeight = orig.mScaleHeight;
                 mGravity = orig.mGravity;
+                mUseIntrinsicSizeAsMin = orig.mUseIntrinsicSizeAsMin;
                 mCheckedConstantState = mCanConstantState = true;
             }
         }
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index be1892e..92252fc 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -129,6 +129,7 @@
             }
             mShapeState.mPadding.set(left, top, right, bottom);
         }
+        invalidateSelf();
     }
     
     /**
@@ -144,6 +145,7 @@
             }
             mShapeState.mPadding.set(padding);
         }
+        invalidateSelf();
     }
     
     /**
@@ -153,6 +155,7 @@
      */
     public void setIntrinsicWidth(int width) {
         mShapeState.mIntrinsicWidth = width;
+        invalidateSelf();
     }
     
     /**
@@ -162,6 +165,7 @@
      */
     public void setIntrinsicHeight(int height) {
         mShapeState.mIntrinsicHeight = height;
+        invalidateSelf();
     }
     
     @Override
@@ -236,11 +240,13 @@
      */
     @Override public void setAlpha(int alpha) {
         mShapeState.mAlpha = alpha;
+        invalidateSelf();
     }
     
     @Override
     public void setColorFilter(ColorFilter cf) {
         mShapeState.mPaint.setColorFilter(cf);
+        invalidateSelf();
     }
     
     @Override
@@ -264,6 +270,7 @@
     @Override
     public void setDither(boolean dither) {
         mShapeState.mPaint.setDither(dither);
+        invalidateSelf();
     }
 
     @Override
@@ -344,6 +351,7 @@
                 mShapeState.mPaint.setShader(mShapeState.mShaderFactory.resize(w, h));
             }
         }
+        invalidateSelf();
     }
     
     @Override
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 1081c35..cce2400 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -472,7 +472,7 @@
     AudioParameter(const String8& keyValuePairs);
     virtual ~AudioParameter();
 
-    // reserved parameter keys for changeing standard parameters with setParameters() function.
+    // reserved parameter keys for changing standard parameters with setParameters() function.
     // Using these keys is mandatory for AudioFlinger to properly monitor audio output/input
     // configuration changes and act accordingly.
     //  keyRouting: to change audio routing, value is an int in AudioSystem::audio_devices
@@ -480,11 +480,14 @@
     //  keyFormat: to change audio format, value is an int in AudioSystem::audio_format
     //  keyChannels: to change audio channel configuration, value is an int in AudioSystem::audio_channels
     //  keyFrameCount: to change audio output frame count, value is an int
+    //  keyInputSource: to change audio input source, value is an int in audio_source
+    //     (defined in media/mediarecorder.h)
     static const char *keyRouting;
     static const char *keySamplingRate;
     static const char *keyFormat;
     static const char *keyChannels;
     static const char *keyFrameCount;
+    static const char *keyInputSource;
 
     String8 toString();
 
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 517868c..0aba347 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -293,6 +293,8 @@
             uint32_t flags,
             Vector<String8> *matchingCodecs);
 
+    void restorePatchedDataPointer(BufferInfo *info);
+
     OMXCodec(const OMXCodec &);
     OMXCodec &operator=(const OMXCodec &);
 };
@@ -305,6 +307,7 @@
 struct CodecCapabilities {
     String8 mComponentName;
     Vector<CodecProfileLevel> mProfileLevels;
+    Vector<OMX_U32> mColorFormats;
 };
 
 // Return a vector of componentNames with supported profile/level pairs
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index d6ae5e9..9d589cf 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -285,6 +285,8 @@
     uint32_t getTransform(int buffer) const;
 
     status_t resize(int newNumBuffers);
+    status_t grow(int newNumBuffers);
+    status_t shrink(int newNumBuffers);
 
     SharedBufferStack::Statistics getStats() const;
     
@@ -346,6 +348,14 @@
     int mNumBuffers;
     BufferList mBufferList;
 
+    struct BuffersAvailableCondition : public ConditionBase {
+        int mNumBuffers;
+        inline BuffersAvailableCondition(SharedBufferServer* sbs,
+                int numBuffers);
+        inline bool operator()() const;
+        inline const char* name() const { return "BuffersAvailableCondition"; }
+    };
+
     struct UnlockUpdate : public UpdateBase {
         const int lockedBuffer;
         inline UnlockUpdate(SharedBufferBase* sbb, int lockedBuffer);
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index d09ff41..15a3925 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -219,6 +219,8 @@
      * motion events to be delivered to them with AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED.
      */
     bool isTrustedOverlay() const;
+
+    bool supportsSplitTouch() const;
 };
 
 
@@ -946,7 +948,7 @@
     struct TouchedWindow {
         const InputWindow* window;
         int32_t targetFlags;
-        BitSet32 pointerIds;
+        BitSet32 pointerIds;        // zero unless target flag FLAG_SPLIT is set
         sp<InputChannel> channel;
     };
     struct TouchState {
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index 73f5863..be7db1f 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -189,6 +189,28 @@
     { "NUMPAD_LEFT_PAREN", 162 },
     { "NUMPAD_RIGHT_PAREN", 163 },
     { "VOLUME_MUTE", 164 },
+    { "INFO", 165 },
+    { "CHANNEL_UP", 166 },
+    { "CHANNEL_DOWN", 167 },
+    { "ZOOM_IN", 168 },
+    { "ZOOM_OUT", 169 },
+    { "TV", 170 },
+    { "WINDOW", 171 },
+    { "GUIDE", 172 },
+    { "DVR", 173 },
+    { "BOOKMARK", 174 },
+    { "CAPTIONS", 175 },
+    { "SETTINGS", 176 },
+    { "TV_POWER", 177 },
+    { "TV_INPUT", 178 },
+    { "STB_POWER", 179 },
+    { "STB_INPUT", 180 },
+    { "AVR_POWER", 181 },
+    { "AVR_INPUT", 182 },
+    { "PROG_RED", 183 },
+    { "PROG_GREEN", 184 },
+    { "PROG_YELLOW", 185 },
+    { "PROG_BLUE", 186 },
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/keystore/java/android/security/SystemKeyStore.java b/keystore/java/android/security/SystemKeyStore.java
index 47718e6..bca8f68 100644
--- a/keystore/java/android/security/SystemKeyStore.java
+++ b/keystore/java/android/security/SystemKeyStore.java
@@ -20,8 +20,6 @@
 import android.os.FileUtils;
 import android.os.Process;
 
-import org.apache.harmony.luni.util.InputStreamHelper;
-
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -32,6 +30,8 @@
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
 
+import libcore.io.IoUtils;
+
 /**
  *@hide
  */
@@ -117,13 +117,10 @@
 
     public byte[] retrieveKey(String keyName) throws IOException {
         File keyFile = getKeyFile(keyName);
-
         if (!keyFile.exists()) {
             return null;
         }
-
-        FileInputStream fis = new FileInputStream(keyFile);
-        return InputStreamHelper.readFullyAndClose(fis);
+        return IoUtils.readFileAsByteArray(keyFile.toString());
     }
 
     public void deleteKey(String keyName) {
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 248e054..40dd117 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -19,6 +19,7 @@
 #include <utils/Log.h>
 
 #include "Caches.h"
+#include "Properties.h"
 
 namespace android {
 
@@ -49,6 +50,9 @@
 
     mCurrentBuffer = meshBuffer;
     mRegionMesh = NULL;
+
+    mDebugLevel = readDebugLevel();
+    LOGD("Enabling debug mode %d", mDebugLevel);
 }
 
 Caches::~Caches() {
@@ -91,6 +95,16 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// Memory management
+///////////////////////////////////////////////////////////////////////////////
+
+void Caches::clearGarbage() {
+    textureCache.clearGarbage();
+    gradientCache.clearGarbage();
+    pathCache.clearGarbage();
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // VBO
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 77bbcd1..e8ced9c 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -83,7 +83,7 @@
 
     friend class Singleton<Caches>;
 
-    CacheLogger mlogger;
+    CacheLogger mLogger;
 
     GLuint mCurrentBuffer;
 
@@ -93,6 +93,20 @@
 
 public:
     /**
+     * Indicates whether the renderer is in debug mode.
+     * This debug mode provides limited information to app developers.
+     */
+    DebugLevel getDebugLevel() const {
+        return mDebugLevel;
+    }
+
+    /**
+     * Call this on each frame to ensure that garbage is deleted from
+     * GPU memory.
+     */
+    void clearGarbage();
+
+    /**
      * Binds the VBO used to render simple textured quads.
      */
     void bindMeshBuffer();
@@ -145,6 +159,9 @@
     ResourceCache resourceCache;
 
     Line line;
+
+private:
+    DebugLevel mDebugLevel;
 }; // class Caches
 
 }; // namespace uirenderer
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index d08df44..77d628a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -153,13 +153,13 @@
     mPaints.clear();
 
     for (size_t i = 0; i < mMatrices.size(); i++) {
-        delete  mMatrices.itemAt(i);
+        delete mMatrices.itemAt(i);
     }
     mMatrices.clear();
 
     if (mPathHeap) {
         for (int i = 0; i < mPathHeap->count(); i++) {
-            caches.pathCache.remove(&(*mPathHeap)[i]);
+            caches.pathCache.removeDeferred(&(*mPathHeap)[i]);
         }
         mPathHeap->safeUnref();
     }
diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp
index 97f4cb4..a37964e 100644
--- a/libs/hwui/GradientCache.cpp
+++ b/libs/hwui/GradientCache.cpp
@@ -54,7 +54,6 @@
 }
 
 GradientCache::~GradientCache() {
-    Mutex::Autolock _l(mLock);
     mCache.clear();
 }
 
@@ -63,17 +62,14 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 uint32_t GradientCache::getSize() {
-    Mutex::Autolock _l(mLock);
     return mSize;
 }
 
 uint32_t GradientCache::getMaxSize() {
-    Mutex::Autolock _l(mLock);
     return mMaxSize;
 }
 
 void GradientCache::setMaxSize(uint32_t maxSize) {
-    Mutex::Autolock _l(mLock);
     mMaxSize = maxSize;
     while (mSize > mMaxSize) {
         mCache.removeOldest();
@@ -102,17 +98,28 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 Texture* GradientCache::get(SkShader* shader) {
-    Mutex::Autolock _l(mLock);
     return mCache.get(shader);
 }
 
 void GradientCache::remove(SkShader* shader) {
-    Mutex::Autolock _l(mLock);
     mCache.remove(shader);
 }
 
-void GradientCache::clear() {
+void GradientCache::removeDeferred(SkShader* shader) {
     Mutex::Autolock _l(mLock);
+    mGarbage.push(shader);
+}
+
+void GradientCache::clearGarbage() {
+    Mutex::Autolock _l(mLock);
+    size_t count = mGarbage.size();
+    for (size_t i = 0; i < count; i++) {
+        mCache.remove(mGarbage.itemAt(i));
+    }
+    mGarbage.clear();
+}
+
+void GradientCache::clear() {
     mCache.clear();
 }
 
@@ -138,21 +145,17 @@
 
     canvas.drawRectCoords(0.0f, 0.0f, bitmap.width(), 1.0f, p);
 
-    mLock.lock();
     // Asume the cache is always big enough
     const uint32_t size = bitmap.rowBytes() * bitmap.height();
     while (mSize + size > mMaxSize) {
         mCache.removeOldest();
     }
-    mLock.unlock();
 
     Texture* texture = new Texture;
     generateTexture(&bitmap, texture);
 
-    mLock.lock();
     mSize += size;
     mCache.put(shader, texture);
-    mLock.unlock();
 
     return texture;
 }
diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h
index c9553f4..30da462 100644
--- a/libs/hwui/GradientCache.h
+++ b/libs/hwui/GradientCache.h
@@ -19,6 +19,8 @@
 
 #include <SkShader.h>
 
+#include <utils/Vector.h>
+
 #include "Texture.h"
 #include "utils/GenerationCache.h"
 
@@ -53,11 +55,20 @@
      */
     Texture* get(SkShader* shader);
     /**
-     * Removes the texture associated with the specified shader. Returns NULL
-     * if the texture cannot be found. Upon remove the texture is freed.
+     * Removes the texture associated with the specified shader.
+     * Upon remove the texture is freed.
      */
     void remove(SkShader* shader);
     /**
+     * Removes the texture associated with the specified shader. This is meant
+     * to be called from threads that are not the EGL context thread.
+     */
+    void removeDeferred(SkShader* shader);
+    /**
+     * Process deferred removals.
+     */
+    void clearGarbage();
+    /**
      * Clears the cache. This causes all textures to be deleted.
      */
     void clear();
@@ -83,10 +94,7 @@
     uint32_t mSize;
     uint32_t mMaxSize;
 
-    /**
-     * Used to access mCache and mSize. All methods are accessed from a single
-     * thread except for remove().
-     */
+    Vector<SkShader*> mGarbage;
     mutable Mutex mLock;
 }; // class GradientCache
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 19a5973..ad72584 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -135,6 +135,8 @@
 }
 
 void OpenGLRenderer::prepare(bool opaque) {
+    mCaches.clearGarbage();
+
     mSnapshot = new Snapshot(mFirstSnapshot,
             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
     mSaveCount = 1;
@@ -163,6 +165,10 @@
 #endif
 #if DEBUG_MEMORY_USAGE
     mCaches.dumpMemoryUsage();
+#else
+    if (mCaches.getDebugLevel() & kDebugMemory) {
+        mCaches.dumpMemoryUsage();
+    }
 #endif
 }
 
@@ -1459,7 +1465,9 @@
             dirtyLayer(left, top, right, bottom);
         }
     }
-    mCaches.currentProgram->setColor(r, g, b, a);
+    if (!mShader || (mShader && setColor)) {
+        mCaches.currentProgram->setColor(r, g, b, a);
+    }
 
     // Setup attributes and uniforms required by the shaders
     if (mShader) {
diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp
index 04d07db..8740a64 100644
--- a/libs/hwui/PathCache.cpp
+++ b/libs/hwui/PathCache.cpp
@@ -53,7 +53,6 @@
 }
 
 PathCache::~PathCache() {
-    Mutex::Autolock _l(mLock);
     mCache.clear();
 }
 
@@ -63,6 +62,8 @@
     GLint maxTextureSize;
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
     mMaxTextureSize = maxTextureSize;
+
+    mDebugEnabled = readDebugLevel() & kDebugCaches;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -70,17 +71,14 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 uint32_t PathCache::getSize() {
-    Mutex::Autolock _l(mLock);
     return mSize;
 }
 
 uint32_t PathCache::getMaxSize() {
-    Mutex::Autolock _l(mLock);
     return mMaxSize;
 }
 
 void PathCache::setMaxSize(uint32_t maxSize) {
-    Mutex::Autolock _l(mLock);
     mMaxSize = maxSize;
     while (mSize > mMaxSize) {
         mCache.removeOldest();
@@ -92,51 +90,69 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void PathCache::operator()(PathCacheEntry& path, PathTexture*& texture) {
-    if (texture) {
-        const uint32_t size = texture->width * texture->height;
-        mSize -= size;
-
-        PATH_LOGD("PathCache::callback: delete path: name, size, mSize = %d, %d, %d",
-                texture->id, size, mSize);
-
-        glDeleteTextures(1, &texture->id);
-        delete texture;
-    }
+    removeTexture(texture);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 // Caching
 ///////////////////////////////////////////////////////////////////////////////
 
-void PathCache::remove(SkPath* path) {
-    Mutex::Autolock _l(mLock);
+void PathCache::removeTexture(PathTexture* texture) {
+    if (texture) {
+        const uint32_t size = texture->width * texture->height;
+        mSize -= size;
 
+        PATH_LOGD("PathCache::callback: delete path: name, size, mSize = %d, %d, %d",
+                texture->id, size, mSize);
+        if (mDebugEnabled) {
+            LOGD("Path deleted, size = %d", size);
+        }
+
+        glDeleteTextures(1, &texture->id);
+        delete texture;
+    }
+}
+
+void PathCache::remove(SkPath* path) {
     // TODO: Linear search...
     Vector<uint32_t> pathsToRemove;
     for (uint32_t i = 0; i < mCache.size(); i++) {
         if (mCache.getKeyAt(i).path == path) {
             pathsToRemove.push(i);
+            removeTexture(mCache.getValueAt(i));
         }
     }
 
+    mCache.setOnEntryRemovedListener(NULL);
     for (size_t i = 0; i < pathsToRemove.size(); i++) {
         mCache.removeAt(pathsToRemove.itemAt(i));
     }
+    mCache.setOnEntryRemovedListener(this);
+}
+
+void PathCache::removeDeferred(SkPath* path) {
+    Mutex::Autolock _l(mLock);
+    mGarbage.push(path);
+}
+
+void PathCache::clearGarbage() {
+    Mutex::Autolock _l(mLock);
+    size_t count = mGarbage.size();
+    for (size_t i = 0; i < count; i++) {
+        remove(mGarbage.itemAt(i));
+    }
+    mGarbage.clear();
 }
 
 PathTexture* PathCache::get(SkPath* path, SkPaint* paint) {
     PathCacheEntry entry(path, paint);
 
-    mLock.lock();
     PathTexture* texture = mCache.get(entry);
-    mLock.unlock();
 
     if (!texture) {
         texture = addTexture(entry, path, paint);
     } else if (path->getGenerationID() != texture->generation) {
-        mLock.lock();
         mCache.remove(entry);
-        mLock.unlock();
         texture = addTexture(entry, path, paint);
     }
 
@@ -162,11 +178,9 @@
     const uint32_t size = width * height;
     // Don't even try to cache a bitmap that's bigger than the cache
     if (size < mMaxSize) {
-        mLock.lock();
         while (mSize + size > mMaxSize) {
             mCache.removeOldest();
         }
-        mLock.unlock();
     }
 
     PathTexture* texture = new PathTexture;
@@ -195,12 +209,13 @@
     generateTexture(bitmap, texture);
 
     if (size < mMaxSize) {
-        mLock.lock();
         mSize += size;
         PATH_LOGD("PathCache::get: create path: name, size, mSize = %d, %d, %d",
                 texture->id, size, mSize);
+        if (mDebugEnabled) {
+            LOGD("Path created, size = %d", size);
+        }
         mCache.put(entry, texture);
-        mLock.unlock();
     } else {
         texture->cleanup = true;
     }
@@ -209,7 +224,6 @@
 }
 
 void PathCache::clear() {
-    Mutex::Autolock _l(mLock);
     mCache.clear();
 }
 
diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h
index 23aa7ef..ae2e55d 100644
--- a/libs/hwui/PathCache.h
+++ b/libs/hwui/PathCache.h
@@ -21,6 +21,8 @@
 #include <SkPaint.h>
 #include <SkPath.h>
 
+#include <utils/Vector.h>
+
 #include "Debug.h"
 #include "Texture.h"
 #include "utils/Compare.h"
@@ -146,6 +148,15 @@
      * Removes an entry.
      */
     void remove(SkPath* path);
+    /**
+     * Removes the specified path. This is meant to be called from threads
+     * that are not the EGL context thread.
+     */
+    void removeDeferred(SkPath* path);
+    /**
+     * Process deferred removals.
+     */
+    void clearGarbage();
 
     /**
      * Sets the maximum size of the cache in bytes.
@@ -166,6 +177,8 @@
      */
     void generateTexture(SkBitmap& bitmap, Texture* texture);
 
+    void removeTexture(PathTexture* texture);
+
     PathTexture* addTexture(const PathCacheEntry& entry, const SkPath *path, const SkPaint* paint);
 
     void init();
@@ -176,10 +189,9 @@
     uint32_t mMaxSize;
     GLuint mMaxTextureSize;
 
-    /**
-     * Used to access mCache and mSize. All methods are accessed from a single
-     * thread except for remove().
-     */
+    bool mDebugEnabled;
+
+    Vector<SkPath*> mGarbage;
     mutable Mutex mLock;
 }; // class PathCache
 
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 813392b..96d8b69 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -18,12 +18,27 @@
 #define ANDROID_HWUI_PROPERTIES_H
 
 #include <cutils/properties.h>
+#include <stdlib.h>
 
 /**
  * This file contains the list of system properties used to configure
  * the OpenGLRenderer.
  */
 
+/**
+ * Debug level for app developers.
+ */
+#define PROPERTY_DEBUG "hwui.debug_level"
+
+/**
+ * Debug levels. Debug levels are used as flags.
+ */
+enum DebugLevel {
+    kDebugDisabled = 0,
+    kDebugMemory = 1,
+    kDebugCaches = 2
+};
+
 // These properties are defined in mega-bytes
 #define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size"
 #define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
@@ -56,4 +71,12 @@
 #define DEFAULT_TEXT_BLACK_GAMMA_THRESHOLD 64
 #define DEFAULT_TEXT_WHITE_GAMMA_THRESHOLD 192
 
+static DebugLevel readDebugLevel() {
+    char property[PROPERTY_VALUE_MAX];
+    if (property_get(PROPERTY_DEBUG, property, NULL) > 0) {
+        return (DebugLevel) atoi(property);
+    }
+    return kDebugDisabled;
+}
+
 #endif // ANDROID_HWUI_PROPERTIES_H
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 47c5d48..5ebd2c0 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -37,14 +37,17 @@
 }
 
 ResourceCache::ResourceCache() {
+    Mutex::Autolock _l(mLock);
     mCache = new KeyedVector<void *, ResourceReference *>();
 }
 
 ResourceCache::~ResourceCache() {
+    Mutex::Autolock _l(mLock);
     delete mCache;
 }
 
 void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) {
+    Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mCache->size(); ++i) {
         void* ref = mCache->valueAt(i);
     }
@@ -73,6 +76,7 @@
 }
 
 void ResourceCache::decrementRefcount(void* resource) {
+    Mutex::Autolock _l(mLock);
     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
     if (ref == NULL) {
         // Should not get here - shouldn't get a call to decrement if we're not yet tracking it
@@ -101,6 +105,7 @@
 }
 
 void ResourceCache::recycle(SkBitmap* resource) {
+    Mutex::Autolock _l(mLock);
     if (mCache->indexOfKey(resource) < 0) {
         // not tracking this resource; just recycle the pixel data
         resource->setPixels(NULL, NULL);
@@ -110,6 +115,7 @@
 }
 
 void ResourceCache::recycle(void* resource) {
+    Mutex::Autolock _l(mLock);
     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
     if (ref == NULL) {
         // Should not get here - shouldn't get a call to recycle if we're not yet tracking it
@@ -122,11 +128,12 @@
 }
 
 void ResourceCache::destructor(SkBitmap* resource) {
+    Mutex::Autolock _l(mLock);
     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
-            Caches::getInstance().textureCache.remove(resource);
+            Caches::getInstance().textureCache.removeDeferred(resource);
         }
         delete resource;
         return;
@@ -139,11 +146,12 @@
 }
 
 void ResourceCache::destructor(SkiaShader* resource) {
+    Mutex::Autolock _l(mLock);
     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
         if (Caches::hasInstance()) {
-            Caches::getInstance().gradientCache.remove(resource->getSkShader());
+            Caches::getInstance().gradientCache.removeDeferred(resource->getSkShader());
         }
         delete resource;
         return;
@@ -156,6 +164,7 @@
 }
 
 void ResourceCache::destructor(SkiaColorFilter* resource) {
+    Mutex::Autolock _l(mLock);
     ResourceReference* ref = mCache->indexOfKey(resource) >= 0 ? mCache->valueFor(resource) : NULL;
     if (ref == NULL) {
         // If we're not tracking this resource, just delete it
@@ -169,6 +178,10 @@
     }
 }
 
+/**
+ * This method should only be called while the mLock mutex is held (that mutex is grabbed
+ * by the various destructor() and recycle() methods which call this method).
+ */
 void ResourceCache::deleteResourceReference(void* resource, ResourceReference* ref) {
     if (ref->recycled && ref->resourceType == kBitmap) {
         ((SkBitmap*) resource)->setPixels(NULL, NULL);
@@ -179,7 +192,7 @@
             {
                 SkBitmap* bitmap = (SkBitmap*)resource;
                 if (Caches::hasInstance()) {
-                    Caches::getInstance().textureCache.remove(bitmap);
+                    Caches::getInstance().textureCache.removeDeferred(bitmap);
                 }
                 delete bitmap;
             }
@@ -188,7 +201,7 @@
             {
                 SkiaShader* shader = (SkiaShader*)resource;
                 if (Caches::hasInstance()) {
-                    Caches::getInstance().gradientCache.remove(shader->getSkShader());
+                    Caches::getInstance().gradientCache.removeDeferred(shader->getSkShader());
                 }
                 delete shader;
             }
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 2256fd1..b0abe2c 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -70,6 +70,13 @@
     void deleteResourceReference(void* resource, ResourceReference* ref);
     void incrementRefcount(void* resource, ResourceType resourceType);
     void logCache();
+
+    /**
+     * Used to increment, decrement, and destroy. Incrementing is generally accessed on the UI
+     * thread, but destroying resources may be called from the GC thread, the finalizer thread,
+     * or a reference queue finalization thread.
+     */
+    mutable Mutex mLock;
 };
 
 }; // namespace uirenderer
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index e7e1187..590a9d7 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -63,8 +63,7 @@
         GLuint* textureUnit) {
 }
 
-void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit) {
-    glActiveTexture(gTextureUnitsMap[textureUnit]);
+void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
     glBindTexture(GL_TEXTURE_2D, texture->id);
     if (wrapS != texture->wrapS) {
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
@@ -132,7 +131,7 @@
     computeScreenSpaceMatrix(textureTransform, modelView);
 
     // Uniforms
-    bindTexture(texture, mWrapS, mWrapT, textureSlot);
+    bindTexture(texture, mWrapS, mWrapT);
     glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
     glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
             GL_FALSE, &textureTransform.data[0]);
@@ -204,7 +203,7 @@
     computeScreenSpaceMatrix(screenSpace, modelView);
 
     // Uniforms
-    bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY], textureSlot);
+    bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
     glUniform1i(program->getUniform("gradientSampler"), textureSlot);
     glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
 }
@@ -297,7 +296,7 @@
     computeScreenSpaceMatrix(screenSpace, modelView);
 
     // Uniforms
-    bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY], textureSlot);
+    bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
     glUniform1i(program->getUniform("gradientSampler"), textureSlot);
     glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
 }
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 1d884ab..6702129 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -97,7 +97,11 @@
     void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView);
 
 protected:
-    inline void bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT, GLuint textureUnit);
+    /**
+     * The appropriate texture unit must have been activated prior to invoking
+     * this method.
+     */
+    inline void bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT);
 
     Type mType;
     SkShader* mKey;
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 2497925..ebecebe 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -53,7 +53,6 @@
 }
 
 TextureCache::~TextureCache() {
-    Mutex::Autolock _l(mLock);
     mCache.clear();
 }
 
@@ -62,6 +61,8 @@
 
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
     LOGD("    Maximum texture dimension is %d pixels", mMaxTextureSize);
+
+    mDebugEnabled = readDebugLevel() & kDebugCaches;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -69,17 +70,14 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 uint32_t TextureCache::getSize() {
-    Mutex::Autolock _l(mLock);
     return mSize;
 }
 
 uint32_t TextureCache::getMaxSize() {
-    Mutex::Autolock _l(mLock);
     return mMaxSize;
 }
 
 void TextureCache::setMaxSize(uint32_t maxSize) {
-    Mutex::Autolock _l(mLock);
     mMaxSize = maxSize;
     while (mSize > mMaxSize) {
         mCache.removeOldest();
@@ -96,6 +94,9 @@
         mSize -= texture->bitmapSize;
         TEXTURE_LOGD("TextureCache::callback: name, removed size, mSize = %d, %d, %d",
                 texture->id, texture->bitmapSize, mSize);
+        if (mDebugEnabled) {
+            LOGD("Texture deleted, size = %d", texture->bitmapSize);
+        }
         glDeleteTextures(1, &texture->id);
         delete texture;
     }
@@ -106,9 +107,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 Texture* TextureCache::get(SkBitmap* bitmap) {
-    mLock.lock();
     Texture* texture = mCache.get(bitmap);
-    mLock.unlock();
 
     if (!texture) {
         if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
@@ -119,11 +118,9 @@
         const uint32_t size = bitmap->rowBytes() * bitmap->height();
         // Don't even try to cache a bitmap that's bigger than the cache
         if (size < mMaxSize) {
-            mLock.lock();
             while (mSize + size > mMaxSize) {
                 mCache.removeOldest();
             }
-            mLock.unlock();
         }
 
         texture = new Texture;
@@ -131,12 +128,13 @@
         generateTexture(bitmap, texture, false);
 
         if (size < mMaxSize) {
-            mLock.lock();
             mSize += size;
             TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d",
                      bitmap, texture->id, size, mSize);
+            if (mDebugEnabled) {
+                LOGD("Texture created, size = %d", size);
+            }
             mCache.put(bitmap, texture);
-            mLock.unlock();
         } else {
             texture->cleanup = true;
         }
@@ -148,12 +146,24 @@
 }
 
 void TextureCache::remove(SkBitmap* bitmap) {
-    Mutex::Autolock _l(mLock);
     mCache.remove(bitmap);
 }
 
-void TextureCache::clear() {
+void TextureCache::removeDeferred(SkBitmap* bitmap) {
     Mutex::Autolock _l(mLock);
+    mGarbage.push(bitmap);
+}
+
+void TextureCache::clearGarbage() {
+    Mutex::Autolock _l(mLock);
+    size_t count = mGarbage.size();
+    for (size_t i = 0; i < count; i++) {
+        mCache.remove(mGarbage.itemAt(i));
+    }
+    mGarbage.clear();
+}
+
+void TextureCache::clear() {
     mCache.clear();
     TEXTURE_LOGD("TextureCache:clear(), miSize = %d", mSize);
 }
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 2ee88b1..f7707f7 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -19,6 +19,8 @@
 
 #include <SkBitmap.h>
 
+#include <utils/Vector.h>
+
 #include "Debug.h"
 #include "Texture.h"
 #include "utils/GenerationCache.h"
@@ -64,11 +66,21 @@
      */
     Texture* get(SkBitmap* bitmap);
     /**
-     * Removes the texture associated with the specified bitmap. Returns NULL
-     * if the texture cannot be found. Upon remove the texture is freed.
+     * Removes the texture associated with the specified bitmap.
+     * Upon remove the texture is freed.
      */
     void remove(SkBitmap* bitmap);
     /**
+     * Removes the texture associated with the specified bitmap. This is meant
+     * to be called from threads that are not the EGL context thread.
+     */
+    void removeDeferred(SkBitmap* bitmap);
+    /**
+     * Process deferred removals.
+     */
+    void clearGarbage();
+
+    /**
      * Clears the cache. This causes all textures to be deleted.
      */
     void clear();
@@ -107,10 +119,9 @@
     uint32_t mMaxSize;
     GLint mMaxTextureSize;
 
-    /**
-     * Used to access mCache and mSize. All methods are accessed from a single
-     * thread except for remove().
-     */
+    bool mDebugEnabled;
+
+    Vector<SkBitmap*> mGarbage;
     mutable Mutex mLock;
 }; // class TextureCache
 
diff --git a/libs/hwui/utils/GenerationCache.h b/libs/hwui/utils/GenerationCache.h
index 2e76236..42e6d9b 100644
--- a/libs/hwui/utils/GenerationCache.h
+++ b/libs/hwui/utils/GenerationCache.h
@@ -130,7 +130,7 @@
 
 template<typename K, typename V>
 V GenerationCache<K, V>::getValueAt(uint32_t index) const {
-    return mCache.valueAt(index);
+    return mCache.valueAt(index)->value;
 }
 
 template<typename K, typename V>
diff --git a/libs/surfaceflinger_client/SharedBufferStack.cpp b/libs/surfaceflinger_client/SharedBufferStack.cpp
index 8f583f06..3b2ef84 100644
--- a/libs/surfaceflinger_client/SharedBufferStack.cpp
+++ b/libs/surfaceflinger_client/SharedBufferStack.cpp
@@ -265,6 +265,14 @@
             (stack.queued > 0 && stack.inUse != buf));
 }
 
+SharedBufferServer::BuffersAvailableCondition::BuffersAvailableCondition(
+        SharedBufferServer* sbs, int numBuffers) : ConditionBase(sbs),
+        mNumBuffers(numBuffers) {
+}
+bool SharedBufferServer::BuffersAvailableCondition::operator()() const {
+    return stack.available == mNumBuffers;
+}
+
 // ----------------------------------------------------------------------------
 
 SharedBufferClient::QueueUpdate::QueueUpdate(SharedBufferBase* sbb)
@@ -448,6 +456,7 @@
 
     const nsecs_t now = systemTime(SYSTEM_TIME_THREAD);
     stack.stats.totalTime = ns2us(now - mDequeueTime[buf]);
+
     return err;
 }
 
@@ -492,6 +501,7 @@
     if (err == NO_ERROR) {
         mNumBuffers = bufferCount;
         queued_head = (stack.head + stack.queued) % mNumBuffers;
+        tail = computeTail();
     }
     return err;
 }
@@ -606,17 +616,24 @@
  */
 status_t SharedBufferServer::resize(int newNumBuffers)
 {
-    if (uint32_t(newNumBuffers) >= SharedBufferStack::NUM_BUFFER_MAX)
+    if ((unsigned int)(newNumBuffers) < SharedBufferStack::NUM_BUFFER_MIN ||
+        (unsigned int)(newNumBuffers) > SharedBufferStack::NUM_BUFFER_MAX) {
         return BAD_VALUE;
+    }
 
     RWLock::AutoWLock _l(mLock);
 
-    // for now we're not supporting shrinking
-    const int numBuffers = mNumBuffers;
-    if (newNumBuffers < numBuffers)
-        return BAD_VALUE;
+    if (newNumBuffers < mNumBuffers) {
+        return shrink(newNumBuffers);
+    } else {
+        return grow(newNumBuffers);
+    }
+}
 
+status_t SharedBufferServer::grow(int newNumBuffers)
+{
     SharedBufferStack& stack( *mSharedStack );
+    const int numBuffers = mNumBuffers;
     const int extra = newNumBuffers - numBuffers;
 
     // read the head, make sure it's valid
@@ -650,6 +667,54 @@
     return NO_ERROR;
 }
 
+status_t SharedBufferServer::shrink(int newNumBuffers)
+{
+    SharedBufferStack& stack( *mSharedStack );
+
+    // Shrinking is only supported if there are no buffers currently dequeued.
+    int32_t avail = stack.available;
+    int32_t queued = stack.queued;
+    if (avail + queued != mNumBuffers) {
+        return INVALID_OPERATION;
+    }
+
+    // Wait for any queued buffers to be displayed.
+    BuffersAvailableCondition condition(this, mNumBuffers);
+    status_t err = waitForCondition(condition);
+    if (err < 0) {
+        return err;
+    }
+
+    // Reset head to index 0 and make it refer to buffer 0.  The same renaming
+    // (head -> 0) is done in the BufferManager.
+    int32_t head = stack.head;
+    int8_t* index = const_cast<int8_t*>(stack.index);
+    for (int8_t i = 0; i < newNumBuffers; i++) {
+        index[i] = i;
+    }
+    stack.head = 0;
+    stack.headBuf = 0;
+
+    // If one of the buffers is in use it must be the head buffer, which we are
+    // renaming to buffer 0.
+    if (stack.inUse > 0) {
+        stack.inUse = 0;
+    }
+
+    // Free the buffers from the end of the list that are no longer needed.
+    for (int i = newNumBuffers; i < mNumBuffers; i++) {
+        mBufferList.remove(i);
+    }
+
+    // Tell the client to reallocate all the buffers.
+    reallocateAll();
+
+    mNumBuffers = newNumBuffers;
+    stack.available = newNumBuffers;
+
+    return NO_ERROR;
+}
+
 SharedBufferStack::Statistics SharedBufferServer::getStats() const
 {
     SharedBufferStack& stack( *mSharedStack );
diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp
index 7af6ce8..9467a4c 100644
--- a/libs/surfaceflinger_client/Surface.cpp
+++ b/libs/surfaceflinger_client/Surface.cpp
@@ -855,6 +855,12 @@
     status_t err = mSharedBufferClient->setBufferCount(bufferCount, ipc);
     LOGE_IF(err, "ISurface::setBufferCount(%d) returned %s",
             bufferCount, strerror(-err));
+
+    if (err == NO_ERROR) {
+        // Clear out any references to the old buffers.
+        mBuffers.clear();
+    }
+
     return err;
 }
 
@@ -1029,7 +1035,7 @@
         // one of the buffers for which we do know the index.  This can happen
         // e.g. if GraphicBuffer is used to wrap an android_native_buffer_t that
         // was dequeued from an ANativeWindow.
-        for (int i = 0; i < mBuffers.size(); i++) {
+        for (size_t i = 0; i < mBuffers.size(); i++) {
             if (buffer->handle == mBuffers[i]->handle) {
                 idx = mBuffers[i]->getIndex();
                 break;
diff --git a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
index f409f48..7ef5926 100644
--- a/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
+++ b/libs/surfaceflinger_client/tests/SharedBufferStack/SharedBufferStackTest.cpp
@@ -32,7 +32,8 @@
 int main(int argc, char** argv)
 {
     SharedClient client;
-    SharedBufferServer s(&client, 0, 4, 0);
+    sp<SharedBufferServer> ps(new SharedBufferServer(&client, 0, 4, 0));
+    SharedBufferServer& s(*ps);
     SharedBufferClient c(&client, 0, 4, 0);
 
     printf("basic test 0\n");
@@ -67,6 +68,10 @@
     int list3[6] = {3, 2, 1, 4, 5, 0};
     test0(s, c, 6, list3);
 
+    c.setBufferCount(4, resize);
+    int list4[4] = {1, 2, 3, 0};
+    test0(s, c, 4, list4);
+
     return 0;
 }
 
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 7ddb3c7..db7d448 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -157,6 +157,10 @@
             || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
 }
 
+bool InputWindow::supportsSplitTouch() const {
+    return layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH;
+}
+
 
 // --- InputDispatcher ---
 
@@ -1110,8 +1114,7 @@
         }
 
         // Figure out whether splitting will be allowed for this window.
-        if (newTouchedWindow
-                && (newTouchedWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH)) {
+        if (newTouchedWindow && newTouchedWindow->supportsSplitTouch()) {
             // New window supports splitting.
             isSplit = true;
         } else if (isSplit) {
@@ -2648,13 +2651,8 @@
 
                 mTouchState.windows.removeAt(i);
 
-                int32_t newTargetFlags = 0;
-                if (oldTargetFlags & InputTarget::FLAG_FOREGROUND) {
-                    newTargetFlags |= InputTarget::FLAG_FOREGROUND;
-                    if (toWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH) {
-                        newTargetFlags |= InputTarget::FLAG_SPLIT;
-                    }
-                }
+                int32_t newTargetFlags = oldTargetFlags
+                        & (InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_SPLIT);
                 mTouchState.addOrUpdateWindow(toWindow, newTargetFlags, pointerIds);
 
                 found = true;
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 532a2df..80c97a0 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -170,6 +170,7 @@
         addFileType("OTA", FILE_TYPE_MID, "audio/midi");
         
         addFileType("MPEG", FILE_TYPE_MP4, "video/mpeg", MtpConstants.FORMAT_MPEG);
+        addFileType("MPG", FILE_TYPE_MP4, "video/mpeg", MtpConstants.FORMAT_MPEG);
         addFileType("MP4", FILE_TYPE_MP4, "video/mp4", MtpConstants.FORMAT_MPEG);
         addFileType("M4V", FILE_TYPE_M4V, "video/mp4", MtpConstants.FORMAT_MPEG);
         addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp",  MtpConstants.FORMAT_3GP_CONTAINER);
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
index e01a26b..a969ac1 100755
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ b/media/java/android/media/videoeditor/MediaImageItem.java
@@ -17,6 +17,7 @@
 package android.media.videoeditor;

 

 import java.io.IOException;

+import java.util.List;

 

 import android.graphics.Bitmap;

 import android.graphics.BitmapFactory;

@@ -161,6 +162,57 @@
      * @param durationMs The duration of the image in the storyboard timeline

      */

     public void setDuration(long durationMs) {

+        // Invalidate the beginning and end transitions if necessary

+        if (mBeginTransition != null) {

+            final long transitionDurationMs = mBeginTransition.getDuration();

+

+            // The begin transition must be invalidated if it overlaps with

+            // an effect. To optimize this code we could invalidate the

+            // begin transition only for a Ken Burns effect (color effects

+            // should not affect the begin transition) however when new effects

+            // will be added this code would have to be modified... so we

+            // opted to always invalidate the transition if there is an

+            // overlap.

+            final List<Effect> effects = getAllEffects();

+            for (Effect effect : effects) {

+                // Check if the effect overlaps with the begin transition

+                if (effect.getStartTime() < transitionDurationMs) {

+                    mBeginTransition.invalidate();

+                    break;

+                }

+            }

+        }

+

+        if (mEndTransition != null) {

+            final long transitionDurationMs = mEndTransition.getDuration();

+

+            // The end transition must be invalidated if it overlaps with

+            // an effect

+            final List<Effect> effects = getAllEffects();

+            for (Effect effect : effects) {

+                // Check if the effect overlaps with the end transition

+                if (effect.getStartTime() + effect.getDuration() >

+                            mDurationMs - transitionDurationMs) {

+                    mEndTransition.invalidate();

+                    break;

+                }

+            }

+

+            if (mEndTransition.isGenerated()) {

+                // The end transition must be invalidated if it overlaps with

+                // an overlay

+                final List<Overlay> overlays = getAllOverlays();

+                for (Overlay overlay : overlays) {

+                    // Check if the overlay overlaps with the end transition

+                    if (overlay.getStartTime() + overlay.getDuration() >

+                                mDurationMs - transitionDurationMs) {

+                        mEndTransition.invalidate();

+                        break;

+                    }

+                }

+            }

+        }

+

         mDurationMs = durationMs;

 

         adjustTransitions();

@@ -226,6 +278,64 @@
     }

 

     /**

+     * Adjust the start time and/or duration of effects.

+     */

+    private void adjustEffects() {

+        final List<Effect> effects = getAllEffects();

+        for (Effect effect : effects) {

+            // Adjust the start time if necessary

+            final long effectStartTimeMs;

+            if (effect.getStartTime() > getDuration()) {

+                effectStartTimeMs = 0;

+            } else {

+                effectStartTimeMs = effect.getStartTime();

+            }

+

+            // Adjust the duration if necessary

+            final long effectDurationMs;

+            if (effectStartTimeMs + effect.getDuration() > getDuration()) {

+                effectDurationMs = getDuration() - effectStartTimeMs;

+            } else {

+                effectDurationMs = effect.getDuration();

+            }

+

+            if (effectStartTimeMs != effect.getStartTime() ||

+                    effectDurationMs != effect.getDuration()) {

+                effect.setStartTimeAndDuration(effectStartTimeMs, effectDurationMs);

+            }

+        }

+    }

+

+    /**

+     * Adjust the start time and/or duration of overlays.

+     */

+    private void adjustOverlays() {

+        final List<Overlay> overlays = getAllOverlays();

+        for (Overlay overlay : overlays) {

+            // Adjust the start time if necessary

+            final long overlayStartTimeMs;

+            if (overlay.getStartTime() > getDuration()) {

+                overlayStartTimeMs = 0;

+            } else {

+                overlayStartTimeMs = overlay.getStartTime();

+            }

+

+            // Adjust the duration if necessary

+            final long overlayDurationMs;

+            if (overlayStartTimeMs + overlay.getDuration() > getDuration()) {

+                overlayDurationMs = getDuration() - overlayStartTimeMs;

+            } else {

+                overlayDurationMs = overlay.getDuration();

+            }

+

+            if (overlayStartTimeMs != overlay.getStartTime() ||

+                    overlayDurationMs != overlay.getDuration()) {

+                overlay.setStartTimeAndDuration(overlayStartTimeMs, overlayDurationMs);

+            }

+        }

+    }

+

+    /**

      * Resize a bitmap to the specified width and height

      *

      * @param filename The filename

@@ -234,8 +344,7 @@
      *

      * @return The resized bitmap

      */

-    private Bitmap scaleImage(String filename, int width, int height)

-            throws IOException {

+    private Bitmap scaleImage(String filename, int width, int height) throws IOException {

         final BitmapFactory.Options dbo = new BitmapFactory.Options();

         dbo.inJustDecodeBounds = true;

         BitmapFactory.decodeFile(filename, dbo);

diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java
index 870de63..12f6084 100755
--- a/media/java/android/media/videoeditor/MediaItem.java
+++ b/media/java/android/media/videoeditor/MediaItem.java
@@ -473,62 +473,4 @@
             }

         }

     }

-

-    /**

-     * Adjust the start time and/or duration of effects.

-     */

-    protected void adjustEffects() {

-        final List<Effect> effects = getAllEffects();

-        for (Effect effect : effects) {

-            // Adjust the start time if necessary

-            final long effectStartTimeMs;

-            if (effect.getStartTime() > getDuration()) {

-                effectStartTimeMs = 0;

-            } else {

-                effectStartTimeMs = effect.getStartTime();

-            }

-

-            // Adjust the duration if necessary

-            final long effectDurationMs;

-            if (effectStartTimeMs + effect.getDuration() > getDuration()) {

-                effectDurationMs = getDuration() - effectStartTimeMs;

-            } else {

-                effectDurationMs = effect.getDuration();

-            }

-

-            if (effectStartTimeMs != effect.getStartTime() ||

-                    effectDurationMs != effect.getDuration()) {

-                effect.setStartTimeAndDuration(effectStartTimeMs, effectDurationMs);

-            }

-        }

-    }

-

-    /**

-     * Adjust the start time and/or duration of overlays.

-     */

-    protected void adjustOverlays() {

-        final List<Overlay> overlays = getAllOverlays();

-        for (Overlay overlay : overlays) {

-            // Adjust the start time if necessary

-            final long overlayStartTimeMs;

-            if (overlay.getStartTime() > getDuration()) {

-                overlayStartTimeMs = 0;

-            } else {

-                overlayStartTimeMs = overlay.getStartTime();

-            }

-

-            // Adjust the duration if necessary

-            final long overlayDurationMs;

-            if (overlayStartTimeMs + overlay.getDuration() > getDuration()) {

-                overlayDurationMs = getDuration() - overlayStartTimeMs;

-            } else {

-                overlayDurationMs = overlay.getDuration();

-            }

-

-            if (overlayStartTimeMs != overlay.getStartTime() ||

-                    overlayDurationMs != overlay.getDuration()) {

-                overlay.setStartTimeAndDuration(overlayStartTimeMs, overlayDurationMs);

-            }

-        }

-    }

 }

diff --git a/media/java/android/media/videoeditor/VideoEditorTestImpl.java b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
index 157dd62..ca896c3 100644
--- a/media/java/android/media/videoeditor/VideoEditorTestImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
@@ -748,121 +748,126 @@
      */
     private void load() throws FileNotFoundException, XmlPullParserException, IOException {
         final File file = new File(mProjectPath, PROJECT_FILENAME);
-        // Load the metadata
-        final XmlPullParser parser = Xml.newPullParser();
         final FileInputStream fis = new FileInputStream(file);
-        parser.setInput(fis, "UTF-8");
-        int eventType = parser.getEventType();
-        String name;
-        MediaItem currentMediaItem = null;
-        Overlay currentOverlay = null;
-        while (eventType != XmlPullParser.END_DOCUMENT) {
-            switch (eventType) {
-                case XmlPullParser.START_TAG: {
-                    name = parser.getName();
-                    if (TAG_PROJECT.equals(name)) {
-                        mAspectRatio = Integer.parseInt(parser.getAttributeValue("",
-                                ATTR_ASPECT_RATIO));
-                    } else if (TAG_MEDIA_ITEM.equals(name)) {
-                        final String mediaItemId = parser.getAttributeValue("", ATTR_ID);
-                        final String type = parser.getAttributeValue("", ATTR_TYPE);
-                        final String filename = parser.getAttributeValue("", ATTR_FILENAME);
-                        final int renderingMode = Integer.parseInt(parser.getAttributeValue("",
-                                ATTR_RENDERING_MODE));
 
-                        if (MediaImageItem.class.getSimpleName().equals(type)) {
-                            final long durationMs = Long.parseLong(parser.getAttributeValue("",
-                                    ATTR_DURATION));
-                            currentMediaItem = new MediaImageItem(this, mediaItemId, filename,
-                                    durationMs, renderingMode);
-                        } else if (MediaVideoItem.class.getSimpleName().equals(type)) {
-                            final long beginMs = Long.parseLong(parser.getAttributeValue("",
-                                    ATTR_BEGIN_TIME));
-                            final long endMs = Long.parseLong(parser.getAttributeValue("",
-                                    ATTR_END_TIME));
-                            final int volume = Integer.parseInt(parser.getAttributeValue("",
-                                    ATTR_VOLUME));
-                            final boolean muted = Boolean.parseBoolean(parser.getAttributeValue("",
-                                    ATTR_MUTED));
-                            final String audioWaveformFilename = parser.getAttributeValue("",
-                                    ATTR_AUDIO_WAVEFORM_FILENAME);
-                            currentMediaItem = new MediaVideoItem(this, mediaItemId, filename,
-                                    renderingMode, beginMs, endMs, volume, muted,
-                                    audioWaveformFilename);
+        try {
+            // Load the metadata
+            final XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(fis, "UTF-8");
+            int eventType = parser.getEventType();
+            String name;
+            MediaItem currentMediaItem = null;
+            Overlay currentOverlay = null;
+            while (eventType != XmlPullParser.END_DOCUMENT) {
+                switch (eventType) {
+                    case XmlPullParser.START_TAG: {
+                        name = parser.getName();
+                        if (TAG_PROJECT.equals(name)) {
+                            mAspectRatio = Integer.parseInt(parser.getAttributeValue("",
+                                    ATTR_ASPECT_RATIO));
+                        } else if (TAG_MEDIA_ITEM.equals(name)) {
+                            final String mediaItemId = parser.getAttributeValue("", ATTR_ID);
+                            final String type = parser.getAttributeValue("", ATTR_TYPE);
+                            final String filename = parser.getAttributeValue("", ATTR_FILENAME);
+                            final int renderingMode = Integer.parseInt(
+                                    parser.getAttributeValue("", ATTR_RENDERING_MODE));
 
-                            final long beginTimeMs = Long.parseLong(parser.getAttributeValue("",
-                                    ATTR_BEGIN_TIME));
-                            final long endTimeMs = Long.parseLong(parser.getAttributeValue("",
-                                    ATTR_END_TIME));
-                            ((MediaVideoItem)currentMediaItem).setExtractBoundaries(beginTimeMs,
-                                    endTimeMs);
+                            if (MediaImageItem.class.getSimpleName().equals(type)) {
+                                final long durationMs = Long.parseLong(
+                                        parser.getAttributeValue("", ATTR_DURATION));
+                                currentMediaItem = new MediaImageItem(this, mediaItemId, filename,
+                                        durationMs, renderingMode);
+                            } else if (MediaVideoItem.class.getSimpleName().equals(type)) {
+                                final long beginMs = Long.parseLong(
+                                        parser.getAttributeValue("", ATTR_BEGIN_TIME));
+                                final long endMs = Long.parseLong(
+                                        parser.getAttributeValue("", ATTR_END_TIME));
+                                final int volume = Integer.parseInt(
+                                        parser.getAttributeValue("", ATTR_VOLUME));
+                                final boolean muted = Boolean.parseBoolean(
+                                        parser.getAttributeValue("", ATTR_MUTED));
+                                final String audioWaveformFilename =
+                                        parser.getAttributeValue("", ATTR_AUDIO_WAVEFORM_FILENAME);
+                                currentMediaItem = new MediaVideoItem(this, mediaItemId, filename,
+                                        renderingMode, beginMs, endMs, volume, muted,
+                                        audioWaveformFilename);
 
-                            final int volumePercent = Integer.parseInt(parser.getAttributeValue("",
-                                    ATTR_VOLUME));
-                            ((MediaVideoItem)currentMediaItem).setVolume(volumePercent);
-                        } else {
-                            Log.e(TAG, "Unknown media item type: " + type);
-                            currentMediaItem = null;
-                        }
+                                final long beginTimeMs = Long.parseLong(
+                                        parser.getAttributeValue("", ATTR_BEGIN_TIME));
+                                final long endTimeMs = Long.parseLong(
+                                        parser.getAttributeValue("", ATTR_END_TIME));
+                                ((MediaVideoItem)currentMediaItem).setExtractBoundaries(
+                                        beginTimeMs, endTimeMs);
 
-                        if (currentMediaItem != null) {
-                            mMediaItems.add(currentMediaItem);
-                        }
-                    } else if (TAG_TRANSITION.equals(name)) {
-                        final Transition transition = parseTransition(parser);
-                        if (transition != null) {
-                            mTransitions.add(transition);
-                        }
-                    } else if (TAG_OVERLAY.equals(name)) {
-                        if (currentMediaItem != null) {
-                            currentOverlay = parseOverlay(parser, currentMediaItem);
+                                final int volumePercent = Integer.parseInt(
+                                        parser.getAttributeValue("", ATTR_VOLUME));
+                                ((MediaVideoItem)currentMediaItem).setVolume(volumePercent);
+                            } else {
+                                Log.e(TAG, "Unknown media item type: " + type);
+                                currentMediaItem = null;
+                            }
+
+                            if (currentMediaItem != null) {
+                                mMediaItems.add(currentMediaItem);
+                            }
+                        } else if (TAG_TRANSITION.equals(name)) {
+                            final Transition transition = parseTransition(parser);
+                            if (transition != null) {
+                                mTransitions.add(transition);
+                            }
+                        } else if (TAG_OVERLAY.equals(name)) {
+                            if (currentMediaItem != null) {
+                                currentOverlay = parseOverlay(parser, currentMediaItem);
+                                if (currentOverlay != null) {
+                                    currentMediaItem.addOverlay(currentOverlay);
+                                }
+                            }
+                        } else if (TAG_OVERLAY_USER_ATTRIBUTES.equals(name)) {
                             if (currentOverlay != null) {
-                                currentMediaItem.addOverlay(currentOverlay);
+                                final int attributesCount = parser.getAttributeCount();
+                                for (int i = 0; i < attributesCount; i++) {
+                                    currentOverlay.setUserAttribute(parser.getAttributeName(i),
+                                            parser.getAttributeValue(i));
+                                }
+                            }
+                        } else if (TAG_EFFECT.equals(name)) {
+                            if (currentMediaItem != null) {
+                                final Effect effect = parseEffect(parser, currentMediaItem);
+                                if (effect != null) {
+                                    currentMediaItem.addEffect(effect);
+                                }
+                            }
+                        } else if (TAG_AUDIO_TRACK.equals(name)) {
+                            final AudioTrack audioTrack = parseAudioTrack(parser);
+                            if (audioTrack != null) {
+                                addAudioTrack(audioTrack);
                             }
                         }
-                    } else if (TAG_OVERLAY_USER_ATTRIBUTES.equals(name)) {
-                        if (currentOverlay != null) {
-                            final int attributesCount = parser.getAttributeCount();
-                            for (int i = 0; i < attributesCount; i++) {
-                                currentOverlay.setUserAttribute(parser.getAttributeName(i),
-                                        parser.getAttributeValue(i));
-                            }
-                        }
-                    } else if (TAG_EFFECT.equals(name)) {
-                        if (currentMediaItem != null) {
-                            final Effect effect = parseEffect(parser, currentMediaItem);
-                            if (effect != null) {
-                                currentMediaItem.addEffect(effect);
-                            }
-                        }
-                    } else if (TAG_AUDIO_TRACK.equals(name)) {
-                        final AudioTrack audioTrack = parseAudioTrack(parser);
-                        if (audioTrack != null) {
-                            addAudioTrack(audioTrack);
-                        }
+                        break;
                     }
-                    break;
-                }
 
-                case XmlPullParser.END_TAG: {
-                    name = parser.getName();
-                    if (TAG_MEDIA_ITEM.equals(name)) {
-                        currentMediaItem = null;
-                    } else if (TAG_OVERLAY.equals(name)) {
-                        currentOverlay = null;
+                    case XmlPullParser.END_TAG: {
+                        name = parser.getName();
+                        if (TAG_MEDIA_ITEM.equals(name)) {
+                            currentMediaItem = null;
+                        } else if (TAG_OVERLAY.equals(name)) {
+                            currentOverlay = null;
+                        }
+                        break;
                     }
-                    break;
-                }
 
-                default: {
-                    break;
+                    default: {
+                        break;
+                    }
                 }
+                eventType = parser.next();
             }
-            eventType = parser.next();
+            computeTimelineDuration();
+        } finally {
+            if (fis != null) {
+                fis.close();
+            }
         }
-
-        fis.close();
-        computeTimelineDuration();
     }
 
     /**
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 9c2a8ba..1a3fcd6 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -835,6 +835,7 @@
 const char *AudioParameter::keyFormat = "format";
 const char *AudioParameter::keyChannels = "channels";
 const char *AudioParameter::keyFrameCount = "frame_count";
+const char *AudioParameter::keyInputSource = "input_source";
 
 AudioParameter::AudioParameter(const String8& keyValuePairs)
 {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 9da5f01..5f9b6e6 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -1442,6 +1442,7 @@
     mCameraSourceTimeLapse = NULL;
     mIsMetaDataStoredInVideoBuffers = false;
     mEncoderProfiles = MediaProfiles::getInstance();
+    mRotationDegrees = 0;
 
     mOutputFd = -1;
     mOutputFdAux = -1;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 4e1969b..f084e28 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -564,6 +564,12 @@
     return false;
 }
 
+void AwesomePlayer::ensureCacheIsFetching_l() {
+    if (mCachedSource != NULL) {
+        mCachedSource->resumeFetchingIfNecessary();
+    }
+}
+
 void AwesomePlayer::onBufferingUpdate() {
     Mutex::Autolock autoLock(mLock);
     if (!mBufferingEventPending) {
@@ -606,6 +612,7 @@
                          kLowWaterMarkBytes);
                     mFlags |= CACHE_UNDERRUN;
                     pause_l();
+                    ensureCacheIsFetching_l();
                     notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
                 } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
                     if (mFlags & CACHE_UNDERRUN) {
@@ -627,12 +634,16 @@
     int64_t cachedDurationUs;
     bool eos;
     if (getCachedDuration_l(&cachedDurationUs, &eos)) {
+        LOGV("cachedDurationUs = %.2f secs, eos=%d",
+             cachedDurationUs / 1E6, eos);
+
         if ((mFlags & PLAYING) && !eos
                 && (cachedDurationUs < kLowWaterMarkUs)) {
             LOGI("cache is running low (%.2f secs) , pausing.",
                  cachedDurationUs / 1E6);
             mFlags |= CACHE_UNDERRUN;
             pause_l();
+            ensureCacheIsFetching_l();
             notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
         } else if (eos || cachedDurationUs > kHighWaterMarkUs) {
             if (mFlags & CACHE_UNDERRUN) {
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index a69c396..4a2402b 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -325,15 +325,17 @@
     mCondition.signal();
 }
 
-void NuCachedSource2::restartPrefetcherIfNecessary_l() {
+void NuCachedSource2::restartPrefetcherIfNecessary_l(
+        bool ignoreLowWaterThreshold) {
     static const size_t kGrayArea = 256 * 1024;
 
     if (mFetching || mFinalStatus != OK) {
         return;
     }
 
-    if (mCacheOffset + mCache->totalSize() - mLastAccessPos
-            >= kLowWaterThreshold) {
+    if (!ignoreLowWaterThreshold
+            && mCacheOffset + mCache->totalSize() - mLastAccessPos
+                >= kLowWaterThreshold) {
         return;
     }
 
@@ -510,6 +512,12 @@
     mSuspended = true;
 }
 
+void NuCachedSource2::resumeFetchingIfNecessary() {
+    Mutex::Autolock autoLock(mLock);
+
+    restartPrefetcherIfNecessary_l(true /* ignore low water threshold */);
+}
+
 DecryptHandle* NuCachedSource2::DrmInitialization(DrmManagerClient* client) {
     return mSource->DrmInitialization(client);
 }
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 9f9c83a..3d490c9 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1913,6 +1913,13 @@
 
             // Buffer could not be released until empty buffer done is called.
             if (info->mMediaBuffer != NULL) {
+                if (mIsEncoder &&
+                    (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
+                    // If zero-copy mode is enabled this will send the
+                    // input buffer back to the upstream source.
+                    restorePatchedDataPointer(info);
+                }
+
                 info->mMediaBuffer->release();
                 info->mMediaBuffer = NULL;
             }
@@ -2462,6 +2469,7 @@
     status_t err = mOMX->freeBuffer(mNode, portIndex, info->mBuffer);
 
     if (err == OK && info->mMediaBuffer != NULL) {
+        CHECK_EQ(portIndex, kPortIndexOutput);
         info->mMediaBuffer->setObserver(NULL);
 
         // Make sure nobody but us owns this buffer at this point.
@@ -2474,6 +2482,7 @@
         }
 
         info->mMediaBuffer->release();
+        info->mMediaBuffer = NULL;
     }
 
     if (err == OK) {
@@ -2714,10 +2723,10 @@
         if (mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames)) {
             CHECK(mOMXLivesLocally && offset == 0);
             OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *) info->mBuffer;
+            CHECK(header->pBuffer == info->mData);
             header->pBuffer = (OMX_U8 *) srcBuffer->data() + srcBuffer->range_offset();
             releaseBuffer = false;
             info->mMediaBuffer = srcBuffer;
-            // FIXME: we are leaking memory
         } else {
             if (mIsMetaDataStoredInVideoBuffers) {
                 releaseBuffer = false;
@@ -3997,8 +4006,30 @@
             caps->mProfileLevels.push(profileLevel);
         }
 
+        // Color format query
+        OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
+        InitOMXParams(&portFormat);
+        portFormat.nPortIndex = queryDecoders ? 1 : 0;
+        for (portFormat.nIndex = 0;; ++portFormat.nIndex)  {
+            err = omx->getParameter(
+                    node, OMX_IndexParamVideoPortFormat,
+                    &portFormat, sizeof(portFormat));
+            if (err != OK) {
+                break;
+            }
+            caps->mColorFormats.push(portFormat.eColorFormat);
+        }
+
         CHECK_EQ(omx->freeNode(node), OK);
     }
 }
 
+void OMXCodec::restorePatchedDataPointer(BufferInfo *info) {
+    CHECK(mIsEncoder && (mQuirks & kAvoidMemcopyInputRecordingFrames));
+    CHECK(mOMXLivesLocally);
+
+    OMX_BUFFERHEADERTYPE *header = (OMX_BUFFERHEADERTYPE *)info->mBuffer;
+    header->pBuffer = (OMX_U8 *)info->mData;
+}
+
 }  // namespace android
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index a0a7436..302a1ba 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -274,6 +274,7 @@
     bool getBitrate(int64_t *bitrate);
 
     void finishSeekIfNecessary(int64_t videoTimeUs);
+    void ensureCacheIsFetching_l();
 
     AwesomePlayer(const AwesomePlayer &);
     AwesomePlayer &operator=(const AwesomePlayer &);
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 4067585..8cec1b1 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -47,6 +47,8 @@
     void suspend();
     void clearCacheAndResume();
 
+    void resumeFetchingIfNecessary();
+
 protected:
     virtual ~NuCachedSource2();
 
@@ -56,7 +58,7 @@
     enum {
         kPageSize            = 65536,
         kHighWaterThreshold  = 5 * 1024 * 1024,
-        kLowWaterThreshold   = 512 * 1024,
+        kLowWaterThreshold   = 1024 * 1024,
 
         // Read data after a 15 sec timeout whether we're actively
         // fetching or not.
@@ -96,7 +98,7 @@
     status_t seekInternal_l(off_t offset);
 
     size_t approxDataRemaining_l(bool *eos);
-    void restartPrefetcherIfNecessary_l();
+    void restartPrefetcherIfNecessary_l(bool ignoreLowWaterThreshold = false);
 
     DISALLOW_EVIL_CONSTRUCTORS(NuCachedSource2);
 };
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index f74f395..5ba6be9 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -736,6 +736,7 @@
             unlink(pathbuf);
         }
     }
+    closedir(dir);
 }
 
 static void deletePath(const char* path) {
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
index 23bbb87..64ffa4e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
@@ -344,10 +344,8 @@
     
     @LargeTest
     public void testWAVSeekToEnd() throws Exception {
-        if (isWMVEnable) {
-            boolean isEnd = CodecTest.seekToEnd(MediaNames.WAV);
-            assertTrue("WAV seekToEnd", isEnd);
-        }
+        boolean isEnd = CodecTest.seekToEnd(MediaNames.WAV);
+        assertTrue("WAV seekToEnd", isEnd);
     }  
     
     @MediumTest
diff --git a/native/include/android/keycodes.h b/native/include/android/keycodes.h
index 11142537..5f33ad5 100644
--- a/native/include/android/keycodes.h
+++ b/native/include/android/keycodes.h
@@ -208,6 +208,28 @@
     AKEYCODE_NUMPAD_LEFT_PAREN = 162,
     AKEYCODE_NUMPAD_RIGHT_PAREN = 163,
     AKEYCODE_VOLUME_MUTE     = 164,
+    AKEYCODE_INFO            = 165,
+    AKEYCODE_CHANNEL_UP      = 166,
+    AKEYCODE_CHANNEL_DOWN    = 167,
+    AKEYCODE_ZOOM_IN         = 168,
+    AKEYCODE_ZOOM_OUT        = 169,
+    AKEYCODE_TV              = 170,
+    AKEYCODE_WINDOW          = 171,
+    AKEYCODE_GUIDE           = 172,
+    AKEYCODE_DVR             = 173,
+    AKEYCODE_BOOKMARK        = 174,
+    AKEYCODE_CAPTIONS        = 175,
+    AKEYCODE_SETTINGS        = 176,
+    AKEYCODE_TV_POWER        = 177,
+    AKEYCODE_TV_INPUT        = 178,
+    AKEYCODE_STB_POWER       = 179,
+    AKEYCODE_STB_INPUT       = 180,
+    AKEYCODE_AVR_POWER       = 181,
+    AKEYCODE_AVR_INPUT       = 182,
+    AKEYCODE_PROG_RED        = 183,
+    AKEYCODE_PROG_GREEN      = 184,
+    AKEYCODE_PROG_YELLOW     = 185,
+    AKEYCODE_PROG_BLUE       = 186,
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index fee7263..828fae8 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nejnovější"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index b6ca93b..74def1c 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Seneste"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index d3fb06e..e033982 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Zuletzt verwendet"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index f50395b..ddcfc2c 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Πρόσφατα"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index a6ce25a..aff9f4ca 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Reciente"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index fc75775..0b6af34 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Reciente"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 22b8d5e..0e2a765 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Récentes"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 8af1d9a..c45bb4c 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recenti"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 807ecd6..f6a8e5f 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"新着"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 0c13821..1189194 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"최근 사용한 앱"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 380e751..b5f4676 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Nylig"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 7159b06..ec8fcfb 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recent"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 3b03b52..7034a6d 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Najnowsze"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index f59ce9b..80028a2 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 950f196..006379c 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Recente"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 8a8d8ae..646d7f5 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Utilisà sco ultim"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index bb8b375..d598ff3 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Недавние"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 1bcd55f..6ecdfa8 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"Senaste"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 96b88de..059a4f1 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"En Son Görevler"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 0dcb31c..9c1f71f 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"近期任务"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 16c3427..11051be 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -40,6 +40,8 @@
     <string name="recent_tasks_title" msgid="3691764623638127888">"最新的"</string>
     <!-- no translation found for recent_tasks_empty (1905484479067697884) -->
     <skip />
+    <!-- no translation found for recent_tasks_app_label (3796483981246752469) -->
+    <skip />
     <!-- no translation found for toast_rotation_free (2700542202836832631) -->
     <skip />
     <!-- no translation found for toast_rotation_locked (7484691306949652450) -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
index b174973..d3d2285 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/PhoneStatusBarService.java
@@ -298,7 +298,8 @@
                     | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                     | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
         lp.y += height * 1.5; // FIXME
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index 00b39c5..776b59c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -109,7 +109,8 @@
                 height,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR,
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING,
+                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.RGBX_8888);
         lp.gravity = getStatusBarGravity();
         lp.setTitle("StatusBar");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index 7ee3c19..09c8cd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -197,7 +197,8 @@
                 250,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
 //        int pos[] = new int[2];
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index 29f0fe2..da44f43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -153,7 +153,8 @@
                 ViewGroup.LayoutParams.WRAP_CONTENT,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
         lp.setTitle("NotificationPanel");
@@ -188,7 +189,8 @@
                 ViewGroup.LayoutParams.WRAP_CONTENT,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
         lp.setTitle("NotificationPeekWindow");
@@ -208,7 +210,8 @@
                 ViewGroup.LayoutParams.WRAP_CONTENT,
                 WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 PixelFormat.TRANSLUCENT);
         lp.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
         lp.setTitle("SystemPanel");
@@ -232,7 +235,8 @@
                     ViewGroup.LayoutParams.WRAP_CONTENT,
                     WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
                     WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                        | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                        | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                     PixelFormat.TRANSLUCENT);
             lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
             lp.setTitle("RecentsPanel");
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 1bded54..71bf956 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -22,6 +22,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
 
 import com.android.internal.view.BaseSurfaceHolder;
 import com.android.internal.view.RootViewSurfaceTaker;
@@ -497,7 +498,8 @@
                 WRAP_CONTENT, WRAP_CONTENT,
                 st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
                 WindowManager.LayoutParams.FLAG_DITHER
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
                 st.decorView.mDefaultOpacity);
 
         lp.gravity = st.gravity;
@@ -2164,6 +2166,12 @@
             setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags()));
         }
 
+        if (a.getBoolean(com.android.internal.R.styleable.Window_windowEnableSplitTouch,
+                getContext().getApplicationInfo().targetSdkVersion
+                        >= android.os.Build.VERSION_CODES.HONEYCOMB)) {
+            setFlags(FLAG_SPLIT_TOUCH, FLAG_SPLIT_TOUCH&(~getForcedWindowFlags()));
+        }
+
         if (getContext().getApplicationInfo().targetSdkVersion
                 < android.os.Build.VERSION_CODES.HONEYCOMB) {
             addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index edea2c5..b17584a 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -760,10 +760,8 @@
     AudioParameter param = AudioParameter();
     param.addInt(String8(AudioParameter::keyRouting), (int)inputDesc->mDevice);
 
-    // use Voice Recognition mode or not for this input based on input source
-    int vr_enabled = inputDesc->mInputSource == AUDIO_SOURCE_VOICE_RECOGNITION ? 1 : 0;
-    param.addInt(String8("vr_mode"), vr_enabled);
-    LOGV("AudioPolicyManager::startInput(%d), setting vr_mode to %d", inputDesc->mInputSource, vr_enabled);
+    param.addInt(String8(AudioParameter::keyInputSource), (int)inputDesc->mInputSource);
+    LOGV("AudioPolicyManager::startInput() input source = %d", inputDesc->mInputSource);
 
     mpClientInterface->setParameters(input, param.toString());
 
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 535f07f..a0013d0 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -277,6 +277,10 @@
 
 void CameraService::playSound(sound_kind kind) {
     LOG1("playSound(%d)", kind);
+    // FIXME: temporarily disable sound while working on audio HAL issues preventing simultaneous
+    // playback and record
+    if (kind == SOUND_RECORDING) return;
+
     Mutex::Autolock lock(mSoundLock);
     sp<MediaPlayer> player = mSoundPlayer[kind];
     if (player != 0) {
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 5ef3d35..ae408fc 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -803,6 +803,8 @@
             info.icon = ri.getIconResource();
             info.previewImage = sa.getResourceId(
             		com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0);
+            info.autoAdvanceViewId = sa.getResourceId(
+                    com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId, -1);
 
             sa.recycle();
         } catch (Exception e) {
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 68aa8e3..3dcad38 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -28,6 +28,8 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
 import android.app.admin.DeviceAdminInfo;
 import android.app.admin.DeviceAdminReceiver;
 import android.app.admin.DevicePolicyManager;
@@ -37,10 +39,13 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.net.ConnectivityManager;
 import android.os.Binder;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.IPowerManager;
 import android.os.PowerManager;
@@ -49,7 +54,6 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
-import android.net.Proxy;
 import android.provider.Settings;
 import android.util.Slog;
 import android.util.PrintWriterPrinter;
@@ -64,8 +68,9 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.net.InetSocketAddress;
+import java.text.DateFormat;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Set;
@@ -74,8 +79,20 @@
  * Implementation of the device policy APIs.
  */
 public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+    private static final int REQUEST_EXPIRE_PASSWORD = 5571;
+
     static final String TAG = "DevicePolicyManagerService";
 
+    private static final long EXPIRATION_GRACE_PERIOD_MS = 5 * 86400 * 1000; // 5 days, in ms
+
+    protected static final String ACTION_EXPIRED_PASSWORD_NOTIFICATION
+            = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
+
+    private static final long MS_PER_DAY = 86400 * 1000;
+    private static final long MS_PER_HOUR = 3600 * 1000;
+    private static final long MS_PER_MINUTE = 60 * 1000;
+    private static final long MIN_TIMEOUT = 86400 * 1000; // minimum expiration timeout is 1 day
+
     final Context mContext;
     final MyPackageMonitor mMonitor;
     final PowerManager.WakeLock mWakeLock;
@@ -93,12 +110,29 @@
     int mFailedPasswordAttempts = 0;
 
     int mPasswordOwner = -1;
+    Handler mHandler = new Handler();
 
     final HashMap<ComponentName, ActiveAdmin> mAdminMap
             = new HashMap<ComponentName, ActiveAdmin>();
     final ArrayList<ActiveAdmin> mAdminList
             = new ArrayList<ActiveAdmin>();
 
+    BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (Intent.ACTION_BOOT_COMPLETED.equals(action)
+                    || ACTION_EXPIRED_PASSWORD_NOTIFICATION.equals(action)) {
+                Slog.v(TAG, "Sending password expiration notifications for action " + action);
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        handlePasswordExpirationNotification();
+                    }
+                });
+            }
+        }
+    };
+
     static class ActiveAdmin {
         final DeviceAdminInfo info;
 
@@ -113,6 +147,8 @@
         int minimumPasswordNonLetter = 0;
         long maximumTimeToUnlock = 0;
         int maximumFailedPasswordsForWipe = 0;
+        long passwordExpirationTimeout = 0L;
+        long passwordExpirationDate = 0L;
 
         // TODO: review implementation decisions with frameworks team
         boolean specifiesGlobalProxy = false;
@@ -200,6 +236,16 @@
                     out.endTag(null, "global-proxy-exclusion-list");
                 }
             }
+            if (passwordExpirationTimeout != 0L) {
+                out.startTag(null, "password-expiration-timeout");
+                out.attribute(null, "value", Long.toString(passwordExpirationTimeout));
+                out.endTag(null, "password-expiration-timeout");
+            }
+            if (passwordExpirationDate != 0L) {
+                out.startTag(null, "password-expiration-date");
+                out.attribute(null, "value", Long.toString(passwordExpirationDate));
+                out.endTag(null, "password-expiration-date");
+            }
         }
 
         void readFromXml(XmlPullParser parser)
@@ -256,6 +302,12 @@
                 } else if ("global-proxy-exclusion-list".equals(tag)) {
                     globalProxyExclusionList =
                         parser.getAttributeValue(null, "value");
+                } else if ("password-expiration-timeout".equals(tag)) {
+                    passwordExpirationTimeout = Long.parseLong(
+                            parser.getAttributeValue(null, "value"));
+                } else if ("password-expiration-date".equals(tag)) {
+                    passwordExpirationDate = Long.parseLong(
+                            parser.getAttributeValue(null, "value"));
                 } else {
                     Slog.w(TAG, "Unknown admin tag: " + tag);
                 }
@@ -296,6 +348,10 @@
                     pw.println(maximumFailedPasswordsForWipe);
             pw.print(prefix); pw.print("specifiesGlobalProxy=");
                     pw.println(specifiesGlobalProxy);
+            pw.print(prefix); pw.print("passwordExpirationTimeout=");
+                    pw.println(passwordExpirationTimeout);
+            pw.print(prefix); pw.print("passwordExpirationDate=");
+                    pw.println(passwordExpirationDate);
             if (globalProxySpec != null) {
                 pw.print(prefix); pw.print("globalProxySpec=");
                         pw.println(globalProxySpec);
@@ -348,6 +404,38 @@
         mMonitor.register(context, true);
         mWakeLock = ((PowerManager)context.getSystemService(Context.POWER_SERVICE))
                 .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "DPM");
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+        filter.addAction(ACTION_EXPIRED_PASSWORD_NOTIFICATION);
+        context.registerReceiver(mReceiver, filter);
+    }
+
+    static String countdownString(long time) {
+        long days = time / MS_PER_DAY;
+        long hours = (time / MS_PER_HOUR) % 24;
+        long minutes = (time / MS_PER_MINUTE) % 60;
+        return days + "d" + hours + "h" + minutes + "m";
+    }
+
+    protected void setExpirationAlarmCheckLocked(Context context) {
+        final long expiration = getPasswordExpirationLocked(null);
+        final long now = System.currentTimeMillis();
+        final long timeToExpire = expiration - now;
+        final long alarmTime;
+        if (timeToExpire > 0L && timeToExpire < MS_PER_DAY) {
+            // Next expiration is less than a day, set alarm for exact expiration time
+            alarmTime = now + timeToExpire;
+        } else {
+            // Check again in 24 hours...
+            alarmTime = now + MS_PER_DAY;
+        }
+
+        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        PendingIntent pi = PendingIntent.getBroadcast(context, REQUEST_EXPIRE_PASSWORD,
+                new Intent(ACTION_EXPIRED_PASSWORD_NOTIFICATION),
+                PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
+        am.cancel(pi);
+        am.set(AlarmManager.RTC, alarmTime, pi);
     }
 
     private IPowerManager getIPowerManager() {
@@ -402,6 +490,9 @@
     void sendAdminCommandLocked(ActiveAdmin admin, String action) {
         Intent intent = new Intent(action);
         intent.setComponent(admin.info.getComponent());
+        if (action.equals(DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING)) {
+            intent.putExtra("expiration", admin.passwordExpirationDate);
+        }
         mContext.sendBroadcast(intent);
     }
 
@@ -696,6 +787,26 @@
         }
     }
 
+    private void handlePasswordExpirationNotification() {
+        synchronized (this) {
+            final long now = System.currentTimeMillis();
+            final int N = mAdminList.size();
+            if (N <= 0) {
+                return;
+            }
+            for (int i=0; i < N; i++) {
+                ActiveAdmin admin = mAdminList.get(i);
+                if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
+                        && admin.passwordExpirationTimeout > 0L
+                        && admin.passwordExpirationDate > 0L
+                        && now > admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS) {
+                    sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING);
+                }
+            }
+            setExpirationAlarmCheckLocked(mContext);
+        }
+    }
+
     public void setActiveAdmin(ComponentName adminReceiver) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
@@ -877,6 +988,74 @@
         }
     }
 
+    public void setPasswordExpirationTimeout(ComponentName who, long timeout) {
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            if (timeout != 0L && timeout < MIN_TIMEOUT) {
+                throw new IllegalArgumentException("Timeout must be > " + MIN_TIMEOUT + "ms");
+            }
+            ActiveAdmin ap = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD);
+            // Calling this API automatically bumps the expiration date
+            final long expiration = timeout > 0L ? (timeout + System.currentTimeMillis()) : 0L;
+            ap.passwordExpirationDate = expiration;
+            ap.passwordExpirationTimeout = timeout;
+            if (timeout > 0L) {
+                Slog.w(TAG, "setPasswordExpiration(): password will expire on "
+                        + DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)
+                        .format(new Date(expiration)));
+            }
+            saveSettingsLocked();
+            setExpirationAlarmCheckLocked(mContext); // in case this is the first one
+        }
+    }
+
+    public long getPasswordExpirationTimeout(ComponentName who) {
+        synchronized (this) {
+            long timeout = 0L;
+            if (who != null) {
+                ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+                return admin != null ? admin.passwordExpirationTimeout : timeout;
+            }
+
+            final int N = mAdminList.size();
+            for (int i = 0; i < N; i++) {
+                ActiveAdmin admin = mAdminList.get(i);
+                if (timeout == 0L || (admin.passwordExpirationTimeout != 0L
+                        && timeout > admin.passwordExpirationTimeout)) {
+                    timeout = admin.passwordExpirationTimeout;
+                }
+            }
+            return timeout;
+        }
+    }
+
+    private long getPasswordExpirationLocked(ComponentName who) {
+        long timeout = 0L;
+        if (who != null) {
+            ActiveAdmin admin = getActiveAdminUncheckedLocked(who);
+            return admin != null ? admin.passwordExpirationDate : timeout;
+        }
+
+        final int N = mAdminList.size();
+        for (int i = 0; i < N; i++) {
+            ActiveAdmin admin = mAdminList.get(i);
+            if (timeout == 0L || (admin.passwordExpirationDate != 0
+                    && timeout > admin.passwordExpirationDate)) {
+                timeout = admin.passwordExpirationDate;
+            }
+        }
+        return timeout;
+    }
+
+    public long getPasswordExpiration(ComponentName who) {
+        synchronized (this) {
+            return getPasswordExpirationLocked(who);
+        }
+    }
+
     public void setPasswordMinimumUpperCase(ComponentName who, int length) {
         synchronized (this) {
             if (who == null) {
@@ -1431,6 +1610,7 @@
                     mActivePasswordNonLetter = nonletter;
                     mFailedPasswordAttempts = 0;
                     saveSettingsLocked();
+                    updatePasswordExpirationsLocked();
                     sendAdminCommandLocked(DeviceAdminReceiver.ACTION_PASSWORD_CHANGED,
                             DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
                 } finally {
@@ -1440,6 +1620,20 @@
         }
     }
 
+    private void updatePasswordExpirationsLocked() {
+        final int N = mAdminList.size();
+        if (N > 0) {
+            for (int i=0; i<N; i++) {
+                ActiveAdmin admin = mAdminList.get(i);
+                if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
+                    admin.passwordExpirationDate = System.currentTimeMillis()
+                            + admin.passwordExpirationTimeout;
+                }
+            }
+            saveSettingsLocked();
+        }
+    }
+
     public void reportFailedPasswordAttempt() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.BIND_DEVICE_ADMIN, null);
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index d035eb5..0d3cfde 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -116,6 +116,7 @@
     static final long TIME_TO_RECONNECT = 10*1000;
 
     private static final int NOT_A_SUBTYPE_ID = -1;
+    private static final String NOT_A_SUBTYPE_ID_STR = String.valueOf(NOT_A_SUBTYPE_ID);
     // If IME doesn't support the system locale, the default subtype will be the first defined one.
     private static final int DEFAULT_SUBTYPE_ID = 0;
 
@@ -366,9 +367,7 @@
                                     if (!doit) {
                                         return true;
                                     }
-                                    Settings.Secure.putString(mContext.getContentResolver(),
-                                            Settings.Secure.DEFAULT_INPUT_METHOD, "");
-                                    resetSelectedInputMethodSubtype();
+                                    resetSelectedInputMethodAndSubtypeLocked("");
                                     chooseNewDefaultIMELocked();
                                     return true;
                                 }
@@ -425,9 +424,7 @@
                                 changed = true;
                                 curIm = null;
                                 Slog.i(TAG, "Unsetting current input method");
-                                Settings.Secure.putString(mContext.getContentResolver(),
-                                        Settings.Secure.DEFAULT_INPUT_METHOD, "");
-                                resetSelectedInputMethodSubtype();
+                                resetSelectedInputMethodAndSubtypeLocked("");
                             }
                         }
                     }
@@ -510,9 +507,7 @@
                 Slog.i(TAG, "No default found, using " + defIm.getId());
             }
             if (defIm != null) {
-                Settings.Secure.putString(mContext.getContentResolver(),
-                        Settings.Secure.DEFAULT_INPUT_METHOD, defIm.getId());
-                putSelectedInputMethodSubtype(defIm, NOT_A_SUBTYPE_ID);
+                setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
             }
         }
 
@@ -994,7 +989,7 @@
                     synchronized (mMethodMap) {
                         if (mCurMethod != null) {
                             try {
-                                putSelectedInputMethodSubtype(info, subtypeId);
+                                setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
                                 if (mInputShown) {
                                     // If mInputShown is false, there is no IME button on the
                                     // system bar.
@@ -1014,13 +1009,13 @@
 
         final long ident = Binder.clearCallingIdentity();
         try {
-            mCurMethodId = id;
             // Set a subtype to this input method.
             // subtypeId the name of a subtype which will be set.
-            putSelectedInputMethodSubtype(info, subtypeId);
-
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.DEFAULT_INPUT_METHOD, id);
+            setSelectedInputMethodAndSubtypeLocked(info, subtypeId, false);
+            // mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked()
+            // because mCurMethodId is stored as a history in
+            // setSelectedInputMethodAndSubtypeLocked().
+            mCurMethodId = id;
 
             if (ActivityManagerNative.isSystemReady()) {
                 Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
@@ -1487,9 +1482,7 @@
                 }
             }
             InputMethodInfo imi = enabled.get(i);
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.DEFAULT_INPUT_METHOD, imi.getId());
-            putSelectedInputMethodSubtype(imi, NOT_A_SUBTYPE_ID);
+            resetSelectedInputMethodAndSubtypeLocked(imi.getId());
             return true;
         }
 
@@ -1793,11 +1786,8 @@
                 String selId = Settings.Secure.getString(mContext.getContentResolver(),
                         Settings.Secure.DEFAULT_INPUT_METHOD);
                 if (id.equals(selId)) {
-                    Settings.Secure.putString(
-                            mContext.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD,
-                            enabledInputMethodsList.size() > 0
-                                    ? enabledInputMethodsList.get(0).first : "");
-                    resetSelectedInputMethodSubtype();
+                    resetSelectedInputMethodAndSubtypeLocked(enabledInputMethodsList.size() > 0
+                            ? enabledInputMethodsList.get(0).first : "");
                 }
                 // Previous state was enabled.
                 return true;
@@ -1809,22 +1799,56 @@
         }
     }
 
-    private void resetSelectedInputMethodSubtype() {
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, NOT_A_SUBTYPE_ID);
+    private void saveCurrentInputMethodAndSubtypeToHistory() {
+        String subtypeId = NOT_A_SUBTYPE_ID_STR;
+        if (mCurrentSubtype != null) {
+            subtypeId = String.valueOf(mCurrentSubtype.hashCode());
+        }
+        mSettings.addSubtypeToHistory(mCurMethodId, subtypeId);
     }
 
-    private void putSelectedInputMethodSubtype(InputMethodInfo imi, int subtypeId) {
-        final ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes();
-        if (subtypeId >= 0 && subtypeId < subtypes.size()) {
-            Settings.Secure.putInt(mContext.getContentResolver(),
-                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
-                    subtypes.get(subtypeId).hashCode());
-            mCurrentSubtype = subtypes.get(subtypeId);
-        } else {
-            resetSelectedInputMethodSubtype();
+    private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
+            boolean setSubtypeOnly) {
+        // Update the history of InputMethod and Subtype
+        saveCurrentInputMethodAndSubtypeToHistory();
+
+        // Set Subtype here
+        if (imi == null || subtypeId < 0) {
+            mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
             mCurrentSubtype = null;
+        } else {
+            final ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes();
+            if (subtypeId < subtypes.size()) {
+                mSettings.putSelectedSubtype(subtypes.get(subtypeId).hashCode());
+                mCurrentSubtype = subtypes.get(subtypeId);
+            } else {
+                mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
+                mCurrentSubtype = null;
+            }
         }
+
+        if (!setSubtypeOnly) {
+            // Set InputMethod here
+            mSettings.putSelectedInputMethod(imi != null ? imi.getId() : "");
+        }
+    }
+
+    private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) {
+        InputMethodInfo imi = mMethodMap.get(newDefaultIme);
+        int lastSubtypeId = NOT_A_SUBTYPE_ID;
+        // newDefaultIme is empty when there is no candidate for the selected IME.
+        if (imi != null && !TextUtils.isEmpty(newDefaultIme)) {
+            String subtypeHashCode = mSettings.getLastSubtypeForInputMethodLocked(newDefaultIme);
+            if (subtypeHashCode != null) {
+                try {
+                    lastSubtypeId = getSubtypeIdFromHashCode(
+                            imi, Integer.valueOf(subtypeHashCode));
+                } catch (NumberFormatException e) {
+                    Slog.w(TAG, "HashCode for subtype looks broken: " + subtypeHashCode, e);
+                }
+            }
+        }
+        setSelectedInputMethodAndSubtypeLocked(imi, lastSubtypeId, false);
     }
 
     private int getSelectedInputMethodSubtypeId(String id) {
@@ -1832,7 +1856,6 @@
         if (imi == null) {
             return NOT_A_SUBTYPE_ID;
         }
-        ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes();
         int subtypeId;
         try {
             subtypeId = Settings.Secure.getInt(mContext.getContentResolver(),
@@ -1840,9 +1863,14 @@
         } catch (SettingNotFoundException e) {
             return NOT_A_SUBTYPE_ID;
         }
+        return getSubtypeIdFromHashCode(imi, subtypeId);
+    }
+
+    private int getSubtypeIdFromHashCode(InputMethodInfo imi, int subtypeHashCode) {
+        ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes();
         for (int i = 0; i < subtypes.size(); ++i) {
             InputMethodSubtype ims = subtypes.get(i);
-            if (subtypeId == ims.hashCode()) {
+            if (subtypeHashCode == ims.hashCode()) {
                 return i;
             }
         }
@@ -1922,10 +1950,10 @@
         // example: ("ime0;subtype0;subtype1;subtype2:ime1:ime2;subtype0")
         private static final char INPUT_METHOD_SEPARATER = ':';
         private static final char INPUT_METHOD_SUBTYPE_SEPARATER = ';';
-        private final TextUtils.SimpleStringSplitter mStringColonSplitter =
+        private final TextUtils.SimpleStringSplitter mInputMethodSplitter =
                 new TextUtils.SimpleStringSplitter(INPUT_METHOD_SEPARATER);
 
-        private final TextUtils.SimpleStringSplitter mStringSemiColonSplitter =
+        private final TextUtils.SimpleStringSplitter mSubtypeSplitter =
                 new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER);
 
         private final ContentResolver mResolver;
@@ -1988,16 +2016,16 @@
             if (TextUtils.isEmpty(enabledInputMethodsStr)) {
                 return imsList;
             }
-            mStringColonSplitter.setString(enabledInputMethodsStr);
-            while (mStringColonSplitter.hasNext()) {
-                String nextImsStr = mStringColonSplitter.next();
-                mStringSemiColonSplitter.setString(nextImsStr);
-                if (mStringSemiColonSplitter.hasNext()) {
+            mInputMethodSplitter.setString(enabledInputMethodsStr);
+            while (mInputMethodSplitter.hasNext()) {
+                String nextImsStr = mInputMethodSplitter.next();
+                mSubtypeSplitter.setString(nextImsStr);
+                if (mSubtypeSplitter.hasNext()) {
                     ArrayList<String> subtypeHashes = new ArrayList<String>();
                     // The first element is ime id.
-                    String imeId = mStringSemiColonSplitter.next();
-                    while (mStringSemiColonSplitter.hasNext()) {
-                        subtypeHashes.add(mStringSemiColonSplitter.next());
+                    String imeId = mSubtypeSplitter.next();
+                    while (mSubtypeSplitter.hasNext()) {
+                        subtypeHashes.add(mSubtypeSplitter.next());
                     }
                     imsList.add(new Pair<String, ArrayList<String>>(imeId, subtypeHashes));
                 }
@@ -2083,8 +2111,161 @@
         private String getEnabledInputMethodsStr() {
             mEnabledInputMethodsStrCache = Settings.Secure.getString(
                     mResolver, Settings.Secure.ENABLED_INPUT_METHODS);
+            if (DEBUG) {
+                Slog.d(TAG, "getEnabledInputMethodsStr: " + mEnabledInputMethodsStrCache);
+            }
             return mEnabledInputMethodsStrCache;
         }
+
+        private void saveSubtypeHistory(
+                List<Pair<String, String>> savedImes, String newImeId, String newSubtypeId) {
+            StringBuilder builder = new StringBuilder();
+            boolean isImeAdded = false;
+            if (!TextUtils.isEmpty(newImeId) && !TextUtils.isEmpty(newSubtypeId)) {
+                builder.append(newImeId).append(INPUT_METHOD_SUBTYPE_SEPARATER).append(
+                        newSubtypeId);
+                isImeAdded = true;
+            }
+            for (Pair<String, String> ime: savedImes) {
+                String imeId = ime.first;
+                String subtypeId = ime.second;
+                if (TextUtils.isEmpty(subtypeId)) {
+                    subtypeId = NOT_A_SUBTYPE_ID_STR;
+                }
+                if (isImeAdded) {
+                    builder.append(INPUT_METHOD_SEPARATER);
+                } else {
+                    isImeAdded = true;
+                }
+                builder.append(imeId).append(INPUT_METHOD_SUBTYPE_SEPARATER).append(
+                        subtypeId);
+            }
+            // Remove the last INPUT_METHOD_SEPARATER
+            putSubtypeHistoryStr(builder.toString());
+        }
+
+        public void addSubtypeToHistory(String imeId, String subtypeId) {
+            List<Pair<String, String>> subtypeHistory = loadInputMethodAndSubtypeHistoryLocked();
+            for (Pair<String, String> ime: subtypeHistory) {
+                if (ime.first.equals(imeId)) {
+                    if (DEBUG) {
+                        Slog.v(TAG, "Subtype found in the history: " + imeId
+                                + ime.second);
+                    }
+                    // We should break here
+                    subtypeHistory.remove(ime);
+                    break;
+                }
+            }
+            saveSubtypeHistory(subtypeHistory, imeId, subtypeId);
+        }
+
+        private void putSubtypeHistoryStr(String str) {
+            if (DEBUG) {
+                Slog.d(TAG, "putSubtypeHistoryStr: " + str);
+            }
+            Settings.Secure.putString(
+                    mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY, str);
+        }
+
+        public Pair<String, String> getLastInputMethodAndSubtypeLocked() {
+            // Gets the first one from the history
+            return getLastSubtypeForInputMethodLockedInternal(null);
+        }
+
+        public String getLastSubtypeForInputMethodLocked(String imeId) {
+            Pair<String, String> ime = getLastSubtypeForInputMethodLockedInternal(imeId);
+            if (ime != null) {
+                return ime.second;
+            } else {
+                return null;
+            }
+        }
+
+        private Pair<String, String> getLastSubtypeForInputMethodLockedInternal(String imeId) {
+            List<Pair<String, ArrayList<String>>> enabledImes =
+                    getEnabledInputMethodsAndSubtypeListLocked();
+            List<Pair<String, String>> subtypeHistory = loadInputMethodAndSubtypeHistoryLocked();
+            for (Pair<String, String> imeAndSubtype: subtypeHistory) {
+                final String imeInTheHistory = imeAndSubtype.first;
+                // If imeId is empty, returns the first IME and subtype in the history
+                if (TextUtils.isEmpty(imeId) || imeInTheHistory.equals(imeId)) {
+                    final String subtypeInTheHistory = imeAndSubtype.second;
+                    final String subtypeHashCode = getEnabledSubtypeForInputMethodAndSubtypeLocked(
+                            enabledImes, imeInTheHistory, subtypeInTheHistory);
+                    if (!TextUtils.isEmpty(subtypeHashCode)) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Enabled subtype found in the history:" + subtypeHashCode);
+                        }
+                        return new Pair<String, String>(imeInTheHistory, subtypeHashCode);
+                    }
+                }
+            }
+            if (DEBUG) {
+                Slog.d(TAG, "No enabled IME found in the history");
+            }
+            return null;
+        }
+
+        private String getEnabledSubtypeForInputMethodAndSubtypeLocked(List<Pair<String,
+                ArrayList<String>>> enabledImes, String imeId, String subtypeHashCode) {
+            for (Pair<String, ArrayList<String>> enabledIme: enabledImes) {
+                if (enabledIme.first.equals(imeId)) {
+                    for (String s: enabledIme.second) {
+                        if (s.equals(subtypeHashCode)) {
+                            // If both imeId and subtypeId are enabled, return subtypeId.
+                            return s;
+                        }
+                    }
+                    // If imeId was enabled but subtypeId was disabled.
+                    return NOT_A_SUBTYPE_ID_STR;
+                }
+            }
+            // If both imeId and subtypeId are disabled, return null
+            return null;
+        }
+
+        private List<Pair<String, String>> loadInputMethodAndSubtypeHistoryLocked() {
+            ArrayList<Pair<String, String>> imsList = new ArrayList<Pair<String, String>>();
+            final String subtypeHistoryStr = getSubtypeHistoryStr();
+            if (TextUtils.isEmpty(subtypeHistoryStr)) {
+                return imsList;
+            }
+            mInputMethodSplitter.setString(subtypeHistoryStr);
+            while (mInputMethodSplitter.hasNext()) {
+                String nextImsStr = mInputMethodSplitter.next();
+                mSubtypeSplitter.setString(nextImsStr);
+                if (mSubtypeSplitter.hasNext()) {
+                    String subtypeId = NOT_A_SUBTYPE_ID_STR;
+                    // The first element is ime id.
+                    String imeId = mSubtypeSplitter.next();
+                    while (mSubtypeSplitter.hasNext()) {
+                        subtypeId = mSubtypeSplitter.next();
+                        break;
+                    }
+                    imsList.add(new Pair<String, String>(imeId, subtypeId));
+                }
+            }
+            return imsList;
+        }
+
+        private String getSubtypeHistoryStr() {
+            if (DEBUG) {
+                Slog.d(TAG, "getSubtypeHistoryStr: " + Settings.Secure.getString(
+                        mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY));
+            }
+            return Settings.Secure.getString(
+                    mResolver, Settings.Secure.INPUT_METHODS_SUBTYPE_HISTORY);
+        }
+
+        public void putSelectedInputMethod(String imeId) {
+            Settings.Secure.putString(mResolver, Settings.Secure.DEFAULT_INPUT_METHOD, imeId);
+        }
+
+        public void putSelectedSubtype(int subtypeId) {
+            Settings.Secure.putInt(
+                    mResolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, subtypeId);
+        }
     }
 
     // ----------------------------------------------------------------------
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index ba8d7d2..1ec8a22 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6702,9 +6702,14 @@
             if (info.broadcastIntentAction != null) {
                 sb.append("Broadcast-Intent-Action: ").append(info.broadcastIntentAction).append("\n");
             }
-            if (info != null && info.durationMillis != -1) {
+            if (info.durationMillis != -1) {
                 sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
             }
+            if (info.tags != null) {
+                for (String tag : info.tags) {
+                    sb.append("Span-Tag: ").append(tag).append("\n");
+                }
+            }
             sb.append("\n");
             if (info.crashInfo != null && info.crashInfo.stackTrace != null) {
                 sb.append(info.crashInfo.stackTrace);
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index c9ab992..b5e73ac 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -218,25 +218,13 @@
             break;
         }
 
+        recordLastValue(buffer, count);
+
         const SortedVector< wp<SensorEventConnection> > activeConnections(
                 getActiveConnections());
 
         size_t numConnections = activeConnections.size();
         if (numConnections) {
-            Mutex::Autolock _l(mLock);
-
-            // record the last event for each sensor
-            int32_t prev = buffer[0].sensor;
-            for (ssize_t i=1 ; i<count ; i++) {
-                // record the last event of each sensor type in this buffer
-                int32_t curr = buffer[i].sensor;
-                if (curr != prev) {
-                    mLastEventSeen.editValueFor(prev) = buffer[i-1];
-                    prev = curr;
-                }
-            }
-            mLastEventSeen.editValueFor(prev) = buffer[count-1];
-
             for (size_t i=0 ; i<numConnections ; i++) {
                 sp<SensorEventConnection> connection(activeConnections[i].promote());
                 if (connection != 0) {
@@ -251,6 +239,24 @@
     return false;
 }
 
+void SensorService::recordLastValue(
+        sensors_event_t const * buffer, size_t count)
+{
+    Mutex::Autolock _l(mLock);
+
+    // record the last event for each sensor
+    int32_t prev = buffer[0].sensor;
+    for (size_t i=1 ; i<count ; i++) {
+        // record the last event of each sensor type in this buffer
+        int32_t curr = buffer[i].sensor;
+        if (curr != prev) {
+            mLastEventSeen.editValueFor(prev) = buffer[i-1];
+            prev = curr;
+        }
+    }
+    mLastEventSeen.editValueFor(prev) = buffer[count-1];
+}
+
 SortedVector< wp<SensorService::SensorEventConnection> >
 SensorService::getActiveConnections() const
 {
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index dfb1c0e..b442779 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -111,6 +111,8 @@
     String8 getSensorName(int handle) const;
     status_t recomputeEventsPeriodLocked(int32_t handle);
 
+    void recordLastValue(sensors_event_t const * buffer, size_t count);
+
     // constants
     Vector<Sensor> mSensorList;
     struct sensors_poll_device_t* mSensorDevice;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 1b06843..7be58c6 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -340,8 +340,10 @@
 
     // NOTE: lcblk->resize() is protected by an internal lock
     status_t err = lcblk->resize(bufferCount);
-    if (err == NO_ERROR)
-        mBufferManager.resize(bufferCount);
+    if (err == NO_ERROR) {
+        EGLDisplay dpy(mFlinger->graphicPlane(0).getEGLDisplay());
+        mBufferManager.resize(bufferCount, mFlinger, dpy);
+    }
 
     return err;
 }
@@ -774,9 +776,52 @@
 {
 }
 
-status_t Layer::BufferManager::resize(size_t size)
+status_t Layer::BufferManager::resize(size_t size,
+        const sp<SurfaceFlinger>& flinger, EGLDisplay dpy)
 {
     Mutex::Autolock _l(mLock);
+
+    if (size < mNumBuffers) {
+        // Move the active texture into slot 0
+        BufferData activeBufferData = mBufferData[mActiveBuffer];
+        mBufferData[mActiveBuffer] = mBufferData[0];
+        mBufferData[0] = activeBufferData;
+        mActiveBuffer = 0;
+
+        // Free the buffers that are no longer needed.
+        for (size_t i = size; i < mNumBuffers; i++) {
+            mBufferData[i].buffer = 0;
+
+            // Create a message to destroy the textures on SurfaceFlinger's GL
+            // thread.
+            class MessageDestroyTexture : public MessageBase {
+                Image mTexture;
+                EGLDisplay mDpy;
+             public:
+                MessageDestroyTexture(const Image& texture, EGLDisplay dpy)
+                    : mTexture(texture), mDpy(dpy) { }
+                virtual bool handler() {
+                    status_t err = Layer::BufferManager::destroyTexture(
+                            &mTexture, mDpy);
+                    LOGE_IF(err<0, "error destroying texture: %d (%s)",
+                            mTexture.name, strerror(-err));
+                    return true; // XXX: err == 0;  ????
+                }
+            };
+
+            MessageDestroyTexture *msg = new MessageDestroyTexture(
+                    mBufferData[i].texture, dpy);
+
+            // Don't allow this texture to be cleaned up by
+            // BufferManager::destroy.
+            mBufferData[i].texture.name = -1U;
+            mBufferData[i].texture.image = EGL_NO_IMAGE_KHR;
+
+            // Post the message to the SurfaceFlinger object.
+            flinger->postMessageAsync(msg);
+        }
+    }
+
     mNumBuffers = size;
     return NO_ERROR;
 }
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index caa6d17..07434cf 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -177,7 +177,8 @@
         sp<GraphicBuffer> detachBuffer(size_t index);
         status_t attachBuffer(size_t index, const sp<GraphicBuffer>& buffer);
         // resize the number of active buffers
-        status_t resize(size_t size);
+        status_t resize(size_t size, const sp<SurfaceFlinger>& flinger,
+                EGLDisplay dpy);
 
         // ----------------------------------------------
         // must be called from GL thread
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index c59f2fd..2e785aa 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -786,10 +786,6 @@
 {
     // compute the invalid region
     mInvalidRegion.orSelf(mDirtyRegion);
-    if (mInvalidRegion.isEmpty()) {
-        // nothing to do
-        return;
-    }
 
     if (UNLIKELY(mDebugRegion)) {
         debugFlashRegions();
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 5f9a3e7..d74a547 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -380,7 +380,11 @@
                 break;
             case OFFHOOK:
                 Phone fgPhone = getFgPhone();
-                if (hasActiveFgCall() && !(fgPhone instanceof SipPhone)) {
+                // Enable IN_CALL mode while foreground call is in DIALING,
+                // ALERTING, ACTIVE and DISCONNECTING state and not from sipPhone
+                if (getActiveFgCallState() != Call.State.IDLE
+                        && getActiveFgCallState() != Call.State.DISCONNECTED
+                        && !(fgPhone instanceof SipPhone)) {
                     mode = AudioManager.MODE_IN_CALL;
                 }
                 break;
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index 2a21f6d..96c90a2 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -478,7 +478,7 @@
      *         {@code true} otherwise.
      */
     public synchronized boolean getDataEnabled() {
-        return dataEnabled[APN_DEFAULT_ID];
+        return (mMasterDataEnabled && dataEnabled[APN_DEFAULT_ID]);
     }
 
     /**
@@ -487,8 +487,8 @@
      * @return {@code false} if data connectivity has been explicitly disabled,
      *         {@code true} otherwise.
      */
-    public boolean getAnyDataEnabled() {
-        return (enabledCount != 0);
+    public synchronized boolean getAnyDataEnabled() {
+        return (mMasterDataEnabled && (enabledCount != 0));
     }
 
     protected abstract void startNetStatPoll();
@@ -832,7 +832,9 @@
 
     protected void onSetDataEnabled(boolean enable) {
         if (mMasterDataEnabled != enable) {
-            mMasterDataEnabled = enable;
+            synchronized (this) {
+                mMasterDataEnabled = enable;
+            }
             if (enable) {
                 mRetryMgr.resetRetryCount();
                 onTrySetupData(Phone.REASON_DATA_ENABLED);
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 2cbd63c..632615d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -251,7 +251,7 @@
     }
 
     @Override
-    public Phone getPhone() {
+    protected Phone getPhone() {
         return phone;
     }
 
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 50111f6..c62f4de 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -89,7 +89,6 @@
         // This first block of tests are for features for which Android
         // should pass all tests. They are skipped only temporarily.
         // TODO: Fix these failing tests and remove them from this list.
-        ignoreResultList.add("fast/encoding/char-encoding.html"); // fails in Java HTTP stack, see http://b/issue?id=3047156
         ignoreResultList.add("fast/encoding/char-decoding.html"); // fails in Java HTTP stack, see http://b/issue?id=3047156
         ignoreResultList.add("fast/encoding/hanarei-blog32-fc2-com.html"); // fails in Java HTTP stack, see http://b/issue?id=3046986
         ignoreResultList.add("fast/encoding/mailto-always-utf-8.html"); // Requires waitForPolicyDelegate(), see http://b/issue?id=3043468
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/EventSenderImpl.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/EventSenderImpl.java
index 68bcf11..d425734 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/EventSenderImpl.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/EventSenderImpl.java
@@ -56,21 +56,38 @@
     private static final int MSG_SET_TOUCH_MODIFIER = 16;
     private static final int MSG_CANCEL_TOUCH_POINT = 17;
 
-    public static class TouchPoint {
-        WebView mWebView;
-        private int mId;
+    private static class Point {
         private int mX;
         private int mY;
+
+        public Point(int x, int y) {
+            mX = x;
+            mY = y;
+        }
+        public int x() {
+            return mX;
+        }
+        public int y() {
+            return mY;
+        }
+    }
+
+    private Point createViewPointFromContentCoordinates(int x, int y) {
+        return new Point((int)(x * mWebView.getScale()) - mWebView.getScrollX(),
+                         (int)(y * mWebView.getScale()) - mWebView.getScrollY());
+    }
+
+    public static class TouchPoint {
+        private int mId;
+        private Point mPoint;
         private long mDownTime;
         private boolean mReleased = false;
         private boolean mMoved = false;
         private boolean mCancelled = false;
 
-        public TouchPoint(WebView webView, int id, int x, int y) {
-            mWebView = webView;
+        public TouchPoint(int id, Point point) {
             mId = id;
-            mX = scaleX(x);
-            mY = scaleY(y);
+            mPoint = point;
         }
 
         public int getId() {
@@ -78,20 +95,19 @@
         }
 
         public int getX() {
-            return mX;
+            return mPoint.x();
         }
 
         public int getY() {
-            return mY;
+            return mPoint.y();
         }
 
         public boolean hasMoved() {
             return mMoved;
         }
 
-        public void move(int newX, int newY) {
-            mX = scaleX(newX);
-            mY = scaleY(newY);
+        public void move(Point point) {
+            mPoint = point;
             mMoved = true;
         }
 
@@ -122,20 +138,11 @@
         public void cancel() {
             mCancelled = true;
         }
-
-        private int scaleX(int x) {
-            return (int)(x * mWebView.getScale()) - mWebView.getScrollX();
-        }
-
-        private int scaleY(int y) {
-            return (int)(y * mWebView.getScale()) - mWebView.getScrollY();
-        }
     }
 
     private List<TouchPoint> mTouchPoints;
     private int mTouchMetaState;
-    private int mMouseX;
-    private int mMouseY;
+    private Point mMousePoint;
 
     private WebView mWebView;
 
@@ -177,15 +184,19 @@
                 /** MOUSE */
 
                 case MSG_MOUSE_DOWN:
-                    ts = SystemClock.uptimeMillis();
-                    event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_DOWN, mMouseX, mMouseY, 0);
-                    mWebView.onTouchEvent(event);
+                    if (mMousePoint != null) {
+                        ts = SystemClock.uptimeMillis();
+                        event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_DOWN, mMousePoint.x(), mMousePoint.y(), 0);
+                        mWebView.onTouchEvent(event);
+                    }
                     break;
 
                 case MSG_MOUSE_UP:
-                    ts = SystemClock.uptimeMillis();
-                    event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_UP, mMouseX, mMouseY, 0);
-                    mWebView.onTouchEvent(event);
+                    if (mMousePoint != null) {
+                        ts = SystemClock.uptimeMillis();
+                        event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_UP, mMousePoint.x(), mMousePoint.y(), 0);
+                        mWebView.onTouchEvent(event);
+                    }
                     break;
 
                 case MSG_MOUSE_CLICK:
@@ -194,8 +205,7 @@
                     break;
 
                 case MSG_MOUSE_MOVE_TO:
-                    mMouseX = msg.arg1;
-                    mMouseY = msg.arg2;
+                    mMousePoint = createViewPointFromContentCoordinates(msg.arg1, msg.arg2);
                     break;
 
                 /** TOUCH */
@@ -208,8 +218,8 @@
                     } else {
                         id = getTouchPoints().get(numPoints - 1).getId() + 1;
                     }
-                    getTouchPoints().add(new TouchPoint(mWebView, id,
-                            msg.arg1, msg.arg2));
+                    getTouchPoints().add(
+                            new TouchPoint(id, createViewPointFromContentCoordinates(msg.arg1, msg.arg2)));
                     break;
 
                 case MSG_TOUCH_START:
@@ -232,7 +242,8 @@
                         break;
                     }
 
-                    getTouchPoints().get(index).move(bundle.getInt("x"), bundle.getInt("y"));
+                    getTouchPoints().get(index).move(
+                            createViewPointFromContentCoordinates(bundle.getInt("x"), bundle.getInt("y")));
                     break;
 
                 case MSG_TOUCH_MOVE:
@@ -333,8 +344,7 @@
         mWebView = webView;
         mTouchPoints = null;
         mTouchMetaState = 0;
-        mMouseX = 0;
-        mMouseY = 0;
+        mMousePoint = null;
     }
 
     public void enableDOMUIEventLogging(int domNode) {
diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath
index aeeffa6..7204ace 100644
--- a/tools/layoutlib/bridge/.classpath
+++ b/tools/layoutlib/bridge/.classpath
@@ -4,9 +4,9 @@
 	<classpathentry kind="src" path="tests"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
 	<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
-	<classpathentry kind="var" path="ANDROID_SRC/prebuilt/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
-	<classpathentry kind="var" path="ANDROID_SRC/prebuilt/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_SRC/dalvik/libcore/xml/src/main/java"/>
-	<classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/ninepatch.jar" sourcepath="/ANDROID_SRC/development/tools/ninepatch/src"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_SRC/prebuilt/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_PLAT_SRC/dalvik/libcore/xml/src/main/java"/>
+	<classpathentry kind="var" path="ANDROID_PLAT_OUT_FRAMEWORK/ninepatch.jar" sourcepath="/ANDROID_PLAT_SRC/development/tools/ninepatch/src"/>
 	<classpathentry kind="var" path="ANDROID_PLAT_SRC/out/host/common/obj/JAVA_LIBRARIES/temp_layoutlib_intermediates/javalib.jar" sourcepath="/ANDROID_PLAT_SRC/frameworks/base"/>
 	<classpathentry kind="output" path="bin"/>
 </classpath>
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index e97b1e6..392462f 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -17,7 +17,7 @@
 package android.graphics;
 
 import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Bitmap.Config;
 import android.os.Parcel;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index ce8e960..a5f3456 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -17,7 +17,7 @@
 package android.graphics;
 
 import com.android.layoutlib.api.ILayoutLog;
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Paint_Delegate.FontInfo;
 import android.text.TextUtils;
@@ -480,13 +480,9 @@
             graphics.setTransform(new AffineTransform());
 
             // set the color
-            graphics.setColor(new Color(color));
+            graphics.setColor(new Color(color, true /*alpha*/));
 
-            // set the mode and alpha.
-            int alpha = color >>> 24;
-            float falpha = alpha / 255.f;
-
-            setModeInGraphics(graphics, mode, falpha);
+            setModeInGraphics(graphics, mode);
 
             graphics.fillRect(0, 0, canvasDelegate.mBufferedImage.getWidth(),
                     canvasDelegate.mBufferedImage.getHeight());
@@ -996,15 +992,8 @@
             }
         }
 
-        // need to get the alpha to set it in the composite.
-        float falpha = 1.f;
-
         if (useColorPaint) {
-            g.setColor(new Color(paint.getColor()));
-
-            // the alpha is taken from the alpha channel of the color
-            int alpha = paint.getAlpha();
-            falpha = alpha / 255.f;
+            g.setColor(new Color(paint.getColor(), true /*hasAlpha*/));
         }
 
         int style = paint.getStyle();
@@ -1036,10 +1025,10 @@
         if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) {
             int mode = ((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode();
 
-            setModeInGraphics(g, mode, falpha);
+            setModeInGraphics(g, mode);
         } else {
             // default mode is src_over
-            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha));
+            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
 
             // if xfermode wasn't null, then it's something we don't support. log it.
             if (mLogger != null && xfermodeDelegate != null) {
@@ -1052,36 +1041,36 @@
         return g;
     }
 
-    private static void setModeInGraphics(Graphics2D g, int mode, float falpha) {
+    private static void setModeInGraphics(Graphics2D g, int mode) {
         for (PorterDuff.Mode m : PorterDuff.Mode.values()) {
             if (m.nativeInt == mode) {
-                setModeInGraphics(g, m, falpha);
+                setModeInGraphics(g, m);
                 return;
             }
         }
     }
 
-    private static void setModeInGraphics(Graphics2D g, PorterDuff.Mode mode, float falpha) {
+    private static void setModeInGraphics(Graphics2D g, PorterDuff.Mode mode) {
         switch (mode) {
             case CLEAR:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 1.0f /*alpha*/));
                 break;
             case DARKEN:
                 break;
             case DST:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST, 1.0f /*alpha*/));
                 break;
             case DST_ATOP:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_ATOP, 1.0f /*alpha*/));
                 break;
             case DST_IN:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_IN, 1.0f /*alpha*/));
                 break;
             case DST_OUT:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OUT, 1.0f /*alpha*/));
                 break;
             case DST_OVER:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.DST_OVER, 1.0f /*alpha*/));
                 break;
             case LIGHTEN:
                 break;
@@ -1090,22 +1079,22 @@
             case SCREEN:
                 break;
             case SRC:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, 1.0f /*alpha*/));
                 break;
             case SRC_ATOP:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0f /*alpha*/));
                 break;
             case SRC_IN:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, 1.0f /*alpha*/));
                 break;
             case SRC_OUT:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OUT, 1.0f /*alpha*/));
                 break;
             case SRC_OVER:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f /*alpha*/));
                 break;
             case XOR:
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.XOR, falpha));
+                g.setComposite(AlphaComposite.getInstance(AlphaComposite.XOR, 1.0f /*alpha*/));
                 break;
         }
     }
@@ -1156,12 +1145,6 @@
                 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                         RenderingHints.VALUE_INTERPOLATION_BILINEAR);
             }
-
-            if (paintDelegate.getAlpha() != 0xFF) {
-                c = g.getComposite();
-                g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
-                        paintDelegate.getAlpha()/255.f));
-            }
         }
 
         g.drawImage(image, dleft, dtop, dright, dbottom,
diff --git a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
index 59b6a91..7ee72d8 100644
--- a/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/DashPathEffect_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 /**
  * Delegate implementing the native methods of android.graphics.DashPathEffect
diff --git a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
index 405e537..7573dc1 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LinearGradient_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Shader.TileMode;
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index 0966f39..77de32d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -17,7 +17,7 @@
 package android.graphics;
 
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Matrix.ScaleToFit;
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index 6e90bdd..93f757a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Paint.FontMetrics;
 import android.graphics.Paint.FontMetricsInt;
@@ -114,10 +114,6 @@
         return mColor;
     }
 
-    public int getAlpha() {
-        return mColor >>> 24;
-    }
-
     public int getTextAlign() {
         return mTextAlign;
     }
@@ -260,7 +256,7 @@
             return 0;
         }
 
-        return delegate.getAlpha();
+        return delegate.mColor >>> 24;
     }
 
     /*package*/ static void setAlpha(Paint thisPaint, int a) {
diff --git a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
index 6827ae7..ce7eef0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PathEffect_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 /**
  * Delegate implementing the native methods of android.graphics.PathEffect
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
index c242e80..a5885ea 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 /**
  * Delegate implementing the native methods of android.graphics.PorterDuffXfermode
diff --git a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
index c4e764c..c36ce53 100644
--- a/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/RadialGradient_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import android.graphics.Shader.TileMode;
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
index 4dcf144..646ac80 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Shader_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 /**
  * Delegate implementing the native methods of android.graphics.Shader
diff --git a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
index 0492e4f..358c3c7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/SweepGradient_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 import java.awt.Paint;
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 7e90e7d..0b54a0e 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -16,8 +16,8 @@
 
 package android.graphics;
 
-import com.android.layoutlib.bridge.DelegateManager;
-import com.android.layoutlib.bridge.FontLoader;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.layoutlib.bridge.impl.FontLoader;
 
 import android.content.res.AssetManager;
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
index d4408cf..0c1170d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Xfermode_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.graphics;
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 /**
  * Delegate implementing the native methods of android.graphics.Xfermode
diff --git a/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java b/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java
index ed24e16..9ca1338 100644
--- a/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/util/FloatMath_Delegate.java
@@ -16,7 +16,7 @@
 
 package android.util;
 
-import com.android.layoutlib.bridge.DelegateManager;
+import com.android.layoutlib.bridge.impl.DelegateManager;
 
 /**
  * Delegate implementing the native methods of android.util.FloatMath
diff --git a/tools/layoutlib/bridge/src/android/view/SurfaceView.java b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
index ce32da9..f7db98a 100644
--- a/tools/layoutlib/bridge/src/android/view/SurfaceView.java
+++ b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
@@ -16,7 +16,7 @@
 
 package android.view;
 
-import com.android.layoutlib.bridge.MockView;
+import com.android.layoutlib.bridge.android.MockView;
 
 import android.content.Context;
 import android.graphics.Canvas;
diff --git a/tools/layoutlib/bridge/src/android/view/View_Delegate.java b/tools/layoutlib/bridge/src/android/view/View_Delegate.java
new file mode 100644
index 0000000..ee6694c
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/View_Delegate.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 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.view;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link View}
+ *
+ * Through the layoutlib_create tool, the original  methods of View have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class View_Delegate {
+
+    /*package*/ static boolean isInEditMode(View thisView) {
+        return true;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/android/webkit/WebView.java b/tools/layoutlib/bridge/src/android/webkit/WebView.java
index 3b66188..a20a9d1 100644
--- a/tools/layoutlib/bridge/src/android/webkit/WebView.java
+++ b/tools/layoutlib/bridge/src/android/webkit/WebView.java
@@ -16,7 +16,7 @@
 
 package android.webkit;
 
-import com.android.layoutlib.bridge.MockView;
+import com.android.layoutlib.bridge.android.MockView;
 
 import android.content.Context;
 import android.graphics.Bitmap;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 996a942..53da2ca 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -16,63 +16,26 @@
 
 package com.android.layoutlib.bridge;
 
-import com.android.internal.util.XmlUtils;
-import com.android.layoutlib.api.ILayoutBridge;
 import com.android.layoutlib.api.ILayoutLog;
-import com.android.layoutlib.api.ILayoutResult;
 import com.android.layoutlib.api.IProjectCallback;
 import com.android.layoutlib.api.IResourceValue;
-import com.android.layoutlib.api.IStyleResourceValue;
 import com.android.layoutlib.api.IXmlPullParser;
-import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
-import com.android.layoutlib.api.ILayoutResult.ILayoutViewInfo;
-import com.android.layoutlib.bridge.LayoutResult.LayoutViewInfo;
+import com.android.layoutlib.api.LayoutBridge;
+import com.android.layoutlib.api.SceneParams;
+import com.android.layoutlib.api.SceneResult;
+import com.android.layoutlib.bridge.android.BridgeAssetManager;
+import com.android.layoutlib.bridge.impl.FontLoader;
+import com.android.layoutlib.bridge.impl.LayoutSceneImpl;
 import com.android.ninepatch.NinePatch;
 import com.android.tools.layoutlib.create.MethodAdapter;
 import com.android.tools.layoutlib.create.OverrideMethod;
 
-import android.app.Fragment_Delegate;
-import android.content.ClipData;
-import android.content.res.Configuration;
 import android.graphics.Bitmap;
-import android.graphics.Bitmap_Delegate;
-import android.graphics.Canvas;
-import android.graphics.Canvas_Delegate;
-import android.graphics.Rect;
-import android.graphics.Region;
 import android.graphics.Typeface_Delegate;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.BridgeInflater;
-import android.view.DragEvent;
-import android.view.IWindow;
-import android.view.IWindowSession;
-import android.view.InputChannel;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
-import android.view.Surface;
-import android.view.SurfaceView;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.View.AttachInfo;
-import android.view.View.MeasureSpec;
-import android.view.WindowManager.LayoutParams;
-import android.widget.FrameLayout;
-import android.widget.TabHost;
-import android.widget.TabWidget;
 
-import java.awt.image.BufferedImage;
 import java.lang.ref.SoftReference;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -81,10 +44,7 @@
  * <p/>To use this bridge, simply instantiate an object of type {@link Bridge} and call
  * {@link #computeLayout(IXmlPullParser, Object, int, int, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}.
  */
-public final class Bridge implements ILayoutBridge {
-
-    private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
-    private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
+public final class Bridge extends LayoutBridge {
 
     public static class StaticMethodNotImplementedException extends RuntimeException {
         private static final long serialVersionUID = 1L;
@@ -143,34 +103,28 @@
         }
     };
 
-    /**
-     * Logger defined during a compute layout operation.
-     * <p/>
-     * This logger is generally set to {@link #sDefaultLogger} except during rendering
-     * operations when it might be set to a specific provided logger.
-     * <p/>
-     * To change this value, use a block synchronized on {@link #sDefaultLogger}.
-     */
-    private static ILayoutLog sLogger = sDefaultLogger;
-
-    /*
-     * (non-Javadoc)
-     * @see com.android.layoutlib.api.ILayoutBridge#getApiLevel()
-     */
+    @Override
     public int getApiLevel() {
-        return API_CURRENT;
+        return LayoutBridge.API_CURRENT;
     }
 
     /*
      * (non-Javadoc)
      * @see com.android.layoutlib.api.ILayoutLibBridge#init(java.lang.String, java.util.Map)
      */
-    public boolean init(
-            String fontOsLocation, Map<String, Map<String, Integer>> enumValueMap) {
+    @Override
+    public boolean init(String fontOsLocation, Map<String, Map<String, Integer>> enumValueMap) {
+        BridgeAssetManager.initSystem();
 
         return sinit(fontOsLocation, enumValueMap);
     }
 
+    @Override
+    public boolean dispose() {
+        BridgeAssetManager.clearSystem();
+        return true;
+    }
+
     private static synchronized boolean sinit(String fontOsLocation,
             Map<String, Map<String, Integer>> enumValueMap) {
 
@@ -189,12 +143,8 @@
             OverrideMethod.setDefaultListener(new MethodAdapter() {
                 @Override
                 public void onInvokeV(String signature, boolean isNative, Object caller) {
-                    if (sLogger != null) {
-                        synchronized (sDefaultLogger) {
-                            sLogger.error("Missing Stub: " + signature +
-                                    (isNative ? " (native)" : ""));
-                        }
-                    }
+                    sDefaultLogger.error("Missing Stub: " + signature +
+                            (isNative ? " (native)" : ""));
 
                     if (debug.equalsIgnoreCase("throw")) {
                         // Throwing this exception doesn't seem that useful. It breaks
@@ -207,20 +157,6 @@
             });
         }
 
-        // Override View.isInEditMode to return true.
-        //
-        // This allows custom views that are drawn in the Graphical Layout Editor to adapt their
-        // rendering for preview. Most important this let custom views know that they can't expect
-        // the rest of their activities to be alive.
-        OverrideMethod.setMethodListener("android.view.View#isInEditMode()Z",
-            new MethodAdapter() {
-                @Override
-                public int onInvokeI(String signature, boolean isNative, Object caller) {
-                    return 1;
-                }
-            }
-        );
-
         // load the fonts.
         FontLoader fontLoader = FontLoader.create(fontOsLocation);
         if (fontLoader != null) {
@@ -278,236 +214,82 @@
         return true;
     }
 
-    /*
-     * For compatilibty purposes, we implement the old deprecated version of computeLayout.
-     * (non-Javadoc)
-     * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
+    /**
+     * Sets a 9 patch in a project cache or in the framework cache.
+     * @param value the path of the 9 patch
+     * @param ninePatch the 9 patch object
+     * @param projectKey the key of the project, or null to put the bitmap in the framework cache.
      */
-    @Deprecated
-    public ILayoutResult computeLayout(IXmlPullParser layoutDescription,
-            Object projectKey,
-            int screenWidth, int screenHeight, String themeName,
-            Map<String, Map<String, IResourceValue>> projectResources,
-            Map<String, Map<String, IResourceValue>> frameworkResources,
-            IProjectCallback customViewLoader, ILayoutLog logger) {
-        boolean isProjectTheme = false;
-        if (themeName.charAt(0) == '*') {
-            themeName = themeName.substring(1);
-            isProjectTheme = true;
-        }
+    public static void setCached9Patch(String value, NinePatch ninePatch, Object projectKey) {
+        if (projectKey != null) {
+            Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey);
 
-        return computeLayout(layoutDescription, projectKey,
-                screenWidth, screenHeight, DisplayMetrics.DENSITY_DEFAULT,
-                DisplayMetrics.DENSITY_DEFAULT, DisplayMetrics.DENSITY_DEFAULT,
-                themeName, isProjectTheme,
-                projectResources, frameworkResources, customViewLoader, logger);
+            if (map == null) {
+                map = new HashMap<String, SoftReference<NinePatch>>();
+                sProject9PatchCache.put(projectKey, map);
+            }
+
+            map.put(value, new SoftReference<NinePatch>(ninePatch));
+        } else {
+            sFramework9PatchCache.put(value, new SoftReference<NinePatch>(ninePatch));
+        }
     }
 
-    /*
-     * For compatilibty purposes, we implement the old deprecated version of computeLayout.
-     * (non-Javadoc)
-     * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
+    /**
+     * Starts a layout session by inflating and rendering it. The method returns a
+     * {@link ILayoutScene} on which further actions can be taken.
+     *
+     * @param layoutDescription the {@link IXmlPullParser} letting the LayoutLib Bridge visit the
+     * layout file.
+     * @param projectKey An Object identifying the project. This is used for the cache mechanism.
+     * @param screenWidth the screen width
+     * @param screenHeight the screen height
+     * @param renderFullSize if true, the rendering will render the full size needed by the
+     * layout. This size is never smaller than <var>screenWidth</var> x <var>screenHeight</var>.
+     * @param density the density factor for the screen.
+     * @param xdpi the screen actual dpi in X
+     * @param ydpi the screen actual dpi in Y
+     * @param themeName The name of the theme to use.
+     * @param isProjectTheme true if the theme is a project theme, false if it is a framework theme.
+     * @param projectResources the resources of the project. The map contains (String, map) pairs
+     * where the string is the type of the resource reference used in the layout file, and the
+     * map contains (String, {@link IResourceValue}) pairs where the key is the resource name,
+     * and the value is the resource value.
+     * @param frameworkResources the framework resources. The map contains (String, map) pairs
+     * where the string is the type of the resource reference used in the layout file, and the map
+     * contains (String, {@link IResourceValue}) pairs where the key is the resource name, and the
+     * value is the resource value.
+     * @param projectCallback The {@link IProjectCallback} object to get information from
+     * the project.
+     * @param logger the object responsible for displaying warning/errors to the user.
+     * @return a new {@link ILayoutScene} object that contains the result of the layout.
+     * @since 5
      */
-    @Deprecated
-    public ILayoutResult computeLayout(IXmlPullParser layoutDescription, Object projectKey,
-            int screenWidth, int screenHeight, String themeName, boolean isProjectTheme,
-            Map<String, Map<String, IResourceValue>> projectResources,
-            Map<String, Map<String, IResourceValue>> frameworkResources,
-            IProjectCallback customViewLoader, ILayoutLog logger) {
-        return computeLayout(layoutDescription, projectKey,
-                screenWidth, screenHeight, DisplayMetrics.DENSITY_DEFAULT,
-                DisplayMetrics.DENSITY_DEFAULT, DisplayMetrics.DENSITY_DEFAULT,
-                themeName, isProjectTheme,
-                projectResources, frameworkResources, customViewLoader, logger);
-    }
-
-    /*
-     * For compatilibty purposes, we implement the old deprecated version of computeLayout.
-     * (non-Javadoc)
-     * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, int, float, float, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
-     */
-    public ILayoutResult computeLayout(IXmlPullParser layoutDescription, Object projectKey,
-            int screenWidth, int screenHeight, int density, float xdpi, float ydpi,
-            String themeName, boolean isProjectTheme,
-            Map<String, Map<String, IResourceValue>> projectResources,
-            Map<String, Map<String, IResourceValue>> frameworkResources,
-            IProjectCallback customViewLoader, ILayoutLog logger) {
-        return computeLayout(layoutDescription, projectKey,
-                screenWidth, screenHeight, false /* renderFullSize */,
-                density, xdpi, ydpi, themeName, isProjectTheme,
-                projectResources, frameworkResources, customViewLoader, logger);
-    }
-
-    /*
-     * (non-Javadoc)
-     * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, boolean, int, float, float, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
-     */
-    public ILayoutResult computeLayout(IXmlPullParser layoutDescription, Object projectKey,
-            int screenWidth, int screenHeight, boolean renderFullSize,
-            int density, float xdpi, float ydpi,
-            String themeName, boolean isProjectTheme,
-            Map<String, Map<String, IResourceValue>> projectResources,
-            Map<String, Map<String, IResourceValue>> frameworkResources,
-            IProjectCallback customViewLoader, ILayoutLog logger) {
-        if (logger == null) {
-            logger = sDefaultLogger;
-        }
-
-        synchronized (sDefaultLogger) {
-            sLogger = logger;
-        }
-
-        // find the current theme and compute the style inheritance map
-        Map<IStyleResourceValue, IStyleResourceValue> styleParentMap =
-            new HashMap<IStyleResourceValue, IStyleResourceValue>();
-
-        IStyleResourceValue currentTheme = computeStyleMaps(themeName, isProjectTheme,
-                projectResources.get(BridgeConstants.RES_STYLE),
-                frameworkResources.get(BridgeConstants.RES_STYLE), styleParentMap);
-
-        BridgeContext context = null;
+    @Override
+    public BridgeLayoutScene createScene(SceneParams params) {
         try {
-            // we need to make sure the Looper has been initialized for this thread.
-            // this is required for View that creates Handler objects.
-            if (Looper.myLooper() == null) {
-                Looper.prepare();
-            }
+            SceneResult lastResult = SceneResult.SUCCESS;
+            LayoutSceneImpl scene = null;
+            synchronized (this) {
+                try {
+                    scene = new LayoutSceneImpl(params);
 
-            // setup the display Metrics.
-            DisplayMetrics metrics = new DisplayMetrics();
-            metrics.densityDpi = density;
-            metrics.density = density / (float) DisplayMetrics.DENSITY_DEFAULT;
-            metrics.scaledDensity = metrics.density;
-            metrics.widthPixels = screenWidth;
-            metrics.heightPixels = screenHeight;
-            metrics.xdpi = xdpi;
-            metrics.ydpi = ydpi;
-
-            context = new BridgeContext(projectKey, metrics, currentTheme, projectResources,
-                    frameworkResources, styleParentMap, customViewLoader, logger);
-            BridgeInflater inflater = new BridgeInflater(context, customViewLoader);
-            context.setBridgeInflater(inflater);
-            inflater.setFactory2(context);
-
-            IResourceValue windowBackground = null;
-            int screenOffset = 0;
-            if (currentTheme != null) {
-                windowBackground = context.findItemInStyle(currentTheme, "windowBackground");
-                windowBackground = context.resolveResValue(windowBackground);
-
-                screenOffset = getScreenOffset(frameworkResources, currentTheme, context);
-            }
-
-            BridgeXmlBlockParser parser = new BridgeXmlBlockParser(layoutDescription,
-                    context, false /* platformResourceFlag */);
-
-            ViewGroup root = new FrameLayout(context);
-
-            // Sets the project callback (custom view loader) to the fragment delegate so that
-            // it can instantiate the custom Fragment.
-            Fragment_Delegate.setProjectCallback(customViewLoader);
-
-            View view = inflater.inflate(parser, root);
-
-            // post-inflate process. For now this supports TabHost/TabWidget
-            postInflateProcess(view, customViewLoader);
-
-            Fragment_Delegate.setProjectCallback(null);
-
-            // set the AttachInfo on the root view.
-            AttachInfo info = new AttachInfo(new WindowSession(), new Window(),
-                    new Handler(), null);
-            info.mHasWindowFocus = true;
-            info.mWindowVisibility = View.VISIBLE;
-            info.mInTouchMode = false; // this is so that we can display selections.
-            root.dispatchAttachedToWindow(info, 0);
-
-            // get the background drawable
-            if (windowBackground != null) {
-                Drawable d = ResourceHelper.getDrawable(windowBackground,
-                        context, true /* isFramework */);
-                root.setBackgroundDrawable(d);
-            }
-
-            // measure the views
-            int w_spec, h_spec;
-
-            if (renderFullSize) {
-                // measure the full size needed by the layout.
-                w_spec = MeasureSpec.makeMeasureSpec(screenWidth,
-                        MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size
-                h_spec = MeasureSpec.makeMeasureSpec(screenHeight - screenOffset,
-                        MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size
-                root.measure(w_spec, h_spec);
-
-                int neededWidth = root.getChildAt(0).getMeasuredWidth();
-                if (neededWidth > screenWidth) {
-                    screenWidth = neededWidth;
-                }
-
-                int neededHeight = root.getChildAt(0).getMeasuredHeight();
-                if (neededHeight > screenHeight - screenOffset) {
-                    screenHeight = neededHeight + screenOffset;
+                    scene.prepare();
+                    lastResult = scene.inflate();
+                    if (lastResult == SceneResult.SUCCESS) {
+                        lastResult = scene.render();
+                    }
+                } finally {
+                    if (scene != null) {
+                        scene.cleanup();
+                    }
                 }
             }
 
-            // remeasure with only the size we need
-            // This must always be done before the call to layout
-            w_spec = MeasureSpec.makeMeasureSpec(screenWidth, MeasureSpec.EXACTLY);
-            h_spec = MeasureSpec.makeMeasureSpec(screenHeight - screenOffset,
-                    MeasureSpec.EXACTLY);
-            root.measure(w_spec, h_spec);
-
-            // now do the layout.
-            root.layout(0, screenOffset, screenWidth, screenHeight);
-
-            // draw the views
-            // create the BufferedImage into which the layout will be rendered.
-            BufferedImage image = new BufferedImage(screenWidth, screenHeight - screenOffset,
-                    BufferedImage.TYPE_INT_ARGB);
-
-            // create an Android bitmap around the BufferedImage
-            Bitmap bitmap = Bitmap_Delegate.createBitmap(image, Density.getEnum(density));
-
-            // create a Canvas around the Android bitmap
-            Canvas canvas = new Canvas(bitmap);
-
-            // to set the logger, get the native delegate
-            Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
-            canvasDelegate.setLogger(logger);
-
-            root.draw(canvas);
-            canvasDelegate.dispose();
-
-            return new LayoutResult(
-                    visit(((ViewGroup)view).getChildAt(0), context),
-                    image);
-
-        } catch (PostInflateException e) {
-            return new LayoutResult(ILayoutResult.ERROR, "Error during post inflation process:\n"
-                    + e.getMessage());
-        } catch (Throwable e) {
-            // get the real cause of the exception.
-            Throwable t = e;
-            while (t.getCause() != null) {
-                t = t.getCause();
-            }
-
-            // log it
-            logger.error(t);
-
-            // then return with an ERROR status and the message from the real exception
-            return new LayoutResult(ILayoutResult.ERROR,
-                    t.getClass().getSimpleName() + ": " + t.getMessage());
-        } finally {
-            // Make sure to remove static references, otherwise we could not unload the lib
-            BridgeResources.clearSystem();
-            BridgeAssetManager.clearSystem();
-
-            // Remove the global logger
-            synchronized (sDefaultLogger) {
-                sLogger = sDefaultLogger;
-            }
+            return new BridgeLayoutScene(this, scene, lastResult);
+        } catch (Throwable t) {
+            t.printStackTrace();
+            return new BridgeLayoutScene(this, null, new SceneResult("error!", t));
         }
     }
 
@@ -515,6 +297,7 @@
      * (non-Javadoc)
      * @see com.android.layoutlib.api.ILayoutLibBridge#clearCaches(java.lang.Object)
      */
+    @Override
     public void clearCaches(Object projectKey) {
         if (projectKey != null) {
             sProjectBitmapCache.remove(projectKey);
@@ -556,7 +339,10 @@
         return null;
     }
 
-    static Map<String, Integer> getEnumValues(String attributeName) {
+    /**
+     * Returns the list of possible enums for a given attribute name.
+     */
+    public static Map<String, Integer> getEnumValues(String attributeName) {
         if (sEnumValueMap != null) {
             return sEnumValueMap.get(attributeName);
         }
@@ -565,358 +351,13 @@
     }
 
     /**
-     * Visits a View and its children and generate a {@link ILayoutViewInfo} containing the
-     * bounds of all the views.
-     * @param view the root View
-     * @param context the context.
-     */
-    private ILayoutViewInfo visit(View view, BridgeContext context) {
-        if (view == null) {
-            return null;
-        }
-
-        LayoutViewInfo result = new LayoutViewInfo(view.getClass().getName(),
-                context.getViewKey(view),
-                view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
-
-        if (view instanceof ViewGroup) {
-            ViewGroup group = ((ViewGroup) view);
-            int n = group.getChildCount();
-            ILayoutViewInfo[] children = new ILayoutViewInfo[n];
-            for (int i = 0; i < group.getChildCount(); i++) {
-                children[i] = visit(group.getChildAt(i), context);
-            }
-            result.setChildren(children);
-        }
-
-        return result;
-    }
-
-    /**
-     * Compute style information from the given list of style for the project and framework.
-     * @param themeName the name of the current theme.  In order to differentiate project and
-     * platform themes sharing the same name, all project themes must be prepended with
-     * a '*' character.
-     * @param isProjectTheme Is this a project theme
-     * @param inProjectStyleMap the project style map
-     * @param inFrameworkStyleMap the framework style map
-     * @param outInheritanceMap the map of style inheritance. This is filled by the method
-     * @return the {@link IStyleResourceValue} matching <var>themeName</var>
-     */
-    private IStyleResourceValue computeStyleMaps(
-            String themeName, boolean isProjectTheme, Map<String,
-            IResourceValue> inProjectStyleMap, Map<String, IResourceValue> inFrameworkStyleMap,
-            Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) {
-
-        if (inProjectStyleMap != null && inFrameworkStyleMap != null) {
-            // first, get the theme
-            IResourceValue theme = null;
-
-            // project theme names have been prepended with a *
-            if (isProjectTheme) {
-                theme = inProjectStyleMap.get(themeName);
-            } else {
-                theme = inFrameworkStyleMap.get(themeName);
-            }
-
-            if (theme instanceof IStyleResourceValue) {
-                // compute the inheritance map for both the project and framework styles
-                computeStyleInheritance(inProjectStyleMap.values(), inProjectStyleMap,
-                        inFrameworkStyleMap, outInheritanceMap);
-
-                // Compute the style inheritance for the framework styles/themes.
-                // Since, for those, the style parent values do not contain 'android:'
-                // we want to force looking in the framework style only to avoid using
-                // similarly named styles from the project.
-                // To do this, we pass null in lieu of the project style map.
-                computeStyleInheritance(inFrameworkStyleMap.values(), null /*inProjectStyleMap */,
-                        inFrameworkStyleMap, outInheritanceMap);
-
-                return (IStyleResourceValue)theme;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Compute the parent style for all the styles in a given list.
-     * @param styles the styles for which we compute the parent.
-     * @param inProjectStyleMap the map of project styles.
-     * @param inFrameworkStyleMap the map of framework styles.
-     * @param outInheritanceMap the map of style inheritance. This is filled by the method.
-     */
-    private void computeStyleInheritance(Collection<IResourceValue> styles,
-            Map<String, IResourceValue> inProjectStyleMap,
-            Map<String, IResourceValue> inFrameworkStyleMap,
-            Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) {
-        for (IResourceValue value : styles) {
-            if (value instanceof IStyleResourceValue) {
-                IStyleResourceValue style = (IStyleResourceValue)value;
-                IStyleResourceValue parentStyle = null;
-
-                // first look for a specified parent.
-                String parentName = style.getParentStyle();
-
-                // no specified parent? try to infer it from the name of the style.
-                if (parentName == null) {
-                    parentName = getParentName(value.getName());
-                }
-
-                if (parentName != null) {
-                    parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap);
-
-                    if (parentStyle != null) {
-                        outInheritanceMap.put(style, parentStyle);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Searches for and returns the {@link IStyleResourceValue} from a given name.
-     * <p/>The format of the name can be:
-     * <ul>
-     * <li>[android:]&lt;name&gt;</li>
-     * <li>[android:]style/&lt;name&gt;</li>
-     * <li>@[android:]style/&lt;name&gt;</li>
-     * </ul>
-     * @param parentName the name of the style.
-     * @param inProjectStyleMap the project style map. Can be <code>null</code>
-     * @param inFrameworkStyleMap the framework style map.
-     * @return The matching {@link IStyleResourceValue} object or <code>null</code> if not found.
-     */
-    private IStyleResourceValue getStyle(String parentName,
-            Map<String, IResourceValue> inProjectStyleMap,
-            Map<String, IResourceValue> inFrameworkStyleMap) {
-        boolean frameworkOnly = false;
-
-        String name = parentName;
-
-        // remove the useless @ if it's there
-        if (name.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
-            name = name.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
-        }
-
-        // check for framework identifier.
-        if (name.startsWith(BridgeConstants.PREFIX_ANDROID)) {
-            frameworkOnly = true;
-            name = name.substring(BridgeConstants.PREFIX_ANDROID.length());
-        }
-
-        // at this point we could have the format <type>/<name>. we want only the name as long as
-        // the type is style.
-        if (name.startsWith(BridgeConstants.REFERENCE_STYLE)) {
-            name = name.substring(BridgeConstants.REFERENCE_STYLE.length());
-        } else if (name.indexOf('/') != -1) {
-            return null;
-        }
-
-        IResourceValue parent = null;
-
-        // if allowed, search in the project resources.
-        if (frameworkOnly == false && inProjectStyleMap != null) {
-            parent = inProjectStyleMap.get(name);
-        }
-
-        // if not found, then look in the framework resources.
-        if (parent == null) {
-            parent = inFrameworkStyleMap.get(name);
-        }
-
-        // make sure the result is the proper class type and return it.
-        if (parent instanceof IStyleResourceValue) {
-            return (IStyleResourceValue)parent;
-        }
-
-        sLogger.error(String.format("Unable to resolve parent style name: %s", parentName));
-
-        return null;
-    }
-
-    /**
-     * Computes the name of the parent style, or <code>null</code> if the style is a root style.
-     */
-    private String getParentName(String styleName) {
-        int index = styleName.lastIndexOf('.');
-        if (index != -1) {
-            return styleName.substring(0, index);
-        }
-
-        return null;
-    }
-
-    /**
-     * Returns the top screen offset. This depends on whether the current theme defines the user
-     * of the title and status bars.
-     * @param frameworkResources The framework resources
-     * @param currentTheme The current theme
-     * @param context The context
-     * @return the pixel height offset
-     */
-    private int getScreenOffset(Map<String, Map<String, IResourceValue>> frameworkResources,
-            IStyleResourceValue currentTheme, BridgeContext context) {
-        int offset = 0;
-
-        // get the title bar flag from the current theme.
-        IResourceValue value = context.findItemInStyle(currentTheme, "windowNoTitle");
-
-        // because it may reference something else, we resolve it.
-        value = context.resolveResValue(value);
-
-        // if there's a value and it's true (default is false)
-        if (value == null || value.getValue() == null ||
-                XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
-            // default size of the window title bar
-            int defaultOffset = DEFAULT_TITLE_BAR_HEIGHT;
-
-            // get value from the theme.
-            value = context.findItemInStyle(currentTheme, "windowTitleSize");
-
-            // resolve it
-            value = context.resolveResValue(value);
-
-            if (value != null) {
-                // get the numerical value, if available
-                TypedValue typedValue = ResourceHelper.getValue(value.getValue());
-                if (typedValue != null) {
-                    // compute the pixel value based on the display metrics
-                    defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
-                }
-            }
-
-            offset += defaultOffset;
-        }
-
-        // get the fullscreen flag from the current theme.
-        value = context.findItemInStyle(currentTheme, "windowFullscreen");
-
-        // because it may reference something else, we resolve it.
-        value = context.resolveResValue(value);
-
-        if (value == null || value.getValue() == null ||
-                XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
-
-            // default value
-            int defaultOffset = DEFAULT_STATUS_BAR_HEIGHT;
-
-            // get the real value, first the list of Dimensions from the framework map
-            Map<String, IResourceValue> dimens = frameworkResources.get(BridgeConstants.RES_DIMEN);
-
-            // now get the value
-            value = dimens.get("status_bar_height");
-            if (value != null) {
-                TypedValue typedValue = ResourceHelper.getValue(value.getValue());
-                if (typedValue != null) {
-                    // compute the pixel value based on the display metrics
-                    defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
-                }
-            }
-
-            // add the computed offset.
-            offset += defaultOffset;
-        }
-
-        return offset;
-    }
-
-    /**
-     * Post process on a view hierachy that was just inflated.
-     * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the
-     * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
-     * based on the content of the {@link FrameLayout}.
-     * @param view the root view to process.
-     * @param projectCallback callback to the project.
-     */
-    private void postInflateProcess(View view, IProjectCallback projectCallback)
-            throws PostInflateException {
-        if (view instanceof TabHost) {
-            setupTabHost((TabHost)view, projectCallback);
-        } else if (view instanceof ViewGroup) {
-            ViewGroup group = (ViewGroup)view;
-            final int count = group.getChildCount();
-            for (int c = 0 ; c < count ; c++) {
-                View child = group.getChildAt(c);
-                postInflateProcess(child, projectCallback);
-            }
-        }
-    }
-
-    /**
-     * Sets up a {@link TabHost} object.
-     * @param tabHost the TabHost to setup.
-     * @param projectCallback The project callback object to access the project R class.
-     * @throws PostInflateException
-     */
-    private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
-            throws PostInflateException {
-        // look for the TabWidget, and the FrameLayout. They have their own specific names
-        View v = tabHost.findViewById(android.R.id.tabs);
-
-        if (v == null) {
-            throw new PostInflateException(
-                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
-        }
-
-        if ((v instanceof TabWidget) == false) {
-            throw new PostInflateException(String.format(
-                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
-                    "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
-        }
-
-        v = tabHost.findViewById(android.R.id.tabcontent);
-
-        if (v == null) {
-            // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty)
-            throw new PostInflateException(
-                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
-        }
-
-        if ((v instanceof FrameLayout) == false) {
-            throw new PostInflateException(String.format(
-                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
-                    "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
-        }
-
-        FrameLayout content = (FrameLayout)v;
-
-        // now process the content of the framelayout and dynamically create tabs for it.
-        final int count = content.getChildCount();
-
-        if (count == 0) {
-            throw new PostInflateException(
-                    "The FrameLayout for the TabHost has no content. Rendering failed.\n");
-        }
-
-        // this must be called before addTab() so that the TabHost searches its TabWidget
-        // and FrameLayout.
-        tabHost.setup();
-
-        // for each child of the framelayout, add a new TabSpec
-        for (int i = 0 ; i < count ; i++) {
-            View child = content.getChildAt(i);
-            String tabSpec = String.format("tab_spec%d", i+1);
-            int id = child.getId();
-            String[] resource = projectCallback.resolveResourceValue(id);
-            String name;
-            if (resource != null) {
-                name = resource[0]; // 0 is resource name, 1 is resource type.
-            } else {
-                name = String.format("Tab %d", i+1); // default name if id is unresolved.
-            }
-            tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
-        }
-    }
-
-    /**
      * Returns the bitmap for a specific path, from a specific project cache, or from the
      * framework cache.
      * @param value the path of the bitmap
      * @param projectKey the key of the project, or null to query the framework cache.
      * @return the cached Bitmap or null if not found.
      */
-    static Bitmap getCachedBitmap(String value, Object projectKey) {
+    public static Bitmap getCachedBitmap(String value, Object projectKey) {
         if (projectKey != null) {
             Map<String, SoftReference<Bitmap>> map = sProjectBitmapCache.get(projectKey);
             if (map != null) {
@@ -941,7 +382,7 @@
      * @param bmp the Bitmap object
      * @param projectKey the key of the project, or null to put the bitmap in the framework cache.
      */
-    static void setCachedBitmap(String value, Bitmap bmp, Object projectKey) {
+    public static void setCachedBitmap(String value, Bitmap bmp, Object projectKey) {
         if (projectKey != null) {
             Map<String, SoftReference<Bitmap>> map = sProjectBitmapCache.get(projectKey);
 
@@ -963,7 +404,7 @@
      * @param projectKey the key of the project, or null to query the framework cache.
      * @return the cached 9 patch or null if not found.
      */
-    static NinePatch getCached9Patch(String value, Object projectKey) {
+    public static NinePatch getCached9Patch(String value, Object projectKey) {
         if (projectKey != null) {
             Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey);
 
@@ -983,262 +424,69 @@
         return null;
     }
 
-    /**
-     * Sets a 9 patch in a project cache or in the framework cache.
-     * @param value the path of the 9 patch
-     * @param ninePatch the 9 patch object
-     * @param projectKey the key of the project, or null to put the bitmap in the framework cache.
+
+    // ---------- OBSOLETE API METHODS ----------
+
+    /*
+     * For compatilibty purposes, we implement the old deprecated version of computeLayout.
+     * (non-Javadoc)
+     * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
      */
-    static void setCached9Patch(String value, NinePatch ninePatch, Object projectKey) {
-        if (projectKey != null) {
-            Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey);
-
-            if (map == null) {
-                map = new HashMap<String, SoftReference<NinePatch>>();
-                sProject9PatchCache.put(projectKey, map);
-            }
-
-            map.put(value, new SoftReference<NinePatch>(ninePatch));
-        } else {
-            sFramework9PatchCache.put(value, new SoftReference<NinePatch>(ninePatch));
-        }
+    @Deprecated
+    public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription,
+            Object projectKey,
+            int screenWidth, int screenHeight, String themeName,
+            Map<String, Map<String, IResourceValue>> projectResources,
+            Map<String, Map<String, IResourceValue>> frameworkResources,
+            IProjectCallback customViewLoader, ILayoutLog logger) {
+        throw new UnsupportedOperationException();
     }
 
-    private static final class PostInflateException extends Exception {
-        private static final long serialVersionUID = 1L;
-
-        public PostInflateException(String message) {
-            super(message);
-        }
+    /*
+     * For compatilibty purposes, we implement the old deprecated version of computeLayout.
+     * (non-Javadoc)
+     * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
+     */
+    @Deprecated
+    public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription,
+            Object projectKey,
+            int screenWidth, int screenHeight, String themeName, boolean isProjectTheme,
+            Map<String, Map<String, IResourceValue>> projectResources,
+            Map<String, Map<String, IResourceValue>> frameworkResources,
+            IProjectCallback customViewLoader, ILayoutLog logger) {
+        throw new UnsupportedOperationException();
     }
 
-    /**
-     * Implementation of {@link IWindowSession} so that mSession is not null in
-     * the {@link SurfaceView}.
+    /*
+     * For compatilibty purposes, we implement the old deprecated version of computeLayout.
+     * (non-Javadoc)
+     * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, int, float, float, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
      */
-    private static final class WindowSession implements IWindowSession {
-
-        @SuppressWarnings("unused")
-        public int add(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3,
-                InputChannel outInputchannel)
-                throws RemoteException {
-            // pass for now.
-            return 0;
-        }
-
-        @SuppressWarnings("unused")
-        public int addWithoutInputChannel(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3)
-                throws RemoteException {
-            // pass for now.
-            return 0;
-        }
-
-        @SuppressWarnings("unused")
-        public void finishDrawing(IWindow arg0) throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void finishKey(IWindow arg0) throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public boolean getInTouchMode() throws RemoteException {
-            // pass for now.
-            return false;
-        }
-
-        @SuppressWarnings("unused")
-        public boolean performHapticFeedback(IWindow window, int effectId, boolean always) {
-            // pass for now.
-            return false;
-        }
-
-        @SuppressWarnings("unused")
-        public MotionEvent getPendingPointerMove(IWindow arg0) throws RemoteException {
-            // pass for now.
-            return null;
-        }
-
-        @SuppressWarnings("unused")
-        public MotionEvent getPendingTrackballMove(IWindow arg0) throws RemoteException {
-            // pass for now.
-            return null;
-        }
-
-        @SuppressWarnings("unused")
-        public int relayout(IWindow arg0, LayoutParams arg1, int arg2, int arg3, int arg4,
-                boolean arg4_5, Rect arg5, Rect arg6, Rect arg7, Configuration arg7b, Surface arg8)
-                throws RemoteException {
-            // pass for now.
-            return 0;
-        }
-
-        public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void remove(IWindow arg0) throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void setInTouchMode(boolean arg0) throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void setTransparentRegion(IWindow arg0, Region arg1) throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void setInsets(IWindow window, int touchable, Rect contentInsets,
-                Rect visibleInsets) {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public IBinder prepareDrag(IWindow window, boolean localOnly,
-                int thumbnailWidth, int thumbnailHeight, Surface outSurface)
-                throws RemoteException {
-            // pass for now
-            return null;
-        }
-
-        @SuppressWarnings("unused")
-        public boolean performDrag(IWindow window, IBinder dragToken,
-                float touchX, float touchY, float thumbCenterX, float thumbCenterY,
-                ClipData data)
-                throws RemoteException {
-            // pass for now
-            return false;
-        }
-
-        @SuppressWarnings("unused")
-        public void reportDropResult(IWindow window, boolean consumed) throws RemoteException {
-            // pass for now
-        }
-
-        @SuppressWarnings("unused")
-        public void dragRecipientEntered(IWindow window) throws RemoteException {
-            // pass for now
-        }
-
-        @SuppressWarnings("unused")
-        public void dragRecipientExited(IWindow window) throws RemoteException {
-            // pass for now
-        }
-
-        @SuppressWarnings("unused")
-        public void setWallpaperPosition(IBinder window, float x, float y,
-            float xStep, float yStep) {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void wallpaperOffsetsComplete(IBinder window) {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
-                int z, Bundle extras, boolean sync) {
-            // pass for now.
-            return null;
-        }
-
-        @SuppressWarnings("unused")
-        public void wallpaperCommandComplete(IBinder window, Bundle result) {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void closeSystemDialogs(String reason) {
-            // pass for now.
-        }
-
-        public IBinder asBinder() {
-            // pass for now.
-            return null;
-        }
+    @Deprecated
+    public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription,
+            Object projectKey,
+            int screenWidth, int screenHeight, int density, float xdpi, float ydpi,
+            String themeName, boolean isProjectTheme,
+            Map<String, Map<String, IResourceValue>> projectResources,
+            Map<String, Map<String, IResourceValue>> frameworkResources,
+            IProjectCallback customViewLoader, ILayoutLog logger) {
+        throw new UnsupportedOperationException();
     }
 
-    /**
-     * Implementation of {@link IWindow} to pass to the {@link AttachInfo}.
+    /*
+     * (non-Javadoc)
+     * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, boolean, int, float, float, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog)
      */
-    private static final class Window implements IWindow {
-
-        @SuppressWarnings("unused")
-        public void dispatchAppVisibility(boolean arg0) throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void dispatchGetNewSurface() throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void dispatchKey(KeyEvent arg0) throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void dispatchPointer(MotionEvent arg0, long arg1, boolean arg2) throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void dispatchTrackball(MotionEvent arg0, long arg1, boolean arg2) throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void executeCommand(String arg0, String arg1, ParcelFileDescriptor arg2)
-                throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void resized(int arg0, int arg1, Rect arg2, Rect arg3, boolean arg4, Configuration arg5)
-                throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void windowFocusChanged(boolean arg0, boolean arg1) throws RemoteException {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
-                boolean sync) {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void dispatchWallpaperCommand(String action, int x, int y,
-                int z, Bundle extras, boolean sync) {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void closeSystemDialogs(String reason) {
-            // pass for now.
-        }
-
-        @SuppressWarnings("unused")
-        public void dispatchDragEvent(DragEvent event) {
-            // pass for now.
-        }
-
-        public IBinder asBinder() {
-            // pass for now.
-            return null;
-        }
+    @Deprecated
+    public com.android.layoutlib.api.ILayoutResult computeLayout(IXmlPullParser layoutDescription,
+            Object projectKey,
+            int screenWidth, int screenHeight, boolean renderFullSize,
+            int density, float xdpi, float ydpi,
+            String themeName, boolean isProjectTheme,
+            Map<String, Map<String, IResourceValue>> projectResources,
+            Map<String, Map<String, IResourceValue>> frameworkResources,
+            IProjectCallback customViewLoader, ILayoutLog logger) {
+        throw new UnsupportedOperationException();
     }
 
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
new file mode 100644
index 0000000..8b67166
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeLayoutScene.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 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.layoutlib.bridge;
+
+import com.android.layoutlib.api.LayoutScene;
+import com.android.layoutlib.api.SceneResult;
+import com.android.layoutlib.api.ViewInfo;
+import com.android.layoutlib.bridge.impl.LayoutSceneImpl;
+
+import java.awt.image.BufferedImage;
+import java.util.Map;
+
+/**
+ * An implementation of {@link LayoutScene}.
+ *
+ * This is a pretty basic class that does almost nothing. All of the work is done in
+ * {@link LayoutSceneImpl}.
+ *
+ */
+public class BridgeLayoutScene extends LayoutScene {
+
+    private final Bridge mBridge;
+    private final LayoutSceneImpl mScene;
+    private SceneResult mLastResult;
+
+    @Override
+    public SceneResult getResult() {
+        return mLastResult;
+    }
+
+    @Override
+    public BufferedImage getImage() {
+        return mScene.getImage();
+    }
+
+    @Override
+    public ViewInfo getRootView() {
+        return mScene.getViewInfo();
+    }
+
+    @Override
+    public Map<String, String> getDefaultViewPropertyValues(Object viewObject) {
+        return mScene.getDefaultViewPropertyValues(viewObject);
+    }
+
+    @Override
+    public SceneResult render() {
+
+        synchronized (mBridge) {
+            try {
+                mScene.prepare();
+                mLastResult = mScene.render();
+            } finally {
+                mScene.cleanup();
+            }
+        }
+
+        return mLastResult;
+    }
+
+    @Override
+    public void dispose() {
+        // TODO Auto-generated method stub
+
+    }
+
+    /*package*/ BridgeLayoutScene(Bridge bridge, LayoutSceneImpl scene, SceneResult lastResult) {
+        mBridge = bridge;
+        mScene = scene;
+        mLastResult = lastResult;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/LayoutResult.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/LayoutResult.java
deleted file mode 100644
index c4c5225..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/LayoutResult.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (C) 2008 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.layoutlib.bridge;
-
-import com.android.layoutlib.api.ILayoutResult;
-
-import java.awt.image.BufferedImage;
-
-/**
- * Implementation of {@link ILayoutResult}
- */
-public final class LayoutResult implements ILayoutResult {
-
-    private final ILayoutViewInfo mRootView;
-    private final BufferedImage mImage;
-    private final int mSuccess;
-    private final String mErrorMessage;
-
-    /**
-     * Creates a {@link #SUCCESS} {@link ILayoutResult} with the specified params
-     * @param rootView
-     * @param image
-     */
-    public LayoutResult(ILayoutViewInfo rootView, BufferedImage image) {
-        mSuccess = SUCCESS;
-        mErrorMessage = null;
-        mRootView = rootView;
-        mImage = image;
-    }
-    
-    /**
-     * Creates a LayoutResult with a specific success code and associated message
-     * @param code
-     * @param message
-     */
-    public LayoutResult(int code, String message) {
-        mSuccess = code;
-        mErrorMessage = message;
-        mRootView = null;
-        mImage = null;
-    }
-
-    public int getSuccess() {
-        return mSuccess;
-    }
-
-    public String getErrorMessage() {
-        return mErrorMessage;
-    }
-
-    public BufferedImage getImage() {
-        return mImage;
-    }
-
-    public ILayoutViewInfo getRootView() {
-        return mRootView;
-    }
-    
-    /**
-     * Implementation of {@link ILayoutResult.ILayoutViewInfo}
-     */
-    public static final class LayoutViewInfo implements ILayoutViewInfo {
-        private final Object mKey;
-        private final String mName;
-        private final int mLeft;
-        private final int mRight;
-        private final int mTop;
-        private final int mBottom;
-        private ILayoutViewInfo[] mChildren;
-
-        public LayoutViewInfo(String name, Object key, int left, int top, int right, int bottom) {
-            mName = name;
-            mKey = key;
-            mLeft = left;
-            mRight = right;
-            mTop = top;
-            mBottom = bottom;
-        }
-        
-        public void setChildren(ILayoutViewInfo[] children) {
-            mChildren = children;
-        }
-
-        public ILayoutViewInfo[] getChildren() {
-            return mChildren;
-        }
-
-        public Object getViewKey() {
-            return mKey;
-        }
-
-        public String getName() {
-            return mName;
-        }
-
-        public int getLeft() {
-            return mLeft;
-        }
-
-        public int getTop() {
-            return mTop;
-        }
-
-        public int getRight() {
-            return mRight;
-        }
-
-        public int getBottom() {
-            return mBottom;
-        }
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeAssetManager.java
similarity index 89%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeAssetManager.java
index 71803fc..a825060 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeAssetManager.java
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
+
+import com.android.layoutlib.bridge.Bridge;
 
 import android.content.res.AssetManager;
 
@@ -28,7 +30,7 @@
      * <p/>
      * {@link Bridge} calls this method after setting up a new bridge.
      */
-    /*package*/ static AssetManager initSystem() {
+    /*package*/ public static AssetManager initSystem() {
         if (!(AssetManager.sSystem instanceof BridgeAssetManager)) {
             // Note that AssetManager() creates a system AssetManager and we override it
             // with our BridgeAssetManager.
@@ -42,7 +44,7 @@
      * Clears the static {@link AssetManager#sSystem} to make sure we don't leave objects
      * around that would prevent us from unloading the library.
      */
-    /*package*/ static void clearSystem() {
+    public static void clearSystem() {
         AssetManager.sSystem = null;
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
similarity index 98%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
index 9d6dd27..3835378 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentProvider.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentProvider.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
 
 import android.content.ContentProviderOperation;
 import android.content.ContentProviderResult;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java
similarity index 98%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java
index e15cb69..0257686 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContentResolver.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
 
 import android.content.ContentResolver;
 import android.content.Context;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
similarity index 93%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index b9899b2..02db2cf 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -14,12 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
 
 import com.android.layoutlib.api.ILayoutLog;
 import com.android.layoutlib.api.IProjectCallback;
 import com.android.layoutlib.api.IResourceValue;
 import com.android.layoutlib.api.IStyleResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.impl.TempResourceValue;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -50,7 +53,6 @@
 import android.os.Looper;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
-import android.view.BridgeInflater;
 import android.view.LayoutInflater;
 import android.view.View;
 
@@ -61,24 +63,29 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashMap;
+import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.Map.Entry;
 
 /**
- * Custom implementation of Context to handle non compiled resources.
+ * Custom implementation of Context/Activity to handle non compiled resources.
  */
 public final class BridgeContext extends Activity {
 
-    private final Resources mResources;
-    private final Theme mTheme;
+    private Resources mResources;
+    private Theme mTheme;
     private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
     private final IStyleResourceValue mThemeValues;
     private final Object mProjectKey;
+    private final DisplayMetrics mMetrics;
     private final Map<String, Map<String, IResourceValue>> mProjectResources;
     private final Map<String, Map<String, IResourceValue>> mFrameworkResources;
     private final Map<IStyleResourceValue, IStyleResourceValue> mStyleInheritanceMap;
 
+    private final Map<Object, Map<String, String>> mDefaultPropMaps =
+        new IdentityHashMap<Object, Map<String,String>>();
+
     // maps for dynamically generated id representing style objects (IStyleResourceValue)
     private Map<Integer, IStyleResourceValue> mDynamicIdToStyleMap;
     private Map<IStyleResourceValue, Integer> mStyleToDynamicIdMap;
@@ -105,28 +112,18 @@
      * contains (String, {@link IResourceValue}) pairs where the key is the resource name, and the
      * value is the resource value.
      * @param styleInheritanceMap
-     * @param customViewLoader
+     * @param projectCallback
      */
     public BridgeContext(Object projectKey, DisplayMetrics metrics,
             IStyleResourceValue currentTheme,
             Map<String, Map<String, IResourceValue>> projectResources,
             Map<String, Map<String, IResourceValue>> frameworkResources,
             Map<IStyleResourceValue, IStyleResourceValue> styleInheritanceMap,
-            IProjectCallback customViewLoader, ILayoutLog logger) {
+            IProjectCallback projectCallback, ILayoutLog logger) {
         mProjectKey = projectKey;
-        mProjectCallback = customViewLoader;
+        mMetrics = metrics;
+        mProjectCallback = projectCallback;
         mLogger = logger;
-        Configuration config = new Configuration();
-
-        AssetManager assetManager = BridgeAssetManager.initSystem();
-        mResources = BridgeResources.initSystem(
-                this,
-                assetManager,
-                metrics,
-                config,
-                customViewLoader);
-
-        mTheme = mResources.newTheme();
 
         mThemeValues = currentTheme;
         mProjectResources = projectResources;
@@ -137,6 +134,32 @@
         mFragments.mActivity = this;
     }
 
+    /**
+     * Initializes the {@link Resources} singleton to be linked to this {@link Context}, its
+     * {@link DisplayMetrics}, {@link Configuration}, and {@link IProjectCallback}.
+     *
+     * @see #disposeResources()
+     */
+    public void initResources() {
+        AssetManager assetManager = AssetManager.getSystem();
+        Configuration config = new Configuration();
+
+        mResources = BridgeResources.initSystem(
+                this,
+                assetManager,
+                mMetrics,
+                config,
+                mProjectCallback);
+        mTheme = mResources.newTheme();
+    }
+
+    /**
+     * Disposes the {@link Resources} singleton.
+     */
+    public void disposeResources() {
+        BridgeResources.disposeSystem();
+    }
+
     public void setBridgeInflater(BridgeInflater inflater) {
         mInflater = inflater;
     }
@@ -161,6 +184,9 @@
         return mLogger;
     }
 
+    public Map<String, String> getDefaultPropMap(Object key) {
+        return mDefaultPropMaps.get(key);
+    }
 
     // ------------- Activity Methods
 
@@ -266,6 +292,18 @@
             return null;
         }
 
+        Map<String, String> defaultPropMap = null;
+        if (parser != null) {
+            Object key = parser.getViewKey();
+            if (key != null) {
+                defaultPropMap = mDefaultPropMaps.get(key);
+                if (defaultPropMap == null) {
+                    defaultPropMap = new HashMap<String, String>();
+                    mDefaultPropMaps.put(key, defaultPropMap);
+                }
+            }
+        }
+
         boolean[] frameworkAttributes = new boolean[1];
         TreeMap<Integer, String> styleNameMap = searchAttrs(attrs, frameworkAttributes);
 
@@ -292,6 +330,10 @@
             // get the name from the int.
             String defStyleName = searchAttr(defStyleAttr);
 
+            if (defaultPropMap != null) {
+                defaultPropMap.put("style", defStyleName);
+            }
+
             // look for the style in the current theme, and its parent:
             if (mThemeValues != null) {
                 IResourceValue item = findItemInStyle(mThemeValues, defStyleName);
@@ -350,6 +392,11 @@
                     // if we found a value, we make sure this doesn't reference another value.
                     // So we resolve it.
                     if (resValue != null) {
+                        // put the first default value, before the resolution.
+                        if (defaultPropMap != null) {
+                            defaultPropMap.put(name, resValue.getValue());
+                        }
+
                         resValue = resolveResValue(resValue);
                     }
 
@@ -433,7 +480,7 @@
         // if resValue is null, but value is not null, this means it was not a reference.
         // we return the name/value wrapper in a IResourceValue
         if (resValue == null) {
-            return new ResourceValue(type, name, value);
+            return new TempResourceValue(type, name, value);
         }
 
         // we resolved a first reference, but we need to make sure this isn't a reference also.
@@ -453,7 +500,7 @@
      * @param value the value containing the reference to resolve.
      * @return a {@link IResourceValue} object or <code>null</code>
      */
-    IResourceValue resolveResValue(IResourceValue value) {
+    public IResourceValue resolveResValue(IResourceValue value) {
         if (value == null) {
             return null;
         }
@@ -661,7 +708,7 @@
      * @param itemName the name of the item to search for.
      * @return the {@link IResourceValue} object or <code>null</code>
      */
-    IResourceValue findItemInStyle(IStyleResourceValue style, String itemName) {
+    public IResourceValue findItemInStyle(IStyleResourceValue style, String itemName) {
         IResourceValue item = style.findItem(itemName);
 
         // if we didn't find it, we look in the parent style (if applicable)
@@ -1058,25 +1105,20 @@
 
     }
 
-    @SuppressWarnings("unused")
     @Override
-    public FileInputStream openFileInput(String arg0)
-            throws FileNotFoundException {
-        // TODO Auto-generated method stub
-        return null;
-    }
-
-    @SuppressWarnings("unused")
-    @Override
-    public FileOutputStream openFileOutput(String arg0, int arg1)
-            throws FileNotFoundException {
+    public FileInputStream openFileInput(String arg0) throws FileNotFoundException {
         // TODO Auto-generated method stub
         return null;
     }
 
     @Override
-    public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1,
-            CursorFactory arg2) {
+    public FileOutputStream openFileOutput(String arg0, int arg1) throws FileNotFoundException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public SQLiteDatabase openOrCreateDatabase(String arg0, int arg1, CursorFactory arg2) {
         // TODO Auto-generated method stub
         return null;
     }
@@ -1164,14 +1206,12 @@
 
     }
 
-    @SuppressWarnings("unused")
     @Override
     public void setWallpaper(Bitmap arg0) throws IOException {
         // TODO Auto-generated method stub
 
     }
 
-    @SuppressWarnings("unused")
     @Override
     public void setWallpaper(InputStream arg0) throws IOException {
         // TODO Auto-generated method stub
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
similarity index 97%
rename from tools/layoutlib/bridge/src/android/view/BridgeInflater.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
index 4bc8855..b4a28a6 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
@@ -14,20 +14,22 @@
  * limitations under the License.
  */
 
-package android.view;
+package com.android.layoutlib.bridge.android;
 
 import com.android.layoutlib.api.IProjectCallback;
 import com.android.layoutlib.api.IResourceValue;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.BridgeConstants;
-import com.android.layoutlib.bridge.BridgeContext;
-import com.android.layoutlib.bridge.BridgeXmlBlockParser;
 
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
 
 import android.content.Context;
 import android.util.AttributeSet;
+import android.view.InflateException;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
 
 import java.io.File;
 import java.io.FileReader;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
similarity index 97%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index 6358abb..46eb776 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
 
 import com.android.layoutlib.api.IProjectCallback;
 import com.android.layoutlib.api.IResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
 
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
@@ -64,21 +67,18 @@
             DisplayMetrics metrics,
             Configuration config,
             IProjectCallback projectCallback) {
-        if (!(Resources.mSystem instanceof BridgeResources)) {
-            Resources.mSystem = new BridgeResources(context,
-                    assets,
-                    metrics,
-                    config,
-                    projectCallback);
-        }
-        return Resources.mSystem;
+        return Resources.mSystem = new BridgeResources(context,
+                assets,
+                metrics,
+                config,
+                projectCallback);
     }
 
     /**
-     * Clears the static {@link Resources#mSystem} to make sure we don't leave objects
+     * Disposes the static {@link Resources#mSystem} to make sure we don't leave objects
      * around that would prevent us from unloading the library.
      */
-    /*package*/ static void clearSystem() {
+    /*package*/ static void disposeSystem() {
         if (Resources.mSystem instanceof BridgeResources) {
             ((BridgeResources)(Resources.mSystem)).mContext = null;
             ((BridgeResources)(Resources.mSystem)).mProjectCallback = null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
similarity index 98%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index 70c5bd7..c8dc9e6 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -14,11 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
 
 import com.android.internal.util.XmlUtils;
 import com.android.layoutlib.api.IResourceValue;
 import com.android.layoutlib.api.IStyleResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
 
 import org.kxml2.io.KXmlParser;
 import org.xmlpull.v1.XmlPullParser;
@@ -36,14 +39,12 @@
 import java.util.Map;
 
 /**
- * TODO: describe.
+ * Custom implementation of TypedArray to handle non compiled resources.
  */
 public final class BridgeTypedArray extends TypedArray {
 
-    @SuppressWarnings("hiding")
     private BridgeResources mResources;
     private BridgeContext mContext;
-    @SuppressWarnings("hiding")
     private IResourceValue[] mData;
     private String[] mNames;
     private final boolean mPlatformFile;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
new file mode 100644
index 0000000..4a7ab58
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 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.layoutlib.bridge.android;
+
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.view.DragEvent;
+import android.view.IWindow;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.View.AttachInfo;
+
+/**
+ * Implementation of {@link IWindow} to pass to the {@link AttachInfo}.
+ */
+public final class BridgeWindow implements IWindow {
+
+    public void dispatchAppVisibility(boolean arg0) throws RemoteException {
+        // pass for now.
+    }
+
+    public void dispatchGetNewSurface() throws RemoteException {
+        // pass for now.
+    }
+
+    public void dispatchKey(KeyEvent arg0) throws RemoteException {
+        // pass for now.
+    }
+
+    public void dispatchPointer(MotionEvent arg0, long arg1, boolean arg2) throws RemoteException {
+        // pass for now.
+    }
+
+    public void dispatchTrackball(MotionEvent arg0, long arg1, boolean arg2)
+    throws RemoteException {
+        // pass for now.
+    }
+
+    public void executeCommand(String arg0, String arg1, ParcelFileDescriptor arg2)
+            throws RemoteException {
+        // pass for now.
+    }
+
+    public void resized(int arg0, int arg1, Rect arg2, Rect arg3, boolean arg4, Configuration arg5)
+            throws RemoteException {
+        // pass for now.
+    }
+
+    public void windowFocusChanged(boolean arg0, boolean arg1) throws RemoteException {
+        // pass for now.
+    }
+
+    public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
+            boolean sync) {
+        // pass for now.
+    }
+
+    public void dispatchWallpaperCommand(String action, int x, int y,
+            int z, Bundle extras, boolean sync) {
+        // pass for now.
+    }
+
+    public void closeSystemDialogs(String reason) {
+        // pass for now.
+    }
+
+    public void dispatchDragEvent(DragEvent event) {
+        // pass for now.
+    }
+
+    public IBinder asBinder() {
+        // pass for now.
+        return null;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
new file mode 100644
index 0000000..74e5a65
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2010 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.layoutlib.bridge.android;
+
+import android.content.ClipData;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.IWindow;
+import android.view.IWindowSession;
+import android.view.InputChannel;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.WindowManager.LayoutParams;
+
+/**
+ * Implementation of {@link IWindowSession} so that mSession is not null in
+ * the {@link SurfaceView}.
+ */
+public final class BridgeWindowSession implements IWindowSession {
+
+    public int add(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3,
+            InputChannel outInputchannel)
+            throws RemoteException {
+        // pass for now.
+        return 0;
+    }
+
+    public int addWithoutInputChannel(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3)
+            throws RemoteException {
+        // pass for now.
+        return 0;
+    }
+
+    public void finishDrawing(IWindow arg0) throws RemoteException {
+        // pass for now.
+    }
+
+    public void finishKey(IWindow arg0) throws RemoteException {
+        // pass for now.
+    }
+
+    public boolean getInTouchMode() throws RemoteException {
+        // pass for now.
+        return false;
+    }
+
+    public boolean performHapticFeedback(IWindow window, int effectId, boolean always) {
+        // pass for now.
+        return false;
+    }
+
+    public MotionEvent getPendingPointerMove(IWindow arg0) throws RemoteException {
+        // pass for now.
+        return null;
+    }
+
+    public MotionEvent getPendingTrackballMove(IWindow arg0) throws RemoteException {
+        // pass for now.
+        return null;
+    }
+
+    public int relayout(IWindow arg0, LayoutParams arg1, int arg2, int arg3, int arg4,
+            boolean arg4_5, Rect arg5, Rect arg6, Rect arg7, Configuration arg7b, Surface arg8)
+            throws RemoteException {
+        // pass for now.
+        return 0;
+    }
+
+    public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
+        // pass for now.
+    }
+
+    public void remove(IWindow arg0) throws RemoteException {
+        // pass for now.
+    }
+
+    public void setInTouchMode(boolean arg0) throws RemoteException {
+        // pass for now.
+    }
+
+    public void setTransparentRegion(IWindow arg0, Region arg1) throws RemoteException {
+        // pass for now.
+    }
+
+    public void setInsets(IWindow window, int touchable, Rect contentInsets,
+            Rect visibleInsets) {
+        // pass for now.
+    }
+
+    public IBinder prepareDrag(IWindow window, boolean localOnly,
+            int thumbnailWidth, int thumbnailHeight, Surface outSurface)
+            throws RemoteException {
+        // pass for now
+        return null;
+    }
+
+    public boolean performDrag(IWindow window, IBinder dragToken,
+            float touchX, float touchY, float thumbCenterX, float thumbCenterY,
+            ClipData data)
+            throws RemoteException {
+        // pass for now
+        return false;
+    }
+
+    public void reportDropResult(IWindow window, boolean consumed) throws RemoteException {
+        // pass for now
+    }
+
+    public void dragRecipientEntered(IWindow window) throws RemoteException {
+        // pass for now
+    }
+
+    public void dragRecipientExited(IWindow window) throws RemoteException {
+        // pass for now
+    }
+
+    public void setWallpaperPosition(IBinder window, float x, float y,
+        float xStep, float yStep) {
+        // pass for now.
+    }
+
+    public void wallpaperOffsetsComplete(IBinder window) {
+        // pass for now.
+    }
+
+    public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
+            int z, Bundle extras, boolean sync) {
+        // pass for now.
+        return null;
+    }
+
+    public void wallpaperCommandComplete(IBinder window, Bundle result) {
+        // pass for now.
+    }
+
+    public void closeSystemDialogs(String reason) {
+        // pass for now.
+    }
+
+    public IBinder asBinder() {
+        // pass for now.
+        return null;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlBlockParser.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
similarity index 99%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlBlockParser.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
index d842a66..24f61c8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlBlockParser.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlBlockParser.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
 
 import com.android.layoutlib.api.IXmlPullParser;
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
similarity index 96%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlPullAttributes.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
index d145ff6..c99b70b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeXmlPullAttributes.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
 
 import com.android.layoutlib.api.IResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
 
 import org.xmlpull.v1.XmlPullParser;
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/MockView.java
similarity index 96%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/MockView.java
index 1ca3182..e5bddcb 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/MockView.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
 
 import android.content.Context;
 import android.graphics.Canvas;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java
similarity index 96%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java
index 2c92567..4efa631 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/NinePatchDrawable.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
 
 import com.android.ninepatch.NinePatch;
 
@@ -28,7 +28,7 @@
 
     private NinePatch m9Patch;
 
-    NinePatchDrawable(NinePatch ninePatch) {
+    public NinePatchDrawable(NinePatch ninePatch) {
         m9Patch = ninePatch;
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
similarity index 98%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/DelegateManager.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
index 3d9f960..169d751 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/DelegateManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.impl;
 
 import android.util.SparseArray;
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java
similarity index 99%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java
index de89a81..5d56370 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/FontLoader.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.impl;
 
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
new file mode 100644
index 0000000..b0316a3
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java
@@ -0,0 +1,694 @@
+/*
+ * Copyright (C) 2010 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.layoutlib.bridge.impl;
+
+import com.android.internal.util.XmlUtils;
+import com.android.layoutlib.api.IProjectCallback;
+import com.android.layoutlib.api.IResourceValue;
+import com.android.layoutlib.api.IStyleResourceValue;
+import com.android.layoutlib.api.LayoutBridge;
+import com.android.layoutlib.api.SceneParams;
+import com.android.layoutlib.api.SceneResult;
+import com.android.layoutlib.api.ViewInfo;
+import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
+import com.android.layoutlib.bridge.BridgeConstants;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeInflater;
+import com.android.layoutlib.bridge.android.BridgeWindow;
+import com.android.layoutlib.bridge.android.BridgeWindowSession;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+
+import android.app.Fragment_Delegate;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap_Delegate;
+import android.graphics.Canvas;
+import android.graphics.Canvas_Delegate;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.AttachInfo;
+import android.view.View.MeasureSpec;
+import android.widget.FrameLayout;
+import android.widget.TabHost;
+import android.widget.TabWidget;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Class managing a layout "scene".
+ *
+ * A scene is a stateful representation of a layout file. It is initialized with data coming through
+ * the {@link LayoutBridge} API to inflate the layout. Further actions and rendering can then
+ * be done on the layout.
+ *
+ */
+public class LayoutSceneImpl {
+
+    private static final int DEFAULT_TITLE_BAR_HEIGHT = 25;
+    private static final int DEFAULT_STATUS_BAR_HEIGHT = 25;
+
+    private final SceneParams mParams;
+
+    // scene state
+    private BridgeContext mContext;
+    private BridgeXmlBlockParser mBlockParser;
+    private BridgeInflater mInflater;
+    private IStyleResourceValue mCurrentTheme;
+    private int mScreenOffset;
+    private IResourceValue mWindowBackground;
+    private FrameLayout mViewRoot;
+
+    // information being returned through the API
+    private BufferedImage mImage;
+    private ViewInfo mViewInfo;
+
+    private static final class PostInflateException extends Exception {
+        private static final long serialVersionUID = 1L;
+
+        public PostInflateException(String message) {
+            super(message);
+        }
+    }
+
+    /**
+     * Creates a layout scene with all the information coming from the layout bridge API.
+     *
+     * This also calls {@link LayoutSceneImpl#prepare()}.
+     * <p>
+     * <b>THIS MUST BE INSIDE A SYNCHRONIZED BLOCK on the BRIDGE OBJECT.<b>
+     *
+     * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
+     */
+    public LayoutSceneImpl(SceneParams params) {
+        // we need to make sure the Looper has been initialized for this thread.
+        // this is required for View that creates Handler objects.
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        // copy the params.
+        mParams = new SceneParams(params);
+
+        // setup the display Metrics.
+        DisplayMetrics metrics = new DisplayMetrics();
+        metrics.densityDpi = mParams.getDensity();
+        metrics.density = mParams.getDensity() / (float) DisplayMetrics.DENSITY_DEFAULT;
+        metrics.scaledDensity = metrics.density;
+        metrics.widthPixels = mParams.getScreenWidth();
+        metrics.heightPixels = mParams.getScreenHeight();
+        metrics.xdpi = mParams.getXdpi();
+        metrics.ydpi = mParams.getYdpi();
+
+        // find the current theme and compute the style inheritance map
+        Map<IStyleResourceValue, IStyleResourceValue> styleParentMap =
+            new HashMap<IStyleResourceValue, IStyleResourceValue>();
+
+        mCurrentTheme = computeStyleMaps(mParams.getThemeName(), mParams.getIsProjectTheme(),
+                mParams.getProjectResources().get(BridgeConstants.RES_STYLE),
+                mParams.getFrameworkResources().get(BridgeConstants.RES_STYLE), styleParentMap);
+
+        // build the context
+        mContext = new BridgeContext(mParams.getProjectKey(), metrics, mCurrentTheme,
+                mParams.getProjectResources(), mParams.getFrameworkResources(),
+                styleParentMap, mParams.getProjectCallback(), mParams.getLogger());
+
+        // make sure the Resources object references the context (and other objects) for this
+        // scene
+        mContext.initResources();
+
+        // get the screen offset and window-background resource
+        mWindowBackground = null;
+        mScreenOffset = 0;
+        if (mCurrentTheme != null && mParams.isCustomBackgroundEnabled() == false) {
+            mWindowBackground = mContext.findItemInStyle(mCurrentTheme, "windowBackground");
+            mWindowBackground = mContext.resolveResValue(mWindowBackground);
+
+            mScreenOffset = getScreenOffset(mParams.getFrameworkResources(), mCurrentTheme, mContext);
+        }
+
+        // build the inflater and parser.
+        mInflater = new BridgeInflater(mContext, mParams.getProjectCallback());
+        mContext.setBridgeInflater(mInflater);
+        mInflater.setFactory2(mContext);
+
+        mBlockParser = new BridgeXmlBlockParser(mParams.getLayoutDescription(),
+                mContext, false /* platformResourceFlag */);
+    }
+
+    /**
+     * Prepares the scene for action.
+     * <p>
+     * <b>THIS MUST BE INSIDE A SYNCHRONIZED BLOCK on the BRIDGE OBJECT.<b>
+     */
+    public void prepare() {
+        // we need to make sure the Looper has been initialized for this thread.
+        // this is required for View that creates Handler objects.
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        // make sure the Resources object references the context (and other objects) for this
+        // scene
+        mContext.initResources();
+    }
+
+    /**
+     * Cleans up the scene after an action.
+     * <p>
+     * <b>THIS MUST BE INSIDE A SYNCHRONIZED BLOCK on the BRIDGE OBJECT.<b>
+     */
+    public void cleanup() {
+        // clean up the looper
+        Looper.sThreadLocal.remove();
+
+        // Make sure to remove static references, otherwise we could not unload the lib
+        mContext.disposeResources();
+    }
+
+    /**
+     * Inflates the layout.
+     * <p>
+     * <b>THIS MUST BE INSIDE A SYNCHRONIZED BLOCK on the BRIDGE OBJECT.<b>
+     */
+    public SceneResult inflate() {
+        try {
+
+            mViewRoot = new FrameLayout(mContext);
+
+            // Sets the project callback (custom view loader) to the fragment delegate so that
+            // it can instantiate the custom Fragment.
+            Fragment_Delegate.setProjectCallback(mParams.getProjectCallback());
+
+            View view = mInflater.inflate(mBlockParser, mViewRoot);
+
+            // post-inflate process. For now this supports TabHost/TabWidget
+            postInflateProcess(view, mParams.getProjectCallback());
+
+            Fragment_Delegate.setProjectCallback(null);
+
+            // set the AttachInfo on the root view.
+            AttachInfo info = new AttachInfo(new BridgeWindowSession(), new BridgeWindow(),
+                    new Handler(), null);
+            info.mHasWindowFocus = true;
+            info.mWindowVisibility = View.VISIBLE;
+            info.mInTouchMode = false; // this is so that we can display selections.
+            mViewRoot.dispatchAttachedToWindow(info, 0);
+
+            // get the background drawable
+            if (mWindowBackground != null) {
+                Drawable d = ResourceHelper.getDrawable(mWindowBackground,
+                        mContext, true /* isFramework */);
+                mViewRoot.setBackgroundDrawable(d);
+            }
+
+            return SceneResult.SUCCESS;
+        } catch (PostInflateException e) {
+            return new SceneResult("Error during post inflation process:\n" + e.getMessage());
+        } catch (Throwable e) {
+            // get the real cause of the exception.
+            Throwable t = e;
+            while (t.getCause() != null) {
+                t = t.getCause();
+            }
+
+            // log it
+            mParams.getLogger().error(t);
+
+            return new SceneResult("Unknown error during inflation.", t);
+        }
+    }
+
+    /**
+     * Renders the scene.
+     * <p>
+     * <b>THIS MUST BE INSIDE A SYNCHRONIZED BLOCK on the BRIDGE OBJECT.<b>
+     */
+    public SceneResult render() {
+        try {
+            if (mViewRoot == null) {
+                return new SceneResult("Layout has not been inflated!");
+            }
+            // measure the views
+            int w_spec, h_spec;
+
+            int renderScreenWidth = mParams.getScreenWidth();
+            int renderScreenHeight = mParams.getScreenHeight();
+
+            if (mParams.getRenderFullSize()) {
+                // measure the full size needed by the layout.
+                w_spec = MeasureSpec.makeMeasureSpec(renderScreenWidth,
+                        MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size
+                h_spec = MeasureSpec.makeMeasureSpec(renderScreenHeight - mScreenOffset,
+                        MeasureSpec.UNSPECIFIED); // this lets us know the actual needed size
+                mViewRoot.measure(w_spec, h_spec);
+
+                int neededWidth = mViewRoot.getChildAt(0).getMeasuredWidth();
+                if (neededWidth > renderScreenWidth) {
+                    renderScreenWidth = neededWidth;
+                }
+
+                int neededHeight = mViewRoot.getChildAt(0).getMeasuredHeight();
+                if (neededHeight > renderScreenHeight - mScreenOffset) {
+                    renderScreenHeight = neededHeight + mScreenOffset;
+                }
+            }
+
+            // remeasure with the size we need
+            // This must always be done before the call to layout
+            w_spec = MeasureSpec.makeMeasureSpec(renderScreenWidth, MeasureSpec.EXACTLY);
+            h_spec = MeasureSpec.makeMeasureSpec(renderScreenHeight - mScreenOffset,
+                    MeasureSpec.EXACTLY);
+            mViewRoot.measure(w_spec, h_spec);
+
+            // now do the layout.
+            mViewRoot.layout(0, mScreenOffset, renderScreenWidth, renderScreenHeight);
+
+            // draw the views
+            // create the BufferedImage into which the layout will be rendered.
+            mImage = new BufferedImage(renderScreenWidth, renderScreenHeight - mScreenOffset,
+                    BufferedImage.TYPE_INT_ARGB);
+
+            if (mParams.isCustomBackgroundEnabled()) {
+                Graphics2D gc = mImage.createGraphics();
+                gc.setColor(new Color(mParams.getCustomBackgroundColor(), true));
+                gc.fillRect(0, 0, renderScreenWidth, renderScreenHeight - mScreenOffset);
+                gc.dispose();
+            }
+
+            // create an Android bitmap around the BufferedImage
+            Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage,
+                    Density.getEnum(mParams.getDensity()));
+
+            // create a Canvas around the Android bitmap
+            Canvas canvas = new Canvas(bitmap);
+
+            // to set the logger, get the native delegate
+            Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
+            canvasDelegate.setLogger(mParams.getLogger());
+
+            mViewRoot.draw(canvas);
+            canvasDelegate.dispose();
+
+            mViewInfo = visit(((ViewGroup)mViewRoot).getChildAt(0), mContext);
+
+            // success!
+            return SceneResult.SUCCESS;
+        } catch (Throwable e) {
+            // get the real cause of the exception.
+            Throwable t = e;
+            while (t.getCause() != null) {
+                t = t.getCause();
+            }
+
+            // log it
+            mParams.getLogger().error(t);
+
+            return new SceneResult("Unknown error during inflation.", t);
+        }
+    }
+
+    /**
+     * Compute style information from the given list of style for the project and framework.
+     * @param themeName the name of the current theme.  In order to differentiate project and
+     * platform themes sharing the same name, all project themes must be prepended with
+     * a '*' character.
+     * @param isProjectTheme Is this a project theme
+     * @param inProjectStyleMap the project style map
+     * @param inFrameworkStyleMap the framework style map
+     * @param outInheritanceMap the map of style inheritance. This is filled by the method
+     * @return the {@link IStyleResourceValue} matching <var>themeName</var>
+     */
+    private IStyleResourceValue computeStyleMaps(
+            String themeName, boolean isProjectTheme, Map<String,
+            IResourceValue> inProjectStyleMap, Map<String, IResourceValue> inFrameworkStyleMap,
+            Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) {
+
+        if (inProjectStyleMap != null && inFrameworkStyleMap != null) {
+            // first, get the theme
+            IResourceValue theme = null;
+
+            // project theme names have been prepended with a *
+            if (isProjectTheme) {
+                theme = inProjectStyleMap.get(themeName);
+            } else {
+                theme = inFrameworkStyleMap.get(themeName);
+            }
+
+            if (theme instanceof IStyleResourceValue) {
+                // compute the inheritance map for both the project and framework styles
+                computeStyleInheritance(inProjectStyleMap.values(), inProjectStyleMap,
+                        inFrameworkStyleMap, outInheritanceMap);
+
+                // Compute the style inheritance for the framework styles/themes.
+                // Since, for those, the style parent values do not contain 'android:'
+                // we want to force looking in the framework style only to avoid using
+                // similarly named styles from the project.
+                // To do this, we pass null in lieu of the project style map.
+                computeStyleInheritance(inFrameworkStyleMap.values(), null /*inProjectStyleMap */,
+                        inFrameworkStyleMap, outInheritanceMap);
+
+                return (IStyleResourceValue)theme;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Compute the parent style for all the styles in a given list.
+     * @param styles the styles for which we compute the parent.
+     * @param inProjectStyleMap the map of project styles.
+     * @param inFrameworkStyleMap the map of framework styles.
+     * @param outInheritanceMap the map of style inheritance. This is filled by the method.
+     */
+    private void computeStyleInheritance(Collection<IResourceValue> styles,
+            Map<String, IResourceValue> inProjectStyleMap,
+            Map<String, IResourceValue> inFrameworkStyleMap,
+            Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) {
+        for (IResourceValue value : styles) {
+            if (value instanceof IStyleResourceValue) {
+                IStyleResourceValue style = (IStyleResourceValue)value;
+                IStyleResourceValue parentStyle = null;
+
+                // first look for a specified parent.
+                String parentName = style.getParentStyle();
+
+                // no specified parent? try to infer it from the name of the style.
+                if (parentName == null) {
+                    parentName = getParentName(value.getName());
+                }
+
+                if (parentName != null) {
+                    parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap);
+
+                    if (parentStyle != null) {
+                        outInheritanceMap.put(style, parentStyle);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Searches for and returns the {@link IStyleResourceValue} from a given name.
+     * <p/>The format of the name can be:
+     * <ul>
+     * <li>[android:]&lt;name&gt;</li>
+     * <li>[android:]style/&lt;name&gt;</li>
+     * <li>@[android:]style/&lt;name&gt;</li>
+     * </ul>
+     * @param parentName the name of the style.
+     * @param inProjectStyleMap the project style map. Can be <code>null</code>
+     * @param inFrameworkStyleMap the framework style map.
+     * @return The matching {@link IStyleResourceValue} object or <code>null</code> if not found.
+     */
+    private IStyleResourceValue getStyle(String parentName,
+            Map<String, IResourceValue> inProjectStyleMap,
+            Map<String, IResourceValue> inFrameworkStyleMap) {
+        boolean frameworkOnly = false;
+
+        String name = parentName;
+
+        // remove the useless @ if it's there
+        if (name.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
+            name = name.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
+        }
+
+        // check for framework identifier.
+        if (name.startsWith(BridgeConstants.PREFIX_ANDROID)) {
+            frameworkOnly = true;
+            name = name.substring(BridgeConstants.PREFIX_ANDROID.length());
+        }
+
+        // at this point we could have the format <type>/<name>. we want only the name as long as
+        // the type is style.
+        if (name.startsWith(BridgeConstants.REFERENCE_STYLE)) {
+            name = name.substring(BridgeConstants.REFERENCE_STYLE.length());
+        } else if (name.indexOf('/') != -1) {
+            return null;
+        }
+
+        IResourceValue parent = null;
+
+        // if allowed, search in the project resources.
+        if (frameworkOnly == false && inProjectStyleMap != null) {
+            parent = inProjectStyleMap.get(name);
+        }
+
+        // if not found, then look in the framework resources.
+        if (parent == null) {
+            parent = inFrameworkStyleMap.get(name);
+        }
+
+        // make sure the result is the proper class type and return it.
+        if (parent instanceof IStyleResourceValue) {
+            return (IStyleResourceValue)parent;
+        }
+
+        mParams.getLogger().error(
+                String.format("Unable to resolve parent style name: %s", parentName));
+
+        return null;
+    }
+
+    /**
+     * Computes the name of the parent style, or <code>null</code> if the style is a root style.
+     */
+    private String getParentName(String styleName) {
+        int index = styleName.lastIndexOf('.');
+        if (index != -1) {
+            return styleName.substring(0, index);
+        }
+
+        return null;
+    }
+
+    /**
+     * Returns the top screen offset. This depends on whether the current theme defines the user
+     * of the title and status bars.
+     * @param frameworkResources The framework resources
+     * @param currentTheme The current theme
+     * @param context The context
+     * @return the pixel height offset
+     */
+    private int getScreenOffset(Map<String, Map<String, IResourceValue>> frameworkResources,
+            IStyleResourceValue currentTheme, BridgeContext context) {
+        int offset = 0;
+
+        // get the title bar flag from the current theme.
+        IResourceValue value = context.findItemInStyle(currentTheme, "windowNoTitle");
+
+        // because it may reference something else, we resolve it.
+        value = context.resolveResValue(value);
+
+        // if there's a value and it's true (default is false)
+        if (value == null || value.getValue() == null ||
+                XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
+            // default size of the window title bar
+            int defaultOffset = DEFAULT_TITLE_BAR_HEIGHT;
+
+            // get value from the theme.
+            value = context.findItemInStyle(currentTheme, "windowTitleSize");
+
+            // resolve it
+            value = context.resolveResValue(value);
+
+            if (value != null) {
+                // get the numerical value, if available
+                TypedValue typedValue = ResourceHelper.getValue(value.getValue());
+                if (typedValue != null) {
+                    // compute the pixel value based on the display metrics
+                    defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
+                }
+            }
+
+            offset += defaultOffset;
+        }
+
+        // get the fullscreen flag from the current theme.
+        value = context.findItemInStyle(currentTheme, "windowFullscreen");
+
+        // because it may reference something else, we resolve it.
+        value = context.resolveResValue(value);
+
+        if (value == null || value.getValue() == null ||
+                XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
+
+            // default value
+            int defaultOffset = DEFAULT_STATUS_BAR_HEIGHT;
+
+            // get the real value, first the list of Dimensions from the framework map
+            Map<String, IResourceValue> dimens = frameworkResources.get(BridgeConstants.RES_DIMEN);
+
+            // now get the value
+            value = dimens.get("status_bar_height");
+            if (value != null) {
+                TypedValue typedValue = ResourceHelper.getValue(value.getValue());
+                if (typedValue != null) {
+                    // compute the pixel value based on the display metrics
+                    defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
+                }
+            }
+
+            // add the computed offset.
+            offset += defaultOffset;
+        }
+
+        return offset;
+
+    }
+
+    /**
+     * Post process on a view hierachy that was just inflated.
+     * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the
+     * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
+     * based on the content of the {@link FrameLayout}.
+     * @param view the root view to process.
+     * @param projectCallback callback to the project.
+     */
+    private void postInflateProcess(View view, IProjectCallback projectCallback)
+            throws PostInflateException {
+        if (view instanceof TabHost) {
+            setupTabHost((TabHost)view, projectCallback);
+        } else if (view instanceof ViewGroup) {
+            ViewGroup group = (ViewGroup)view;
+            final int count = group.getChildCount();
+            for (int c = 0 ; c < count ; c++) {
+                View child = group.getChildAt(c);
+                postInflateProcess(child, projectCallback);
+            }
+        }
+    }
+
+    /**
+     * Sets up a {@link TabHost} object.
+     * @param tabHost the TabHost to setup.
+     * @param projectCallback The project callback object to access the project R class.
+     * @throws PostInflateException
+     */
+    private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback)
+            throws PostInflateException {
+        // look for the TabWidget, and the FrameLayout. They have their own specific names
+        View v = tabHost.findViewById(android.R.id.tabs);
+
+        if (v == null) {
+            throw new PostInflateException(
+                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
+        }
+
+        if ((v instanceof TabWidget) == false) {
+            throw new PostInflateException(String.format(
+                    "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
+                    "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
+        }
+
+        v = tabHost.findViewById(android.R.id.tabcontent);
+
+        if (v == null) {
+            // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty)
+            throw new PostInflateException(
+                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
+        }
+
+        if ((v instanceof FrameLayout) == false) {
+            throw new PostInflateException(String.format(
+                    "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
+                    "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
+        }
+
+        FrameLayout content = (FrameLayout)v;
+
+        // now process the content of the framelayout and dynamically create tabs for it.
+        final int count = content.getChildCount();
+
+        if (count == 0) {
+            throw new PostInflateException(
+                    "The FrameLayout for the TabHost has no content. Rendering failed.\n");
+        }
+
+        // this must be called before addTab() so that the TabHost searches its TabWidget
+        // and FrameLayout.
+        tabHost.setup();
+
+        // for each child of the framelayout, add a new TabSpec
+        for (int i = 0 ; i < count ; i++) {
+            View child = content.getChildAt(i);
+            String tabSpec = String.format("tab_spec%d", i+1);
+            int id = child.getId();
+            String[] resource = projectCallback.resolveResourceValue(id);
+            String name;
+            if (resource != null) {
+                name = resource[0]; // 0 is resource name, 1 is resource type.
+            } else {
+                name = String.format("Tab %d", i+1); // default name if id is unresolved.
+            }
+            tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id));
+        }
+    }
+
+
+    /**
+     * Visits a View and its children and generate a {@link ViewInfo} containing the
+     * bounds of all the views.
+     * @param view the root View
+     * @param context the context.
+     */
+    private ViewInfo visit(View view, BridgeContext context) {
+        if (view == null) {
+            return null;
+        }
+
+        ViewInfo result = new ViewInfo(view.getClass().getName(),
+                context.getViewKey(view),
+                view.getLeft(), view.getTop(), view.getRight(), view.getBottom(),
+                view, view.getLayoutParams());
+
+        if (view instanceof ViewGroup) {
+            ViewGroup group = ((ViewGroup) view);
+            List<ViewInfo> children = new ArrayList<ViewInfo>();
+            for (int i = 0; i < group.getChildCount(); i++) {
+                children.add(visit(group.getChildAt(i), context));
+            }
+            result.setChildren(children);
+        }
+
+        return result;
+    }
+
+    public BufferedImage getImage() {
+        return mImage;
+    }
+
+    public ViewInfo getViewInfo() {
+        return mViewInfo;
+    }
+
+    public Map<String, String> getDefaultViewPropertyValues(Object viewObject) {
+        return mContext.getDefaultPropMap(viewObject);
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
similarity index 97%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index f13ecdc..3e506b8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -14,11 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.impl;
 
 import com.android.layoutlib.api.IDensityBasedResourceValue;
 import com.android.layoutlib.api.IDensityBasedResourceValue.Density;
 import com.android.layoutlib.api.IResourceValue;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+import com.android.layoutlib.bridge.android.NinePatchDrawable;
 import com.android.ninepatch.NinePatch;
 
 import org.kxml2.io.KXmlParser;
@@ -56,7 +60,7 @@
      * @return the color as an int
      * @throw NumberFormatException if the conversion failed.
      */
-    static int getColor(String value) {
+    public static int getColor(String value) {
         if (value != null) {
             if (value.startsWith("#") == false) {
                 throw new NumberFormatException();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceValue.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/TempResourceValue.java
similarity index 74%
rename from tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceValue.java
rename to tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/TempResourceValue.java
index 01a4871..a3c5826 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/ResourceValue.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/TempResourceValue.java
@@ -14,24 +14,24 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.impl;
 
 import com.android.layoutlib.api.IResourceValue;
+import com.android.layoutlib.api.LayoutBridge;
 
 /**
- * Basic implementation of IResourceValue.
+ * Basic implementation of IResourceValue for when it is needed to dynamically make a new
+ * {@link IResourceValue} object.
+ *
+ * Most of the time, implementations of IResourceValue come through the {@link LayoutBridge}
+ * API.
  */
-class ResourceValue implements IResourceValue {
+public class TempResourceValue implements IResourceValue {
     private final String mType;
     private final String mName;
     private String mValue = null;
-    
-    ResourceValue(String name) {
-        mType = null;
-        mName = name;
-    }
 
-    public ResourceValue(String type, String name, String value) {
+    public TempResourceValue(String type, String name, String value) {
         mType = type;
         mName = name;
         mValue = value;
@@ -44,16 +44,16 @@
     public final String getName() {
         return mName;
     }
-    
+
     public final String getValue() {
         return mValue;
     }
-    
+
     public final void setValue(String value) {
         mValue = value;
     }
-    
-    public void replaceWith(ResourceValue value) {
+
+    public void replaceWith(TempResourceValue value) {
         mValue = value.mValue;
     }
 
diff --git a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java b/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java
index 6d013bb..1ec6262 100644
--- a/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java
+++ b/tools/layoutlib/bridge/src/com/google/android/maps/MapView.java
@@ -16,7 +16,7 @@
 
 package com.google.android.maps;
 
-import com.android.layoutlib.bridge.MockView;
+import com.android.layoutlib.bridge.android.MockView;
 
 import android.content.Context;
 import android.os.Bundle;
diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestDelegates.java
similarity index 88%
rename from tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java
rename to tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestDelegates.java
index a86b5c9..23b7e94 100644
--- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestNativeDelegate.java
+++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestDelegates.java
@@ -37,9 +37,9 @@
  * include the original class as first parameter (to access "this").
  *
  */
-public class TestNativeDelegate extends TestCase {
+public class TestDelegates extends TestCase {
 
-    public void  testNativeDelegates() {
+    public void testNativeDelegates() {
 
         final String[] classes = CreateInfo.DELEGATE_CLASS_NATIVES;
         final int count = classes.length;
@@ -48,10 +48,23 @@
         }
     }
 
+    public void testMethodDelegates() {
+        final String[] methods = CreateInfo.DELEGATE_METHODS;
+        final int count = methods.length;
+        for (int i = 0 ; i < count ; i++) {
+            String methodName = methods[i];
+
+            // extract the class name
+            String className = methodName.substring(0, methodName.indexOf('#'));
+
+            loadAndCompareClasses(className, className + "_Delegate");
+        }
+    }
+
     private void loadAndCompareClasses(String originalClassName, String delegateClassName) {
         // load the classes
         try {
-            ClassLoader classLoader = TestNativeDelegate.class.getClassLoader();
+            ClassLoader classLoader = TestDelegates.class.getClassLoader();
             Class<?> originalClass = classLoader.loadClass(originalClassName);
             Class<?> delegateClass = classLoader.loadClass(delegateClassName);
 
diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/BridgeXmlBlockParserTest.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java
similarity index 96%
rename from tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/BridgeXmlBlockParserTest.java
rename to tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java
index db1262f..3252fb4 100644
--- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/BridgeXmlBlockParserTest.java
+++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/android/BridgeXmlBlockParserTest.java
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.layoutlib.bridge;
+package com.android.layoutlib.bridge.android;
+
+import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
 
 import org.kxml2.io.KXmlParser;
 import org.w3c.dom.Node;
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 1c95400..b9c71133 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -95,8 +95,8 @@
      */
     private final static String[] DELEGATE_METHODS = new String[] {
         "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;",
+        "android.view.View#isInEditMode",
         // TODO: comment out once DelegateClass is working
-        // "android.view.View#isInEditMode",
         // "android.content.res.Resources$Theme#obtainStyledAttributes",
     };
 
@@ -126,7 +126,6 @@
      */
     private final static String[] OVERRIDDEN_METHODS = new String[] {
         // TODO: remove once DelegateClass is working
-        "android.view.View#isInEditMode",
         "android.content.res.Resources$Theme#obtainStyledAttributes",
     };
 
@@ -141,6 +140,7 @@
             "android.os.ServiceManager",            "android.os._Original_ServiceManager",
             "android.view.SurfaceView",             "android.view._Original_SurfaceView",
             "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
+            "android.webkit.WebView",               "android.webkit._Original_WebView",
         };
 
     /**