Merge "Fix NPE when restarting ChooseTypeAndAccountActiivty." into jb-mr2-dev
diff --git a/api/current.txt b/api/current.txt
index 2ec1533..2a68997 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13931,8 +13931,11 @@
     ctor public WifiEnterpriseConfig(android.net.wifi.WifiEnterpriseConfig);
     method public int describeContents();
     method public java.lang.String getAnonymousIdentity();
+    method public java.security.cert.X509Certificate getCaCertificate();
+    method public java.security.cert.X509Certificate getClientCertificate();
     method public int getEapMethod();
     method public java.lang.String getIdentity();
+    method public java.lang.String getPassword();
     method public int getPhase2Method();
     method public java.lang.String getSubjectMatch();
     method public void setAnonymousIdentity(java.lang.String);
@@ -13948,7 +13951,6 @@
   }
 
   public static final class WifiEnterpriseConfig.Eap {
-    ctor public WifiEnterpriseConfig.Eap();
     field public static final int NONE = -1; // 0xffffffff
     field public static final int PEAP = 0; // 0x0
     field public static final int PWD = 3; // 0x3
@@ -13957,7 +13959,6 @@
   }
 
   public static final class WifiEnterpriseConfig.Phase2 {
-    ctor public WifiEnterpriseConfig.Phase2();
     field public static final int GTC = 4; // 0x4
     field public static final int MSCHAP = 2; // 0x2
     field public static final int MSCHAPV2 = 3; // 0x3
@@ -13996,7 +13997,7 @@
     method public deprecated android.net.DhcpInfo getDhcpInfo();
     method public java.util.List<android.net.wifi.ScanResult> getScanResults();
     method public int getWifiState();
-    method public boolean isScanningAlwaysAvailable();
+    method public boolean isScanAlwaysAvailable();
     method public boolean isWifiEnabled();
     method public boolean pingSupplicant();
     method public boolean reassociate();
@@ -17523,16 +17524,17 @@
 
   public class StatFs {
     ctor public StatFs(java.lang.String);
-    method public int getAvailableBlocks();
+    method public deprecated int getAvailableBlocks();
     method public long getAvailableBlocksLong();
     method public long getAvailableBytes();
-    method public int getBlockCount();
+    method public deprecated int getBlockCount();
     method public long getBlockCountLong();
-    method public int getBlockSize();
+    method public deprecated int getBlockSize();
     method public long getBlockSizeLong();
-    method public int getFreeBlocks();
+    method public deprecated int getFreeBlocks();
     method public long getFreeBlocksLong();
     method public long getFreeBytes();
+    method public long getTotalBytes();
     method public void restat(java.lang.String);
   }
 
@@ -21127,37 +21129,6 @@
 
 package android.security {
 
-  public final class AndroidKeyPairGeneratorSpec implements java.security.spec.AlgorithmParameterSpec {
-    method public android.content.Context getContext();
-    method public java.util.Date getEndDate();
-    method public java.lang.String getKeystoreAlias();
-    method public java.math.BigInteger getSerialNumber();
-    method public java.util.Date getStartDate();
-    method public javax.security.auth.x500.X500Principal getSubjectDN();
-    method public boolean isEncryptionRequired();
-  }
-
-  public static final class AndroidKeyPairGeneratorSpec.Builder {
-    ctor public AndroidKeyPairGeneratorSpec.Builder(android.content.Context);
-    method public android.security.AndroidKeyPairGeneratorSpec build();
-    method public android.security.AndroidKeyPairGeneratorSpec.Builder setAlias(java.lang.String);
-    method public android.security.AndroidKeyPairGeneratorSpec.Builder setEncryptionRequired();
-    method public android.security.AndroidKeyPairGeneratorSpec.Builder setEndDate(java.util.Date);
-    method public android.security.AndroidKeyPairGeneratorSpec.Builder setSerialNumber(java.math.BigInteger);
-    method public android.security.AndroidKeyPairGeneratorSpec.Builder setStartDate(java.util.Date);
-    method public android.security.AndroidKeyPairGeneratorSpec.Builder setSubject(javax.security.auth.x500.X500Principal);
-  }
-
-  public final class AndroidKeyStoreParameter implements java.security.KeyStore.ProtectionParameter {
-    method public boolean isEncryptionRequired();
-  }
-
-  public static final class AndroidKeyStoreParameter.Builder {
-    ctor public AndroidKeyStoreParameter.Builder(android.content.Context);
-    method public android.security.AndroidKeyStoreParameter build();
-    method public android.security.AndroidKeyStoreParameter.Builder setEncryptionRequired();
-  }
-
   public final class KeyChain {
     ctor public KeyChain();
     method public static void choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, java.lang.String[], java.security.Principal[], java.lang.String, int, java.lang.String);
@@ -21183,6 +21154,37 @@
     ctor public KeyChainException(java.lang.Throwable);
   }
 
+  public final class KeyPairGeneratorSpec implements java.security.spec.AlgorithmParameterSpec {
+    method public android.content.Context getContext();
+    method public java.util.Date getEndDate();
+    method public java.lang.String getKeystoreAlias();
+    method public java.math.BigInteger getSerialNumber();
+    method public java.util.Date getStartDate();
+    method public javax.security.auth.x500.X500Principal getSubjectDN();
+    method public boolean isEncryptionRequired();
+  }
+
+  public static final class KeyPairGeneratorSpec.Builder {
+    ctor public KeyPairGeneratorSpec.Builder(android.content.Context);
+    method public android.security.KeyPairGeneratorSpec build();
+    method public android.security.KeyPairGeneratorSpec.Builder setAlias(java.lang.String);
+    method public android.security.KeyPairGeneratorSpec.Builder setEncryptionRequired();
+    method public android.security.KeyPairGeneratorSpec.Builder setEndDate(java.util.Date);
+    method public android.security.KeyPairGeneratorSpec.Builder setSerialNumber(java.math.BigInteger);
+    method public android.security.KeyPairGeneratorSpec.Builder setStartDate(java.util.Date);
+    method public android.security.KeyPairGeneratorSpec.Builder setSubject(javax.security.auth.x500.X500Principal);
+  }
+
+  public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter {
+    method public boolean isEncryptionRequired();
+  }
+
+  public static final class KeyStoreParameter.Builder {
+    ctor public KeyStoreParameter.Builder(android.content.Context);
+    method public android.security.KeyStoreParameter build();
+    method public android.security.KeyStoreParameter.Builder setEncryptionRequired(boolean);
+  }
+
 }
 
 package android.service.dreams {
@@ -24447,17 +24449,6 @@
     method public void set(T, V);
   }
 
-  public class PropertyValueModel extends android.util.ValueModel {
-    method public T get();
-    method public H getHost();
-    method public android.util.Property<H, T> getProperty();
-    method public java.lang.Class<T> getType();
-    method public static android.util.PropertyValueModel<H, T> of(H, android.util.Property<H, T>);
-    method public static android.util.PropertyValueModel<H, T> of(H, java.lang.Class<T>, java.lang.String);
-    method public static android.util.PropertyValueModel of(java.lang.Object, java.lang.String);
-    method public void set(T);
-  }
-
   public class SparseArray implements java.lang.Cloneable {
     ctor public SparseArray();
     ctor public SparseArray(int);
@@ -24624,14 +24615,6 @@
     field public int type;
   }
 
-  public abstract class ValueModel {
-    ctor protected ValueModel();
-    method public abstract T get();
-    method public abstract java.lang.Class<T> getType();
-    method public abstract void set(T);
-    field public static final android.util.ValueModel EMPTY;
-  }
-
   public class Xml {
     method public static android.util.AttributeSet asAttributeSet(org.xmlpull.v1.XmlPullParser);
     method public static android.util.Xml.Encoding findEncodingByName(java.lang.String) throws java.io.UnsupportedEncodingException;
@@ -29097,12 +29080,10 @@
     method public abstract void onSelectedDayChange(android.widget.CalendarView, int, int, int);
   }
 
-  public class CheckBox extends android.widget.CompoundButton implements android.widget.ValueEditor {
+  public class CheckBox extends android.widget.CompoundButton {
     ctor public CheckBox(android.content.Context);
     ctor public CheckBox(android.content.Context, android.util.AttributeSet);
     ctor public CheckBox(android.content.Context, android.util.AttributeSet, int);
-    method public android.util.ValueModel<java.lang.Boolean> getValueModel();
-    method public void setValueModel(android.util.ValueModel<java.lang.Boolean>);
   }
 
   public abstract interface Checkable {
@@ -29275,16 +29256,14 @@
     method public void setSize(int, int);
   }
 
-  public class EditText extends android.widget.TextView implements android.widget.ValueEditor {
+  public class EditText extends android.widget.TextView {
     ctor public EditText(android.content.Context);
     ctor public EditText(android.content.Context, android.util.AttributeSet);
     ctor public EditText(android.content.Context, android.util.AttributeSet, int);
     method public void extendSelection(int);
-    method public android.util.ValueModel<java.lang.CharSequence> getValueModel();
     method public void selectAll();
     method public void setSelection(int, int);
     method public void setSelection(int);
-    method public void setValueModel(android.util.ValueModel<java.lang.CharSequence>);
   }
 
   public abstract interface ExpandableListAdapter {
@@ -30313,13 +30292,11 @@
     method public abstract java.lang.Object[] getSections();
   }
 
-  public class SeekBar extends android.widget.AbsSeekBar implements android.widget.ValueEditor {
+  public class SeekBar extends android.widget.AbsSeekBar {
     ctor public SeekBar(android.content.Context);
     ctor public SeekBar(android.content.Context, android.util.AttributeSet);
     ctor public SeekBar(android.content.Context, android.util.AttributeSet, int);
-    method public android.util.ValueModel<java.lang.Integer> getValueModel();
     method public void setOnSeekBarChangeListener(android.widget.SeekBar.OnSeekBarChangeListener);
-    method public void setValueModel(android.util.ValueModel<java.lang.Integer>);
   }
 
   public static abstract interface SeekBar.OnSeekBarChangeListener {
@@ -30907,11 +30884,6 @@
     method public android.widget.TextView getText2();
   }
 
-  public abstract interface ValueEditor {
-    method public abstract android.util.ValueModel<T> getValueModel();
-    method public abstract void setValueModel(android.util.ValueModel<T>);
-  }
-
   public class VideoView extends android.view.SurfaceView implements android.widget.MediaController.MediaPlayerControl {
     ctor public VideoView(android.content.Context);
     ctor public VideoView(android.content.Context, android.util.AttributeSet);
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index d64bff9..d8d5f2b 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -17,6 +17,7 @@
 package android.content.res;
 
 import android.os.Trace;
+import android.view.View;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -80,16 +81,16 @@
 
     private static final Object sSync = new Object();
     /*package*/ static Resources mSystem = null;
-    
+
     // Information about preloaded resources.  Note that they are not
     // protected by a lock, because while preloading in zygote we are all
     // single-threaded, and after that these are immutable.
-    private static final LongSparseArray<Drawable.ConstantState> sPreloadedDrawables
+    private static final LongSparseArray<Drawable.ConstantState>[] sPreloadedDrawables;
+    private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
             = new LongSparseArray<Drawable.ConstantState>();
     private static final LongSparseArray<ColorStateList> sPreloadedColorStateLists
             = new LongSparseArray<ColorStateList>();
-    private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
-            = new LongSparseArray<Drawable.ConstantState>();
+
     private static boolean sPreloaded;
     private static int sPreloadedDensity;
 
@@ -120,6 +121,12 @@
     
     private CompatibilityInfo mCompatibilityInfo;
 
+    static {
+        sPreloadedDrawables = new LongSparseArray[2];
+        sPreloadedDrawables[0] = new LongSparseArray<Drawable.ConstantState>();
+        sPreloadedDrawables[1] = new LongSparseArray<Drawable.ConstantState>();
+    }
+
     /** @hide */
     public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
         return selectSystemTheme(curTheme, targetSdkVersion,
@@ -1982,6 +1989,7 @@
             ActivityInfo.CONFIG_LAYOUT_DIRECTION);
 
     private boolean verifyPreloadConfig(int changingConfigurations, int resourceId, String name) {
+        // We dont want to preloadd a Drawable when there is both a LTR and RTL version of it
         if (((changingConfigurations&~(ActivityInfo.CONFIG_FONT_SCALE |
                 ActivityInfo.CONFIG_DENSITY)) & VARYING_CONFIGS) != 0) {
             String resName;
@@ -1995,6 +2003,17 @@
                     + " (" + resName + ") that varies with configuration!!");
             return false;
         }
+        if (TRACE_FOR_PRELOAD) {
+            String resName;
+            try {
+                resName = getResourceName(resourceId);
+            } catch (NotFoundException e) {
+                resName = "?";
+            }
+            Log.w(TAG, "Preloading " + name + " resource #0x"
+                    + Integer.toHexString(resourceId)
+                    + " (" + resName + ")");
+        }
         return true;
     }
 
@@ -2022,11 +2041,11 @@
         if (dr != null) {
             return dr;
         }
-
+        final int layoutDirection = mConfiguration.getLayoutDirection();
         Drawable.ConstantState cs = isColorDrawable
                 ? sPreloadedColorDrawables.get(key)
                 : (sPreloadedDensity == mConfiguration.densityDpi
-                        ? sPreloadedDrawables.get(key) : null);
+                        ? sPreloadedDrawables[layoutDirection].get(key) : null);
         if (cs != null) {
             dr = cs.newDrawable(this);
         } else {
@@ -2100,11 +2119,12 @@
             cs = dr.getConstantState();
             if (cs != null) {
                 if (mPreloading) {
-                    if (verifyPreloadConfig(cs.getChangingConfigurations(), value.resourceId, "drawable")) {
+                    if (verifyPreloadConfig(cs.getChangingConfigurations(), value.resourceId,
+                            "drawable")) {
                         if (isColorDrawable) {
                             sPreloadedColorDrawables.put(key, cs);
                         } else {
-                            sPreloadedDrawables.put(key, cs);
+                            sPreloadedDrawables[layoutDirection].put(key, cs);
                         }
                     }
                 } else {
diff --git a/core/java/android/net/DhcpInfo.java b/core/java/android/net/DhcpInfo.java
index 2b359eb..ab4cd9b 100644
--- a/core/java/android/net/DhcpInfo.java
+++ b/core/java/android/net/DhcpInfo.java
@@ -22,8 +22,7 @@
 
 /**
  * A simple object for retrieving the results of a DHCP request.
- * @deprecated - use LinkProperties - To be removed 11/2013
- * STOPSHIP - make sure we expose LinkProperties through ConnectivityManager
+ * @deprecated - use LinkProperties - To be removed 11/2014
  */
 public class DhcpInfo implements Parcelable {
     public int ipAddress;
diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java
index 60ec0d7..2314057 100644
--- a/core/java/android/os/StatFs.java
+++ b/core/java/android/os/StatFs.java
@@ -57,9 +57,9 @@
     }
 
     /**
-     * The size, in bytes, of a block on the file system. This corresponds to
-     * the Unix {@code statfs.f_bsize} field.
+     * @deprecated Use {@link #getBlockSizeLong()} instead.
      */
+    @Deprecated
     public int getBlockSize() {
         return (int) mStat.f_bsize;
     }
@@ -73,27 +73,25 @@
     }
 
     /**
-     * The total number of blocks on the file system. This corresponds to the
-     * Unix {@code statfs.f_blocks} field.
+     * @deprecated Use {@link #getBlockCountLong()} instead.
      */
+    @Deprecated
     public int getBlockCount() {
         return (int) mStat.f_blocks;
     }
 
     /**
-     * The size, in bytes, of a block on the file system. This corresponds to
-     * the Unix {@code statfs.f_bsize} field.
+     * The total number of blocks on the file system. This corresponds to the
+     * Unix {@code statfs.f_blocks} field.
      */
     public long getBlockCountLong() {
         return mStat.f_blocks;
     }
 
     /**
-     * The total number of blocks that are free on the file system, including
-     * reserved blocks (that are not available to normal applications). This
-     * corresponds to the Unix {@code statfs.f_bfree} field. Most applications
-     * will want to use {@link #getAvailableBlocks()} instead.
+     * @deprecated Use {@link #getFreeBlocksLong()} instead.
      */
+    @Deprecated
     public int getFreeBlocks() {
         return (int) mStat.f_bfree;
     }
@@ -109,17 +107,18 @@
     }
 
     /**
-     * The number of bytes that are free on the file system, including
-     * reserved blocks (that are not available to normal applications).
+     * The number of bytes that are free on the file system, including reserved
+     * blocks (that are not available to normal applications). Most applications
+     * will want to use {@link #getAvailableBytes()} instead.
      */
     public long getFreeBytes() {
         return mStat.f_bfree * mStat.f_bsize;
     }
 
     /**
-     * The number of blocks that are free on the file system and available to
-     * applications. This corresponds to the Unix {@code statfs.f_bavail} field.
+     * @deprecated Use {@link #getAvailableBlocksLong()} instead.
      */
+    @Deprecated
     public int getAvailableBlocks() {
         return (int) mStat.f_bavail;
     }
@@ -139,4 +138,11 @@
     public long getAvailableBytes() {
         return mStat.f_bavail * mStat.f_bsize;
     }
+
+    /**
+     * The total number of bytes supported by the file system.
+     */
+    public long getTotalBytes() {
+        return mStat.f_blocks * mStat.f_bsize;
+    }
 }
diff --git a/core/java/android/util/PropertyValueModel.java b/core/java/android/util/PropertyValueModel.java
deleted file mode 100755
index eb9c47d..0000000
--- a/core/java/android/util/PropertyValueModel.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2012 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.util;
-
-/**
- * A value model for a {@link Property property} of a host object. This class can be used for
- * both reflective and non-reflective property implementations.
- *
- * @param <H> the host type, where the host is the object that holds this property
- * @param <T> the value type
- *
- * @see Property
- * @see ValueModel
- */
-public class PropertyValueModel<H, T> extends ValueModel<T> {
-    private final H mHost;
-    private final Property<H, T> mProperty;
-
-    private PropertyValueModel(H host, Property<H, T> property) {
-        mProperty = property;
-        mHost = host;
-    }
-
-    /**
-     * Returns the host.
-     *
-     * @return the host
-     */
-    public H getHost() {
-        return mHost;
-    }
-
-    /**
-     * Returns the property.
-     *
-     * @return the property
-     */
-    public Property<H, T> getProperty() {
-        return mProperty;
-    }
-
-    @Override
-    public Class<T> getType() {
-        return mProperty.getType();
-    }
-
-    @Override
-    public T get() {
-        return mProperty.get(mHost);
-    }
-
-    @Override
-    public void set(T value) {
-        mProperty.set(mHost, value);
-    }
-
-    /**
-     * Return an appropriate PropertyValueModel for this host and property.
-     *
-     * @param host the host
-     * @param property the property
-     * @return the value model
-     */
-    public static <H, T> PropertyValueModel<H, T> of(H host, Property<H, T> property) {
-        return new PropertyValueModel<H, T>(host, property);
-    }
-
-    /**
-     * Return a PropertyValueModel for this {@code host} and a
-     * reflective property, constructed from this {@code propertyType} and {@code propertyName}.
-     *
-     * @param host
-     * @param propertyType the property type
-     * @param propertyName the property name
-     * @return a value model with this host and a reflective property with this type and name
-     *
-     * @see Property#of
-     */
-    public static <H, T> PropertyValueModel<H, T> of(H host, Class<T> propertyType,
-            String propertyName) {
-        return of(host, Property.of((Class<H>) host.getClass(), propertyType, propertyName));
-    }
-
-    private static Class getNullaryMethodReturnType(Class c, String name) {
-        try {
-            return c.getMethod(name).getReturnType();
-        } catch (NoSuchMethodException e) {
-            return null;
-        }
-    }
-
-    private static Class getFieldType(Class c, String name) {
-        try {
-            return c.getField(name).getType();
-        } catch (NoSuchFieldException e) {
-            return null;
-        }
-    }
-
-    private static String capitalize(String name) {
-        if (name.isEmpty()) {
-            return name;
-        }
-        return Character.toUpperCase(name.charAt(0)) + name.substring(1);
-    }
-
-    /**
-     * Return a PropertyValueModel for this {@code host} and and {@code propertyName}.
-     *
-     * @param host the host
-     * @param propertyName the property name
-     * @return a value model with this host and a reflective property with this name
-     */
-    public static PropertyValueModel of(Object host, String propertyName) {
-        Class clazz = host.getClass();
-        String suffix = capitalize(propertyName);
-        Class propertyType = getNullaryMethodReturnType(clazz, "get" + suffix);
-        if (propertyType == null) {
-            propertyType = getNullaryMethodReturnType(clazz, "is" + suffix);
-        } 
-        if (propertyType == null) {
-            propertyType = getFieldType(clazz, propertyName); 
-        }         
-        if (propertyType == null) {
-            throw new NoSuchPropertyException(propertyName); 
-        }
-        return of(host, propertyType, propertyName);
-    }
-}
diff --git a/core/java/android/util/ValueModel.java b/core/java/android/util/ValueModel.java
deleted file mode 100755
index 4789682..0000000
--- a/core/java/android/util/ValueModel.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2012 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.util;
-
-/**
- * A ValueModel is an abstraction for a 'slot' or place in memory in which a value
- * may be stored and retrieved. A common implementation of ValueModel is a regular property of
- * an object, whose value may be retrieved by calling the appropriate <em>getter</em>
- * method and set by calling the corresponding <em>setter</em> method.
- *
- * @param <T> the value type
- *
- * @see PropertyValueModel
- */
-public abstract class ValueModel<T> {
-    /**
-     * The empty model should be used in place of {@code null} to indicate that a
-     * model has not been set. The empty model has no value and does nothing when it is set.
-     */
-    public static final ValueModel EMPTY = new ValueModel() {
-        @Override
-        public Class getType() {
-            return Object.class;
-        }
-
-        @Override
-        public Object get() {
-            return null;
-        }
-
-        @Override
-        public void set(Object value) {
-
-        }
-    };
-
-    protected ValueModel() {
-    }
-
-    /**
-     * Returns the type of this property.
-     *
-     * @return the property type
-     */
-    public abstract Class<T> getType();
-
-    /**
-     * Returns the value of this property.
-     *
-     * @return the property value
-     */
-    public abstract T get();
-
-    /**
-     * Sets the value of this property.
-     *
-     * @param value the new value for this property
-     */
-    public abstract void set(T value);
-}
\ No newline at end of file
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index be26d20..a0a63a6 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2915,14 +2915,14 @@
      *
      * @hide
      */
-    int mUserPaddingLeftInitial = 0;
+    int mUserPaddingLeftInitial;
 
     /**
      * Cache initial right padding.
      *
      * @hide
      */
-    int mUserPaddingRightInitial = 0;
+    int mUserPaddingRightInitial;
 
     /**
      * Default undefined padding
@@ -3388,11 +3388,11 @@
                     break;
                 case com.android.internal.R.styleable.View_paddingStart:
                     startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
-                    startPaddingDefined = true;
+                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
                     break;
                 case com.android.internal.R.styleable.View_paddingEnd:
                     endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
-                    endPaddingDefined = true;
+                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
                     break;
                 case com.android.internal.R.styleable.View_scrollX:
                     x = a.getDimensionPixelOffset(attr, 0);
@@ -3712,10 +3712,12 @@
             // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
             // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
             // defined.
-            if (leftPaddingDefined) {
+            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
+
+            if (leftPaddingDefined && !hasRelativePadding) {
                 mUserPaddingLeftInitial = leftPadding;
             }
-            if (rightPaddingDefined) {
+            if (rightPaddingDefined && !hasRelativePadding) {
                 mUserPaddingRightInitial = rightPadding;
             }
         }
@@ -11952,26 +11954,30 @@
             // left / right or right / left depending on the resolved layout direction.
             // If start / end padding are not defined, use the left / right ones.
             int resolvedLayoutDirection = getLayoutDirection();
-            // Set user padding to initial values ...
-            mUserPaddingLeft = mUserPaddingLeftInitial;
-            mUserPaddingRight = mUserPaddingRightInitial;
-            // ... then resolve it.
             switch (resolvedLayoutDirection) {
                 case LAYOUT_DIRECTION_RTL:
                     if (mUserPaddingStart != UNDEFINED_PADDING) {
                         mUserPaddingRight = mUserPaddingStart;
+                    } else {
+                        mUserPaddingRight = mUserPaddingRightInitial;
                     }
                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
                         mUserPaddingLeft = mUserPaddingEnd;
+                    } else {
+                        mUserPaddingLeft = mUserPaddingLeftInitial;
                     }
                     break;
                 case LAYOUT_DIRECTION_LTR:
                 default:
                     if (mUserPaddingStart != UNDEFINED_PADDING) {
                         mUserPaddingLeft = mUserPaddingStart;
+                    } else {
+                        mUserPaddingLeft = mUserPaddingLeftInitial;
                     }
                     if (mUserPaddingEnd != UNDEFINED_PADDING) {
                         mUserPaddingRight = mUserPaddingEnd;
+                    } else {
+                        mUserPaddingRight = mUserPaddingRightInitial;
                     }
             }
 
diff --git a/core/java/android/widget/CheckBox.java b/core/java/android/widget/CheckBox.java
index 41ab5f2..f1804f8 100644
--- a/core/java/android/widget/CheckBox.java
+++ b/core/java/android/widget/CheckBox.java
@@ -20,7 +20,6 @@
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.util.ValueModel;
 
 
 /**
@@ -56,9 +55,7 @@
  * {@link android.R.styleable#View View Attributes}
  * </p>
  */
-public class CheckBox extends CompoundButton implements ValueEditor<Boolean> {
-    private ValueModel<Boolean> mValueModel = ValueModel.EMPTY;
-
+public class CheckBox extends CompoundButton {
     public CheckBox(Context context) {
         this(context, null);
     }
@@ -82,22 +79,4 @@
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(CheckBox.class.getName());
     }
-
-    @Override
-    public ValueModel<Boolean> getValueModel() {
-        return mValueModel;
-    }
-
-    @Override
-    public void setValueModel(ValueModel<Boolean> valueModel) {
-        mValueModel = valueModel;
-        setChecked(mValueModel.get());
-    }
-
-    @Override
-    public boolean performClick() {
-        boolean handled = super.performClick();
-        mValueModel.set(isChecked());
-        return handled;
-    }
 }
diff --git a/core/java/android/widget/EditText.java b/core/java/android/widget/EditText.java
index ec81214..57e51c2 100644
--- a/core/java/android/widget/EditText.java
+++ b/core/java/android/widget/EditText.java
@@ -17,7 +17,6 @@
 package android.widget;
 
 import android.content.Context;
-import android.graphics.Rect;
 import android.text.Editable;
 import android.text.Selection;
 import android.text.Spannable;
@@ -25,7 +24,6 @@
 import android.text.method.ArrowKeyMovementMethod;
 import android.text.method.MovementMethod;
 import android.util.AttributeSet;
-import android.util.ValueModel;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -49,9 +47,7 @@
  * {@link android.R.styleable#TextView TextView Attributes},
  * {@link android.R.styleable#View View Attributes}
  */
-public class EditText extends TextView implements ValueEditor<CharSequence> {
-    private ValueModel<CharSequence> mValueModel = ValueModel.EMPTY;
-
+public class EditText extends TextView {
     public EditText(Context context) {
         this(context, null);
     }
@@ -132,21 +128,4 @@
         super.onInitializeAccessibilityNodeInfo(info);
         info.setClassName(EditText.class.getName());
     }
-
-    @Override
-    public ValueModel<CharSequence> getValueModel() {
-        return mValueModel;
-    }
-
-    @Override
-    public void setValueModel(ValueModel<CharSequence> valueModel) {
-        mValueModel = valueModel;
-        setText(mValueModel.get());
-    }
-
-    @Override
-    void sendAfterTextChanged(Editable text) {
-        super.sendAfterTextChanged(text);
-        mValueModel.set(text);
-    }
 }
diff --git a/core/java/android/widget/SeekBar.java b/core/java/android/widget/SeekBar.java
index a6486a8..2737f94 100644
--- a/core/java/android/widget/SeekBar.java
+++ b/core/java/android/widget/SeekBar.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.util.ValueModel;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
@@ -34,7 +33,7 @@
  *
  * @attr ref android.R.styleable#SeekBar_thumb
  */
-public class SeekBar extends AbsSeekBar implements ValueEditor<Integer> {
+public class SeekBar extends AbsSeekBar {
 
     /**
      * A callback that notifies clients when the progress level has been
@@ -70,9 +69,8 @@
         void onStopTrackingTouch(SeekBar seekBar);
     }
 
-    private ValueModel<Integer> mValueModel = ValueModel.EMPTY;
     private OnSeekBarChangeListener mOnSeekBarChangeListener;
-
+    
     public SeekBar(Context context) {
         this(context, null);
     }
@@ -91,23 +89,9 @@
 
         if (mOnSeekBarChangeListener != null) {
             mOnSeekBarChangeListener.onProgressChanged(this, getProgress(), fromUser);
-            if (fromUser) {
-                mValueModel.set(getProgress());
-            }
         }
     }
 
-    @Override
-    public ValueModel<Integer> getValueModel() {
-        return mValueModel;
-    }
-
-    @Override
-    public void setValueModel(ValueModel<Integer> valueModel) {
-        mValueModel = valueModel;
-        setProgress(mValueModel.get());
-    }
-
     /**
      * Sets a listener to receive notifications of changes to the SeekBar's progress level. Also
      * provides notifications of when the user starts and stops a touch gesture within the SeekBar.
diff --git a/core/java/android/widget/ValueEditor.java b/core/java/android/widget/ValueEditor.java
deleted file mode 100755
index 2b91abf..0000000
--- a/core/java/android/widget/ValueEditor.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-import android.util.ValueModel;
-
-/**
- * An interface for editors of simple values. Classes implementing this interface are normally
- * UI controls (subclasses of {@link android.view.View View}) that can provide a suitable
- * user interface to display and edit values of the specified type. This interface is
- * intended to describe editors for simple types, like {@code boolean}, {@code int} or
- * {@code String}, where the values themselves are immutable.
- * <p>
- * For example, {@link android.widget.CheckBox CheckBox} implements
- * this interface for the Boolean type as it is capable of providing an appropriate
- * mechanism for displaying and changing the value of a Boolean property.
- *
- * @param <T> the value type that this editor supports
- */
-public interface ValueEditor<T> {
-    /**
-     * Return the last value model that was set. If no value model has been set, the editor
-     * should return the value {@link android.util.ValueModel#EMPTY}.
-     *
-     * @return the value model
-     */
-    public ValueModel<T> getValueModel();
-
-    /**
-     * Sets the value model for this editor. When the value model is set, the editor should
-     * retrieve the value from the value model, using {@link android.util.ValueModel#get()},
-     * and set its internal state accordingly. Likewise, when the editor's internal state changes
-     * it should update the value model by calling  {@link android.util.ValueModel#set(T)}
-     * with the appropriate value.
-     *
-     * @param valueModel the new value model for this editor.
-     */
-    public void setValueModel(ValueModel<T> valueModel);
-}
diff --git a/keystore/java/android/security/AndroidKeyPairGenerator.java b/keystore/java/android/security/AndroidKeyPairGenerator.java
index 6975583..43d1eb6 100644
--- a/keystore/java/android/security/AndroidKeyPairGenerator.java
+++ b/keystore/java/android/security/AndroidKeyPairGenerator.java
@@ -52,12 +52,12 @@
 public class AndroidKeyPairGenerator extends KeyPairGeneratorSpi {
     private android.security.KeyStore mKeyStore;
 
-    private AndroidKeyPairGeneratorSpec mSpec;
+    private KeyPairGeneratorSpec mSpec;
 
     /**
      * Generate a KeyPair which is backed by the Android keystore service. You
      * must call {@link KeyPairGenerator#initialize(AlgorithmParameterSpec)}
-     * with an {@link AndroidKeyPairGeneratorSpec} as the {@code params}
+     * with an {@link KeyPairGeneratorSpec} as the {@code params}
      * argument before calling this otherwise an {@code IllegalStateException}
      * will be thrown.
      * <p>
@@ -73,7 +73,7 @@
     public KeyPair generateKeyPair() {
         if (mKeyStore == null || mSpec == null) {
             throw new IllegalStateException(
-                    "Must call initialize with an AndroidKeyPairGeneratorSpec first");
+                    "Must call initialize with an android.security.KeyPairGeneratorSpec first");
         }
 
         if (((mSpec.getFlags() & KeyStore.FLAG_ENCRYPTED) != 0)
@@ -156,13 +156,13 @@
             throws InvalidAlgorithmParameterException {
         if (params == null) {
             throw new InvalidAlgorithmParameterException(
-                    "must supply params of type AndroidKeyPairGenericSpec");
-        } else if (!(params instanceof AndroidKeyPairGeneratorSpec)) {
+                    "must supply params of type android.security.KeyPairGeneratorSpec");
+        } else if (!(params instanceof KeyPairGeneratorSpec)) {
             throw new InvalidAlgorithmParameterException(
-                    "params must be of type AndroidKeyPairGeneratorSpec");
+                    "params must be of type android.security.KeyPairGeneratorSpec");
         }
 
-        AndroidKeyPairGeneratorSpec spec = (AndroidKeyPairGeneratorSpec) params;
+        KeyPairGeneratorSpec spec = (KeyPairGeneratorSpec) params;
 
         mSpec = spec;
         mKeyStore = android.security.KeyStore.getInstance();
diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java
index dcc9516..04ee8c4 100644
--- a/keystore/java/android/security/AndroidKeyStore.java
+++ b/keystore/java/android/security/AndroidKeyStore.java
@@ -209,7 +209,7 @@
     }
 
     private void setPrivateKeyEntry(String alias, PrivateKey key, Certificate[] chain,
-            AndroidKeyStoreParameter params) throws KeyStoreException {
+            KeyStoreParameter params) throws KeyStoreException {
         byte[] keyBytes = null;
 
         final String pkeyAlias;
@@ -544,15 +544,16 @@
             return;
         }
 
-        if (param != null && !(param instanceof AndroidKeyStoreParameter)) {
-            throw new KeyStoreException("protParam should be AndroidKeyStoreParameter; was: "
+        if (param != null && !(param instanceof KeyStoreParameter)) {
+            throw new KeyStoreException(
+                    "protParam should be android.security.KeyStoreParameter; was: "
                     + param.getClass().getName());
         }
 
         if (entry instanceof PrivateKeyEntry) {
             PrivateKeyEntry prE = (PrivateKeyEntry) entry;
             setPrivateKeyEntry(alias, prE.getPrivateKey(), prE.getCertificateChain(),
-                    (AndroidKeyStoreParameter) param);
+                    (KeyStoreParameter) param);
             return;
         }
 
diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java
index 8ca301e..b17e450 100644
--- a/keystore/java/android/security/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/AndroidKeyStoreProvider.java
@@ -24,7 +24,7 @@
  * @hide
  */
 public class AndroidKeyStoreProvider extends Provider {
-    public static final String PROVIDER_NAME = "AndroidKeyStoreProvider";
+    public static final String PROVIDER_NAME = "AndroidKeyStore";
 
     public AndroidKeyStoreProvider() {
         super(PROVIDER_NAME, 1.0, "Android KeyStore security provider");
@@ -33,6 +33,6 @@
         put("KeyStore." + AndroidKeyStore.NAME, AndroidKeyStore.class.getName());
 
         // java.security.KeyPairGenerator
-        put("KeyPairGenerator." + AndroidKeyStore.NAME, AndroidKeyPairGenerator.class.getName());
+        put("KeyPairGenerator.RSA", AndroidKeyPairGenerator.class.getName());
     }
 }
diff --git a/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
similarity index 89%
rename from keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
rename to keystore/java/android/security/KeyPairGeneratorSpec.java
index b126f03..59f89bc 100644
--- a/keystore/java/android/security/AndroidKeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/KeyPairGeneratorSpec.java
@@ -29,9 +29,9 @@
 
 /**
  * This provides the required parameters needed for initializing the
- * {@code KeyPairGenerator} that works with <a href="{@docRoot}
- * guide/topics/security/keystore.html">Android KeyStore facility</a>. The
- * Android KeyStore facility is accessed through a
+ * {@code KeyPairGenerator} that works with
+ * <a href="{@docRoot}guide/topics/security/keystore.html">Android KeyStore
+ * facility</a>. The Android KeyStore facility is accessed through a
  * {@link java.security.KeyPairGenerator} API using the {@code AndroidKeyStore}
  * provider. The {@code context} passed in may be used to pop up some UI to ask
  * the user to unlock or initialize the Android KeyStore facility.
@@ -49,7 +49,7 @@
  * The self-signed X.509 certificate may be replaced at a later time by a
  * certificate signed by a real Certificate Authority.
  */
-public final class AndroidKeyPairGeneratorSpec implements AlgorithmParameterSpec {
+public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
     private final String mKeystoreAlias;
 
     private final Context mContext;
@@ -91,9 +91,9 @@
      *            period
      * @throws IllegalArgumentException when any argument is {@code null} or
      *             {@code endDate} is before {@code startDate}.
-     * @hide should be built with AndroidKeyPairGeneratorSpecBuilder
+     * @hide should be built with KeyPairGeneratorSpecBuilder
      */
-    public AndroidKeyPairGeneratorSpec(Context context, String keyStoreAlias,
+    public KeyPairGeneratorSpec(Context context, String keyStoreAlias,
             X500Principal subjectDN, BigInteger serialNumber, Date startDate, Date endDate,
             int flags) {
         if (context == null) {
@@ -184,7 +184,7 @@
     }
 
     /**
-     * Builder class for {@link AndroidKeyPairGeneratorSpec} objects.
+     * Builder class for {@link KeyPairGeneratorSpec} objects.
      * <p>
      * This will build a parameter spec for use with the <a href="{@docRoot}
      * guide/topics/security/keystore.html">Android KeyStore facility</a>.
@@ -198,14 +198,10 @@
      * Calendar end = new Calendar();
      * end.add(1, Calendar.YEAR);
      *
-     * AndroidKeyPairGeneratorSpec spec =
-     *         new AndroidKeyPairGeneratorSpec.Builder(mContext)
-     *                 .setAlias(&quot;myKey&quot;)
-     *                 .setSubject(new X500Principal(&quot;CN=myKey&quot;))
-     *                 .setSerial(BigInteger.valueOf(1337))
-     *                 .setStartDate(start.getTime())
-     *                 .setEndDate(end.getTime())
-     *                 .build();
+     * KeyPairGeneratorSpec spec =
+     *         new KeyPairGeneratorSpec.Builder(mContext).setAlias(&quot;myKey&quot;)
+     *                 .setSubject(new X500Principal(&quot;CN=myKey&quot;)).setSerial(BigInteger.valueOf(1337))
+     *                 .setStartDate(start.getTime()).setEndDate(end.getTime()).build();
      * </pre>
      */
     public final static class Builder {
@@ -309,13 +305,13 @@
         }
 
         /**
-         * Builds the instance of the {@code AndroidKeyPairGeneratorSpec}.
+         * Builds the instance of the {@code KeyPairGeneratorSpec}.
          *
          * @throws IllegalArgumentException if a required field is missing
-         * @return built instance of {@code AndroidKeyPairGeneratorSpec}
+         * @return built instance of {@code KeyPairGeneratorSpec}
          */
-        public AndroidKeyPairGeneratorSpec build() {
-            return new AndroidKeyPairGeneratorSpec(mContext, mKeystoreAlias, mSubjectDN,
+        public KeyPairGeneratorSpec build() {
+            return new KeyPairGeneratorSpec(mContext, mKeystoreAlias, mSubjectDN,
                     mSerialNumber, mStartDate, mEndDate, mFlags);
         }
     }
diff --git a/keystore/java/android/security/AndroidKeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java
similarity index 72%
rename from keystore/java/android/security/AndroidKeyStoreParameter.java
rename to keystore/java/android/security/KeyStoreParameter.java
index 44f57c4..621a605 100644
--- a/keystore/java/android/security/AndroidKeyStoreParameter.java
+++ b/keystore/java/android/security/KeyStoreParameter.java
@@ -17,7 +17,7 @@
 package android.security;
 
 import android.content.Context;
-import android.security.AndroidKeyPairGeneratorSpec.Builder;
+import android.security.KeyPairGeneratorSpec.Builder;
 
 import java.security.KeyPairGenerator;
 import java.security.PrivateKey;
@@ -26,9 +26,9 @@
 
 /**
  * This provides the optional parameters that can be specified for
- * {@code KeyStore} entries that work with <a href="{@docRoot}
- * guide/topics/security/keystore.html">Android KeyStore facility</a>. The
- * Android KeyStore facility is accessed through a
+ * {@code KeyStore} entries that work with
+ * <a href="{@docRoot}guide/topics/security/keystore.html">Android KeyStore
+ * facility</a>. The Android KeyStore facility is accessed through a
  * {@link java.security.KeyStore} API using the {@code AndroidKeyStore}
  * provider. The {@code context} passed in may be used to pop up some UI to ask
  * the user to unlock or initialize the Android KeyStore facility.
@@ -39,15 +39,15 @@
  * {@code KeyStore}.
  * <p>
  * Keys may be generated using the {@link KeyPairGenerator} facility with a
- * {@link AndroidKeyPairGeneratorSpec} to specify the entry's {@code alias}. A
+ * {@link KeyPairGeneratorSpec} to specify the entry's {@code alias}. A
  * self-signed X.509 certificate will be attached to generated entries, but that
  * may be replaced at a later time by a certificate signed by a real Certificate
  * Authority.
  */
-public final class AndroidKeyStoreParameter implements ProtectionParameter {
+public final class KeyStoreParameter implements ProtectionParameter {
     private int mFlags;
 
-    private AndroidKeyStoreParameter(int flags) {
+    private KeyStoreParameter(int flags) {
         mFlags = flags;
     }
 
@@ -67,10 +67,10 @@
     }
 
     /**
-     * Builder class for {@link AndroidKeyStoreParameter} objects.
+     * Builder class for {@link KeyStoreParameter} objects.
      * <p>
-     * This will build protection parameters for use with the <a
-     * href="{@docRoot} guide/topics/security/keystore.html">Android KeyStore
+     * This will build protection parameters for use with the
+     * <a href="{@docRoot}guide/topics/security/keystore.html">Android KeyStore
      * facility</a>.
      * <p>
      * This can be used to require that KeyStore entries be stored encrypted.
@@ -78,8 +78,9 @@
      * Example:
      *
      * <pre class="prettyprint">
-     * AndroidKeyStoreParameter params =
-     *         new AndroidKeyStoreParameter.Builder(mContext).setEncryptionRequired().build();
+     * KeyStoreParameter params = new KeyStoreParameter.Builder(mContext)
+     *         .setEncryptionRequired()
+     *         .build();
      * </pre>
      */
     public final static class Builder {
@@ -105,19 +106,23 @@
          * screen (e.g., PIN, password) before creating or using the generated
          * key is successful.
          */
-        public Builder setEncryptionRequired() {
-            mFlags |= KeyStore.FLAG_ENCRYPTED;
+        public Builder setEncryptionRequired(boolean required) {
+            if (required) {
+                mFlags |= KeyStore.FLAG_ENCRYPTED;
+            } else {
+                mFlags &= ~KeyStore.FLAG_ENCRYPTED;
+            }
             return this;
         }
 
         /**
-         * Builds the instance of the {@code AndroidKeyPairGeneratorSpec}.
+         * Builds the instance of the {@code KeyPairGeneratorSpec}.
          *
          * @throws IllegalArgumentException if a required field is missing
-         * @return built instance of {@code AndroidKeyPairGeneratorSpec}
+         * @return built instance of {@code KeyPairGeneratorSpec}
          */
-        public AndroidKeyStoreParameter build() {
-            return new AndroidKeyStoreParameter(mFlags);
+        public KeyStoreParameter build() {
+            return new KeyStoreParameter(mFlags);
         }
     }
 }
diff --git a/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java b/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
index c5cf514..1582f74 100644
--- a/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
+++ b/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
@@ -65,7 +65,7 @@
 
         assertFalse(mAndroidKeyStore.isUnlocked());
 
-        mGenerator = java.security.KeyPairGenerator.getInstance("AndroidKeyStore");
+        mGenerator = java.security.KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
     }
 
     private void setupPassword() {
@@ -80,7 +80,7 @@
     public void testKeyPairGenerator_Initialize_Params_Encrypted_Success() throws Exception {
         setupPassword();
 
-        mGenerator.initialize(new AndroidKeyPairGeneratorSpec.Builder(getContext())
+        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
                 .setAlias(TEST_ALIAS_1)
                 .setSubject(TEST_DN_1)
                 .setSerialNumber(TEST_SERIAL_1)
@@ -116,7 +116,7 @@
         setupPassword();
 
         mGenerator.initialize(
-                new AndroidKeyPairGeneratorSpec.Builder(getContext())
+                new KeyPairGeneratorSpec.Builder(getContext())
                         .setAlias(TEST_ALIAS_1)
                         .setSubject(TEST_DN_1)
                         .setSerialNumber(TEST_SERIAL_1)
@@ -130,7 +130,7 @@
     public void testKeyPairGenerator_GenerateKeyPair_Encrypted_Success() throws Exception {
         setupPassword();
 
-        mGenerator.initialize(new AndroidKeyPairGeneratorSpec.Builder(getContext())
+        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
                 .setAlias(TEST_ALIAS_1)
                 .setSubject(TEST_DN_1)
                 .setSerialNumber(TEST_SERIAL_1)
@@ -146,7 +146,7 @@
     }
 
     public void testKeyPairGenerator_GenerateKeyPair_Unencrypted_Success() throws Exception {
-        mGenerator.initialize(new AndroidKeyPairGeneratorSpec.Builder(getContext())
+        mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
                 .setAlias(TEST_ALIAS_1)
                 .setSubject(TEST_DN_1)
                 .setSerialNumber(TEST_SERIAL_1)
@@ -163,7 +163,7 @@
     public void testKeyPairGenerator_GenerateKeyPair_Replaced_Success() throws Exception {
         // Generate the first key
         {
-            mGenerator.initialize(new AndroidKeyPairGeneratorSpec.Builder(getContext())
+            mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
                     .setAlias(TEST_ALIAS_1)
                     .setSubject(TEST_DN_1)
                     .setSerialNumber(TEST_SERIAL_1)
@@ -178,7 +178,7 @@
 
         // Replace the original key
         {
-            mGenerator.initialize(new AndroidKeyPairGeneratorSpec.Builder(getContext())
+            mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
                     .setAlias(TEST_ALIAS_2)
                     .setSubject(TEST_DN_2)
                     .setSerialNumber(TEST_SERIAL_2)
@@ -196,7 +196,7 @@
             throws Exception {
         // Generate the first key
         {
-            mGenerator.initialize(new AndroidKeyPairGeneratorSpec.Builder(getContext())
+            mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
                     .setAlias(TEST_ALIAS_1)
                     .setSubject(TEST_DN_1)
                     .setSerialNumber(TEST_SERIAL_1)
@@ -211,7 +211,7 @@
 
         // Attempt to replace previous key
         {
-            mGenerator.initialize(new AndroidKeyPairGeneratorSpec.Builder(getContext())
+            mGenerator.initialize(new KeyPairGeneratorSpec.Builder(getContext())
                     .setAlias(TEST_ALIAS_1)
                     .setSubject(TEST_DN_2)
                     .setSerialNumber(TEST_SERIAL_2)
diff --git a/keystore/tests/src/android/security/AndroidKeyStoreTest.java b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
index 507d41c..8798fb5 100644
--- a/keystore/tests/src/android/security/AndroidKeyStoreTest.java
+++ b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
@@ -1232,8 +1232,8 @@
 
         try {
             mKeyStore.setEntry(TEST_ALIAS_1, entry,
-                    new AndroidKeyStoreParameter.Builder(getContext())
-                    .setEncryptionRequired()
+                    new KeyStoreParameter.Builder(getContext())
+                    .setEncryptionRequired(true)
                     .build());
             fail("Shouldn't be able to insert encrypted entry when KeyStore uninitialized");
         } catch (KeyStoreException expected) {
@@ -1752,8 +1752,10 @@
             Entry entry = mKeyStore.getEntry(TEST_ALIAS_1, null);
 
             try {
-                mKeyStore.setEntry(TEST_ALIAS_1, entry, new AndroidKeyStoreParameter.Builder(
-                        getContext()).setEncryptionRequired().build());
+                mKeyStore.setEntry(TEST_ALIAS_1, entry,
+                        new KeyStoreParameter.Builder(getContext())
+                                .setEncryptionRequired(true)
+                                .build());
                 fail("Should not allow setting of Entry without unlocked keystore");
             } catch (KeyStoreException success) {
             }
@@ -1762,8 +1764,8 @@
             assertTrue(mAndroidKeyStore.isUnlocked());
 
             mKeyStore.setEntry(TEST_ALIAS_1, entry,
-                    new AndroidKeyStoreParameter.Builder(getContext())
-                            .setEncryptionRequired()
+                    new KeyStoreParameter.Builder(getContext())
+                            .setEncryptionRequired(true)
                             .build());
         }
     }
diff --git a/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java b/keystore/tests/src/android/security/KeyPairGeneratorSpecTest.java
similarity index 83%
rename from keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
rename to keystore/tests/src/android/security/KeyPairGeneratorSpecTest.java
index 5d4ab9c..113d730 100644
--- a/keystore/tests/src/android/security/AndroidKeyPairGeneratorSpecTest.java
+++ b/keystore/tests/src/android/security/KeyPairGeneratorSpecTest.java
@@ -23,7 +23,7 @@
 
 import javax.security.auth.x500.X500Principal;
 
-public class AndroidKeyPairGeneratorSpecTest extends AndroidTestCase {
+public class KeyPairGeneratorSpecTest extends AndroidTestCase {
     private static final String TEST_ALIAS_1 = "test1";
 
     private static final X500Principal TEST_DN_1 = new X500Principal("CN=test1");
@@ -39,8 +39,8 @@
     private static final Date NOW_PLUS_10_YEARS = new Date(NOW.getYear() + 10, 0, 1);
 
     public void testConstructor_Success() throws Exception {
-        AndroidKeyPairGeneratorSpec spec =
-                new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1,
+        KeyPairGeneratorSpec spec =
+                new KeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1,
                         NOW, NOW_PLUS_10_YEARS, 0);
 
         assertEquals("Context should be the one specified", getContext(), spec.getContext());
@@ -55,7 +55,7 @@
     }
 
     public void testBuilder_Success() throws Exception {
-        AndroidKeyPairGeneratorSpec spec = new AndroidKeyPairGeneratorSpec.Builder(getContext())
+        KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(getContext())
                 .setAlias(TEST_ALIAS_1)
                 .setSubject(TEST_DN_1)
                 .setSerialNumber(SERIAL_1)
@@ -79,7 +79,7 @@
 
     public void testConstructor_NullContext_Failure() throws Exception {
         try {
-            new AndroidKeyPairGeneratorSpec(null, TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW,
+            new KeyPairGeneratorSpec(null, TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW,
                     NOW_PLUS_10_YEARS, 0);
             fail("Should throw IllegalArgumentException when context is null");
         } catch (IllegalArgumentException success) {
@@ -88,7 +88,7 @@
 
     public void testConstructor_NullKeystoreAlias_Failure() throws Exception {
         try {
-            new AndroidKeyPairGeneratorSpec(getContext(), null, TEST_DN_1, SERIAL_1, NOW,
+            new KeyPairGeneratorSpec(getContext(), null, TEST_DN_1, SERIAL_1, NOW,
                     NOW_PLUS_10_YEARS, 0);
             fail("Should throw IllegalArgumentException when keystoreAlias is null");
         } catch (IllegalArgumentException success) {
@@ -97,7 +97,7 @@
 
     public void testConstructor_NullSubjectDN_Failure() throws Exception {
         try {
-            new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, null, SERIAL_1, NOW,
+            new KeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, null, SERIAL_1, NOW,
                     NOW_PLUS_10_YEARS, 0);
             fail("Should throw IllegalArgumentException when subjectDN is null");
         } catch (IllegalArgumentException success) {
@@ -106,7 +106,7 @@
 
     public void testConstructor_NullSerial_Failure() throws Exception {
         try {
-            new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, null, NOW,
+            new KeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, null, NOW,
                     NOW_PLUS_10_YEARS, 0);
             fail("Should throw IllegalArgumentException when startDate is null");
         } catch (IllegalArgumentException success) {
@@ -115,7 +115,7 @@
 
     public void testConstructor_NullStartDate_Failure() throws Exception {
         try {
-            new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1, null,
+            new KeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1, null,
                     NOW_PLUS_10_YEARS, 0);
             fail("Should throw IllegalArgumentException when startDate is null");
         } catch (IllegalArgumentException success) {
@@ -124,7 +124,7 @@
 
     public void testConstructor_NullEndDate_Failure() throws Exception {
         try {
-            new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW,
+            new KeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1, NOW,
                     null, 0);
             fail("Should throw IllegalArgumentException when keystoreAlias is null");
         } catch (IllegalArgumentException success) {
@@ -133,7 +133,7 @@
 
     public void testConstructor_EndBeforeStart_Failure() throws Exception {
         try {
-            new AndroidKeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1,
+            new KeyPairGeneratorSpec(getContext(), TEST_ALIAS_1, TEST_DN_1, SERIAL_1,
                     NOW_PLUS_10_YEARS, NOW, 0);
             fail("Should throw IllegalArgumentException when end is before start");
         } catch (IllegalArgumentException success) {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 917a47d..56e98e4 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -1205,6 +1206,11 @@
      * call {@link #stopBluetoothSco()} to clear the request and turn down the bluetooth connection.
      * <p>Even if a SCO connection is established, the following restrictions apply on audio
      * output streams so that they can be routed to SCO headset:
+     * <p>NOTE: up to and including API version
+     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}, this method initiates a virtual
+     * voice call to the bluetooth headset.
+     * After API version {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2} only a raw SCO audio
+     * connection is established.
      * <ul>
      *   <li> the stream type must be {@link #STREAM_VOICE_CALL} </li>
      *   <li> the format must be mono </li>
@@ -1226,7 +1232,7 @@
     public void startBluetoothSco(){
         IAudioService service = getService();
         try {
-            service.startBluetoothSco(mICallBack);
+            service.startBluetoothSco(mICallBack, mContext.getApplicationInfo().targetSdkVersion);
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in startBluetoothSco", e);
         }
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 637ac85..0df4f82 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -48,6 +48,7 @@
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
@@ -369,6 +370,14 @@
     // waiting for headset service to connect
     private static final int SCO_STATE_DEACTIVATE_EXT_REQ = 4;
 
+    // Indicates the mode used for SCO audio connection. The mode is virtual call if the request
+    // originated from an app targeting an API version before JB MR2 and raw audio after that.
+    private int mScoAudioMode;
+    // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall())
+    private static final int SCO_MODE_VIRTUAL_CALL = 0;
+    // SCO audio mode is raw audio (BluetoothHeadset.connectAudio())
+    private static final int SCO_MODE_RAW = 1;
+
     // Current connection state indicated by bluetooth headset
     private int mScoConnectionState;
 
@@ -1910,7 +1919,7 @@
     }
 
     /** @see AudioManager#startBluetoothSco() */
-    public void startBluetoothSco(IBinder cb){
+    public void startBluetoothSco(IBinder cb, int targetSdkVersion){
         if (!checkAudioSettingsPermission("startBluetoothSco()") ||
                 !mBootCompleted) {
             return;
@@ -1922,7 +1931,7 @@
         // The caller identity must be cleared after getScoClient() because it is needed if a new
         // client is created.
         final long ident = Binder.clearCallingIdentity();
-        client.incCount();
+        client.incCount(targetSdkVersion);
         Binder.restoreCallingIdentity(ident);
     }
 
@@ -1968,9 +1977,9 @@
             }
         }
 
-        public void incCount() {
+        public void incCount(int targetSdkVersion) {
             synchronized(mScoClients) {
-                requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED);
+                requestScoState(BluetoothHeadset.STATE_AUDIO_CONNECTED, targetSdkVersion);
                 if (mStartcount == 0) {
                     try {
                         mCb.linkToDeath(this, 0);
@@ -1996,7 +2005,7 @@
                             Log.w(TAG, "decCount() going to 0 but not registered to binder");
                         }
                     }
-                    requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
+                    requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
                 }
             }
         }
@@ -2012,7 +2021,7 @@
                 }
                 mStartcount = 0;
                 if (stopSco) {
-                    requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED);
+                    requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED, 0);
                 }
             }
         }
@@ -2040,7 +2049,7 @@
             }
         }
 
-        private void requestScoState(int state) {
+        private void requestScoState(int state, int targetSdkVersion) {
             checkScoAudioState();
             if (totalCount() == 0) {
                 if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) {
@@ -2055,8 +2064,18 @@
                                 (mScoAudioState == SCO_STATE_INACTIVE ||
                                  mScoAudioState == SCO_STATE_DEACTIVATE_REQ)) {
                             if (mScoAudioState == SCO_STATE_INACTIVE) {
+                                mScoAudioMode =
+                                        (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR2) ?
+                                                SCO_MODE_VIRTUAL_CALL : SCO_MODE_RAW;
                                 if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
-                                    if (mBluetoothHeadset.connectAudio()) {
+                                    boolean status;
+                                    if (mScoAudioMode == SCO_MODE_RAW) {
+                                        status = mBluetoothHeadset.connectAudio();
+                                    } else {
+                                        status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
+                                                                            mBluetoothHeadsetDevice);
+                                    }
+                                    if (status) {
                                         mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
                                     } else {
                                         broadcastScoConnectionState(
@@ -2078,7 +2097,14 @@
                                mScoAudioState == SCO_STATE_ACTIVATE_REQ)) {
                     if (mScoAudioState == SCO_STATE_ACTIVE_INTERNAL) {
                         if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null) {
-                            if (!mBluetoothHeadset.disconnectAudio()) {
+                            boolean status;
+                            if (mScoAudioMode == SCO_MODE_RAW) {
+                                status = mBluetoothHeadset.disconnectAudio();
+                            } else {
+                                status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
+                                                                        mBluetoothHeadsetDevice);
+                            }
+                            if (!status) {
                                 mScoAudioState = SCO_STATE_INACTIVE;
                                 broadcastScoConnectionState(
                                         AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
@@ -2251,10 +2277,20 @@
                             switch (mScoAudioState) {
                             case SCO_STATE_ACTIVATE_REQ:
                                 mScoAudioState = SCO_STATE_ACTIVE_INTERNAL;
-                                status = mBluetoothHeadset.connectAudio();
+                                if (mScoAudioMode == SCO_MODE_RAW) {
+                                    status = mBluetoothHeadset.connectAudio();
+                                } else {
+                                    status = mBluetoothHeadset.startScoUsingVirtualVoiceCall(
+                                                                        mBluetoothHeadsetDevice);
+                                }
                                 break;
                             case SCO_STATE_DEACTIVATE_REQ:
-                                status = mBluetoothHeadset.disconnectAudio();
+                                if (mScoAudioMode == SCO_MODE_RAW) {
+                                    status = mBluetoothHeadset.disconnectAudio();
+                                } else {
+                                    status = mBluetoothHeadset.stopScoUsingVirtualVoiceCall(
+                                                                        mBluetoothHeadsetDevice);
+                                }
                                 break;
                             case SCO_STATE_DEACTIVATE_EXT_REQ:
                                 status = mBluetoothHeadset.stopVoiceRecognition(
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 13f6c02..0d285fc 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -179,7 +179,7 @@
            int  getRemoteStreamVolume();
     oneway void registerRemoteVolumeObserverForRcc(int rccId, in IRemoteVolumeObserver rvo);
 
-    void startBluetoothSco(IBinder cb);
+    void startBluetoothSco(IBinder cb, int targetSdkVersion);
     void stopBluetoothSco(IBinder cb);
 
     void forceVolumeControlStream(int streamType, IBinder cb);
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 1501c79..df87db3 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -44,7 +44,16 @@
         return MediaCodecList.getSupportedTypes(mIndex);
     }
 
+    /**
+     * Encapsulates the capabilities of a given codec component,
+     * i.e. what profile/level combinations it supports and what colorspaces
+     * it is capable of providing the decoded data in.
+     */
     public static final class CodecCapabilities {
+        // Enumerates supported profile/level combinations as defined
+        // by the type of encoded data. These combinations impose restrictions
+        // on video resolution, bitrate... and limit the available encoder tools
+        // such as B-frame support, arithmetic coding...
         public CodecProfileLevel[] profileLevels;
 
         // from OMX_COLOR_FORMATTYPE
@@ -219,6 +228,11 @@
         public int level;
     };
 
+    /**
+     * Enumerates the capabilities of the codec component. Since a single
+     * component can support data of a variety of types, the type has to be
+     * specified to yield a meaningful result.
+     */
     public final CodecCapabilities getCapabilitiesForType(
             String type) {
         return MediaCodecList.getCodecCapabilities(mIndex, type);
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index 61a0134..f77ddc4 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -65,6 +65,7 @@
 public class RemoteControlClient
 {
     private final static String TAG = "RemoteControlClient";
+    private final static boolean DEBUG = false;
 
     /**
      * Playback state of a RemoteControlClient which is stopped.
@@ -219,7 +220,7 @@
     public final static int PLAYBACKINFO_USES_STREAM = 5;
 
     //==========================================
-    // Public flags for the supported transport control capabililities
+    // Public flags for the supported transport control capabilities
     /**
      * Flag indicating a RemoteControlClient makes use of the "previous" media key.
      *
@@ -642,6 +643,57 @@
                 sendPlaybackState_syncCacheLock();
                 // update AudioService
                 sendAudioServiceNewPlaybackState_syncCacheLock();
+
+                // handle automatic playback position refreshes
+                if (mEventHandler == null) {
+                    return;
+                }
+                mEventHandler.removeMessages(MSG_POSITION_DRIFT_CHECK);
+                if (timeInMs == PLAYBACK_POSITION_INVALID) {
+                    // this playback state refresh has no known playback position, it's no use
+                    // trying to see if there is any drift at this point
+                    // (this also bypasses this mechanism for older apps that use the old
+                    //  setPlaybackState(int) API)
+                    return;
+                }
+                if (playbackPositionShouldMove(mPlaybackState)) {
+                    // playback position moving, schedule next position drift check
+                    mEventHandler.sendMessageDelayed(
+                            mEventHandler.obtainMessage(MSG_POSITION_DRIFT_CHECK),
+                            getCheckPeriodFromSpeed(playbackSpeed));
+                }
+            }
+        }
+    }
+
+    private void onPositionDriftCheck() {
+        if (DEBUG) { Log.d(TAG, "onPositionDriftCheck()"); }
+        synchronized(mCacheLock) {
+            if ((mEventHandler == null) || (mPositionProvider == null)) {
+                return;
+            }
+            if ((mPlaybackPositionMs == PLAYBACK_POSITION_INVALID) || (mPlaybackSpeed == 0.0f)) {
+                if (DEBUG) { Log.d(TAG, " no position or 0 speed, no check needed"); }
+                return;
+            }
+            long estPos = mPlaybackPositionMs + (long)
+                    ((SystemClock.elapsedRealtime() - mPlaybackStateChangeTimeMs) / mPlaybackSpeed);
+            long actPos = mPositionProvider.onGetPlaybackPosition();
+            if (actPos >= 0) {
+                if (Math.abs(estPos - actPos) > POSITION_DRIFT_MAX_MS) {
+                    // drift happened, report the new position
+                    if (DEBUG) { Log.w(TAG, " drift detected: actual=" +actPos +"  est=" +estPos); }
+                    setPlaybackState(mPlaybackState, actPos, mPlaybackSpeed);
+                } else {
+                    if (DEBUG) { Log.d(TAG, " no drift: actual=" + actPos +"  est=" + estPos); }
+                    // no drift, schedule the next drift check
+                    mEventHandler.sendMessageDelayed(
+                            mEventHandler.obtainMessage(MSG_POSITION_DRIFT_CHECK),
+                            getCheckPeriodFromSpeed(mPlaybackSpeed));
+                }
+            } else {
+                // invalid position (negative value), can't check for drift
+                mEventHandler.removeMessages(MSG_POSITION_DRIFT_CHECK);
             }
         }
     }
@@ -746,6 +798,14 @@
                 // tell RCDs that this RCC's playback position capabilities have changed
                 sendTransportControlInfo_syncCacheLock();
             }
+            if ((mPositionProvider != null) && (mEventHandler != null)
+                    && playbackPositionShouldMove(mPlaybackState)) {
+                // playback position is already moving, but now we have a position provider,
+                // so schedule a drift check right now
+                mEventHandler.sendMessageDelayed(
+                        mEventHandler.obtainMessage(MSG_POSITION_DRIFT_CHECK),
+                        0 /*check now*/);
+            }
         }
     }
 
@@ -1099,6 +1159,7 @@
     private final static int MSG_UNPLUG_DISPLAY = 8;
     private final static int MSG_UPDATE_DISPLAY_ARTWORK_SIZE = 9;
     private final static int MSG_SEEK_TO = 10;
+    private final static int MSG_POSITION_DRIFT_CHECK = 11;
 
     private class EventHandler extends Handler {
         public EventHandler(RemoteControlClient rcc, Looper looper) {
@@ -1146,6 +1207,9 @@
                 case MSG_SEEK_TO:
                     onSeekTo(msg.arg1, ((Long)msg.obj).longValue());
                     break;
+                case MSG_POSITION_DRIFT_CHECK:
+                    onPositionDriftCheck();
+                    break;
                 default:
                     Log.e(TAG, "Unknown event " + msg.what + " in RemoteControlClient handler");
             }
@@ -1440,4 +1504,57 @@
             return false;
         }
     }
+
+    /**
+     * Returns whether, for the given playback state, the playback position is expected to
+     * be changing.
+     * @param playstate the playback state to evaluate
+     * @return true during any form of playback, false if it's not playing anything while in this
+     *     playback state
+     */
+    private static boolean playbackPositionShouldMove(int playstate) {
+        switch(playstate) {
+            case PLAYSTATE_STOPPED:
+            case PLAYSTATE_PAUSED:
+            case PLAYSTATE_BUFFERING:
+            case PLAYSTATE_ERROR:
+            case PLAYSTATE_SKIPPING_FORWARDS:
+            case PLAYSTATE_SKIPPING_BACKWARDS:
+                return false;
+            case PLAYSTATE_PLAYING:
+            case PLAYSTATE_FAST_FORWARDING:
+            case PLAYSTATE_REWINDING:
+            default:
+                return true;
+        }
+    }
+
+    /**
+     * Period for playback position drift checks, 15s when playing at 1x or slower.
+     */
+    private final static long POSITION_REFRESH_PERIOD_PLAYING_MS = 15000;
+    /**
+     * Minimum period for playback position drift checks, never more often when every 2s, when
+     * fast forwarding or rewinding.
+     */
+    private final static long POSITION_REFRESH_PERIOD_MIN_MS = 2000;
+    /**
+     * The value above which the difference between client-reported playback position and
+     * estimated position is considered a drift.
+     */
+    private final static long POSITION_DRIFT_MAX_MS = 500;
+    /**
+     * Compute the period at which the estimated playback position should be compared against the
+     * actual playback position. Is a funciton of playback speed.
+     * @param speed 1.0f is normal playback speed
+     * @return the period in ms
+     */
+    private static long getCheckPeriodFromSpeed(float speed) {
+        if (Math.abs(speed) <= 1.0f) {
+            return POSITION_REFRESH_PERIOD_PLAYING_MS;
+        } else {
+            return Math.max((long)(POSITION_REFRESH_PERIOD_PLAYING_MS / Math.abs(speed)),
+                    POSITION_REFRESH_PERIOD_MIN_MS);
+        }
+    }
 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 7f3fc43..0fb3244 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -18,6 +18,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.AppOpsManager;
+import android.app.IUiModeManager;
 import android.app.ProgressDialog;
 import android.app.SearchManager;
 import android.app.UiModeManager;
@@ -31,6 +32,7 @@
 import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -125,6 +127,11 @@
     static final boolean SHOW_STARTING_ANIMATIONS = true;
     static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
 
+    // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
+    // No longer recommended for desk docks; still useful in car docks.
+    static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
+    static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
+
     static final int LONG_PRESS_POWER_NOTHING = 0;
     static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
     static final int LONG_PRESS_POWER_SHUT_OFF = 2;
@@ -247,6 +254,7 @@
     boolean mSystemReady;
     boolean mSystemBooted;
     boolean mHdmiPlugged;
+    int mUiMode;
     int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
     int mLidOpenRotation;
     int mCarDockRotation;
@@ -832,6 +840,8 @@
         mSettingsObserver.observe();
         mShortcutManager = new ShortcutManager(context, mHandler);
         mShortcutManager.observe();
+        mUiMode = context.getResources().getInteger(
+                com.android.internal.R.integer.config_defaultUiModeType);
         mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
         mHomeIntent.addCategory(Intent.CATEGORY_HOME);
         mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
@@ -3951,6 +3961,13 @@
             if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
                 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
+            } else {
+                try {
+                    IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
+                            ServiceManager.getService(Context.UI_MODE_SERVICE));
+                    mUiMode = uiModeService.getCurrentModeType();
+                } catch (RemoteException e) {
+                }
             }
             updateRotation(true);
             synchronized (mLock) {
@@ -4587,9 +4604,70 @@
         }
     }
 
+    /**
+     * Return an Intent to launch the currently active dock app as home.  Returns
+     * null if the standard home should be launched, which is the case if any of the following is
+     * true:
+     * <ul>
+     *  <li>The device is not in either car mode or desk mode
+     *  <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
+     *  <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
+     *  <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
+     *  <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
+     * </ul>
+     * @return
+     */
+    Intent createHomeDockIntent() {
+        Intent intent = null;
+
+        // What home does is based on the mode, not the dock state.  That
+        // is, when in car mode you should be taken to car home regardless
+        // of whether we are actually in a car dock.
+        if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
+            if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
+                intent = mCarDockIntent;
+            }
+        } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
+            if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
+                intent = mDeskDockIntent;
+            }
+        }
+
+        if (intent == null) {
+            return null;
+        }
+
+        ActivityInfo ai = null;
+        ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser(
+                intent,
+                PackageManager.MATCH_DEFAULT_ONLY,
+                UserHandle.USER_CURRENT);
+        if (info != null) {
+            ai = info.activityInfo;
+        }
+        if (ai != null
+                && ai.metaData != null
+                && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
+            intent = new Intent(intent);
+            intent.setClassName(ai.packageName, ai.name);
+            return intent;
+        }
+
+        return null;
+    }
+
     void startDockOrHome() {
         awakenDreams();
-        // We don't have dock home anymore. Home is home. If you lived here, you'd be home by now.
+
+        Intent dock = createHomeDockIntent();
+        if (dock != null) {
+            try {
+                mContext.startActivityAsUser(dock, UserHandle.CURRENT);
+                return;
+            } catch (ActivityNotFoundException e) {
+            }
+        }
+
         mContext.startActivityAsUser(mHomeIntent, UserHandle.CURRENT);
     }
     
@@ -4616,6 +4694,18 @@
                 } else {
                     ActivityManagerNative.getDefault().stopAppSwitches();
                     sendCloseSystemWindows();
+                    Intent dock = createHomeDockIntent();
+                    if (dock != null) {
+                        int result = ActivityManagerNative.getDefault()
+                                .startActivityAsUser(null, null, dock,
+                                        dock.resolveTypeIfNeeded(mContext.getContentResolver()),
+                                        null, null, 0,
+                                        ActivityManager.START_FLAG_ONLY_IF_NEEDED,
+                                        null, null, null, UserHandle.USER_CURRENT);
+                        if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
+                            return false;
+                        }
+                    }
                 }
                 int result = ActivityManagerNative.getDefault()
                         .startActivityAsUser(null, null, mHomeIntent,
@@ -4844,7 +4934,8 @@
             pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
                     pw.println(mLastFocusNeedsMenu);
         }
-        pw.print(prefix); pw.print("mDockMode="); pw.print(mDockMode);
+        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
+                pw.print(" mDockMode="); pw.print(mDockMode);
                 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
                 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
         pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index 4d23e5c..9560199 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -404,7 +404,7 @@
         try {
 
             /* Turning off Wi-Fi when scans are still available */
-            if (!enable && isScanningAlwaysAvailable()) {
+            if (!enable && isScanAlwaysAvailable()) {
                 /* Notify if device is provisioned and user has not opted out of the notification */
                 if (mNotifyScanMode.get() && mDeviceProvisioned.get()) {
                     Intent intent = new Intent(WifiManager.ACTION_NOTIFY_SCAN_ALWAYS_AVAILABLE);
@@ -497,7 +497,7 @@
      * @return {@code true} if the enable/disable operation was
      *         started or is already in the queue.
      */
-    public boolean isScanningAlwaysAvailable() {
+    public boolean isScanAlwaysAvailable() {
         enforceAccessPermission();
         return mSettingsStore.isScanAlwaysAvailable();
     }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index f093b52..547ae95 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -71,7 +71,7 @@
 
     DhcpInfo getDhcpInfo();
 
-    boolean isScanningAlwaysAvailable();
+    boolean isScanAlwaysAvailable();
 
     boolean acquireWifiLock(IBinder lock, int lockType, String tag, in WorkSource ws);
 
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 4e7497c..e2512a4 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -223,6 +223,9 @@
         public static final int PWD     = 3;
         /** @hide */
         public static final String[] strings = { "PEAP", "TLS", "TTLS", "PWD" };
+
+        /** Prevent initialization */
+        private Eap() {}
     }
 
     /** The inner authentication method used */
@@ -239,6 +242,9 @@
         private static final String PREFIX = "auth=";
         /** @hide */
         public static final String[] strings = {EMPTY_VALUE, "PAP", "MSCHAP", "MSCHAPV2", "GTC" };
+
+        /** Prevent initialization */
+        private Phase2() {}
     }
 
     /** Internal use only */
@@ -363,6 +369,16 @@
     }
 
     /**
+     * Get the password.
+     *
+     * Returns locally set password value. For networks fetched from
+     * framework, returns "*".
+     */
+    public String getPassword() {
+        return getFieldValue(PASSWORD_KEY, "");
+    }
+
+    /**
      * Set CA certificate alias.
      *
      * <p> See the {@link android.security.KeyChain} for details on installing or choosing
@@ -404,6 +420,15 @@
     }
 
     /**
+     * Get CA certificate
+     *
+     * @return X.509 CA certificate
+     */
+    public X509Certificate getCaCertificate() {
+        return mCaCert;
+    }
+
+    /**
      * Set Client certificate alias.
      *
      * <p> See the {@link android.security.KeyChain} for details on installing or choosing
@@ -463,6 +488,15 @@
         mClientCertificate = clientCertificate;
     }
 
+    /**
+     * Get client certificate
+     *
+     * @return X.509 client certificate
+     */
+    public X509Certificate getClientCertificate() {
+        return mClientCertificate;
+    }
+
     boolean needsKeyStore() {
         // Has no keys to be installed
         if (mClientCertificate == null && mCaCert == null) return false;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 0c0a144..a7a5924 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -794,9 +794,9 @@
      *
      * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}.
      */
-    public boolean isScanningAlwaysAvailable() {
+    public boolean isScanAlwaysAvailable() {
         try {
-            return mService.isScanningAlwaysAvailable();
+            return mService.isScanAlwaysAvailable();
         } catch (RemoteException e) {
             return false;
         }