Merge "Update process importance documentation." into jb-dev
diff --git a/api/current.txt b/api/current.txt
index e86bf63..46e3aa0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11076,15 +11076,20 @@
     method public boolean hasCacheReachedEndOfStream();
     method public int readSampleData(java.nio.ByteBuffer, int);
     method public final void release();
-    method public void seekTo(long);
+    method public void seekTo(long, int);
     method public void selectTrack(int);
     method public final void setDataSource(android.content.Context, android.net.Uri, java.util.Map<java.lang.String, java.lang.String>) throws java.io.IOException;
     method public final void setDataSource(java.lang.String, java.util.Map<java.lang.String, java.lang.String>);
     method public final void setDataSource(java.lang.String);
     method public final void setDataSource(java.io.FileDescriptor);
     method public final void setDataSource(java.io.FileDescriptor, long, long);
+    method public void unselectTrack(int);
     field public static final int SAMPLE_FLAG_ENCRYPTED = 2; // 0x2
     field public static final int SAMPLE_FLAG_SYNC = 1; // 0x1
+    field public static final int SEEK_TO_CLOSEST = 3; // 0x3
+    field public static final int SEEK_TO_CLOSEST_SYNC = 2; // 0x2
+    field public static final int SEEK_TO_NEXT_SYNC = 1; // 0x1
+    field public static final int SEEK_TO_PREVIOUS_SYNC = 0; // 0x0
   }
 
   public class MediaMetadataRetriever {
@@ -11251,6 +11256,7 @@
 
   public final class MediaRecorder.AudioEncoder {
     field public static final int AAC = 3; // 0x3
+    field public static final int AAC_ELD = 6; // 0x6
     field public static final int AMR_NB = 1; // 0x1
     field public static final int AMR_WB = 2; // 0x2
     field public static final int DEFAULT = 0; // 0x0
@@ -26608,7 +26614,7 @@
     method public abstract void onNothingSelected(android.widget.AdapterView<?>);
   }
 
-  public abstract class AdapterViewAnimator extends android.widget.AdapterView {
+  public abstract class AdapterViewAnimator extends android.widget.AdapterView implements android.widget.Advanceable {
     ctor public AdapterViewAnimator(android.content.Context);
     ctor public AdapterViewAnimator(android.content.Context, android.util.AttributeSet);
     ctor public AdapterViewAnimator(android.content.Context, android.util.AttributeSet, int);
@@ -26650,6 +26656,11 @@
     method public void stopFlipping();
   }
 
+  public abstract interface Advanceable {
+    method public abstract void advance();
+    method public abstract void fyiWillBeAdvancedByHostKThx();
+  }
+
   public class AlphabetIndexer extends android.database.DataSetObserver implements android.widget.SectionIndexer {
     ctor public AlphabetIndexer(android.database.Cursor, int, java.lang.CharSequence);
     method protected int compare(java.lang.String, java.lang.String);
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 0519d3e..7e1daa4 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -1890,7 +1890,7 @@
         if (mActive != null) {
             for (int i=0; i<mAdded.size(); i++) {
                 Fragment f = mAdded.get(i);
-                if (f != null && !f.mHidden) {
+                if (f != null && !f.mHidden && f.mUserVisibleHint) {
                     if (f.onContextItemSelected(item)) {
                         return true;
                     }
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 0640d7e..f4abda6 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -252,7 +252,7 @@
              * an int consistent with MountServiceResultCode
              */
             public int createSecureContainer(String id, int sizeMb, String fstype, String key,
-                    int ownerUid) throws RemoteException {
+                    int ownerUid, boolean external) throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
                 int _result;
@@ -263,6 +263,7 @@
                     _data.writeString(fstype);
                     _data.writeString(key);
                     _data.writeInt(ownerUid);
+                    _data.writeInt(external ? 1 : 0);
                     mRemote.transact(Stub.TRANSACTION_createSecureContainer, _data, _reply, 0);
                     _reply.readException();
                     _result = _reply.readInt();
@@ -711,6 +712,31 @@
                 }
                 return _result;
             }
+
+            /**
+             * Fix permissions in a container which has just been created and
+             * populated. Returns an int consistent with MountServiceResultCode
+             */
+            public int fixPermissionsSecureContainer(String id, int gid, String filename)
+                    throws RemoteException {
+                Parcel _data = Parcel.obtain();
+                Parcel _reply = Parcel.obtain();
+                int _result;
+                try {
+                    _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeString(id);
+                    _data.writeInt(gid);
+                    _data.writeString(filename);
+                    mRemote.transact(Stub.TRANSACTION_fixPermissionsSecureContainer, _data, _reply, 0);
+                    _reply.readException();
+                    _result = _reply.readInt();
+                } finally {
+                    _reply.recycle();
+                    _data.recycle();
+                }
+                return _result;
+
+            }
         }
 
         private static final String DESCRIPTOR = "IMountService";
@@ -781,6 +807,8 @@
 
         static final int TRANSACTION_verifyEncryptionPassword = IBinder.FIRST_CALL_TRANSACTION + 32;
 
+        static final int TRANSACTION_fixPermissionsSecureContainer = IBinder.FIRST_CALL_TRANSACTION + 33;
+
         /**
          * Cast an IBinder object into an IMountService interface, generating a
          * proxy if needed.
@@ -909,7 +937,10 @@
                     key = data.readString();
                     int ownerUid;
                     ownerUid = data.readInt();
-                    int resultCode = createSecureContainer(id, sizeMb, fstype, key, ownerUid);
+                    boolean external;
+                    external = 0 != data.readInt();
+                    int resultCode = createSecureContainer(id, sizeMb, fstype, key, ownerUid,
+                            external);
                     reply.writeNoException();
                     reply.writeInt(resultCode);
                     return true;
@@ -1109,6 +1140,19 @@
                     reply.writeInt(result);
                     return true;
                 }
+                case TRANSACTION_fixPermissionsSecureContainer: {
+                    data.enforceInterface(DESCRIPTOR);
+                    String id;
+                    id = data.readString();
+                    int gid;
+                    gid = data.readInt();
+                    String filename;
+                    filename = data.readString();
+                    int resultCode = fixPermissionsSecureContainer(id, gid, filename);
+                    reply.writeNoException();
+                    reply.writeInt(resultCode);
+                    return true;
+                }
             }
             return super.onTransact(code, data, reply, flags);
         }
@@ -1118,8 +1162,8 @@
      * Creates a secure container with the specified parameters. Returns an int
      * consistent with MountServiceResultCode
      */
-    public int createSecureContainer(String id, int sizeMb, String fstype, String key, int ownerUid)
-            throws RemoteException;
+    public int createSecureContainer(String id, int sizeMb, String fstype, String key,
+            int ownerUid, boolean external) throws RemoteException;
 
     /*
      * Destroy a secure container, and free up all resources associated with it.
@@ -1317,4 +1361,11 @@
     public Parcelable[] getVolumeList() throws RemoteException;
 
     public String getSecureContainerFilesystemPath(String id) throws RemoteException;
+
+    /*
+     * Fix permissions in a container which has just been created and populated.
+     * Returns an int consistent with MountServiceResultCode
+     */
+    public int fixPermissionsSecureContainer(String id, int gid, String filename)
+            throws RemoteException;
 }
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 7d41e64..018785b 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -5411,8 +5411,9 @@
 
             /**
              * The phone number's E164 representation. This value can be omitted in which
-             * case the provider will try to automatically infer it. If present, {@link #NUMBER}
-             * has to be set as well (it will be ignored otherwise).
+             * case the provider will try to automatically infer it.  (It'll be left null if the
+             * provider fails to infer.)
+             * If present, {@link #NUMBER} has to be set as well (it will be ignored otherwise).
              * <P>Type: TEXT</P>
              */
             public static final String NORMALIZED_NUMBER = DATA4;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 2dcea80..c453a5d 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -45,8 +45,7 @@
     private static final ParagraphStyle[] NO_PARA_SPANS =
         ArrayUtils.emptyArray(ParagraphStyle.class);
 
-    /* package */ static final EmojiFactory EMOJI_FACTORY =
-        EmojiFactory.newAvailableInstance();
+    /* package */ static final EmojiFactory EMOJI_FACTORY = EmojiFactory.newAvailableInstance();
     /* package */ static final int MIN_EMOJI, MAX_EMOJI;
 
     static {
@@ -363,15 +362,15 @@
         // direction of the layout or line.  XXX: Should they?
         // They are evaluated at each line.
         if (mSpannedText) {
-            if (lineBackgroundSpans == null) {
-                lineBackgroundSpans = new SpanSet<LineBackgroundSpan>(LineBackgroundSpan.class);
+            if (mLineBackgroundSpans == null) {
+                mLineBackgroundSpans = new SpanSet<LineBackgroundSpan>(LineBackgroundSpan.class);
             }
 
             Spanned buffer = (Spanned) mText;
             int textLength = buffer.length();
-            lineBackgroundSpans.init(buffer, 0, textLength);
+            mLineBackgroundSpans.init(buffer, 0, textLength);
 
-            if (lineBackgroundSpans.numberOfSpans > 0) {
+            if (mLineBackgroundSpans.numberOfSpans > 0) {
                 int previousLineBottom = getLineTop(firstLine);
                 int previousLineEnd = getLineStart(firstLine);
                 ParagraphStyle[] spans = NO_PARA_SPANS;
@@ -392,17 +391,18 @@
                     if (start >= spanEnd) {
                         // These should be infrequent, so we'll use this so that
                         // we don't have to check as often.
-                        spanEnd = lineBackgroundSpans.getNextTransition(start, textLength);
+                        spanEnd = mLineBackgroundSpans.getNextTransition(start, textLength);
                         // All LineBackgroundSpans on a line contribute to its background.
                         spansLength = 0;
                         // Duplication of the logic of getParagraphSpans
                         if (start != end || start == 0) {
                             // Equivalent to a getSpans(start, end), but filling the 'spans' local
                             // array instead to reduce memory allocation
-                            for (int j = 0; j < lineBackgroundSpans.numberOfSpans; j++) {
-                                // equal test is valid since both intervals are not empty by construction
-                                if (lineBackgroundSpans.spanStarts[j] >= end ||
-                                        lineBackgroundSpans.spanEnds[j] <= start) continue;
+                            for (int j = 0; j < mLineBackgroundSpans.numberOfSpans; j++) {
+                                // equal test is valid since both intervals are not empty by
+                                // construction
+                                if (mLineBackgroundSpans.spanStarts[j] >= end ||
+                                        mLineBackgroundSpans.spanEnds[j] <= start) continue;
                                 if (spansLength == spans.length) {
                                     // The spans array needs to be expanded
                                     int newSize = ArrayUtils.idealObjectArraySize(2 * spansLength);
@@ -410,7 +410,7 @@
                                     System.arraycopy(spans, 0, newSpans, 0, spansLength);
                                     spans = newSpans;
                                 }
-                                spans[spansLength++] = lineBackgroundSpans.spans[j];
+                                spans[spansLength++] = mLineBackgroundSpans.spans[j];
                             }
                         }
                     }
@@ -423,7 +423,7 @@
                     }
                 }
             }
-            lineBackgroundSpans.recycle();
+            mLineBackgroundSpans.recycle();
         }
 
         // There can be a highlight even without spans if we are drawing
@@ -1687,7 +1687,7 @@
      * styles that are already applied to the buffer will apply to text that
      * is inserted into it.
      */
-    /* package */ static <T> T[] getParagraphSpans(Spanned text, int start, int end, Class<T> type) {
+    /* package */static <T> T[] getParagraphSpans(Spanned text, int start, int end, Class<T> type) {
         if (start == end && start > 0) {
             return ArrayUtils.emptyArray(type);
         }
@@ -1857,7 +1857,7 @@
     private static final Rect sTempRect = new Rect();
     private boolean mSpannedText;
     private TextDirectionHeuristic mTextDir;
-    private SpanSet<LineBackgroundSpan> lineBackgroundSpans;
+    private SpanSet<LineBackgroundSpan> mLineBackgroundSpans;
 
     public static final int DIR_LEFT_TO_RIGHT = 1;
     public static final int DIR_RIGHT_TO_LEFT = -1;
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 1c61c6c..5b371eb 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -153,20 +153,26 @@
     private static final int ACCENT_BREVE = '\u02D8';
     private static final int ACCENT_CARON = '\u02C7';
     private static final int ACCENT_CEDILLA = '\u00B8';
+    private static final int ACCENT_CIRCUMFLEX = '\u02C6';
     private static final int ACCENT_COMMA_ABOVE = '\u1FBD';
     private static final int ACCENT_COMMA_ABOVE_RIGHT = '\u02BC';
     private static final int ACCENT_DOT_ABOVE = '\u02D9';
+    private static final int ACCENT_DOT_BELOW = '.'; // approximate
     private static final int ACCENT_DOUBLE_ACUTE = '\u02DD';
     private static final int ACCENT_GRAVE = '\u02CB';
-    private static final int ACCENT_CIRCUMFLEX = '\u02C6';
+    private static final int ACCENT_HOOK_ABOVE = '\u02C0';
+    private static final int ACCENT_HORN = '\''; // approximate
     private static final int ACCENT_MACRON = '\u00AF';
     private static final int ACCENT_MACRON_BELOW = '\u02CD';
     private static final int ACCENT_OGONEK = '\u02DB';
     private static final int ACCENT_REVERSED_COMMA_ABOVE = '\u02BD';
     private static final int ACCENT_RING_ABOVE = '\u02DA';
+    private static final int ACCENT_STROKE = '-'; // approximate
     private static final int ACCENT_TILDE = '\u02DC';
     private static final int ACCENT_TURNED_COMMA_ABOVE = '\u02BB';
     private static final int ACCENT_UMLAUT = '\u00A8';
+    private static final int ACCENT_VERTICAL_LINE_ABOVE = '\u02C8';
+    private static final int ACCENT_VERTICAL_LINE_BELOW = '\u02CC';
 
     /* Legacy dead key display characters used in previous versions of the API.
      * We still support these characters by mapping them to their non-legacy version. */
@@ -188,11 +194,11 @@
         addCombining('\u0306', ACCENT_BREVE);
         addCombining('\u0307', ACCENT_DOT_ABOVE);
         addCombining('\u0308', ACCENT_UMLAUT);
-        //addCombining('\u0309', ACCENT_HOOK_ABOVE);
+        addCombining('\u0309', ACCENT_HOOK_ABOVE);
         addCombining('\u030A', ACCENT_RING_ABOVE);
         addCombining('\u030B', ACCENT_DOUBLE_ACUTE);
         addCombining('\u030C', ACCENT_CARON);
-        //addCombining('\u030D', ACCENT_VERTICAL_LINE_ABOVE);
+        addCombining('\u030D', ACCENT_VERTICAL_LINE_ABOVE);
         //addCombining('\u030E', ACCENT_DOUBLE_VERTICAL_LINE_ABOVE);
         //addCombining('\u030F', ACCENT_DOUBLE_GRAVE);
         //addCombining('\u0310', ACCENT_CANDRABINDU);
@@ -201,13 +207,14 @@
         addCombining('\u0313', ACCENT_COMMA_ABOVE);
         addCombining('\u0314', ACCENT_REVERSED_COMMA_ABOVE);
         addCombining('\u0315', ACCENT_COMMA_ABOVE_RIGHT);
-        //addCombining('\u031B', ACCENT_HORN);
-        //addCombining('\u0323', ACCENT_DOT_BELOW);
+        addCombining('\u031B', ACCENT_HORN);
+        addCombining('\u0323', ACCENT_DOT_BELOW);
         //addCombining('\u0326', ACCENT_COMMA_BELOW);
         addCombining('\u0327', ACCENT_CEDILLA);
         addCombining('\u0328', ACCENT_OGONEK);
-        //addCombining('\u0329', ACCENT_VERTICAL_LINE_BELOW);
+        addCombining('\u0329', ACCENT_VERTICAL_LINE_BELOW);
         addCombining('\u0331', ACCENT_MACRON_BELOW);
+        addCombining('\u0335', ACCENT_STROKE);
         //addCombining('\u0342', ACCENT_PERISPOMENI);
         //addCombining('\u0344', ACCENT_DIALYTIKA_TONOS);
         //addCombining('\u0345', ACCENT_YPOGEGRAMMENI);
@@ -235,6 +242,33 @@
      */
     private static final SparseIntArray sDeadKeyCache = new SparseIntArray();
     private static final StringBuilder sDeadKeyBuilder = new StringBuilder();
+    static {
+        // Non-standard decompositions.
+        // Stroke modifier for Finnish multilingual keyboard and others.
+        addDeadKey(ACCENT_STROKE, 'D', '\u0110');
+        addDeadKey(ACCENT_STROKE, 'G', '\u01e4');
+        addDeadKey(ACCENT_STROKE, 'H', '\u0126');
+        addDeadKey(ACCENT_STROKE, 'I', '\u0197');
+        addDeadKey(ACCENT_STROKE, 'L', '\u0141');
+        addDeadKey(ACCENT_STROKE, 'O', '\u00d8');
+        addDeadKey(ACCENT_STROKE, 'T', '\u0166');
+        addDeadKey(ACCENT_STROKE, 'd', '\u0111');
+        addDeadKey(ACCENT_STROKE, 'g', '\u01e5');
+        addDeadKey(ACCENT_STROKE, 'h', '\u0127');
+        addDeadKey(ACCENT_STROKE, 'i', '\u0268');
+        addDeadKey(ACCENT_STROKE, 'l', '\u0142');
+        addDeadKey(ACCENT_STROKE, 'o', '\u00f8');
+        addDeadKey(ACCENT_STROKE, 't', '\u0167');
+    }
+
+    private static void addDeadKey(int accent, int c, int result) {
+        final int combining = sAccentToCombining.get(accent);
+        if (combining == 0) {
+            throw new IllegalStateException("Invalid dead key declaration.");
+        }
+        final int combination = (combining << 16) | c;
+        sDeadKeyCache.put(combination, result);
+    }
 
     public static final Parcelable.Creator<KeyCharacterMap> CREATOR =
             new Parcelable.Creator<KeyCharacterMap>() {
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index 671c064..f0e6ff0 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -56,6 +56,7 @@
      * Represents a resource stored in the HTTP cache. Instances of this class
      * can be obtained by calling
      * {@link CacheManager#getCacheFile CacheManager.getCacheFile(String, Map<String, String>))}.
+     *
      * @deprecated Access to the HTTP cache will be removed in a future release.
      */
     @Deprecated
@@ -81,7 +82,8 @@
 
         /**
          * Gets the status code of this cache entry.
-         * @return The status code of this cache entry
+         *
+         * @return the status code of this cache entry
          */
         public int getHttpStatusCode() {
             return httpStatusCode;
@@ -89,7 +91,8 @@
 
         /**
          * Gets the content length of this cache entry.
-         * @return The content length of this cache entry
+         *
+         * @return the content length of this cache entry
          */
         public long getContentLength() {
             return contentLength;
@@ -99,7 +102,8 @@
          * Gets the path of the file used to store the content of this cache
          * entry, relative to the base directory of the cache. See
          * {@link CacheManager#getCacheFileBaseDir CacheManager.getCacheFileBaseDir()}.
-         * @return The path of the file used to store this cache entry
+         *
+         * @return the path of the file used to store this cache entry
          */
         public String getLocalPath() {
             return localPath;
@@ -108,7 +112,8 @@
         /**
          * Gets the expiry date of this cache entry, expressed in milliseconds
          * since midnight, January 1, 1970 UTC.
-         * @return The expiry date of this cache entry
+         *
+         * @return the expiry date of this cache entry
          */
         public long getExpires() {
             return expires;
@@ -116,7 +121,8 @@
 
         /**
          * Gets the expiry date of this cache entry, expressed as a string.
-         * @return The expiry date of this cache entry
+         *
+         * @return the expiry date of this cache entry
          *
          */
         public String getExpiresString() {
@@ -126,7 +132,8 @@
         /**
          * Gets the date at which this cache entry was last modified, expressed
          * as a string.
-         * @return The date at which this cache entry was last modified
+         *
+         * @return the date at which this cache entry was last modified
          */
         public String getLastModified() {
             return lastModified;
@@ -134,7 +141,8 @@
 
         /**
          * Gets the entity tag of this cache entry.
-         * @return The entity tag of this cache entry
+         *
+         * @return the entity tag of this cache entry
          */
         public String getETag() {
             return etag;
@@ -142,7 +150,8 @@
 
         /**
          * Gets the MIME type of this cache entry.
-         * @return The MIME type of this cache entry
+         *
+         * @return the MIME type of this cache entry
          */
         public String getMimeType() {
             return mimeType;
@@ -151,7 +160,8 @@
         /**
          * Gets the value of the HTTP 'Location' header with which this cache
          * entry was received.
-         * @return The HTTP 'Location' header for this cache entry
+         *
+         * @return the HTTP 'Location' header for this cache entry
          */
         public String getLocation() {
             return location;
@@ -159,7 +169,8 @@
 
         /**
          * Gets the encoding of this cache entry.
-         * @return The encoding of this cache entry
+         *
+         * @return the encoding of this cache entry
          */
         public String getEncoding() {
             return encoding;
@@ -168,7 +179,8 @@
         /**
          * Gets the value of the HTTP 'Content-Disposition' header with which
          * this cache entry was received.
-         * @return The HTTP 'Content-Disposition' header for this cache entry
+         *
+         * @return the HTTP 'Content-Disposition' header for this cache entry
          *
          */
         public String getContentDisposition() {
@@ -179,7 +191,8 @@
          * Gets the input stream to the content of this cache entry, to allow
          * content to be read. See
          * {@link CacheManager#getCacheFile CacheManager.getCacheFile(String, Map<String, String>)}.
-         * @return An input stream to the content of this cache entry
+         *
+         * @return an input stream to the content of this cache entry
          */
         public InputStream getInputStream() {
             return inStream;
@@ -189,7 +202,8 @@
          * Gets an output stream to the content of this cache entry, to allow
          * content to be written. See
          * {@link CacheManager#saveCacheFile CacheManager.saveCacheFile(String, CacheResult)}.
-         * @return An output stream to the content of this cache entry
+         *
+         * @return an output stream to the content of this cache entry
          */
         // Note that this is always null for objects returned by getCacheFile()!
         public OutputStream getOutputStream() {
@@ -199,7 +213,8 @@
 
         /**
          * Sets an input stream to the content of this cache entry.
-         * @param stream An input stream to the content of this cache entry
+         *
+         * @param stream an input stream to the content of this cache entry
          */
         public void setInputStream(InputStream stream) {
             this.inStream = stream;
@@ -207,7 +222,8 @@
 
         /**
          * Sets the encoding of this cache entry.
-         * @param encoding The encoding of this cache entry
+         *
+         * @param encoding the encoding of this cache entry
          */
         public void setEncoding(String encoding) {
             this.encoding = encoding;
@@ -225,7 +241,8 @@
      * Initializes the HTTP cache. This method must be called before any
      * CacheManager methods are used. Note that this is called automatically
      * when a {@link WebView} is created.
-     * @param context The application context
+     *
+     * @param context the application context
      */
     static void init(Context context) {
         // This isn't actually where the real cache lives, but where we put files for the
@@ -240,7 +257,8 @@
      * Gets the base directory in which the files used to store the contents of
      * cache entries are placed. See
      * {@link CacheManager.CacheResult#getLocalPath CacheManager.CacheResult.getLocalPath()}.
-     * @return The base directory of the cache
+     *
+     * @return the base directory of the cache
      * @deprecated Access to the HTTP cache will be removed in a future release.
      */
     @Deprecated
@@ -250,7 +268,8 @@
 
     /**
      * Gets whether the HTTP cache is disabled.
-     * @return True if the HTTP cache is disabled
+     *
+     * @return true if the HTTP cache is disabled
      * @deprecated Access to the HTTP cache will be removed in a future release.
      */
     @Deprecated
@@ -262,8 +281,9 @@
      * Starts a cache transaction. Returns true if this is the only running
      * transaction. Otherwise, this transaction is nested inside currently
      * running transactions and false is returned.
-     * @return True if this is the only running transaction
-     * @deprecated This method no longer has any effect and always returns false
+     *
+     * @return true if this is the only running transaction
+     * @deprecated This method no longer has any effect and always returns false.
      */
     @Deprecated
     public static boolean startCacheTransaction() {
@@ -273,8 +293,9 @@
     /**
      * Ends the innermost cache transaction and returns whether this was the
      * only running transaction.
-     * @return True if this was the only running transaction
-     * @deprecated This method no longer has any effect and always returns false
+     *
+     * @return true if this was the only running transaction
+     * @deprecated This method no longer has any effect and always returns false.
      */
     @Deprecated
     public static boolean endCacheTransaction() {
@@ -287,10 +308,11 @@
      * entry needs validation, appropriate headers will be added to the map.
      * The input stream of the CacheEntry object should be closed by the caller
      * when access to the underlying file is no longer required.
-     * @param url The URL for which a cache entry is requested
-     * @param headers A map from HTTP header name to value, to be populated
+     *
+     * @param url the URL for which a cache entry is requested
+     * @param headers a map from HTTP header name to value, to be populated
      *                for the returned cache entry
-     * @return The cache entry for the specified URL
+     * @return the cache entry for the specified URL
      * @deprecated Access to the HTTP cache will be removed in a future release.
      */
     @Deprecated
@@ -345,14 +367,15 @@
     }
 
     /**
-     * Given a url and its full headers, returns CacheResult if a local cache
+     * Given a URL and its full headers, gets a CacheResult if a local cache
      * can be stored. Otherwise returns null. The mimetype is passed in so that
      * the function can use the mimetype that will be passed to WebCore which
      * could be different from the mimetype defined in the headers.
      * forceCache is for out-of-package callers to force creation of a
      * CacheResult, and is used to supply surrogate responses for URL
      * interception.
-     * @return CacheResult for a given url
+     *
+     * @return a CacheResult for a given URL
      */
     static CacheResult createCacheFile(String url, int statusCode,
             Headers headers, String mimeType, boolean forceCache) {
@@ -363,8 +386,9 @@
     /**
      * Adds a cache entry to the HTTP cache for the specicifed URL. Also closes
      * the cache entry's output stream.
-     * @param url The URL for which the cache entry should be added
-     * @param cacheResult The cache entry to add
+     *
+     * @param url the URL for which the cache entry should be added
+     * @param cacheResult the cache entry to add
      * @deprecated Access to the HTTP cache will be removed in a future release.
      */
     @Deprecated
@@ -401,9 +425,9 @@
     }
 
     /**
-     * Remove all cache files.
+     * Removes all cache files.
      *
-     * @return Whether the removal succeeded.
+     * @return whether the removal succeeded
      */
     static boolean removeAllCacheFiles() {
         // delete cache files in a separate thread to not block UI.
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 1e7f38c..30c713e 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -40,7 +40,7 @@
      * {@link CookieSyncManager#createInstance(Context)} must be called
      * first.
      *
-     * @return The singleton CookieManager instance
+     * @return the singleton CookieManager instance
      */
     public static synchronized CookieManager getInstance() {
         return WebViewFactory.getProvider().getCookieManager();
@@ -49,7 +49,8 @@
     /**
      * Sets whether the application's {@link WebView} instances should send and
      * accept cookies.
-     * @param accept Whether {@link WebView} instances should send and accept
+     *
+     * @param accept whether {@link WebView} instances should send and accept
      *               cookies
      */
     public synchronized void setAcceptCookie(boolean accept) {
@@ -59,7 +60,8 @@
     /**
      * Gets whether the application's {@link WebView} instances send and accept
      * cookies.
-     * @return True if {@link WebView} instances send and accept cookies
+     *
+     * @return true if {@link WebView} instances send and accept cookies
      */
     public synchronized boolean acceptCookie() {
         throw new MustOverrideException();
@@ -70,8 +72,9 @@
      * path and name will be replaced with the new cookie. The cookie being set
      * must not have expired and must not be a session cookie, otherwise it
      * will be ignored.
-     * @param url The URL for which the cookie is set
-     * @param value The cookie as a string, using the format of the 'Set-Cookie'
+     *
+     * @param url the URL for which the cookie is set
+     * @param value the cookie as a string, using the format of the 'Set-Cookie'
      *              HTTP response header
      */
     public void setCookie(String url, String value) {
@@ -80,8 +83,9 @@
 
     /**
      * Gets the cookies for the given URL.
-     * @param url The URL for which the cookies are requested
-     * @return value The cookies as a string, using the format of the 'Cookie'
+     *
+     * @param url the URL for which the cookies are requested
+     * @return value the cookies as a string, using the format of the 'Cookie'
      *               HTTP request header
      */
     public String getCookie(String url) {
@@ -89,10 +93,11 @@
     }
 
     /**
-     * See {@link #getCookie(String)}
-     * @param url The URL for which the cookies are requested
-     * @param privateBrowsing Whether to use the private browsing cookie jar
-     * @return value The cookies as a string, using the format of the 'Cookie'
+     * See {@link #getCookie(String)}.
+     *
+     * @param url the URL for which the cookies are requested
+     * @param privateBrowsing whether to use the private browsing cookie jar
+     * @return value the cookies as a string, using the format of the 'Cookie'
      *               HTTP request header
      * @hide Used by Browser, no intention to publish.
      */
@@ -101,10 +106,11 @@
     }
 
     /**
-     * Get cookie(s) for a given uri so that it can be set to "cookie:" in http
+     * Gets cookie(s) for a given uri so that it can be set to "cookie:" in http
      * request header.
-     * @param uri The WebAddress for which the cookies are requested
-     * @return value The cookies as a string, using the format of the 'Cookie'
+     *
+     * @param uri the WebAddress for which the cookies are requested
+     * @return value the cookies as a string, using the format of the 'Cookie'
      *               HTTP request header
      * @hide Used by RequestHandle, no intention to publish.
      */
@@ -129,7 +135,8 @@
 
     /**
      * Gets whether there are stored cookies.
-     * @return True if there are stored cookies.
+     *
+     * @return true if there are stored cookies
      */
     public synchronized boolean hasCookies() {
         throw new MustOverrideException();
@@ -137,7 +144,8 @@
 
     /**
      * See {@link #hasCookies()}.
-     * @param privateBrowsing Whether to use the private browsing cookie jar
+     *
+     * @param privateBrowsing whether to use the private browsing cookie jar
      * @hide Used by Browser, no intention to publish.
      */
     public synchronized boolean hasCookies(boolean privateBrowsing) {
@@ -152,7 +160,7 @@
     }
 
     /**
-     * Flush all cookies managed by the Chrome HTTP stack to flash.
+     * Flushes all cookies managed by the Chrome HTTP stack to flash.
      *
      * @hide Package level api, called from CookieSyncManager
      */
@@ -163,7 +171,8 @@
     /**
      * Gets whether the application's {@link WebView} instances send and accept
      * cookies for file scheme URLs.
-     * @return True if {@link WebView} instances send and accept cookies for
+     *
+     * @return true if {@link WebView} instances send and accept cookies for
      *         file scheme URLs
      */
     // Static for backward compatibility.
@@ -172,7 +181,8 @@
     }
 
     /**
-     * Implements {@link #allowFileSchemeCookies()}
+     * Implements {@link #allowFileSchemeCookies()}.
+     *
      * @hide Only for use by WebViewProvider implementations
      */
     protected boolean allowFileSchemeCookiesImpl() {
@@ -195,7 +205,8 @@
     }
 
     /**
-     * Implements {@link #setAcceptFileSchemeCookies(boolean)}
+     * Implements {@link #setAcceptFileSchemeCookies(boolean)}.
+     *
      * @hide Only for use by WebViewProvider implementations
      */
     protected void setAcceptFileSchemeCookiesImpl(boolean accept) {
diff --git a/core/java/android/webkit/GeolocationPermissions.java b/core/java/android/webkit/GeolocationPermissions.java
index cd5c9d1..9c0f754 100755
--- a/core/java/android/webkit/GeolocationPermissions.java
+++ b/core/java/android/webkit/GeolocationPermissions.java
@@ -48,28 +48,31 @@
      */
     public interface Callback {
         /**
-         * Set the Geolocation permission state for the supplied origin.
-         * @param origin The origin for which permissions are set.
-         * @param allow Whether or not the origin should be allowed to use the
-         *              Geolocation API.
-         * @param retain Whether the permission should be retained beyond the
+         * Sets the Geolocation permission state for the supplied origin.
+         *
+         * @param origin the origin for which permissions are set
+         * @param allow whether or not the origin should be allowed to use the
+         *              Geolocation API
+         * @param retain whether the permission should be retained beyond the
          *               lifetime of a page currently being displayed by a
-         *               WebView.
+         *               WebView
          */
         public void invoke(String origin, boolean allow, boolean retain);
     };
 
     /**
-     * Get the singleton instance of this class.
-     * @return The singleton {@link GeolocationPermissions} instance.
+     * Gets the singleton instance of this class.
+     *
+     * @return the singleton {@link GeolocationPermissions} instance
      */
     public static GeolocationPermissions getInstance() {
       return WebViewFactory.getProvider().getGeolocationPermissions();
     }
 
     /**
-     * Get the set of origins for which Geolocation permissions are stored.
-     * @param callback A {@link ValueCallback} to receive the result of this
+     * Gets the set of origins for which Geolocation permissions are stored.
+     *
+     * @param callback a {@link ValueCallback} to receive the result of this
      *                 request. This object's
      *                 {@link ValueCallback#onReceiveValue(T) onReceiveValue()}
      *                 method will be invoked asynchronously with a set of
@@ -85,9 +88,10 @@
     }
 
     /**
-     * Get the Geolocation permission state for the specified origin.
-     * @param origin The origin for which Geolocation permission is requested.
-     * @param callback A {@link ValueCallback} to receive the result of this
+     * Gets the Geolocation permission state for the specified origin.
+     *
+     * @param origin the origin for which Geolocation permission is requested
+     * @param callback a {@link ValueCallback} to receive the result of this
      *                 request. This object's
      *                 {@link ValueCallback#onReceiveValue(T) onReceiveValue()}
      *                 method will be invoked asynchronously with a boolean
@@ -99,23 +103,25 @@
     }
 
     /**
-     * Clear the Geolocation permission state for the specified origin.
-     * @param origin The origin for which Geolocation permissions are cleared.
+     * Clears the Geolocation permission state for the specified origin.
+     *
+     * @param origin the origin for which Geolocation permissions are cleared
      */
     public void clear(String origin) {
         // Must be a no-op for backward compatibility: see the hidden constructor for reason.
     }
 
     /**
-     * Allow the specified origin to use the Geolocation API.
-     * @param origin The origin for which Geolocation API use is allowed.
+     * Allows the specified origin to use the Geolocation API.
+     *
+     * @param origin the origin for which Geolocation API use is allowed
      */
     public void allow(String origin) {
         // Must be a no-op for backward compatibility: see the hidden constructor for reason.
     }
 
     /**
-     * Clear the Geolocation permission state for all origins.
+     * Clears the Geolocation permission state for all origins.
      */
     public void clearAll() {
         // Must be a no-op for backward compatibility: see the hidden constructor for reason.
diff --git a/core/java/android/webkit/ViewStateSerializer.java b/core/java/android/webkit/ViewStateSerializer.java
index 35168cf..c161085 100644
--- a/core/java/android/webkit/ViewStateSerializer.java
+++ b/core/java/android/webkit/ViewStateSerializer.java
@@ -64,7 +64,6 @@
         draw.mViewState = new WebViewCore.ViewState();
         draw.mContentSize = new Point(contentWidth, contentHeight);
         draw.mBaseLayer = baseLayer;
-        draw.mInvalRegion = new Region(0, 0, contentWidth, contentHeight);
         stream.close();
         return draw;
     }
diff --git a/core/java/android/webkit/WebResourceResponse.java b/core/java/android/webkit/WebResourceResponse.java
index 650310e..b7171ee 100644
--- a/core/java/android/webkit/WebResourceResponse.java
+++ b/core/java/android/webkit/WebResourceResponse.java
@@ -36,9 +36,10 @@
      * input stream. Callers must implement
      * {@link InputStream#read(byte[]) InputStream.read(byte[])} for the input
      * stream.
-     * @param mimeType The resource response's MIME type, for example text/html
-     * @param encoding The resource response's encoding
-     * @param data The input stream that provides the resource response's data
+     *
+     * @param mimeType the resource response's MIME type, for example text/html
+     * @param encoding the resource response's encoding
+     * @param data the input stream that provides the resource response's data
      */
     public WebResourceResponse(String mimeType, String encoding,
             InputStream data) {
@@ -49,7 +50,8 @@
 
     /**
      * Sets the resource response's MIME type, for example text/html.
-     * @param mimeType The resource response's MIME type
+     *
+     * @param mimeType the resource response's MIME type
      */
     public void setMimeType(String mimeType) {
         mMimeType = mimeType;
@@ -57,7 +59,8 @@
 
     /**
      * Gets the resource response's MIME type.
-     * @return The resource response's MIME type
+     *
+     * @return the resource response's MIME type
      */
     public String getMimeType() {
         return mMimeType;
@@ -66,7 +69,8 @@
     /**
      * Sets the resource response's encoding, for example UTF-8. This is used
      * to decode the data from the input stream.
-     * @param encoding The resource response's encoding
+     *
+     * @param encoding the resource response's encoding
      */
     public void setEncoding(String encoding) {
         mEncoding = encoding;
@@ -74,7 +78,8 @@
 
     /**
      * Gets the resource response's encoding.
-     * @return The resource response's encoding
+     *
+     * @return the resource response's encoding
      */
     public String getEncoding() {
         return mEncoding;
@@ -83,7 +88,8 @@
     /**
      * Sets the input stream that provides the resource respone's data. Callers
      * must implement {@link InputStream#read(byte[]) InputStream.read(byte[])}.
-     * @param data The input stream that provides the resource response's data
+     *
+     * @param data the input stream that provides the resource response's data
      */
     public void setData(InputStream data) {
         mInputStream = data;
@@ -91,7 +97,8 @@
 
     /**
      * Gets the input stream that provides the resource respone's data.
-     * @return The input stream that provides the resource response's data
+     *
+     * @return the input stream that provides the resource response's data
      */
     public InputStream getData() {
         return mInputStream;
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 1bbf00f..901372b 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -33,10 +33,12 @@
 public abstract class WebSettings {
     /**
      * Enum for controlling the layout of html.
-     * NORMAL means no rendering changes.
-     * SINGLE_COLUMN moves all content into one column that is the width of the
-     * view.
-     * NARROW_COLUMNS makes all columns no wider than the screen if possible.
+     * <ul>
+     *   <li>NORMAL means no rendering changes.</li>
+     *   <li>SINGLE_COLUMN moves all content into one column that is the width of the
+     *       view.</li>
+     *   <li>NARROW_COLUMNS makes all columns no wider than the screen if possible.</li>
+     * </ul>
      */
     // XXX: These must match LayoutAlgorithm in Settings.h in WebCore.
     public enum LayoutAlgorithm {
@@ -51,11 +53,14 @@
 
     /**
      * Enum for specifying the text size.
-     * SMALLEST is 50%
-     * SMALLER is 75%
-     * NORMAL is 100%
-     * LARGER is 150%
-     * LARGEST is 200%
+     * <ul>
+     *   <li>SMALLEST is 50%</li>
+     *   <li>SMALLER is 75%</li>
+     *   <li>NORMAL is 100%</li>
+     *   <li>LARGER is 150%</li>
+     *   <li>LARGEST is 200%</li>
+     * </ul>
+     *
      * @deprecated Use {@link WebSettings#setTextZoom(int)} and {@link WebSettings#getTextZoom()} instead.
      */
     public enum TextSize {
@@ -72,9 +77,11 @@
 
     /**
      * Enum for specifying the WebView's desired density.
-     * FAR makes 100% looking like in 240dpi
-     * MEDIUM makes 100% looking like in 160dpi
-     * CLOSE makes 100% looking like in 120dpi
+     * <ul>
+     *   <li>FAR makes 100% looking like in 240dpi</li>
+     *   <li>MEDIUM makes 100% looking like in 160dpi</li>
+     *   <li>CLOSE makes 100% looking like in 120dpi</li>
+     * </ul>
      */
     public enum ZoomDensity {
         FAR(150),      // 240dpi
@@ -87,24 +94,24 @@
     }
 
     /**
-     * Default cache usage pattern  Use with {@link #setCacheMode}.
+     * Default cache usage pattern. Use with {@link #setCacheMode}.
      */
     public static final int LOAD_DEFAULT = -1;
 
     /**
-     * Normal cache usage pattern  Use with {@link #setCacheMode}.
+     * Normal cache usage pattern. Use with {@link #setCacheMode}.
      */
     public static final int LOAD_NORMAL = 0;
 
     /**
-     * Use cache if content is there, even if expired (eg, history nav)
+     * Use cache if content is there, even if expired (eg, history nav).
      * If it is not in the cache, load from network.
      * Use with {@link #setCacheMode}.
      */
     public static final int LOAD_CACHE_ELSE_NETWORK = 1;
 
     /**
-     * Don't use the cache, load from network
+     * Don't use the cache, load from network.
      * Use with {@link #setCacheMode}.
      */
     public static final int LOAD_NO_CACHE = 2;
@@ -139,6 +146,7 @@
     /**
      * Hidden constructor to prevent clients from creating a new settings
      * instance or deriving the class.
+     *
      * @hide
      */
     protected WebSettings() {
@@ -146,6 +154,7 @@
 
     /**
      * Enables dumping the pages navigation cache to a text file.
+     *
      * @deprecated This method is now obsolete.
      */
     @Deprecated
@@ -154,7 +163,8 @@
     }
 
     /**
-     * Returns true if dumping the navigation cache is enabled.
+     * Gets whether dumping the navigation cache is enabled.
+     *
      * @deprecated This method is now obsolete.
      */
     @Deprecated
@@ -167,16 +177,19 @@
      * controls and gestures. The particular zoom mechanisms that should be used
      * can be set with {@link #setBuiltInZoomControls}. This setting does not
      * affect zooming performed using the {@link WebView#zoomIn()} and
-     * {@link WebView#zoomOut()} methods.
-     * @param support Whether the WebView should support zoom.
+     * {@link WebView#zoomOut()} methods. The default is true.
+     *
+     * @param support whether the WebView should support zoom
      */
     public void setSupportZoom(boolean support) {
         throw new MustOverrideException();
     }
 
     /**
-     * Returns true if the WebView supports zoom. The default is true.
-     * @return True if the WebView supports zoom.
+     * Gets whether the WebView supports zoom.
+     *
+     * @return true if the WebView supports zoom
+     * @see #setSupportZoom
      */
     public boolean supportZoom() {
         throw new MustOverrideException();
@@ -187,11 +200,12 @@
      * built-in zoom mechanisms comprise on-screen zoom controls, which are
      * displayed over the WebView's content, and the use of a pinch gesture to
      * control zooming. Whether or not these on-screen controls are displayed
-     * can be set with {@link #setDisplayZoomControls}.
+     * can be set with {@link #setDisplayZoomControls}. The default is false.
      * <p>
      * The built-in mechanisms are the only currently supported zoom
      * mechanisms, so it is recommended that this setting is always enabled.
-     * @param enabled Whether the WebView should use its built-in zoom mechanisms.
+     *
+     * @param enabled whether the WebView should use its built-in zoom mechanisms
      */
     // This method was intended to select between the built-in zoom mechanisms
     // and the separate zoom controls. The latter were obtained using
@@ -201,9 +215,10 @@
     }
 
     /**
-     * Returns true if the zoom mechanisms built into WebView are being used.
-     * The default is false.
-     * @return True if the zoom mechanisms built into WebView are being used.
+     * Gets whether the zoom mechanisms built into WebView are being used.
+     *
+     * @return true if the zoom mechanisms built into WebView are being used
+     * @see #setBuiltInZoomControls
      */
     public boolean getBuiltInZoomControls() {
         throw new MustOverrideException();
@@ -212,24 +227,28 @@
     /**
      * Sets whether the WebView should display on-screen zoom controls when
      * using the built-in zoom mechanisms. See {@link #setBuiltInZoomControls}.
-     * @param enabled Whether the WebView should display on-screen zoom controls.
+     * The default is true.
+     *
+     * @param enabled whether the WebView should display on-screen zoom controls
      */
     public void setDisplayZoomControls(boolean enabled) {
         throw new MustOverrideException();
     }
 
     /**
-     * Returns true if the WebView displays on-screen zoom controls when using
-     * the built-in zoom mechanisms. The default is true.
-     * @return True if the WebView displays on-screen zoom controls when using
+     * Gets whether the WebView displays on-screen zoom controls when using
      * the built-in zoom mechanisms.
+     *
+     * @return true if the WebView displays on-screen zoom controls when using
+     *         the built-in zoom mechanisms
+     * @see #setDisplayZoomControls
      */
     public boolean getDisplayZoomControls() {
         throw new MustOverrideException();
     }
 
     /**
-     * Enable or disable file access within WebView. File access is enabled by
+     * Enables or disables file access within WebView. File access is enabled by
      * default.  Note that this enables or disables file system access only.
      * Assets and resources are still accessible using file:///android_asset and
      * file:///android_res.
@@ -239,44 +258,48 @@
     }
 
     /**
-     * Returns true if this WebView supports file access.
+     * Gets whether this WebView supports file access.
+     *
+     * @see #setAllowFileAccess
      */
     public boolean getAllowFileAccess() {
         throw new MustOverrideException();
     }
 
     /**
-     * Enable or disable content url access within WebView.  Content url access
-     * allows WebView to load content from a content provider installed in the
-     * system.  The default is enabled.
+     * Enables or disables content URL access within WebView.  Content URL
+     * access allows WebView to load content from a content provider installed
+     * in the system. The default is enabled.
      */
     public void setAllowContentAccess(boolean allow) {
         throw new MustOverrideException();
     }
 
     /**
-     * Returns true if this WebView supports content url access.
+     * Gets whether this WebView supports content URL access.
+     *
+     * @see #setAllowContentAccess
      */
     public boolean getAllowContentAccess() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set whether the WebView loads a page with overview mode.
+     * Sets whether the WebView loads a page with overview mode.
      */
     public void setLoadWithOverviewMode(boolean overview) {
         throw new MustOverrideException();
     }
 
     /**
-     * Returns true if this WebView loads page with overview mode
+     * Gets whether this WebView loads pages with overview mode.
      */
     public boolean getLoadWithOverviewMode() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set whether the WebView will enable smooth transition while panning or
+     * Sets whether the WebView will enable smooth transition while panning or
      * zooming or while the window hosting the WebView does not have focus.
      * If it is true, WebView will choose a solution to maximize the performance.
      * e.g. the WebView's content may not be updated during the transition.
@@ -285,18 +308,22 @@
     public void setEnableSmoothTransition(boolean enable) {
         throw new MustOverrideException();
     }
+
     /**
-     * Returns true if the WebView enables smooth transition while panning or
+     * Gets whether the WebView enables smooth transition while panning or
      * zooming.
+     *
+     * @see #setEnableSmoothTransition
      */
     public boolean enableSmoothTransition() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set whether the WebView uses its background for over scroll background.
+     * Sets whether the WebView uses its background for over scroll background.
      * If true, it will use the WebView's background. If false, it will use an
      * internal pattern. Default is true.
+     *
      * @deprecated This method is now obsolete.
      */
     @Deprecated
@@ -305,8 +332,10 @@
     }
 
     /**
-     * Returns true if this WebView uses WebView's background instead of
+     * Gets whether this WebView uses WebView's background instead of
      * internal pattern for over scroll background.
+     *
+     * @see #setUseWebViewBackgroundForOverscrollBackground
      * @deprecated This method is now obsolete.
      */
     @Deprecated
@@ -315,77 +344,82 @@
     }
 
     /**
-     * Store whether the WebView is saving form data.
+     * Sets whether the WebView is saving form data.
      */
     public void setSaveFormData(boolean save) {
         throw new MustOverrideException();
     }
 
     /**
-     *  Return whether the WebView is saving form data and displaying prior
-     *  entries/autofill++.  Always false in private browsing mode.
+     * Gets whether the WebView is saving form data and displaying prior
+     * entries/autofill++.  Always false in private browsing mode.
      */
     public boolean getSaveFormData() {
         throw new MustOverrideException();
     }
 
     /**
-     *  Store whether the WebView is saving password.
+     * Stores whether the WebView is saving password.
      */
     public void setSavePassword(boolean save) {
         throw new MustOverrideException();
     }
 
     /**
-     *  Return whether the WebView is saving password.
+     * Gets whether the WebView is saving password.
      */
     public boolean getSavePassword() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the text zoom of the page in percent. Default is 100.
-     * @param textZoom A percent value for increasing or decreasing the text.
+     * Sets the text zoom of the page in percent. Default is 100.
+     *
+     * @param textZoom the percent value for increasing or decreasing the text
      */
     public synchronized void setTextZoom(int textZoom) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the text zoom of the page in percent.
-     * @return A percent value describing the text zoom.
-     * @see setTextSizeZoom
+     * Gets the text zoom of the page in percent.
+     *
+     * @return a percent value describing the text zoom
+     * @see #setTextSizeZoom
      */
     public synchronized int getTextZoom() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the text size of the page.
-     * @param t A TextSize value for increasing or decreasing the text.
+     * Sets the text size of the page.
+     *
+     * @param t the TextSize value for increasing or decreasing the text
      * @see WebSettings.TextSize
-     * @deprecated Use {@link #setTextZoom(int)} instead
+     * @deprecated Use {@link #setTextZoom(int)} instead.
      */
     public synchronized void setTextSize(TextSize t) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the text size of the page. If the text size was previously specified
+     * Gets the text size of the page. If the text size was previously specified
      * in percent using {@link #setTextZoom(int)}, this will return
      * the closest matching {@link TextSize}.
-     * @return A TextSize enum value describing the text size.
+     *
+     * @return a TextSize enum value describing the text size
      * @see WebSettings.TextSize
-     * @deprecated Use {@link #getTextZoom()} instead
+     * @deprecated Use {@link #getTextZoom()} instead.
      */
     public synchronized TextSize getTextSize() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the default zoom density of the page. This should be called from UI
+     * Sets the default zoom density of the page. This should be called from UI
      * thread.
-     * @param zoom A ZoomDensity value
+     *
+     * @param zoom a ZoomDensity value
      * @see WebSettings.ZoomDensity
      */
     public void setDefaultZoom(ZoomDensity zoom) {
@@ -393,9 +427,9 @@
     }
 
     /**
-     * Get the default zoom density of the page. This should be called from UI
+     * Gets the default zoom density of the page. This should be called from UI
      * thread.
-     * @return A ZoomDensity value
+     * @return a ZoomDensity value
      * @see WebSettings.ZoomDensity
      */
     public ZoomDensity getDefaultZoom() {
@@ -410,15 +444,17 @@
     }
 
     /**
-     * Returns true if light touches are enabled.
+     * Gets whether light touches are enabled.
      */
     public boolean getLightTouchEnabled() {
         throw new MustOverrideException();
     }
 
     /**
-     * @deprecated This setting controlled a rendering optimization
-     * that is no longer present. Setting it now has no effect.
+     * Controlled a rendering optimization that is no longer present. Setting
+     * it now has no effect.
+     *
+     * @deprecated This setting now has no effect.
      */
     @Deprecated
     public synchronized void setUseDoubleTree(boolean use) {
@@ -426,8 +462,10 @@
     }
 
     /**
-     * @deprecated This setting controlled a rendering optimization
-     * that is no longer present. Setting it now has no effect.
+     * Controlled a rendering optimization that is no longer present. Setting
+     * it now has no effect.
+     *
+     * @deprecated This setting now has no effect.
      */
     @Deprecated
     public synchronized boolean getUseDoubleTree() {
@@ -436,10 +474,10 @@
     }
 
     /**
-     * Tell the WebView about user-agent string.
-     * @param ua 0 if the WebView should use an Android user-agent string,
-     *           1 if the WebView should use a desktop user-agent string.
+     * Tells the WebView about user-agent string.
      *
+     * @param ua 0 if the WebView should use an Android user-agent string,
+     *           1 if the WebView should use a desktop user-agent string
      * @deprecated Please use setUserAgentString instead.
      */
     @Deprecated
@@ -448,11 +486,11 @@
     }
 
     /**
-     * Return user-agent as int
-     * @return int  0 if the WebView is using an Android user-agent string.
-     *              1 if the WebView is using a desktop user-agent string.
-     *             -1 if the WebView is using user defined user-agent string.
+     * Gets the user-agent as an int.
      *
+     * @return 0 if the WebView is using an Android user-agent string,
+     *         1 if the WebView is using a desktop user-agent string,
+     *         -1 if the WebView is using user defined user-agent string
      * @deprecated Please use getUserAgentString instead.
      */
     @Deprecated
@@ -461,30 +499,34 @@
     }
 
     /**
-     * Tell the WebView to use the wide viewport
+     * Tells the WebView to use the wide viewport.
      */
     public synchronized void setUseWideViewPort(boolean use) {
         throw new MustOverrideException();
     }
 
     /**
-     * @return True if the WebView is using a wide viewport
+     * Gets whether the WebView is using a wide viewport.
+     *
+     * @return true if the WebView is using a wide viewport
      */
     public synchronized boolean getUseWideViewPort() {
         throw new MustOverrideException();
     }
 
     /**
-     * Tell the WebView whether it supports multiple windows. TRUE means
-     *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
-     *         boolean, Message)} is implemented by the host application.
+     * Tells the WebView whether it supports multiple windows. TRUE means
+     * that {@link WebChromeClient#onCreateWindow(WebView, boolean,
+     * boolean, Message)} is implemented by the host application.
      */
     public synchronized void setSupportMultipleWindows(boolean support) {
         throw new MustOverrideException();
     }
 
     /**
-     * @return True if the WebView is supporting multiple windows. This means
+     * Gets whether the WebView is supporting multiple windows.
+     *
+     * @return true if the WebView is supporting multiple windows. This means
      *         that {@link WebChromeClient#onCreateWindow(WebView, boolean,
      *         boolean, Message)} is implemented by the host application.
      */
@@ -493,9 +535,10 @@
     }
 
     /**
-     * Set the underlying layout algorithm. This will cause a relayout of the
-     * WebView.
-     * @param l A LayoutAlgorithm enum specifying the algorithm to use.
+     * Sets the underlying layout algorithm. This will cause a relayout of the
+     * WebView. The default is NARROW_COLUMNS.
+     *
+     * @param l a LayoutAlgorithm enum specifying the algorithm to use
      * @see WebSettings.LayoutAlgorithm
      */
     public synchronized void setLayoutAlgorithm(LayoutAlgorithm l) {
@@ -503,9 +546,11 @@
     }
 
     /**
-     * Return the current layout algorithm. The default is NARROW_COLUMNS.
-     * @return LayoutAlgorithm enum value describing the layout algorithm
-     *         being used.
+     * Gets the current layout algorithm.
+     *
+     * @return a LayoutAlgorithm enum value describing the layout algorithm
+     *         being used
+     * @see #setLayoutAlgorithm
      * @see WebSettings.LayoutAlgorithm
      */
     public synchronized LayoutAlgorithm getLayoutAlgorithm() {
@@ -513,164 +558,193 @@
     }
 
     /**
-     * Set the standard font family name.
-     * @param font A font family name.
+     * Sets the standard font family name. The default is "sans-serif".
+     *
+     * @param font a font family name
      */
     public synchronized void setStandardFontFamily(String font) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the standard font family name. The default is "sans-serif".
-     * @return The standard font family name as a string.
+     * Gets the standard font family name.
+     *
+     * @return the standard font family name as a string
+     * @see #setStandardFontFamily
      */
     public synchronized String getStandardFontFamily() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the fixed font family name.
-     * @param font A font family name.
+     * Sets the fixed font family name. The default is "monospace".
+     *
+     * @param font a font family name
      */
     public synchronized void setFixedFontFamily(String font) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the fixed font family name. The default is "monospace".
-     * @return The fixed font family name as a string.
+     * Gets the fixed font family name.
+     *
+     * @return the fixed font family name as a string
+     * @see #setFixedFontFamily
      */
     public synchronized String getFixedFontFamily() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the sans-serif font family name.
-     * @param font A font family name.
+     * Sets the sans-serif font family name.
+     *
+     * @param font a font family name
      */
     public synchronized void setSansSerifFontFamily(String font) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the sans-serif font family name.
-     * @return The sans-serif font family name as a string.
+     * Gets the sans-serif font family name.
+     *
+     * @return the sans-serif font family name as a string
      */
     public synchronized String getSansSerifFontFamily() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the serif font family name. The default is "sans-serif".
-     * @param font A font family name.
+     * Sets the serif font family name. The default is "sans-serif".
+     *
+     * @param font a font family name
      */
     public synchronized void setSerifFontFamily(String font) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the serif font family name. The default is "serif".
-     * @return The serif font family name as a string.
+     * Gets the serif font family name. The default is "serif".
+     *
+     * @return the serif font family name as a string
+     * @see #setSerifFontFamily
      */
     public synchronized String getSerifFontFamily() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the cursive font family name.
-     * @param font A font family name.
+     * Sets the cursive font family name. The default is "cursive".
+     *
+     * @param font a font family name
      */
     public synchronized void setCursiveFontFamily(String font) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the cursive font family name. The default is "cursive".
-     * @return The cursive font family name as a string.
+     * Gets the cursive font family name.
+     *
+     * @return the cursive font family name as a string
+     * @see #setCursiveFontFamily
      */
     public synchronized String getCursiveFontFamily() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the fantasy font family name.
-     * @param font A font family name.
+     * Sets the fantasy font family name. The default is "fantasy".
+     *
+     * @param font a font family name
      */
     public synchronized void setFantasyFontFamily(String font) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the fantasy font family name. The default is "fantasy".
-     * @return The fantasy font family name as a string.
+     * Gets the fantasy font family name.
+     *
+     * @return the fantasy font family name as a string
+     * @see #setFantasyFontFamily
      */
     public synchronized String getFantasyFontFamily() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the minimum font size.
-     * @param size A non-negative integer between 1 and 72.
-     * Any number outside the specified range will be pinned.
+     * Sets the minimum font size. The default is 8.
+     *
+     * @param size a non-negative integer between 1 and 72. Any number outside
+     *             the specified range will be pinned.
      */
     public synchronized void setMinimumFontSize(int size) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the minimum font size. The default is 8.
-     * @return A non-negative integer between 1 and 72.
+     * Gets the minimum font size.
+     *
+     * @return a non-negative integer between 1 and 72
+     * @see #setMinimumFontSize
      */
     public synchronized int getMinimumFontSize() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the minimum logical font size.
-     * @param size A non-negative integer between 1 and 72.
-     * Any number outside the specified range will be pinned.
+     * Sets the minimum logical font size. The default is 8.
+     *
+     * @param size a non-negative integer between 1 and 72. Any number outside
+     *             the specified range will be pinned.
      */
     public synchronized void setMinimumLogicalFontSize(int size) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the minimum logical font size. The default is 8.
-     * @return A non-negative integer between 1 and 72.
+     * Gets the minimum logical font size.
+     *
+     * @return a non-negative integer between 1 and 72
+     * @see #setMinimumLogicalFontSize
      */
     public synchronized int getMinimumLogicalFontSize() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the default font size.
-     * @param size A non-negative integer between 1 and 72.
-     * Any number outside the specified range will be pinned.
+     * Sets the default font size. The default is 16.
+     *
+     * @param size a non-negative integer between 1 and 72. Any number outside
+     *             the specified range will be pinned.
      */
     public synchronized void setDefaultFontSize(int size) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the default font size. The default is 16.
-     * @return A non-negative integer between 1 and 72.
+     * Gets the default font size.
+     *
+     * @return a non-negative integer between 1 and 72
+     * @see #setDefaultFontSize
      */
     public synchronized int getDefaultFontSize() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the default fixed font size.
-     * @param size A non-negative integer between 1 and 72.
-     * Any number outside the specified range will be pinned.
+     * Sets the default fixed font size. The default is 16.
+     *
+     * @param size a non-negative integer between 1 and 72. Any number outside
+     *             the specified range will be pinned.
      */
     public synchronized void setDefaultFixedFontSize(int size) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the default fixed font size. The default is 16.
-     * @return A non-negative integer between 1 and 72.
+     * Gets the default fixed font size.
+     *
+     * @return a non-negative integer between 1 and 72
+     * @see #setDefaultFixedFontSize
      */
     public synchronized int getDefaultFixedFontSize() {
         throw new MustOverrideException();
@@ -683,16 +757,20 @@
      * of images specified using network URI schemes. Note that if the value of this
      * setting is changed from false to true, all images resources referenced
      * by content currently displayed by the WebView are loaded automatically.
-     * @param flag Whether the WebView should load image resources.
+     * The default is true.
+     *
+     * @param flag whether the WebView should load image resources
      */
     public synchronized void setLoadsImagesAutomatically(boolean flag) {
         throw new MustOverrideException();
     }
 
     /**
-     * Returns true if the WebView loads image resources. This includes
-     * images embedded using the data URI scheme. The default is true.
-     * @return True if the WebView loads image resources.
+     * Gets whether the WebView loads image resources. This includes
+     * images embedded using the data URI scheme.
+     *
+     * @return true if the WebView loads image resources
+     * @see #setLoadsImagesAutomatically
      */
     public synchronized boolean getLoadsImagesAutomatically() {
         throw new MustOverrideException();
@@ -707,9 +785,10 @@
      * will also prevent network images from loading, even if this flag is set
      * to false. When the value of this setting is changed from true to false,
      * network images resources referenced by content currently displayed by
-     * the WebView are fetched automatically.
-     * @param flag Whether the WebView should not load image resources from
-     * the network.
+     * the WebView are fetched automatically. The default is false.
+     *
+     * @param flag whether the WebView should not load image resources from the
+     *             network
      * @see #setBlockNetworkLoads
      */
     public synchronized void setBlockNetworkImage(boolean flag) {
@@ -717,9 +796,10 @@
     }
 
     /**
-     * Returns true if the WebView does not load image resources from the network.
-     * The default is false.
-     * @return True if the WebView does not load image resources from the network.
+     * Gets whether the WebView does not load image resources from the network.
+     *
+     * @return true if the WebView does not load image resources from the network
+     * @see #setBlockNetworkImage
      */
     public synchronized boolean getBlockNetworkImage() {
         throw new MustOverrideException();
@@ -735,9 +815,12 @@
      * If the application does not have the
      * {@link android.Manifest.permission#INTERNET} permission, attempts to set
      * a value of false will cause a {@link java.lang.SecurityException}
-     * to be thrown.
-     * @param flag Whether the WebView should not load any resources
-     * from the network.
+     * to be thrown. The default value is false if the application has the
+     * {@link android.Manifest.permission#INTERNET} permission, otherwise it is
+     * true.
+     *
+     * @param flag whether the WebView should not load any resources from the
+     *             network
      * @see android.webkit.WebView#reload
      */
     public synchronized void setBlockNetworkLoads(boolean flag) {
@@ -745,50 +828,52 @@
     }
 
     /**
-     * Returns true if the WebView does not load any resources from the network.
-     * The default value is false if the application has the
-     * {@link android.Manifest.permission#INTERNET} permission, otherwise it is
-     * true.
-     * @return True if the WebView does not load any resources from the network.
+     * Gets whether the WebView does not load any resources from the network.
+     *
+     * @return true if the WebView does not load any resources from the network
+     * @see #setBlockNetworkLoads
      */
     public synchronized boolean getBlockNetworkLoads() {
         throw new MustOverrideException();
     }
 
     /**
-     * Tell the WebView to enable javascript execution.
-     * @param flag True if the WebView should execute javascript.
+     * Tells the WebView to enable JavaScript execution.
+     * <b>The default is false.</b>
+     *
+     * @param flag true if the WebView should execute JavaScript
      */
     public synchronized void setJavaScriptEnabled(boolean flag) {
         throw new MustOverrideException();
     }
 
     /**
-     * Configure scripting (such as XmlHttpRequest) access from file scheme URLs
+     * Configures scripting (such as XmlHttpRequest) access from file scheme URLs
      * to any origin. Note, calling this method with a true argument value also
      * implies calling setAllowFileAccessFromFileURLs with a true. The default
      * value is false for API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN}
      * and higher and true otherwise.
      *
-   . * @param flag True if the WebView should allow scripting access from file
-     *                  scheme URLs to any origin
+     * @param flag true if the WebView should allow scripting access from file
+     *             scheme URLs to any origin
      */
     public abstract void setAllowUniversalAccessFromFileURLs(boolean flag);
 
     /**
-     * Configure scripting (such as XmlHttpRequest) access from file scheme URLs
+     * Configures scripting (such as XmlHttpRequest) access from file scheme URLs
      * to file origin. The default value is false for API level
      * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} and higher and true
      * otherwise.
      *
-     * @param flag True if the WebView should allow scripting access from file
-     *                  scheme URLs to file origin
+     * @param flag true if the WebView should allow scripting access from file
+     *             scheme URLs to file origin
      */
     public abstract void setAllowFileAccessFromFileURLs(boolean flag);
 
     /**
-     * Tell the WebView to enable plugins.
-     * @param flag True if the WebView should load plugins.
+     * Tells the WebView to enable plugins.
+     *
+     * @param flag true if the WebView should load plugins
      * @deprecated This method has been deprecated in favor of
      *             {@link #setPluginState}
      */
@@ -798,22 +883,24 @@
     }
 
     /**
-     * Tell the WebView to enable, disable, or have plugins on demand. On
+     * Tells the WebView to enable, disable, or have plugins on demand. On
      * demand mode means that if a plugin exists that can handle the embedded
      * content, a placeholder icon will be shown instead of the plugin. When
      * the placeholder is clicked, the plugin will be enabled.
-     * @param state One of the PluginState values.
+     *
+     * @param state a PluginState value
      */
     public synchronized void setPluginState(PluginState state) {
         throw new MustOverrideException();
     }
 
     /**
-     * Set a custom path to plugins used by the WebView. This method is
+     * Sets a custom path to plugins used by the WebView. This method is
      * obsolete since each plugin is now loaded from its own package.
-     * @param pluginsPath String path to the directory containing plugins.
+     *
+     * @param pluginsPath a String path to the directory containing plugins
      * @deprecated This method is no longer used as plugins are loaded from
-     * their own APK via the system's package manager.
+     *             their own APK via the system's package manager.
      */
     @Deprecated
     public synchronized void setPluginsPath(String pluginsPath) {
@@ -821,91 +908,101 @@
     }
 
     /**
-     * Set the path to where database storage API databases should be saved.
-     * Nota that the WebCore Database Tracker only allows the path to be set once.
-     * This will update WebCore when the Sync runs in the C++ side.
-     * @param databasePath String path to the directory where databases should
-     *     be saved. May be the empty string but should never be null.
+     * Sets the path to where database storage API databases should be saved.
+     * Note that the WebCore Database Tracker only allows the path to be set once.
+     *
+     * @param databasePath a String path to the directory where databases should
+     *                     be saved. May be the empty string but should never
+     *                     be null.
      */
+    // This will update WebCore when the Sync runs in the C++ side.
     public synchronized void setDatabasePath(String databasePath) {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the path where the Geolocation permissions database should be saved.
-     * This will update WebCore when the Sync runs in the C++ side.
-     * @param databasePath String path to the directory where the Geolocation
-     *     permissions database should be saved. May be the empty string but
-     *     should never be null.
+     * Sets the path where the Geolocation permissions database should be saved.
+     *
+     * @param databasePath a String path to the directory where the Geolocation
+     *                     permissions database should be saved. May be the
+     *                     empty string but should never be null.
      */
+    // This will update WebCore when the Sync runs in the C++ side.
     public synchronized void setGeolocationDatabasePath(String databasePath) {
         throw new MustOverrideException();
     }
 
     /**
-     * Tell the WebView to enable Application Caches API.
-     * @param flag True if the WebView should enable Application Caches.
+     * Tells the WebView to enable Application Caches API.
+     *
+     * @param flag true if the WebView should enable Application Caches
      */
     public synchronized void setAppCacheEnabled(boolean flag) {
         throw new MustOverrideException();
     }
 
     /**
-     * Set a custom path to the Application Caches files. The client
+     * Sets a custom path to the Application Caches files. The client
      * must ensure it exists before this call.
-     * @param appCachePath String path to the directory containing Application
-     * Caches files. The appCache path can be the empty string but should not
-     * be null. Passing null for this parameter will result in a no-op.
+     *
+     * @param appCachePath a String path to the directory containing
+     *                     Application Caches files. The appCache path can be
+     *                     the empty string but should not be null. Passing
+     *                     null for this parameter will result in a no-op.
      */
     public synchronized void setAppCachePath(String appCachePath) {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the maximum size for the Application Caches content.
-     * @param appCacheMaxSize the maximum size in bytes.
+     * Sets the maximum size for the Application Caches content.
+     *
+     * @param appCacheMaxSize the maximum size in bytes
      */
     public synchronized void setAppCacheMaxSize(long appCacheMaxSize) {
         throw new MustOverrideException();
     }
 
     /**
-     * Set whether the database storage API is enabled.
-     * @param flag boolean True if the WebView should use the database storage
-     *     API.
+     * Sets whether the database storage API is enabled.
+     *
+     * @param flag true if the WebView should use the database storage API
      */
     public synchronized void setDatabaseEnabled(boolean flag) {
         throw new MustOverrideException();
     }
 
     /**
-     * Set whether the DOM storage API is enabled.
-     * @param flag boolean True if the WebView should use the DOM storage
-     *     API.
+     * Sets whether the DOM storage API is enabled.
+     *
+     * @param flag true if the WebView should use the DOM storage API
      */
     public synchronized void setDomStorageEnabled(boolean flag) {
         throw new MustOverrideException();
     }
 
     /**
-     * Returns true if the DOM Storage API's are enabled.
-     * @return True if the DOM Storage API's are enabled.
+     * Gets whether the DOM Storage APIs are enabled.
+     *
+     * @return true if the DOM Storage APIs are enabled
      */
     public synchronized boolean getDomStorageEnabled() {
         throw new MustOverrideException();
     }
     /**
-     * Return the path to where database storage API databases are saved for
+     * Gets the path to where database storage API databases are saved for
      * the current WebView.
-     * @return the String path to the database storage API databases.
+     *
+     * @return the String path to the database storage API databases
      */
     public synchronized String getDatabasePath() {
         throw new MustOverrideException();
     }
 
     /**
-     * Returns true if database storage API is enabled.
-     * @return True if the database storage API is enabled.
+     * Gets whether the database storage API is enabled.
+     *
+     * @return true if the database storage API is enabled
      */
     public synchronized boolean getDatabaseEnabled() {
         throw new MustOverrideException();
@@ -913,43 +1010,47 @@
 
     /**
      * Sets whether Geolocation is enabled.
-     * @param flag Whether Geolocation should be enabled.
+     *
+     * @param flag whether Geolocation should be enabled
      */
     public synchronized void setGeolocationEnabled(boolean flag) {
         throw new MustOverrideException();
     }
 
     /**
-     * Return true if javascript is enabled. <b>Note: The default is false.</b>
-     * @return True if javascript is enabled.
+     * Gets whether JavaScript is enabled.
+     *
+     * @return true if JavaScript is enabled
+     * @see #setJavaScriptEnabled
      */
     public synchronized boolean getJavaScriptEnabled() {
         throw new MustOverrideException();
     }
 
     /**
-     * Return true if scripting access {see @setAllowUniversalAccessFromFileURLs} from
-     * file URLs to any origin is enabled. The default value is false for API level
-     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} and higher and true otherwise.
+     * Gets whether scripting access {see @setAllowUniversalAccessFromFileURLs} from
+     * file URLs to any origin is enabled.
      *
-     * @return True if the WebView allows scripting access from file scheme requests
-     *              to any origin
+     * @return true if the WebView allows scripting access from file scheme requests
+     *         to any origin
+     * @see #setAllowUniversalAccessFromFileURLs
      */
     public abstract boolean getAllowUniversalAccessFromFileURLs();
 
     /**
-     * Return true if scripting access {see @setAllowFileAccessFromFileURLs} from file
-     * URLs to file origin is enabled. The default value is false for API level
-     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} and higher, and true otherwise.
+     * Gets whether scripting access {see @setAllowFileAccessFromFileURLs} from file
+     * URLs to file origin is enabled.
      *
-     * @return True if the WebView allows scripting access from file scheme requests
-     *              to file origin
+     * @return true if the WebView allows scripting access from file scheme requests
+     *         to file origin
+     * @see #setAllowFileAccessFromFileURLs
      */
     public abstract boolean getAllowFileAccessFromFileURLs();
 
     /**
-     * Return true if plugins are enabled.
-     * @return True if plugins are enabled.
+     * Gets whether plugins are enabled.
+     *
+     * @return true if plugins are enabled
      * @deprecated This method has been replaced by {@link #getPluginState}
      */
     @Deprecated
@@ -958,17 +1059,19 @@
     }
 
     /**
-     * Return the current plugin state.
-     * @return A value corresponding to the enum PluginState.
+     * Gets the current plugin state.
+     *
+     * @return a value corresponding to the enum PluginState
      */
     public synchronized PluginState getPluginState() {
         throw new MustOverrideException();
     }
 
     /**
-     * Returns the directory that contains the plugin libraries. This method is
+     * Gets the directory that contains the plugin libraries. This method is
      * obsolete since each plugin is now loaded from its own package.
-     * @return An empty string.
+     *
+     * @return an empty string
      * @deprecated This method is no longer used as plugins are loaded from
      * their own APK via the system's package manager.
      */
@@ -979,41 +1082,47 @@
     }
 
     /**
-     * Tell javascript to open windows automatically. This applies to the
-     * javascript function window.open().
-     * @param flag True if javascript can open windows automatically.
+     * Tells JavaScript to open windows automatically. This applies to the
+     * JavaScript function window.open(). The default is false.
+     *
+     * @param flag true if JavaScript can open windows automatically
      */
     public synchronized void setJavaScriptCanOpenWindowsAutomatically(boolean flag) {
         throw new MustOverrideException();
     }
 
     /**
-     * Return true if javascript can open windows automatically. The default
-     * is false.
-     * @return True if javascript can open windows automatically during
-     *         window.open().
+     * Gets whether JavaScript can open windows automatically.
+     *
+     * @return true if JavaScript can open windows automatically during
+     *         window.open()
+     * @see #setJavaScriptCanOpenWindowsAutomatically
      */
     public synchronized boolean getJavaScriptCanOpenWindowsAutomatically() {
         throw new MustOverrideException();
     }
     /**
-     * Set the default text encoding name to use when decoding html pages.
-     * @param encoding The text encoding name.
+     * Sets the default text encoding name to use when decoding html pages.
+     * The default is "Latin-1".
+     *
+     * @param encoding the text encoding name
      */
     public synchronized void setDefaultTextEncodingName(String encoding) {
         throw new MustOverrideException();
     }
 
     /**
-     * Get the default text encoding name. The default is "Latin-1".
-     * @return The default text encoding name as a string.
+     * Gets the default text encoding name.
+     *
+     * @return the default text encoding name as a string
+     * @see #setDefaultTextEncodingName
      */
     public synchronized String getDefaultTextEncodingName() {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the WebView's user-agent string. If the string "ua" is null or empty,
+     * Sets the WebView's user-agent string. If the string "ua" is null or empty,
      * it will use the system default user-agent string.
      */
     public synchronized void setUserAgentString(String ua) {
@@ -1021,46 +1130,47 @@
     }
 
     /**
-     * Return the WebView's user-agent string.
+     * Gets the WebView's user-agent string.
      */
     public synchronized String getUserAgentString() {
         throw new MustOverrideException();
     }
 
     /**
-     * Tell the WebView whether it needs to set a node to have focus when
+     * Tells the WebView whether it needs to set a node to have focus when
      * {@link WebView#requestFocus(int, android.graphics.Rect)} is called.
      *
-     * @param flag
+     * @param flag whether the WebView needs to set a node
      */
     public void setNeedInitialFocus(boolean flag) {
         throw new MustOverrideException();
     }
 
     /**
-     * Set the priority of the Render thread. Unlike the other settings, this
+     * Sets the priority of the Render thread. Unlike the other settings, this
      * one only needs to be called once per process. The default is NORMAL.
      *
-     * @param priority RenderPriority, can be normal, high or low.
+     * @param priority a RenderPriority
      */
     public synchronized void setRenderPriority(RenderPriority priority) {
         throw new MustOverrideException();
     }
 
     /**
-     * Override the way the cache is used. The way the cache is used is based
+     * Overrides the way the cache is used. The way the cache is used is based
      * on the navigation option. For a normal page load, the cache is checked
      * and content is re-validated as needed. When navigating back, content is
      * not revalidated, instead the content is just pulled from the cache.
      * This function allows the client to override this behavior.
-     * @param mode One of the LOAD_ values.
+     *
+     * @param mode one of the LOAD_ values
      */
     public void setCacheMode(int mode) {
         throw new MustOverrideException();
     }
 
     /**
-     * Return the current setting for overriding the cache mode. For a full
+     * Gets the current setting for overriding the cache mode. For a full
      * description, see the {@link #setCacheMode(int)} function.
      */
     public int getCacheMode() {
diff --git a/core/java/android/webkit/WebStorage.java b/core/java/android/webkit/WebStorage.java
index c46d161..76674f4 100644
--- a/core/java/android/webkit/WebStorage.java
+++ b/core/java/android/webkit/WebStorage.java
@@ -44,8 +44,9 @@
     // otherwise the WebCore thread will remain asleep.
     public interface QuotaUpdater {
         /**
-         * Provide a new quota, specified in bytes.
-         * @param newQuota The new quota, in bytes
+         * Provides a new quota, specified in bytes.
+         *
+         * @param newQuota the new quota, in bytes
          */
         public void updateQuota(long newQuota);
     };
@@ -79,8 +80,9 @@
         }
 
         /**
-         * Get the string representation of this origin.
-         * @return The string representation of this origin
+         * Gets the string representation of this origin.
+         *
+         * @return the string representation of this origin
          */
         // An origin string is created using WebCore::SecurityOrigin::toString().
         // Note that WebCore::SecurityOrigin uses 0 (which is not printed) for
@@ -92,19 +94,21 @@
         }
 
         /**
-         * Get the quota for this origin, for the Web SQL Database API, in
+         * Gets the quota for this origin, for the Web SQL Database API, in
          * bytes. If this origin does not use the Web SQL Database API, this
          * quota will be set to zero.
-         * @return The quota, in bytes.
+         *
+         * @return the quota, in bytes
          */
         public long getQuota() {
             return mQuota;
         }
 
         /**
-         * Get the total amount of storage currently being used by this origin,
+         * Gets the total amount of storage currently being used by this origin,
          * for all JavaScript storage APIs, in bytes.
-         * @return The total amount of storage, in bytes.
+         *
+         * @return the total amount of storage, in bytes
          */
         public long getUsage() {
             return mUsage;
@@ -124,7 +128,7 @@
      */
 
     /**
-     * Get the origins currently using either the Application Cache or Web SQL
+     * Gets the origins currently using either the Application Cache or Web SQL
      * Database APIs. This method operates asynchronously, with the result
      * being provided via a {@link ValueCallback}. The origins are provided as
      * a map, of type {@code Map<String, WebStorage.Origin>}, from the string
@@ -135,7 +139,7 @@
     }
 
     /**
-     * Get the amount of storage currently being used by both the Application
+     * Gets the amount of storage currently being used by both the Application
      * Cache and Web SQL Database APIs by the given origin. The amount is given
      * in bytes and the origin is specified using its string representation.
      * This method operates asynchronously, with the result being provided via
@@ -146,7 +150,7 @@
     }
 
     /**
-     * Get the storage quota for the Web SQL Database API for the given origin.
+     * Gets the storage quota for the Web SQL Database API for the given origin.
      * The quota is given in bytes and the origin is specified using its string
      * representation. This method operates asynchronously, with the result
      * being provided via a {@link ValueCallback}. Note that a quota is not
@@ -157,7 +161,7 @@
     }
 
     /**
-     * Set the storage quota for the Web SQL Database API for the given origin.
+     * Sets the storage quota for the Web SQL Database API for the given origin.
      * The quota is specified in bytes and the origin is specified using its string
      * representation. Note that a quota is not enforced on a per-origin basis
      * for the Application Cache API.
@@ -167,7 +171,7 @@
     }
 
     /**
-     * Clear the storage currently being used by both the Application Cache and
+     * Clears the storage currently being used by both the Application Cache and
      * Web SQL Database APIs by the given origin. The origin is specified using
      * its string representation.
      */
@@ -176,7 +180,7 @@
     }
 
     /**
-     * Clear all storage currently being used by the JavaScript storage APIs.
+     * Clears all storage currently being used by the JavaScript storage APIs.
      * This includes the Application Cache, Web SQL Database and the HTML5 Web
      * Storage APIs.
      */
@@ -185,8 +189,9 @@
     }
 
     /**
-     * Get the singleton instance of this class.
-     * @return The singleton {@link WebStorage} instance.
+     * Gets the singleton instance of this class.
+     *
+     * @return the singleton {@link WebStorage} instance
      */
     public static WebStorage getInstance() {
       return WebViewFactory.getProvider().getWebStorage();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 74605e2..ba5a417 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -274,16 +274,18 @@
         private WebView mWebview;
 
         /**
-         * Set the WebView to the transportation object.
-         * @param webview The WebView to transport.
+         * Sets the WebView to the transportation object.
+         *
+         * @param webview the WebView to transport
          */
         public synchronized void setWebView(WebView webview) {
             mWebview = webview;
         }
 
         /**
-         * Return the WebView object.
-         * @return WebView The transported WebView object.
+         * Gets the WebView object.
+         *
+         * @return the transported WebView object
          */
         public synchronized WebView getWebView() {
             return mWebview;
@@ -291,15 +293,15 @@
     }
 
     /**
-     * URI scheme for telephone number
+     * URI scheme for telephone number.
      */
     public static final String SCHEME_TEL = "tel:";
     /**
-     * URI scheme for email address
+     * URI scheme for email address.
      */
     public static final String SCHEME_MAILTO = "mailto:";
     /**
-     * URI scheme for map address
+     * URI scheme for map address.
      */
     public static final String SCHEME_GEO = "geo:0,0?q=";
 
@@ -308,13 +310,15 @@
      */
     public interface FindListener {
         /**
-         * Notify the listener about progress made by a find operation.
+         * Notifies the listener about progress made by a find operation.
          *
-         * @param numberOfMatches How many matches have been found.
-         * @param activeMatchOrdinal The zero-based ordinal of the currently selected match.
-         * @param isDoneCounting Whether the find operation has actually completed. The listener
-         * may be notified multiple times while the operation is underway, and the numberOfMatches
-         * value should not be considered final unless isDoneCounting is true.
+         * @param numberOfMatches how many matches have been found
+         * @param activeMatchOrdinal the zero-based ordinal of the currently selected match
+         * @param isDoneCounting whether the find operation has actually completed. The listener
+         *                       may be notified multiple times while the
+         *                       operation is underway, and the numberOfMatches
+         *                       value should not be considered final unless
+         *                       isDoneCounting is true.
          */
         public void onFindResultReceived(int numberOfMatches, int activeMatchOrdinal,
             boolean isDoneCounting);
@@ -322,19 +326,22 @@
 
     /**
      * Interface to listen for new pictures as they change.
+     *
      * @deprecated This interface is now obsolete.
      */
     @Deprecated
     public interface PictureListener {
         /**
-         * Notify the listener that the picture has changed.
-         * @param view The WebView that owns the picture.
-         * @param picture The new picture.
+         * Notifies the listener that the picture has changed.
+         *
+         * @param view the WebView that owns the picture
+         * @param picture the new picture
          * @deprecated Due to internal changes, the picture does not include
-         * composited layers such as fixed position elements or scrollable divs.
-         * While the PictureListener API can still be used to detect changes in
-         * the WebView content, you are advised against its usage until a replacement
-         * is provided in a future Android release
+         *             composited layers such as fixed position elements or
+         *             scrollable divs. While the PictureListener API can still
+         *             be used to detect changes in the WebView content, you
+         *             are advised against its usage until a replacement is
+         *             provided in a future Android release.
          */
         @Deprecated
         public void onNewPicture(WebView view, Picture picture);
@@ -342,7 +349,7 @@
 
     public static class HitTestResult {
         /**
-         * Default HitTestResult, where the target is unknown
+         * Default HitTestResult, where the target is unknown.
          */
         public static final int UNKNOWN_TYPE = 0;
         /**
@@ -351,19 +358,19 @@
         @Deprecated
         public static final int ANCHOR_TYPE = 1;
         /**
-         * HitTestResult for hitting a phone number
+         * HitTestResult for hitting a phone number.
          */
         public static final int PHONE_TYPE = 2;
         /**
-         * HitTestResult for hitting a map address
+         * HitTestResult for hitting a map address.
          */
         public static final int GEO_TYPE = 3;
         /**
-         * HitTestResult for hitting an email address
+         * HitTestResult for hitting an email address.
          */
         public static final int EMAIL_TYPE = 4;
         /**
-         * HitTestResult for hitting an HTML::img tag
+         * HitTestResult for hitting an HTML::img tag.
          */
         public static final int IMAGE_TYPE = 5;
         /**
@@ -372,15 +379,15 @@
         @Deprecated
         public static final int IMAGE_ANCHOR_TYPE = 6;
         /**
-         * HitTestResult for hitting a HTML::a tag with src=http
+         * HitTestResult for hitting a HTML::a tag with src=http.
          */
         public static final int SRC_ANCHOR_TYPE = 7;
         /**
-         * HitTestResult for hitting a HTML::a tag with src=http + HTML::img
+         * HitTestResult for hitting a HTML::a tag with src=http + HTML::img.
          */
         public static final int SRC_IMAGE_ANCHOR_TYPE = 8;
         /**
-         * HitTestResult for hitting an edit text area
+         * HitTestResult for hitting an edit text area.
          */
         public static final int EDIT_TEXT_TYPE = 9;
 
@@ -409,17 +416,21 @@
         }
 
         /**
-         * Gets the type of the hit test result.
-         * @return See the XXX_TYPE constants defined in this class.
+         * Gets the type of the hit test result. See the XXX_TYPE constants
+         * defined in this class.
+         *
+         * @return the type of the hit test result
          */
         public int getType() {
             return mType;
         }
 
         /**
-         * Gets additional type-dependant information about the result, see
-         * {@link WebView#getHitTestResult()} for details.
-         * @return may either be null or contain extra information about this result.
+         * Gets additional type-dependant information about the result. See
+         * {@link WebView#getHitTestResult()} for details. May either be null
+         * or contain extra information about this result.
+         *
+         * @return additional type-dependant information about the result
          */
         public String getExtra() {
             return mExtra;
@@ -427,38 +438,43 @@
     }
 
     /**
-     * Construct a new WebView with a Context object.
-     * @param context A Context object used to access application assets.
+     * Constructs a new WebView with a Context object.
+     *
+     * @param context a Context object used to access application assets
      */
     public WebView(Context context) {
         this(context, null);
     }
 
     /**
-     * Construct a new WebView with layout parameters.
-     * @param context A Context object used to access application assets.
-     * @param attrs An AttributeSet passed to our parent.
+     * Constructs a new WebView with layout parameters.
+     *
+     * @param context a Context object used to access application assets
+     * @param attrs an AttributeSet passed to our parent
      */
     public WebView(Context context, AttributeSet attrs) {
         this(context, attrs, com.android.internal.R.attr.webViewStyle);
     }
 
     /**
-     * Construct a new WebView with layout parameters and a default style.
-     * @param context A Context object used to access application assets.
-     * @param attrs An AttributeSet passed to our parent.
-     * @param defStyle The default style resource ID.
+     * Constructs a new WebView with layout parameters and a default style.
+     *
+     * @param context a Context object used to access application assets
+     * @param attrs an AttributeSet passed to our parent
+     * @param defStyle the default style resource ID
      */
     public WebView(Context context, AttributeSet attrs, int defStyle) {
         this(context, attrs, defStyle, false);
     }
 
     /**
-     * Construct a new WebView with layout parameters and a default style.
-     * @param context A Context object used to access application assets.
-     * @param attrs An AttributeSet passed to our parent.
-     * @param defStyle The default style resource ID.
-     * @param privateBrowsing If true the web view will be initialized in private mode.
+     * Constructs a new WebView with layout parameters and a default style.
+     *
+     * @param context a Context object used to access application assets
+     * @param attrs an AttributeSet passed to our parent
+     * @param defStyle the default style resource ID
+     * @param privateBrowsing whether this WebView will be initialized in
+     *                        private mode
      */
     public WebView(Context context, AttributeSet attrs, int defStyle,
             boolean privateBrowsing) {
@@ -466,18 +482,21 @@
     }
 
     /**
-     * Construct a new WebView with layout parameters, a default style and a set
-     * of custom Javscript interfaces to be added to the WebView at initialization
+     * Constructs a new WebView with layout parameters, a default style and a set
+     * of custom Javscript interfaces to be added to this WebView at initialization
      * time. This guarantees that these interfaces will be available when the JS
      * context is initialized.
-     * @param context A Context object used to access application assets.
-     * @param attrs An AttributeSet passed to our parent.
-     * @param defStyle The default style resource ID.
-     * @param javaScriptInterfaces is a Map of interface names, as keys, and
-     * object implementing those interfaces, as values.
-     * @param privateBrowsing If true the web view will be initialized in private mode.
+     *
+     * @param context a Context object used to access application assets
+     * @param attrs an AttributeSet passed to our parent
+     * @param defStyle the default style resource ID
+     * @param javaScriptInterfaces a Map of interface names, as keys, and
+     *                             object implementing those interfaces, as
+     *                             values
+     * @param privateBrowsing whether this WebView will be initialized in
+     *                        private mode
      * @hide This is used internally by dumprendertree, as it requires the javaScript interfaces to
-     * be added synchronously, before a subsequent loadUrl call takes effect.
+     *       be added synchronously, before a subsequent loadUrl call takes effect.
      */
     @SuppressWarnings("deprecation")  // for super() call into deprecated base class constructor.
     protected WebView(Context context, AttributeSet attrs, int defStyle,
@@ -493,8 +512,9 @@
     }
 
     /**
-     * Specify whether the horizontal scrollbar has overlay style.
-     * @param overlay TRUE if horizontal scrollbar should have overlay style.
+     * Specifies whether the horizontal scrollbar has overlay style.
+     *
+     * @param overlay true if horizontal scrollbar should have overlay style
      */
     public void setHorizontalScrollbarOverlay(boolean overlay) {
         checkThread();
@@ -502,8 +522,9 @@
     }
 
     /**
-     * Specify whether the vertical scrollbar has overlay style.
-     * @param overlay TRUE if vertical scrollbar should have overlay style.
+     * Specifies whether the vertical scrollbar has overlay style.
+     *
+     * @param overlay true if vertical scrollbar should have overlay style
      */
     public void setVerticalScrollbarOverlay(boolean overlay) {
         checkThread();
@@ -511,8 +532,9 @@
     }
 
     /**
-     * Return whether horizontal scrollbar has overlay style
-     * @return TRUE if horizontal scrollbar has overlay style.
+     * Gets whether horizontal scrollbar has overlay style.
+     *
+     * @return true if horizontal scrollbar has overlay style
      */
     public boolean overlayHorizontalScrollbar() {
         checkThread();
@@ -520,8 +542,9 @@
     }
 
     /**
-     * Return whether vertical scrollbar has overlay style
-     * @return TRUE if vertical scrollbar has overlay style.
+     * Gets whether vertical scrollbar has overlay style.
+     *
+     * @return true if vertical scrollbar has overlay style
      */
     public boolean overlayVerticalScrollbar() {
         checkThread();
@@ -529,7 +552,7 @@
     }
 
     /**
-     * Return the visible height (in pixels) of the embedded title bar (if any).
+     * Gets the visible height (in pixels) of the embedded title bar (if any).
      *
      * @deprecated This method is now obsolete.
      */
@@ -539,8 +562,10 @@
     }
 
     /**
-     * @return The SSL certificate for the main top-level page or null if
-     * there is no certificate (the site is not secure).
+     * Gets the SSL certificate for the main top-level page or null if there is
+     * no certificate (the site is not secure).
+     *
+     * @return the SSL certificate for the main top-level page
      */
     public SslCertificate getCertificate() {
         checkThread();
@@ -560,11 +585,12 @@
     //-------------------------------------------------------------------------
 
     /**
-     * Save the username and password for a particular host in the WebView's
+     * Saves the username and password for a particular host in this WebView's
      * internal database.
-     * @param host The host that required the credentials.
-     * @param username The username for the given host.
-     * @param password The password for the given host.
+     *
+     * @param host the host that required the credentials
+     * @param username the username for the given host
+     * @param password the password for the given host
      */
     public void savePassword(String host, String username, String password) {
         checkThread();
@@ -572,13 +598,13 @@
     }
 
     /**
-     * Set the HTTP authentication credentials for a given host and realm.
+     * Sets the HTTP authentication credentials for a given host and realm.
      *
-     * @param host The host for the credentials.
-     * @param realm The realm for the credentials.
-     * @param username The username for the password. If it is null, it means
+     * @param host the host for the credentials
+     * @param realm the realm for the credentials
+     * @param username the username for the password. If it is null, it means
      *                 password can't be saved.
-     * @param password The password
+     * @param password the password
      */
     public void setHttpAuthUsernamePassword(String host, String realm,
             String username, String password) {
@@ -587,12 +613,12 @@
     }
 
     /**
-     * Retrieve the HTTP authentication username and password for a given
-     * host & realm pair
+     * Retrieves the HTTP authentication username and password for a given
+     * host and realm pair
      *
-     * @param host The host for which the credentials apply.
-     * @param realm The realm for which the credentials apply.
-     * @return String[] if found, String[0] is username, which can be null and
+     * @param host the host for which the credentials apply
+     * @param realm the realm for which the credentials apply
+     * @return String[] if found. String[0] is username, which can be null and
      *         String[1] is password. Return null if it can't find anything.
      */
     public String[] getHttpAuthUsernamePassword(String host, String realm) {
@@ -601,9 +627,9 @@
     }
 
     /**
-     * Destroy the internal state of the WebView. This method should be called
-     * after the WebView has been removed from the view system. No other
-     * methods may be called on a WebView after destroy.
+     * Destroys the internal state of this WebView. This method should be called
+     * after this WebView has been removed from the view system. No other
+     * methods may be called on this WebView after destroy.
      */
     public void destroy() {
         checkThread();
@@ -635,10 +661,11 @@
     }
 
     /**
-     * Inform WebView of the network state. This is used to set
+     * Informs WebView of the network state. This is used to set
      * the JavaScript property window.navigator.isOnline and
      * generates the online/offline event as specified in HTML5, sec. 5.7.7
-     * @param networkUp boolean indicating if network is available
+     *
+     * @param networkUp a boolean indicating if network is available
      */
     public void setNetworkAvailable(boolean networkUp) {
         checkThread();
@@ -646,14 +673,15 @@
     }
 
     /**
-     * Save the state of this WebView used in
+     * Saves the state of this WebView used in
      * {@link android.app.Activity#onSaveInstanceState}. Please note that this
      * method no longer stores the display data for this WebView. The previous
      * behavior could potentially leak files if {@link #restoreState} was never
      * called. See {@link #savePicture} and {@link #restorePicture} for saving
      * and restoring the display data.
-     * @param outState The Bundle to store the WebView state.
-     * @return The same copy of the back/forward list used to save the state. If
+     *
+     * @param outState the Bundle to store this WebView's state
+     * @return the same copy of the back/forward list used to save the state. If
      *         saveState fails, the returned list will be null.
      * @see #savePicture
      * @see #restorePicture
@@ -664,12 +692,12 @@
     }
 
     /**
-     * Save the current display data to the Bundle given. Used in conjunction
+     * Saves the current display data to the Bundle given. Used in conjunction
      * with {@link #saveState}.
-     * @param b A Bundle to store the display data.
-     * @param dest The file to store the serialized picture data. Will be
+     * @param b a Bundle to store the display data
+     * @param dest the file to store the serialized picture data. Will be
      *             overwritten with this WebView's picture data.
-     * @return True if the picture was successfully saved.
+     * @return true if the picture was successfully saved
      * @deprecated This method is now obsolete.
      */
     @Deprecated
@@ -679,13 +707,13 @@
     }
 
     /**
-     * Restore the display data that was save in {@link #savePicture}. Used in
-     * conjunction with {@link #restoreState}.
+     * Restores the display data that was saved in {@link #savePicture}. Used in
+     * conjunction with {@link #restoreState}. Note that this will not work if
+     * this WebView is hardware accelerated.
      *
-     * Note that this will not work if the WebView is hardware accelerated.
-     * @param b A Bundle containing the saved display data.
-     * @param src The file where the picture data was stored.
-     * @return True if the picture was successfully restored.
+     * @param b a Bundle containing the saved display data
+     * @param src the file where the picture data was stored
+     * @return true if the picture was successfully restored
      * @deprecated This method is now obsolete.
      */
     @Deprecated
@@ -695,16 +723,17 @@
     }
 
     /**
-     * Restore the state of this WebView from the given map used in
+     * Restores the state of this WebView from the given map used in
      * {@link android.app.Activity#onRestoreInstanceState}. This method should
-     * be called to restore the state of the WebView before using the object. If
-     * it is called after the WebView has had a chance to build state (load
+     * be called to restore the state of this WebView before using the object. If
+     * it is called after this WebView has had a chance to build state (load
      * pages, create a back/forward list, etc.) there may be undesirable
      * side-effects. Please note that this method no longer restores the
      * display data for this WebView. See {@link #savePicture} and {@link
      * #restorePicture} for saving and restoring the display data.
-     * @param inState The incoming Bundle of state.
-     * @return The restored back/forward list or null if restoreState failed.
+     *
+     * @param inState the incoming Bundle of state
+     * @return the restored back/forward list or null if restoreState failed
      * @see #savePicture
      * @see #restorePicture
      */
@@ -714,14 +743,15 @@
     }
 
     /**
-     * Load the given URL with the specified additional HTTP headers.
-     * @param url The URL of the resource to load.
-     * @param additionalHttpHeaders The additional headers to be used in the
+     * Loads the given URL with the specified additional HTTP headers.
+     *
+     * @param url the URL of the resource to load
+     * @param additionalHttpHeaders the additional headers to be used in the
      *            HTTP request for this URL, specified as a map from name to
      *            value. Note that if this map contains any of the headers
-     *            that are set by default by the WebView, such as those
+     *            that are set by default by this WebView, such as those
      *            controlling caching, accept types or the User-Agent, their
-     *            values may be overriden by the WebView's defaults.
+     *            values may be overriden by this WebView's defaults.
      */
     public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {
         checkThread();
@@ -729,8 +759,9 @@
     }
 
     /**
-     * Load the given URL.
-     * @param url The URL of the resource to load.
+     * Loads the given URL.
+     *
+     * @param url the URL of the resource to load
      */
     public void loadUrl(String url) {
         checkThread();
@@ -738,12 +769,12 @@
     }
 
     /**
-     * Load the url with postData using "POST" method into the WebView. If url
-     * is not a network url, it will be loaded with {link
+     * Loads the URL with postData using "POST" method into this WebView. If url
+     * is not a network URL, it will be loaded with {link
      * {@link #loadUrl(String)} instead.
      *
-     * @param url The url of the resource to load.
-     * @param postData The data will be passed to "POST" request.
+     * @param url the URL of the resource to load
+     * @param postData the data will be passed to "POST" request
      */
     public void postUrl(String url, byte[] postData) {
         checkThread();
@@ -751,7 +782,7 @@
     }
 
     /**
-     * Load the given data into the WebView using a 'data' scheme URL.
+     * Loads the given data into this WebView using a 'data' scheme URL.
      * <p>
      * Note that JavaScript's same origin policy means that script running in a
      * page loaded using this method will be unable to access content loaded
@@ -772,9 +803,10 @@
      * mediatype portion of the URL and call {@link #loadUrl(String)} instead.
      * Note that the charset obtained from the mediatype portion of a data URL
      * always overrides that specified in the HTML or XML document itself.
-     * @param data A String of data in the given encoding.
-     * @param mimeType The MIME type of the data, e.g. 'text/html'.
-     * @param encoding The encoding of the data.
+     *
+     * @param data a String of data in the given encoding
+     * @param mimeType the MIME type of the data, e.g. 'text/html'
+     * @param encoding the encoding of the data
      */
     public void loadData(String data, String mimeType, String encoding) {
         checkThread();
@@ -782,7 +814,7 @@
     }
 
     /**
-     * Load the given data into the WebView, using baseUrl as the base URL for
+     * Loads the given data into this WebView, using baseUrl as the base URL for
      * the content. The base URL is used both to resolve relative URLs and when
      * applying JavaScript's same origin policy. The historyUrl is used for the
      * history entry.
@@ -794,14 +826,15 @@
      * If the base URL uses the data scheme, this method is equivalent to
      * calling {@link #loadData(String,String,String) loadData()} and the
      * historyUrl is ignored.
-     * @param baseUrl URL to use as the page's base URL. If null defaults to
-     *            'about:blank'
-     * @param data A String of data in the given encoding.
-     * @param mimeType The MIMEType of the data, e.g. 'text/html'. If null,
-     *            defaults to 'text/html'.
-     * @param encoding The encoding of the data.
-     * @param historyUrl URL to use as the history entry, if null defaults to
-     *            'about:blank'.
+     *
+     * @param baseUrl the URL to use as the page's base URL. If null defaults to
+     *                'about:blank'.
+     * @param data a String of data in the given encoding
+     * @param mimeType the MIMEType of the data, e.g. 'text/html'. If null,
+     *                 defaults to 'text/html'.
+     * @param encoding the encoding of the data
+     * @param historyUrl the URL to use as the history entry. If null defaults
+     *                   to 'about:blank'.
      */
     public void loadDataWithBaseURL(String baseUrl, String data,
             String mimeType, String encoding, String historyUrl) {
@@ -812,7 +845,7 @@
     /**
      * Saves the current view as a web archive.
      *
-     * @param filename The filename where the archive should be placed.
+     * @param filename the filename where the archive should be placed
      */
     public void saveWebArchive(String filename) {
         checkThread();
@@ -822,11 +855,11 @@
     /**
      * Saves the current view as a web archive.
      *
-     * @param basename The filename where the archive should be placed.
-     * @param autoname If false, takes basename to be a file. If true, basename
+     * @param basename the filename where the archive should be placed
+     * @param autoname if false, takes basename to be a file. If true, basename
      *                 is assumed to be a directory in which a filename will be
-     *                 chosen according to the url of the current page.
-     * @param callback Called after the web archive has been saved. The
+     *                 chosen according to the URL of the current page.
+     * @param callback called after the web archive has been saved. The
      *                 parameter for onReceiveValue will either be the filename
      *                 under which the file was saved, or null if saving the
      *                 file failed.
@@ -837,7 +870,7 @@
     }
 
     /**
-     * Stop the current load.
+     * Stops the current load.
      */
     public void stopLoading() {
         checkThread();
@@ -845,7 +878,7 @@
     }
 
     /**
-     * Reload the current url.
+     * Reloads the current URL.
      */
     public void reload() {
         checkThread();
@@ -853,8 +886,9 @@
     }
 
     /**
-     * Return true if this WebView has a back history item.
-     * @return True iff this WebView has a back history item.
+     * Gets whether this WebView has a back history item.
+     *
+     * @return true iff this WebView has a back history item
      */
     public boolean canGoBack() {
         checkThread();
@@ -862,7 +896,7 @@
     }
 
     /**
-     * Go back in the history of this WebView.
+     * Goes back in the history of this WebView.
      */
     public void goBack() {
         checkThread();
@@ -870,8 +904,9 @@
     }
 
     /**
-     * Return true if this WebView has a forward history item.
-     * @return True iff this Webview has a forward history item.
+     * Gets whether this WebView has a forward history item.
+     *
+     * @return true iff this Webview has a forward history item
      */
     public boolean canGoForward() {
         checkThread();
@@ -879,7 +914,7 @@
     }
 
     /**
-     * Go forward in the history of this WebView.
+     * Goes forward in the history of this WebView.
      */
     public void goForward() {
         checkThread();
@@ -887,10 +922,11 @@
     }
 
     /**
-     * Return true if the page can go back or forward the given
+     * Gets whether the page can go back or forward the given
      * number of steps.
-     * @param steps The negative or positive number of steps to move the
-     *              history.
+     *
+     * @param steps the negative or positive number of steps to move the
+     *              history
      */
     public boolean canGoBackOrForward(int steps) {
         checkThread();
@@ -898,11 +934,12 @@
     }
 
     /**
-     * Go to the history item that is the number of steps away from
+     * Goes to the history item that is the number of steps away from
      * the current item. Steps is negative if backward and positive
      * if forward.
-     * @param steps The number of steps to take back or forward in the back
-     *              forward list.
+     *
+     * @param steps the number of steps to take back or forward in the back
+     *              forward list
      */
     public void goBackOrForward(int steps) {
         checkThread();
@@ -910,7 +947,7 @@
     }
 
     /**
-     * Returns true if private browsing is enabled in this WebView.
+     * Gets whether private browsing is enabled in this WebView.
      */
     public boolean isPrivateBrowsingEnabled() {
         checkThread();
@@ -918,7 +955,8 @@
     }
 
     /**
-     * Scroll the contents of the view up by half the view size
+     * Scrolls the contents of this WebView up by half the view size.
+     *
      * @param top true to jump to the top of the page
      * @return true if the page was scrolled
      */
@@ -928,7 +966,8 @@
     }
 
     /**
-     * Scroll the contents of the view down by half the page size
+     * Scrolls the contents of this WebView down by half the page size.
+     *
      * @param bottom true to jump to bottom of page
      * @return true if the page was scrolled
      */
@@ -938,8 +977,8 @@
     }
 
     /**
-     * Clear the view so that onDraw() will draw nothing but white background,
-     * and onMeasure() will return 0 if MeasureSpec is not MeasureSpec.EXACTLY
+     * Clears this WebView so that onDraw() will draw nothing but white background,
+     * and onMeasure() will return 0 if MeasureSpec is not MeasureSpec.EXACTLY.
      */
     public void clearView() {
         checkThread();
@@ -947,13 +986,13 @@
     }
 
     /**
-     * Return a new picture that captures the current display of the webview.
-     * This is a copy of the display, and will be unaffected if the webview
+     * Gets a new picture that captures the current display of this WebView.
+     * This is a copy of the display, and will be unaffected if this WebView
      * later loads a different URL.
      *
-     * @return a picture containing the current contents of the view. Note this
-     *         picture is of the entire document, and is not restricted to the
-     *         bounds of the view.
+     * @return a picture containing the current contents of this WebView. Note
+     *         this picture is of the entire document, and is not restricted to
+     *         the bounds of the view.
      */
     public Picture capturePicture() {
         checkThread();
@@ -961,8 +1000,9 @@
     }
 
     /**
-     * Return the current scale of the WebView
-     * @return The current scale.
+     * Gets the current scale of this WebView.
+     *
+     * @return the current scale
      */
     public float getScale() {
         checkThread();
@@ -970,14 +1010,14 @@
     }
 
     /**
-     * Set the initial scale for the WebView. 0 means default. If
+     * Sets the initial scale for this WebView. 0 means default. If
      * {@link WebSettings#getUseWideViewPort()} is true, it zooms out all the
      * way. Otherwise it starts with 100%. If initial scale is greater than 0,
      * WebView starts with this value as initial scale.
      * Please note that unlike the scale properties in the viewport meta tag,
      * this method doesn't take the screen density into account.
      *
-     * @param scaleInPercent The initial scale in percent.
+     * @param scaleInPercent the initial scale in percent
      */
     public void setInitialScale(int scaleInPercent) {
         checkThread();
@@ -985,7 +1025,7 @@
     }
 
     /**
-     * Invoke the graphical zoom picker widget for this WebView. This will
+     * Invokes the graphical zoom picker widget for this WebView. This will
      * result in the zoom widget appearing on the screen to control the zoom
      * level of this WebView.
      */
@@ -995,15 +1035,15 @@
     }
 
     /**
-     * Return a HitTestResult based on the current cursor node. If a HTML::a tag
-     * is found and the anchor has a non-JavaScript url, the HitTestResult type
-     * is set to SRC_ANCHOR_TYPE and the url is set in the "extra" field. If the
-     * anchor does not have a url or if it is a JavaScript url, the type will
-     * be UNKNOWN_TYPE and the url has to be retrieved through
+     * Gets a HitTestResult based on the current cursor node. If a HTML::a
+     * tag is found and the anchor has a non-JavaScript URL, the HitTestResult
+     * type is set to SRC_ANCHOR_TYPE and the URL is set in the "extra" field.
+     * If the anchor does not have a URL or if it is a JavaScript URL, the type
+     * will be UNKNOWN_TYPE and the URL has to be retrieved through
      * {@link #requestFocusNodeHref} asynchronously. If a HTML::img tag is
-     * found, the HitTestResult type is set to IMAGE_TYPE and the url is set in
+     * found, the HitTestResult type is set to IMAGE_TYPE and the URL is set in
      * the "extra" field. A type of
-     * SRC_IMAGE_ANCHOR_TYPE indicates an anchor with a url that has an image as
+     * SRC_IMAGE_ANCHOR_TYPE indicates an anchor with a URL that has an image as
      * a child node. If a phone number is found, the HitTestResult type is set
      * to PHONE_TYPE and the phone number is set in the "extra" field of
      * HitTestResult. If a map address is found, the HitTestResult type is set
@@ -1018,18 +1058,17 @@
     }
 
     /**
-     * Request the anchor or image element URL at the last tapped point.
+     * Requests the anchor or image element URL at the last tapped point.
      * If hrefMsg is null, this method returns immediately and does not
      * dispatch hrefMsg to its target. If the tapped point hits an image,
      * an anchor, or an image in an anchor, the message associates
      * strings in named keys in its data. The value paired with the key
      * may be an empty string.
      *
-     * @param hrefMsg This message will be dispatched with the result of the
-     *                request. The message data contains three keys:
-     *                - "url" returns the anchor's href attribute.
-     *                - "title" returns the anchor's text.
-     *                - "src" returns the image's src attribute.
+     * @param hrefMsg the message to be dispatched with the result of the
+     *                request. The message data contains three keys. "url"
+     *                returns the anchor's href attribute. "title" returns the
+     *                anchor's text. "src" returns the image's src attribute.
      */
     public void requestFocusNodeHref(Message hrefMsg) {
         checkThread();
@@ -1037,10 +1076,10 @@
     }
 
     /**
-     * Request the url of the image last touched by the user. msg will be sent
-     * to its target with a String representing the url as its object.
+     * Requests the URL of the image last touched by the user. msg will be sent
+     * to its target with a String representing the URL as its object.
      *
-     * @param msg This message will be dispatched with the result of the request
+     * @param msg the message to be dispatched with the result of the request
      *            as the data member with "url" as key. The result can be null.
      */
     public void requestImageRef(Message msg) {
@@ -1049,10 +1088,11 @@
     }
 
     /**
-     * Get the url for the current page. This is not always the same as the url
+     * Gets the URL for the current page. This is not always the same as the URL
      * passed to WebViewClient.onPageStarted because although the load for
-     * that url has begun, the current page may not have changed.
-     * @return The url for the current page.
+     * that URL has begun, the current page may not have changed.
+     *
+     * @return the URL for the current page
      */
     public String getUrl() {
         checkThread();
@@ -1060,12 +1100,13 @@
     }
 
     /**
-     * Get the original url for the current page. This is not always the same
-     * as the url passed to WebViewClient.onPageStarted because although the
-     * load for that url has begun, the current page may not have changed.
-     * Also, there may have been redirects resulting in a different url to that
+     * Gets the original URL for the current page. This is not always the same
+     * as the URL passed to WebViewClient.onPageStarted because although the
+     * load for that URL has begun, the current page may not have changed.
+     * Also, there may have been redirects resulting in a different URL to that
      * originally requested.
-     * @return The url that was originally requested for the current page.
+     *
+     * @return the URL that was originally requested for the current page
      */
     public String getOriginalUrl() {
         checkThread();
@@ -1073,9 +1114,10 @@
     }
 
     /**
-     * Get the title for the current page. This is the title of the current page
+     * Gets the title for the current page. This is the title of the current page
      * until WebViewClient.onReceivedTitle is called.
-     * @return The title for the current page.
+     *
+     * @return the title for the current page
      */
     public String getTitle() {
         checkThread();
@@ -1083,9 +1125,10 @@
     }
 
     /**
-     * Get the favicon for the current page. This is the favicon of the current
+     * Gets the favicon for the current page. This is the favicon of the current
      * page until WebViewClient.onReceivedIcon is called.
-     * @return The favicon for the current page.
+     *
+     * @return the favicon for the current page
      */
     public Bitmap getFavicon() {
         checkThread();
@@ -1093,9 +1136,10 @@
     }
 
     /**
-     * Get the touch icon url for the apple-touch-icon <link> element, or
+     * Gets the touch icon URL for the apple-touch-icon <link> element, or
      * a URL on this site's server pointing to the standard location of a
      * touch icon.
+     *
      * @hide
      */
     public String getTouchIconUrl() {
@@ -1103,8 +1147,9 @@
     }
 
     /**
-     * Get the progress for the current page.
-     * @return The progress for the current page between 0 and 100.
+     * Gets the progress for the current page.
+     *
+     * @return the progress for the current page between 0 and 100
      */
     public int getProgress() {
         checkThread();
@@ -1112,7 +1157,9 @@
     }
 
     /**
-     * @return the height of the HTML content.
+     * Gets the height of the HTML content.
+     *
+     * @return the height of the HTML content
      */
     public int getContentHeight() {
         checkThread();
@@ -1120,7 +1167,9 @@
     }
 
     /**
-     * @return the width of the HTML content.
+     * Gets the width of the HTML content.
+     *
+     * @return the width of the HTML content
      * @hide
      */
     public int getContentWidth() {
@@ -1128,8 +1177,8 @@
     }
 
     /**
-     * Pause all layout, parsing, and JavaScript timers for all webviews. This
-     * is a global requests, not restricted to just this webview. This can be
+     * Pauses all layout, parsing, and JavaScript timers for all WebViews. This
+     * is a global requests, not restricted to just this WebView. This can be
      * useful if the application has been paused.
      */
     public void pauseTimers() {
@@ -1138,7 +1187,7 @@
     }
 
     /**
-     * Resume all layout, parsing, and JavaScript timers for all webviews.
+     * Resumes all layout, parsing, and JavaScript timers for all WebViews.
      * This will resume dispatching all timers.
      */
     public void resumeTimers() {
@@ -1147,11 +1196,10 @@
     }
 
     /**
-     * Call this to pause any extra processing associated with this WebView and
-     * its associated DOM, plugins, JavaScript etc. For example, if the WebView
-     * is taken offscreen, this could be called to reduce unnecessary CPU or
-     * network traffic. When the WebView is again "active", call onResume().
-     *
+     * Pauses any extra processing associated with this WebView and its
+     * associated DOM, plugins, JavaScript etc. For example, if this WebView is
+     * taken offscreen, this could be called to reduce unnecessary CPU or
+     * network traffic. When this WebView is again "active", call onResume().
      * Note that this differs from pauseTimers(), which affects all WebViews.
      */
     public void onPause() {
@@ -1160,7 +1208,7 @@
     }
 
     /**
-     * Call this to resume a WebView after a previous call to onPause().
+     * Resumes a WebView after a previous call to onPause().
      */
     public void onResume() {
         checkThread();
@@ -1168,8 +1216,9 @@
     }
 
     /**
-     * Returns true if the view is paused, meaning onPause() was called. Calling
-     * onResume() sets the paused state back to false.
+     * Gets whether this WebView is paused, meaning onPause() was called.
+     * Calling onResume() sets the paused state back to false.
+     *
      * @hide
      */
     public boolean isPaused() {
@@ -1177,8 +1226,8 @@
     }
 
     /**
-     * Call this to inform the view that memory is low so that it can
-     * free any available memory.
+     * Informs this WebView that memory is low so that it can free any available
+     * memory.
      */
     public void freeMemory() {
         checkThread();
@@ -1186,10 +1235,10 @@
     }
 
     /**
-     * Clear the resource cache. Note that the cache is per-application, so
+     * Clears the resource cache. Note that the cache is per-application, so
      * this will clear the cache for all WebViews used.
      *
-     * @param includeDiskFiles If false, only the RAM cache is cleared.
+     * @param includeDiskFiles if false, only the RAM cache is cleared
      */
     public void clearCache(boolean includeDiskFiles) {
         checkThread();
@@ -1197,7 +1246,7 @@
     }
 
     /**
-     * Make sure that clearing the form data removes the adapter from the
+     * Makes sure that clearing the form data removes the adapter from the
      * currently focused textfield if there is one.
      */
     public void clearFormData() {
@@ -1206,7 +1255,7 @@
     }
 
     /**
-     * Tell the WebView to clear its internal back/forward list.
+     * Tells this WebView to clear its internal back/forward list.
      */
     public void clearHistory() {
         checkThread();
@@ -1214,8 +1263,8 @@
     }
 
     /**
-     * Clear the SSL preferences table stored in response to proceeding with SSL
-     * certificate errors.
+     * Clears the SSL preferences table stored in response to proceeding with
+     * SSL certificate errors.
      */
     public void clearSslPreferences() {
         checkThread();
@@ -1223,7 +1272,7 @@
     }
 
     /**
-     * Return the WebBackForwardList for this WebView. This contains the
+     * Gets the WebBackForwardList for this WebView. This contains the
      * back/forward list for use in querying each item in the history stack.
      * This is a copy of the private WebBackForwardList so it contains only a
      * snapshot of the current state. Multiple calls to this method may return
@@ -1237,10 +1286,10 @@
     }
 
     /**
-     * Register the listener to be notified as find-on-page operations progress.
-     * This will replace the current listener.
+     * Registers the listener to be notified as find-on-page operations
+     * progress. This will replace the current listener.
      *
-     * @param listener An implementation of {@link FindListener}.
+     * @param listener an implementation of {@link FindListener}
      */
     public void setFindListener(FindListener listener) {
         checkThread();
@@ -1248,14 +1297,14 @@
     }
 
     /**
-     * Highlight and scroll to the next match found by {@link #findAll} or
+     * Highlights and scrolls to the next match found by {@link #findAll} or
      * {@link #findAllAsync}, wrapping around page boundaries as necessary.
      * Notifies any registered {@link FindListener}. If neither
      * {@link #findAll} nor {@link #findAllAsync(String)} has been called yet,
      * or if {@link #clearMatches} has been called since the last find
      * operation, this function does nothing.
      *
-     * @param forward Direction to search.
+     * @param forward the direction to search
      * @see #setFindListener
      */
     public void findNext(boolean forward) {
@@ -1264,12 +1313,11 @@
     }
 
     /**
-     * Find all instances of find on the page and highlight them.
+     * Finds all instances of find on the page and highlights them.
      * Notifies any registered {@link FindListener}.
      *
-     * @param find  String to find.
-     * @return int  The number of occurances of the String "find"
-     *              that were found.
+     * @param find the string to find
+     * @return the number of occurances of the String "find" that were found
      * @deprecated {@link #findAllAsync} is preferred.
      * @see #setFindListener
      */
@@ -1281,12 +1329,12 @@
     }
 
     /**
-     * Find all instances of find on the page and highlight them,
+     * Finds all instances of find on the page and highlights them,
      * asynchronously. Notifies any registered {@link FindListener}.
      * Successive calls to this or {@link #findAll} will cancel any
      * pending searches.
      *
-     * @param find  String to find.
+     * @param find the string to find.
      * @see #setFindListener
      */
     public void findAllAsync(String find) {
@@ -1295,14 +1343,15 @@
     }
 
     /**
-     * Start an ActionMode for finding text in this WebView.  Only works if this
-     *              WebView is attached to the view system.
-     * @param text If non-null, will be the initial text to search for.
+     * Starts an ActionMode for finding text in this WebView.  Only works if this
+     * WebView is attached to the view system.
+     *
+     * @param text if non-null, will be the initial text to search for.
      *             Otherwise, the last String searched for in this WebView will
      *             be used to start.
-     * @param showIme If true, show the IME, assuming the user will begin typing.
-     *             If false and text is non-null, perform a find all.
-     * @return boolean True if the find dialog is shown, false otherwise.
+     * @param showIme if true, show the IME, assuming the user will begin typing.
+     *                If false and text is non-null, perform a find all.
+     * @return true if the find dialog is shown, false otherwise
      */
     public boolean showFindDialog(String text, boolean showIme) {
         checkThread();
@@ -1310,24 +1359,26 @@
     }
 
     /**
-     * Return the first substring consisting of the address of a physical
+     * Gets the first substring consisting of the address of a physical
      * location. Currently, only addresses in the United States are detected,
      * and consist of:
-     * - a house number
-     * - a street name
-     * - a street type (Road, Circle, etc), either spelled out or abbreviated
-     * - a city name
-     * - a state or territory, either spelled out or two-letter abbr.
-     * - an optional 5 digit or 9 digit zip code.
-     *
+     * <ul>
+     *   <li>a house number</li>
+     *   <li>a street name</li>
+     *   <li>a street type (Road, Circle, etc), either spelled out or
+     *       abbreviated</li>
+     *   <li>a city name</li>
+     *   <li>a state or territory, either spelled out or two-letter abbr</li>
+     *   <li>an optional 5 digit or 9 digit zip code</li>
+     * </ul>
      * All names must be correctly capitalized, and the zip code, if present,
      * must be valid for the state. The street type must be a standard USPS
      * spelling or abbreviation. The state or territory must also be spelled
      * or abbreviated using USPS standards. The house number may not exceed
      * five digits.
-     * @param addr The string to search for addresses.
      *
-     * @return the address, or if no address is found, return null.
+     * @param addr the string to search for addresses
+     * @return the address, or if no address is found, null
      */
     public static String findAddress(String addr) {
         checkThread();
@@ -1335,7 +1386,7 @@
     }
 
     /**
-     * Clear the highlighting surrounding text matches created by
+     * Clears the highlighting surrounding text matches created by
      * {@link #findAll} or {@link #findAllAsync}.
      */
     public void clearMatches() {
@@ -1344,10 +1395,11 @@
     }
 
     /**
-     * Query the document to see if it contains any image references. The
+     * Queries the document to see if it contains any image references. The
      * message object will be dispatched with arg1 being set to 1 if images
      * were found and 0 if the document does not reference any images.
-     * @param response The message that will be dispatched with the result.
+     *
+     * @param response the message that will be dispatched with the result
      */
     public void documentHasImages(Message response) {
         checkThread();
@@ -1355,9 +1407,10 @@
     }
 
     /**
-     * Set the WebViewClient that will receive various notifications and
+     * Sets the WebViewClient that will receive various notifications and
      * requests. This will replace the current handler.
-     * @param client An implementation of WebViewClient.
+     *
+     * @param client an implementation of WebViewClient
      */
     public void setWebViewClient(WebViewClient client) {
         checkThread();
@@ -1365,10 +1418,11 @@
     }
 
     /**
-     * Register the interface to be used when content can not be handled by
+     * Registers the interface to be used when content can not be handled by
      * the rendering engine, and should be downloaded instead. This will replace
      * the current handler.
-     * @param listener An implementation of DownloadListener.
+     *
+     * @param listener an implementation of DownloadListener
      */
     public void setDownloadListener(DownloadListener listener) {
         checkThread();
@@ -1376,10 +1430,11 @@
     }
 
     /**
-     * Set the chrome handler. This is an implementation of WebChromeClient for
+     * Sets the chrome handler. This is an implementation of WebChromeClient for
      * use in handling JavaScript dialogs, favicons, titles, and the progress.
      * This will replace the current handler.
-     * @param client An implementation of WebChromeClient.
+     *
+     * @param client an implementation of WebChromeClient
      */
     public void setWebChromeClient(WebChromeClient client) {
         checkThread();
@@ -1387,9 +1442,10 @@
     }
 
     /**
-     * Set the Picture listener. This is an interface used to receive
+     * Sets the Picture listener. This is an interface used to receive
      * notifications of a new Picture.
-     * @param listener An implementation of WebView.PictureListener.
+     *
+     * @param listener an implementation of WebView.PictureListener
      * @deprecated This method is now obsolete.
      */
     @Deprecated
@@ -1419,7 +1475,7 @@
      * permissions of the host application. Use extreme care when using this
      * method in a WebView which could contain untrusted content.</li>
      * <li> JavaScript interacts with Java object on a private, background
-     * thread of the WebView. Care is therefore required to maintain thread
+     * thread of this WebView. Care is therefore required to maintain thread
      * safety.</li>
      * </ul>
      *
@@ -1445,10 +1501,11 @@
     }
 
     /**
-     * Return the WebSettings object used to control the settings for this
+     * Gets the WebSettings object used to control the settings for this
      * WebView.
-     * @return A WebSettings object that can be used to control this WebView's
-     *         settings.
+     *
+     * @return a WebSettings object that can be used to control this WebView's
+     *         settings
      */
     public WebSettings getSettings() {
         checkThread();
@@ -1456,11 +1513,11 @@
     }
 
     /**
-     * Return the list of currently loaded plugins.
-     * @return The list of currently loaded plugins.
+     * Gets the list of currently loaded plugins.
      *
-     * @hide
+     * @return the list of currently loaded plugins
      * @deprecated This was used for Gears, which has been deprecated.
+     * @hide
      */
     @Deprecated
     public static synchronized PluginList getPluginList() {
@@ -1469,8 +1526,8 @@
     }
 
     /**
-     * @hide
      * @deprecated This was used for Gears, which has been deprecated.
+     * @hide
      */
     @Deprecated
     public void refreshPlugins(boolean reloadOpenPages) {
@@ -1478,8 +1535,9 @@
     }
 
     /**
-     * Use this method to put the WebView into text selection mode.
-     * Do not rely on this functionality; it will be deprecated in the future.
+     * Puts this WebView into text selection mode. Do not rely on this
+     * functionality; it will be deprecated in the future.
+     *
      * @deprecated This method is now obsolete.
      */
     @Deprecated
@@ -1528,15 +1586,15 @@
     }
 
     /**
-     * Gets the zoom controls for the WebView, as a separate View. The caller is
-     * responsible for inserting this View into the layout hierarchy.
+     * Gets the zoom controls for this WebView, as a separate View. The caller
+     * is responsible for inserting this View into the layout hierarchy.
      * <p/>
      * API level {@link android.os.Build.VERSION_CODES#CUPCAKE} introduced
      * built-in zoom mechanisms for the WebView, as opposed to these separate
      * zoom controls. The built-in mechanisms are preferred and can be enabled
      * using {@link WebSettings#setBuiltInZoomControls}.
      *
-     * @deprecated The built-in zoom mechanisms are preferred.
+     * @deprecated the built-in zoom mechanisms are preferred
      * @hide Since API level {@link android.os.Build.VERSION_CODES#JELLY_BEAN}
      */
     @Deprecated
@@ -1546,7 +1604,9 @@
     }
 
     /**
-     * @return TRUE if the WebView can be zoomed in.
+     * Gets whether this WebView can be zoomed in.
+     *
+     * @return true if this WebView can be zoomed in
      */
     public boolean canZoomIn() {
         checkThread();
@@ -1554,7 +1614,9 @@
     }
 
     /**
-     * @return TRUE if the WebView can be zoomed out.
+     * Gets whether this WebView can be zoomed out.
+     *
+     * @return true if this WebView can be zoomed out
      */
     public boolean canZoomOut() {
         checkThread();
@@ -1562,8 +1624,9 @@
     }
 
     /**
-     * Perform zoom in in the webview
-     * @return TRUE if zoom in succeeds. FALSE if no zoom changes.
+     * Performs zoom in in this WebView.
+     *
+     * @return true if zoom in succeeds, false if no zoom changes
      */
     public boolean zoomIn() {
         checkThread();
@@ -1571,8 +1634,9 @@
     }
 
     /**
-     * Perform zoom out in the webview
-     * @return TRUE if zoom out succeeds. FALSE if no zoom changes.
+     * Performs zoom out in this WebView.
+     *
+     * @return true if zoom out succeeds, false if no zoom changes
      */
     public boolean zoomOut() {
         checkThread();
@@ -1593,8 +1657,9 @@
     //-------------------------------------------------------------------------
 
     /**
-     * Used by providers to obtain the underlying implementation, e.g. when the appliction
-     * responds to WebViewClient.onCreateWindow() request.
+     * Gets the WebViewProvider. Used by providers to obtain the underlying
+     * implementation, e.g. when the appliction responds to
+     * WebViewClient.onCreateWindow() request.
      *
      * @hide WebViewProvider is not public API.
      */
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 05b3e64..9cf0d54 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -2598,7 +2598,8 @@
      */
     @Override
     public boolean isPrivateBrowsingEnabled() {
-        return getSettings().isPrivateBrowsingEnabled();
+        WebSettingsClassic settings = getSettings();
+        return (settings != null) ? settings.isPrivateBrowsingEnabled() : false;
     }
 
     private void startPrivateBrowsing() {
@@ -2668,7 +2669,7 @@
     public void clearView() {
         mContentWidth = 0;
         mContentHeight = 0;
-        setBaseLayer(0, null, false, false);
+        setBaseLayer(0, false, false);
         mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
     }
 
@@ -3039,14 +3040,14 @@
     // the scale factor is not 1)
     private void calcOurContentVisibleRectF(RectF r) {
         calcOurVisibleRect(mContentVisibleRect);
-        r.left = viewToContentXf(mContentVisibleRect.left);
+        r.left = viewToContentXf(mContentVisibleRect.left) / mWebView.getScaleX();
         // viewToContentY will remove the total height of the title bar.  Add
         // the visible height back in to account for the fact that if the title
         // bar is partially visible, the part of the visible rect which is
         // displaying our content is displaced by that amount.
-        r.top = viewToContentYf(mContentVisibleRect.top + getVisibleTitleHeightImpl());
-        r.right = viewToContentXf(mContentVisibleRect.right);
-        r.bottom = viewToContentYf(mContentVisibleRect.bottom);
+        r.top = viewToContentYf(mContentVisibleRect.top + getVisibleTitleHeightImpl()) / mWebView.getScaleY();
+        r.right = viewToContentXf(mContentVisibleRect.right) / mWebView.getScaleX();
+        r.bottom = viewToContentYf(mContentVisibleRect.bottom) / mWebView.getScaleY();
     }
 
     static class ViewSizeData {
@@ -4447,12 +4448,12 @@
      */
     private SelectActionModeCallback mSelectCallback;
 
-    void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator,
+    void setBaseLayer(int layer, boolean showVisualIndicator,
             boolean isPictureAfterFirstLayout) {
         if (mNativeClass == 0)
             return;
         boolean queueFull;
-        queueFull = nativeSetBaseLayer(mNativeClass, layer, invalRegion,
+        queueFull = nativeSetBaseLayer(mNativeClass, layer,
                                        showVisualIndicator, isPictureAfterFirstLayout);
 
         if (queueFull) {
@@ -7847,7 +7848,7 @@
         boolean isPictureAfterFirstLayout = viewState != null;
 
         if (updateBaseLayer) {
-            setBaseLayer(draw.mBaseLayer, draw.mInvalRegion,
+            setBaseLayer(draw.mBaseLayer,
                     getSettings().getShowVisualIndicator(),
                     isPictureAfterFirstLayout);
         }
@@ -7879,15 +7880,17 @@
         }
         mSendScrollEvent = true;
 
-        if (DebugFlags.WEB_VIEW) {
-            Rect b = draw.mInvalRegion.getBounds();
-            Log.v(LOGTAG, "NEW_PICTURE_MSG_ID {" +
-                    b.left+","+b.top+","+b.right+","+b.bottom+"}");
+        int functor = 0;
+        if (mWebView.isHardwareAccelerated()
+                || mWebView.getLayerType() != View.LAYER_TYPE_HARDWARE) {
+            functor = nativeGetDrawGLFunction(mNativeClass);
         }
-        Rect invalBounds = draw.mInvalRegion.getBounds();
-        if (!invalBounds.isEmpty()) {
-            invalidateContentRect(invalBounds);
+
+        if (functor != 0) {
+            mWebView.getViewRootImpl().attachFunctor(functor);
         } else {
+            // invalidate the screen so that the next repaint will show new content
+            // TODO: partial invalidate
             mWebView.invalidate();
         }
 
@@ -8575,8 +8578,7 @@
     private native Rect     nativeLayerBounds(int layer);
     private native void     nativeSetHeightCanMeasure(boolean measure);
     private native boolean  nativeSetBaseLayer(int nativeInstance,
-            int layer, Region invalRegion,
-            boolean showVisualIndicator, boolean isPictureAfterFirstLayout);
+            int layer, boolean showVisualIndicator, boolean isPictureAfterFirstLayout);
     private native int      nativeGetBaseLayer();
     private native void     nativeReplaceBaseContent(int content);
     private native void     nativeCopyBaseContentToPicture(Picture pict);
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 75141fd..12c9d69 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -601,8 +601,7 @@
      * Redraw a portion of the picture set. The Point wh returns the
      * width and height of the overall picture.
      */
-    private native int nativeRecordContent(int nativeClass, Region invalRegion,
-            Point wh);
+    private native int nativeRecordContent(int nativeClass, Point wh);
 
     /**
      * Notify webkit that animations have begun (on the hardware accelerated content)
@@ -2180,11 +2179,9 @@
     static class DrawData {
         DrawData() {
             mBaseLayer = 0;
-            mInvalRegion = new Region();
             mContentSize = new Point();
         }
         int mBaseLayer;
-        Region mInvalRegion;
         // view size that was used by webkit during the most recent layout
         Point mViewSize;
         Point mContentSize;
@@ -2230,8 +2227,7 @@
         mDrawIsScheduled = false;
         DrawData draw = new DrawData();
         if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw start");
-        draw.mBaseLayer = nativeRecordContent(mNativeClass, draw.mInvalRegion,
-                draw.mContentSize);
+        draw.mBaseLayer = nativeRecordContent(mNativeClass, draw.mContentSize);
         if (draw.mBaseLayer == 0) {
             if (mWebViewClassic != null && !mWebViewClassic.isPaused()) {
                 if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort, resending draw message");
@@ -2277,8 +2273,7 @@
         // the draw path (and fix saving <canvas>)
         DrawData draw = new DrawData();
         if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "saveViewState start");
-        draw.mBaseLayer = nativeRecordContent(mNativeClass, draw.mInvalRegion,
-                draw.mContentSize);
+        draw.mBaseLayer = nativeRecordContent(mNativeClass, draw.mContentSize);
         boolean result = false;
         try {
             result = ViewStateSerializer.serializeViewState(stream, draw);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 53d5e0b..a2531f8 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -58,6 +58,8 @@
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
@@ -660,6 +662,11 @@
     private int mLastHandledItemCount;
 
     /**
+     * Used for smooth scrolling at a consistent rate
+     */
+    static final Interpolator sLinearInterpolator = new LinearInterpolator();
+
+    /**
      * Interface definition for a callback to be invoked when the list or grid
      * has been scrolled.
      */
@@ -3753,6 +3760,7 @@
         void start(int initialVelocity) {
             int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0;
             mLastFlingY = initialY;
+            mScroller.setInterpolator(null);
             mScroller.fling(0, initialY, 0, initialVelocity,
                     0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE);
             mTouchMode = TOUCH_MODE_FLING;
@@ -3782,6 +3790,7 @@
         }
 
         void startOverfling(int initialVelocity) {
+            mScroller.setInterpolator(null);
             mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0,
                     Integer.MIN_VALUE, Integer.MAX_VALUE, 0, getHeight());
             mTouchMode = TOUCH_MODE_OVERFLING;
@@ -3811,9 +3820,10 @@
             postOnAnimation(this);
         }
 
-        void startScroll(int distance, int duration) {
+        void startScroll(int distance, int duration, boolean linear) {
             int initialY = distance < 0 ? Integer.MAX_VALUE : 0;
             mLastFlingY = initialY;
+            mScroller.setInterpolator(linear ? sLinearInterpolator : null);
             mScroller.startScroll(0, initialY, 0, distance, duration);
             mTouchMode = TOUCH_MODE_FLING;
             postOnAnimation(this);
@@ -4107,14 +4117,14 @@
             } else {
                 // On-screen, just scroll.
                 final int targetTop = getChildAt(position - firstPos).getTop();
-                smoothScrollBy(targetTop - offset, duration);
+                smoothScrollBy(targetTop - offset, duration, true);
                 return;
             }
 
             // Estimate how many screens we should travel
             final float screenTravelCount = (float) viewTravelCount / childCount;
-            mScrollDuration = screenTravelCount < 1 ? (int) (screenTravelCount * duration) :
-                    (int) (duration / screenTravelCount);
+            mScrollDuration = screenTravelCount < 1 ?
+                    duration : (int) (duration / screenTravelCount);
             mLastSeenPos = INVALID_POSITION;
 
             postOnAnimation(this);
@@ -4151,7 +4161,7 @@
                         Math.max(mListPadding.bottom, mExtraScroll) : mListPadding.bottom;
 
                 final int scrollBy = lastViewHeight - lastViewPixelsShowing + extraScroll;
-                smoothScrollBy(scrollBy, mScrollDuration);
+                smoothScrollBy(scrollBy, mScrollDuration, true);
 
                 mLastSeenPos = lastPos;
                 if (lastPos < mTargetPos) {
@@ -4182,14 +4192,14 @@
                 final int extraScroll = Math.max(mListPadding.bottom, mExtraScroll);
                 if (nextPos < mBoundPos) {
                     smoothScrollBy(Math.max(0, nextViewHeight + nextViewTop - extraScroll),
-                            mScrollDuration);
+                            mScrollDuration, true);
 
                     mLastSeenPos = nextPos;
 
                     postOnAnimation(this);
                 } else  {
                     if (nextViewTop > extraScroll) {
-                        smoothScrollBy(nextViewTop - extraScroll, mScrollDuration);
+                        smoothScrollBy(nextViewTop - extraScroll, mScrollDuration, true);
                     }
                 }
                 break;
@@ -4210,7 +4220,7 @@
                 final int extraScroll = firstPos > 0 ?
                         Math.max(mExtraScroll, mListPadding.top) : mListPadding.top;
 
-                smoothScrollBy(firstViewTop - extraScroll, mScrollDuration);
+                smoothScrollBy(firstViewTop - extraScroll, mScrollDuration, true);
 
                 mLastSeenPos = firstPos;
 
@@ -4229,7 +4239,7 @@
 
                 if (lastPos == mLastSeenPos) {
                     // No new views, let things keep going.
-                    post(this);
+                    postOnAnimation(this);
                     return;
                 }
 
@@ -4240,13 +4250,13 @@
                 final int extraScroll = Math.max(mListPadding.top, mExtraScroll);
                 mLastSeenPos = lastPos;
                 if (lastPos > mBoundPos) {
-                    smoothScrollBy(-(lastViewPixelsShowing - extraScroll), mScrollDuration);
+                    smoothScrollBy(-(lastViewPixelsShowing - extraScroll), mScrollDuration, true);
                     postOnAnimation(this);
                 } else {
                     final int bottom = listHeight - extraScroll;
                     final int lastViewBottom = lastViewTop + lastViewHeight;
                     if (bottom > lastViewBottom) {
-                        smoothScrollBy(-(bottom - lastViewBottom), mScrollDuration);
+                        smoothScrollBy(-(bottom - lastViewBottom), mScrollDuration, true);
                     }
                 }
                 break;
@@ -4255,7 +4265,7 @@
             case MOVE_OFFSET: {
                 if (mLastSeenPos == firstPos) {
                     // No new views, let things keep going.
-                    post(this);
+                    postOnAnimation(this);
                     return;
                 }
 
@@ -4277,17 +4287,22 @@
 
                 final float modifier = Math.min(Math.abs(screenTravelCount), 1.f);
                 if (position < firstPos) {
-                    smoothScrollBy((int) (-getHeight() * modifier), mScrollDuration);
+                    final int distance = (int) (-getHeight() * modifier);
+                    final int duration = (int) (mScrollDuration * modifier);
+                    smoothScrollBy(distance, duration, true);
                     postOnAnimation(this);
                 } else if (position > lastPos) {
-                    smoothScrollBy((int) (getHeight() * modifier), mScrollDuration);
+                    final int distance = (int) (getHeight() * modifier);
+                    final int duration = (int) (mScrollDuration * modifier);
+                    smoothScrollBy(distance, duration, true);
                     postOnAnimation(this);
                 } else {
                     // On-screen, just scroll.
                     final int targetTop = getChildAt(position - firstPos).getTop();
                     final int distance = targetTop - mOffsetFromTop;
-                    smoothScrollBy(distance,
-                            (int) (mScrollDuration * ((float) distance / getHeight())));
+                    final int duration = (int) (mScrollDuration *
+                            ((float) Math.abs(distance) / getHeight()));
+                    smoothScrollBy(distance, duration, true);
                 }
                 break;
             }
@@ -4393,6 +4408,10 @@
      * @param duration Duration of the scroll animation in milliseconds.
      */
     public void smoothScrollBy(int distance, int duration) {
+        smoothScrollBy(distance, duration, false);
+    }
+
+    void smoothScrollBy(int distance, int duration, boolean linear) {
         if (mFlingRunnable == null) {
             mFlingRunnable = new FlingRunnable();
         }
@@ -4414,7 +4433,7 @@
             }
         } else {
             reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
-            mFlingRunnable.startScroll(distance, duration);
+            mFlingRunnable.startScroll(distance, duration, linear);
         }
     }
 
diff --git a/core/java/android/widget/Advanceable.java b/core/java/android/widget/Advanceable.java
index dc13ebb7..ad8e101 100644
--- a/core/java/android/widget/Advanceable.java
+++ b/core/java/android/widget/Advanceable.java
@@ -21,7 +21,6 @@
  * 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 {
 
diff --git a/core/java/android/widget/OverScroller.java b/core/java/android/widget/OverScroller.java
index 6aee5a0..1c72a0d 100644
--- a/core/java/android/widget/OverScroller.java
+++ b/core/java/android/widget/OverScroller.java
@@ -35,7 +35,7 @@
     private final SplineOverScroller mScrollerX;
     private final SplineOverScroller mScrollerY;
 
-    private final Interpolator mInterpolator;
+    private Interpolator mInterpolator;
 
     private final boolean mFlywheel;
 
@@ -113,6 +113,10 @@
         this(context, interpolator, flywheel);
     }
 
+    void setInterpolator(Interpolator interpolator) {
+        mInterpolator = interpolator;
+    }
+
     /**
      * The amount of friction applied to flings. The default value
      * is {@link ViewConfiguration#getScrollFriction}.
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index a91b16e..98e45fb 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -457,7 +457,16 @@
         public void parse() {
             Editable editable = (Editable) mTextView.getText();
             // Iterate over the newly added text and schedule new SpellCheckSpans
-            final int start = editable.getSpanStart(mRange);
+            final int start;
+            if (mIsSentenceSpellCheckSupported) {
+                // TODO: Find the start position of the sentence.
+                // Set span with the context
+                start =  Math.max(
+                        0, editable.getSpanStart(mRange) - MIN_SENTENCE_LENGTH);
+            } else {
+                start = editable.getSpanStart(mRange);
+            }
+
             final int end = editable.getSpanEnd(mRange);
 
             int wordIteratorWindowEnd = Math.min(end, start + WORD_ITERATOR_INTERVAL);
@@ -512,9 +521,7 @@
                     return;
                 }
                 // TODO: Find the start position of the sentence.
-                // Set span with the context
-                final int spellCheckStart =  Math.max(
-                        0, Math.min(wordStart, regionEnd - MIN_SENTENCE_LENGTH));
+                final int spellCheckStart =  wordStart;
                 if (regionEnd <= spellCheckStart) {
                     return;
                 }
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index 4322a20..727c094 100755
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -22,14 +22,14 @@
 import android.content.res.ObbInfo;
 
 interface IMediaContainerService {
-    String copyResourceToContainer(in Uri packageURI,
-                String containerId,
-                String key, String resFileName);
+    String copyResourceToContainer(in Uri packageURI, String containerId, String key,
+            String resFileName, String publicResFileName, boolean isExternal,
+            boolean isForwardLocked);
     int copyResource(in Uri packageURI,
                 in ParcelFileDescriptor outStream);
     PackageInfoLite getMinimalPackageInfo(in Uri fileUri, in int flags, in long threshold);
-    boolean checkInternalFreeStorage(in Uri fileUri, in long threshold);
-    boolean checkExternalFreeStorage(in Uri fileUri);
+    boolean checkInternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in long threshold);
+    boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked);
     ObbInfo getObbInfo(in String filename);
     long calculateDirectorySize(in String directory);
     /** Return file system stats: [0] is total bytes, [1] is available bytes */
diff --git a/core/java/com/android/internal/app/RingtonePickerActivity.java b/core/java/com/android/internal/app/RingtonePickerActivity.java
deleted file mode 100644
index 36fc24e..0000000
--- a/core/java/com/android/internal/app/RingtonePickerActivity.java
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import com.android.internal.app.AlertActivity;
-import com.android.internal.app.AlertController;
-
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.database.Cursor;
-import android.media.Ringtone;
-import android.media.RingtoneManager;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ListView;
-import android.widget.TextView;
-
-/**
- * The {@link RingtonePickerActivity} allows the user to choose one from all of the
- * available ringtones. The chosen ringtone's URI will be persisted as a string.
- *
- * @see RingtoneManager#ACTION_RINGTONE_PICKER
- */
-public final class RingtonePickerActivity extends AlertActivity implements
-        AdapterView.OnItemSelectedListener, Runnable, DialogInterface.OnClickListener,
-        AlertController.AlertParams.OnPrepareListViewListener {
-
-    private static final String TAG = "RingtonePickerActivity";
-
-    private static final int DELAY_MS_SELECTION_PLAYED = 300;
-
-    private static final String SAVE_CLICKED_POS = "clicked_pos";
-
-    private RingtoneManager mRingtoneManager;
-    
-    private Cursor mCursor;
-    private Handler mHandler;
-
-    /** The position in the list of the 'Silent' item. */
-    private int mSilentPos = -1;
-    
-    /** The position in the list of the 'Default' item. */
-    private int mDefaultRingtonePos = -1;
-
-    /** The position in the list of the last clicked item. */
-    private int mClickedPos = -1;
-    
-    /** The position in the list of the ringtone to sample. */
-    private int mSampleRingtonePos = -1;
-
-    /** Whether this list has the 'Silent' item. */
-    private boolean mHasSilentItem;
-    
-    /** The Uri to place a checkmark next to. */
-    private Uri mExistingUri;
-    
-    /** The number of static items in the list. */
-    private int mStaticItemCount;
-    
-    /** Whether this list has the 'Default' item. */
-    private boolean mHasDefaultItem;
-    
-    /** The Uri to play when the 'Default' item is clicked. */
-    private Uri mUriForDefaultItem;
-    
-    /**
-     * A Ringtone for the default ringtone. In most cases, the RingtoneManager
-     * will stop the previous ringtone. However, the RingtoneManager doesn't
-     * manage the default ringtone for us, so we should stop this one manually.
-     */
-    private Ringtone mDefaultRingtone;
-    
-    private DialogInterface.OnClickListener mRingtoneClickListener =
-            new DialogInterface.OnClickListener() {
-
-        /*
-         * On item clicked
-         */
-        public void onClick(DialogInterface dialog, int which) {
-            // Save the position of most recently clicked item
-            mClickedPos = which;
-            
-            // Play clip
-            playRingtone(which, 0);
-        }
-        
-    };
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-
-        mHandler = new Handler();
-
-        Intent intent = getIntent();
-
-        /*
-         * Get whether to show the 'Default' item, and the URI to play when the
-         * default is clicked
-         */
-        mHasDefaultItem = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
-        mUriForDefaultItem = intent.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI);
-        if (mUriForDefaultItem == null) {
-            mUriForDefaultItem = Settings.System.DEFAULT_RINGTONE_URI;
-        }
-
-        if (savedInstanceState != null) {
-            mClickedPos = savedInstanceState.getInt(SAVE_CLICKED_POS, -1);
-        }
-        // Get whether to show the 'Silent' item
-        mHasSilentItem = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
-        
-        // Give the Activity so it can do managed queries
-        mRingtoneManager = new RingtoneManager(this);
-
-        // Get whether to include DRM ringtones
-        boolean includeDrm = intent.getBooleanExtra(RingtoneManager.EXTRA_RINGTONE_INCLUDE_DRM,
-                true);
-        mRingtoneManager.setIncludeDrm(includeDrm);
-        
-        // Get the types of ringtones to show
-        int types = intent.getIntExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, -1);
-        if (types != -1) {
-            mRingtoneManager.setType(types);
-        }
-        
-        mCursor = mRingtoneManager.getCursor();
-        
-        // The volume keys will control the stream that we are choosing a ringtone for
-        setVolumeControlStream(mRingtoneManager.inferStreamType());
-
-        // Get the URI whose list item should have a checkmark
-        mExistingUri = intent
-                .getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI);
-
-        final AlertController.AlertParams p = mAlertParams;
-        p.mCursor = mCursor;
-        p.mOnClickListener = mRingtoneClickListener;
-        p.mLabelColumn = MediaStore.Audio.Media.TITLE;
-        p.mIsSingleChoice = true;
-        p.mOnItemSelectedListener = this;
-        p.mPositiveButtonText = getString(com.android.internal.R.string.ok);
-        p.mPositiveButtonListener = this;
-        p.mNegativeButtonText = getString(com.android.internal.R.string.cancel);
-        p.mPositiveButtonListener = this;
-        p.mOnPrepareListViewListener = this;
-
-        p.mTitle = intent.getCharSequenceExtra(RingtoneManager.EXTRA_RINGTONE_TITLE);
-        if (p.mTitle == null) {
-            p.mTitle = getString(com.android.internal.R.string.ringtone_picker_title);
-        }
-        
-        setupAlert();
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putInt(SAVE_CLICKED_POS, mClickedPos);
-    }
-
-    public void onPrepareListView(ListView listView) {
-        
-        if (mHasDefaultItem) {
-            mDefaultRingtonePos = addDefaultRingtoneItem(listView);
-            
-            if (RingtoneManager.isDefault(mExistingUri)) {
-                mClickedPos = mDefaultRingtonePos;
-            }
-        }
-        
-        if (mHasSilentItem) {
-            mSilentPos = addSilentItem(listView);
-            
-            // The 'Silent' item should use a null Uri
-            if (mExistingUri == null) {
-                mClickedPos = mSilentPos;
-            }
-        }
-
-        if (mClickedPos == -1) {
-            mClickedPos = getListPosition(mRingtoneManager.getRingtonePosition(mExistingUri));
-        }
-        
-        // Put a checkmark next to an item.
-        mAlertParams.mCheckedItem = mClickedPos;
-    }
-
-    /**
-     * Adds a static item to the top of the list. A static item is one that is not from the
-     * RingtoneManager.
-     * 
-     * @param listView The ListView to add to.
-     * @param textResId The resource ID of the text for the item.
-     * @return The position of the inserted item.
-     */
-    private int addStaticItem(ListView listView, int textResId) {
-        TextView textView = (TextView) getLayoutInflater().inflate(
-                com.android.internal.R.layout.select_dialog_singlechoice_holo, listView, false);
-        textView.setText(textResId);
-        listView.addHeaderView(textView);
-        mStaticItemCount++;
-        return listView.getHeaderViewsCount() - 1;
-    }
-    
-    private int addDefaultRingtoneItem(ListView listView) {
-        return addStaticItem(listView, com.android.internal.R.string.ringtone_default);
-    }
-    
-    private int addSilentItem(ListView listView) {
-        return addStaticItem(listView, com.android.internal.R.string.ringtone_silent);
-    }
-    
-    /*
-     * On click of Ok/Cancel buttons
-     */
-    public void onClick(DialogInterface dialog, int which) {
-        boolean positiveResult = which == DialogInterface.BUTTON_POSITIVE;
-        
-        // Stop playing the previous ringtone
-        mRingtoneManager.stopPreviousRingtone();
-        
-        if (positiveResult) {
-            Intent resultIntent = new Intent();
-            Uri uri = null;
-            
-            if (mClickedPos == mDefaultRingtonePos) {
-                // Set it to the default Uri that they originally gave us
-                uri = mUriForDefaultItem;
-            } else if (mClickedPos == mSilentPos) {
-                // A null Uri is for the 'Silent' item
-                uri = null;
-            } else {
-                uri = mRingtoneManager.getRingtoneUri(getRingtoneManagerPosition(mClickedPos));
-            }
-
-            resultIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, uri);
-            setResult(RESULT_OK, resultIntent);
-        } else {
-            setResult(RESULT_CANCELED);
-        }
-
-        getWindow().getDecorView().post(new Runnable() {
-            public void run() {
-                mCursor.deactivate();
-            }
-        });
-
-        finish();
-    }
-    
-    /*
-     * On item selected via keys
-     */
-    public void onItemSelected(AdapterView parent, View view, int position, long id) {
-        playRingtone(position, DELAY_MS_SELECTION_PLAYED);
-    }
-
-    public void onNothingSelected(AdapterView parent) {
-    }
-
-    private void playRingtone(int position, int delayMs) {
-        mHandler.removeCallbacks(this);
-        mSampleRingtonePos = position;
-        mHandler.postDelayed(this, delayMs);
-    }
-    
-    public void run() {
-        
-        if (mSampleRingtonePos == mSilentPos) {
-            mRingtoneManager.stopPreviousRingtone();
-            return;
-        }
-        
-        /*
-         * Stop the default ringtone, if it's playing (other ringtones will be
-         * stopped by the RingtoneManager when we get another Ringtone from it.
-         */
-        if (mDefaultRingtone != null && mDefaultRingtone.isPlaying()) {
-            mDefaultRingtone.stop();
-            mDefaultRingtone = null;
-        }
-        
-        Ringtone ringtone;
-        if (mSampleRingtonePos == mDefaultRingtonePos) {
-            if (mDefaultRingtone == null) {
-                mDefaultRingtone = RingtoneManager.getRingtone(this, mUriForDefaultItem);
-            }
-            ringtone = mDefaultRingtone;
-            
-            /*
-             * Normally the non-static RingtoneManager.getRingtone stops the
-             * previous ringtone, but we're getting the default ringtone outside
-             * of the RingtoneManager instance, so let's stop the previous
-             * ringtone manually.
-             */
-            mRingtoneManager.stopPreviousRingtone();
-            
-        } else {
-            ringtone = mRingtoneManager.getRingtone(getRingtoneManagerPosition(mSampleRingtonePos));
-        }
-        
-        if (ringtone != null) {
-            ringtone.play();
-        }
-    }
-
-    @Override
-    protected void onStop() {
-        super.onStop();
-        stopAnyPlayingRingtone();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        stopAnyPlayingRingtone();
-    }
-
-    private void stopAnyPlayingRingtone() {
-
-        if (mDefaultRingtone != null && mDefaultRingtone.isPlaying()) {
-            mDefaultRingtone.stop();
-        }
-        
-        if (mRingtoneManager != null) {
-            mRingtoneManager.stopPreviousRingtone();
-        }
-    }
-    
-    private int getRingtoneManagerPosition(int listPos) {
-        return listPos - mStaticItemCount;
-    }
-    
-    private int getListPosition(int ringtoneManagerPos) {
-        
-        // If the manager position is -1 (for not found), return that
-        if (ringtoneManagerPos < 0) return ringtoneManagerPos;
-        
-        return ringtoneManagerPos + mStaticItemCount;
-    }
-    
-}
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index 61866e5..48ed561 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -67,8 +67,8 @@
         return null;
     }
 
-    public static String createSdDir(int sizeMb, String cid,
-            String sdEncKey, int uid) {
+    public static String createSdDir(int sizeMb, String cid, String sdEncKey, int uid,
+            boolean isExternal) {
         // Create mount point via MountService
         IMountService mountService = getMountService();
 
@@ -76,8 +76,8 @@
             Log.i(TAG, "Size of container " + sizeMb + " MB");
 
         try {
-            int rc = mountService.createSecureContainer(
-                    cid, sizeMb, "fat", sdEncKey, uid);
+            int rc = mountService.createSecureContainer(cid, sizeMb, "ext4", sdEncKey, uid,
+                    isExternal);
             if (rc != StorageResultCode.OperationSucceeded) {
                 Log.e(TAG, "Failed to create secure container " + cid);
                 return null;
@@ -206,10 +206,21 @@
        return false;
    }
 
-    public static void extractPublicFiles(String packagePath, File publicZipFile)
+    public static int extractPublicFiles(String packagePath, File publicZipFile)
             throws IOException {
-        final FileOutputStream fstr = new FileOutputStream(publicZipFile);
-        final ZipOutputStream publicZipOutStream = new ZipOutputStream(fstr);
+        final FileOutputStream fstr;
+        final ZipOutputStream publicZipOutStream;
+
+        if (publicZipFile == null) {
+            fstr = null;
+            publicZipOutStream = null;
+        } else {
+            fstr = new FileOutputStream(publicZipFile);
+            publicZipOutStream = new ZipOutputStream(fstr);
+        }
+
+        int size = 0;
+
         try {
             final ZipFile privateZip = new ZipFile(packagePath);
             try {
@@ -219,25 +230,29 @@
                     if ("AndroidManifest.xml".equals(zipEntryName)
                             || "resources.arsc".equals(zipEntryName)
                             || zipEntryName.startsWith("res/")) {
-                        copyZipEntry(zipEntry, privateZip, publicZipOutStream);
+                        size += zipEntry.getSize();
+                        if (publicZipFile != null) {
+                            copyZipEntry(zipEntry, privateZip, publicZipOutStream);
+                        }
                     }
                 }
             } finally {
-                try {
-                    privateZip.close();
-                } catch (IOException e) {
-                }
+                try { privateZip.close(); } catch (IOException e) {}
             }
 
-            publicZipOutStream.finish();
-            publicZipOutStream.flush();
-            FileUtils.sync(fstr);
-            publicZipOutStream.close();
-            FileUtils.setPermissions(publicZipFile.getAbsolutePath(), FileUtils.S_IRUSR
-                    | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IROTH, -1, -1);
+            if (publicZipFile != null) {
+                publicZipOutStream.finish();
+                publicZipOutStream.flush();
+                FileUtils.sync(fstr);
+                publicZipOutStream.close();
+                FileUtils.setPermissions(publicZipFile.getAbsolutePath(), FileUtils.S_IRUSR
+                        | FileUtils.S_IWUSR | FileUtils.S_IRGRP | FileUtils.S_IROTH, -1, -1);
+            }
         } finally {
             IoUtils.closeQuietly(publicZipOutStream);
         }
+
+        return size;
     }
 
     private static void copyZipEntry(ZipEntry zipEntry, ZipFile inZipFile,
@@ -265,4 +280,18 @@
             IoUtils.closeQuietly(data);
         }
     }
+
+    public static boolean fixSdPermissions(String cid, int gid, String filename) {
+        try {
+            int rc = getMountService().fixPermissionsSecureContainer(cid, gid, filename);
+            if (rc != StorageResultCode.OperationSucceeded) {
+                Log.i(TAG, "Failed to fixperms container " + cid);
+                return false;
+            }
+            return true;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to fixperms container " + cid + " with exception " + e);
+        }
+        return false;
+    }
 }
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index dd59444..5507047 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -322,6 +322,7 @@
         const float sy = scaledHeight / float(decoded->height());
 
         bitmap->setConfig(decoded->getConfig(), scaledWidth, scaledHeight);
+        bitmap->setIsOpaque(decoded->isOpaque());
         bitmap->allocPixels(&javaAllocator, NULL);
         bitmap->eraseColor(0);
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e1b9d55..60d2159 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1658,16 +1658,6 @@
                 android:excludeFromRecents="true"
                 android:process=":ui">
         </activity>
-        <activity android:name="com.android.internal.app.RingtonePickerActivity"
-                android:theme="@style/Theme.Holo.Dialog.Alert"
-                android:excludeFromRecents="true"
-                android:multiprocess="true"
-                android:process=":ui">
-            <intent-filter>
-                <action android:name="android.intent.action.RINGTONE_PICKER" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
-        </activity>
 
         <activity android:name="android.accounts.ChooseAccountActivity"
                 android:excludeFromRecents="true"
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 49c8893..7fa7658 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -21,7 +21,7 @@
      for different hardware and product builds. -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- see comment in values/config.xml -->
-    <integer name="config_longPressOnPowerBehavior">1</integer>
+    <integer name="config_longPressOnPowerBehavior">2</integer>
 
     <!-- Enable lockscreen rotation -->
     <bool name="config_enableLockScreenRotation">true</bool>
diff --git a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
index 27112a6..7ad35d0 100644
--- a/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageHelperTests.java
@@ -81,7 +81,8 @@
     public void testMountAndPullSdCard() {
         try {
             fullId = PREFIX;
-            fullId2 = PackageHelper.createSdDir(1024, fullId, "none", android.os.Process.myUid());
+            fullId2 = PackageHelper.createSdDir(1024, fullId, "none", android.os.Process.myUid(),
+                    true);
 
             Log.d(TAG,PackageHelper.getSdDir(fullId));
             PackageHelper.unMountSdDir(fullId);
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 580b4da..8a5f8bb 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -309,9 +309,7 @@
     private static final int INSTALL_LOC_ERR = -1;
     private int getInstallLoc(int flags, int expInstallLocation, long pkgLen) {
         // Flags explicitly over ride everything else.
-        if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 ) {
-            return INSTALL_LOC_INT;
-        } else if ((flags & PackageManager.INSTALL_EXTERNAL) != 0 ) {
+        if ((flags & PackageManager.INSTALL_EXTERNAL) != 0 ) {
             return INSTALL_LOC_SD;
         } else if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
             return INSTALL_LOC_INT;
@@ -380,61 +378,76 @@
             String publicSrcPath = publicSrcDir.getParent();
             long pkgLen = new File(info.sourceDir).length();
 
-            if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
-                assertTrue((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
-                assertEquals(srcPath, drmInstallPath);
-                assertEquals(publicSrcPath, appInstallPath);
-                assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
-            } else {
-                assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
-                int rLoc = getInstallLoc(flags, expInstallLocation, pkgLen);
-                if (rLoc == INSTALL_LOC_INT) {
-                    assertEquals(srcPath, appInstallPath);
-                    assertEquals(publicSrcPath, appInstallPath);
-                    assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
-                    assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
-
-                    // Make sure the native library dir is not a symlink
-                    final File nativeLibDir = new File(info.nativeLibraryDir);
-                    assertTrue("Native library dir should exist at " + info.nativeLibraryDir,
-                            nativeLibDir.exists());
-                    try {
-                        assertEquals("Native library dir should not be a symlink",
-                                info.nativeLibraryDir,
-                                nativeLibDir.getCanonicalPath());
-                    } catch (IOException e) {
-                        fail("Can't read " + nativeLibDir.getPath());
-                    }
-                } else if (rLoc == INSTALL_LOC_SD){
-                    assertTrue("Application flags (" + info.flags
-                            + ") should contain FLAG_EXTERNAL_STORAGE",
-                            (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
+            int rLoc = getInstallLoc(flags, expInstallLocation, pkgLen);
+            if (rLoc == INSTALL_LOC_INT) {
+                if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
+                    assertTrue("The application should be installed forward locked",
+                            (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
                     assertTrue("The APK path (" + srcPath + ") should start with "
-                            + SECURE_CONTAINERS_PREFIX, srcPath
-                            .startsWith(SECURE_CONTAINERS_PREFIX));
+                            + SECURE_CONTAINERS_PREFIX,
+                            srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
                     assertTrue("The public APK path (" + publicSrcPath + ") should start with "
-                            + SECURE_CONTAINERS_PREFIX, publicSrcPath
-                            .startsWith(SECURE_CONTAINERS_PREFIX));
+                            + SECURE_CONTAINERS_PREFIX,
+                            publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
                     assertTrue("The native library path (" + info.nativeLibraryDir
                             + ") should start with " + SECURE_CONTAINERS_PREFIX,
                             info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
-
-                    // Make sure the native library in /data/data/<app>/lib is a
-                    // symlink to the ASEC
-                    final File nativeLibSymLink = new File(info.dataDir, "lib");
-                    assertTrue("Native library symlink should exist at " + nativeLibSymLink.getPath(),
-                            nativeLibSymLink.exists());
-                    try {
-                        assertEquals(nativeLibSymLink.getPath() + " should be a symlink to "
-                                + info.nativeLibraryDir, info.nativeLibraryDir, nativeLibSymLink
-                                .getCanonicalPath());
-                    } catch (IOException e) {
-                        fail("Can't read " + nativeLibSymLink.getPath());
-                    }
                 } else {
-                    // TODO handle error. Install should have failed.
-                    fail("Install should have failed");
+                    assertFalse((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
+                    assertEquals(srcPath, appInstallPath);
+                    assertEquals(publicSrcPath, appInstallPath);
+                    assertTrue(info.nativeLibraryDir.startsWith(dataDir.getPath()));
                 }
+                assertFalse((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
+
+                // Make sure the native library dir is not a symlink
+                final File nativeLibDir = new File(info.nativeLibraryDir);
+                assertTrue("Native library dir should exist at " + info.nativeLibraryDir,
+                        nativeLibDir.exists());
+                try {
+                    assertEquals("Native library dir should not be a symlink",
+                            info.nativeLibraryDir,
+                            nativeLibDir.getCanonicalPath());
+                } catch (IOException e) {
+                    fail("Can't read " + nativeLibDir.getPath());
+                }
+            } else if (rLoc == INSTALL_LOC_SD){
+                if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
+                    assertTrue("The application should be installed forward locked",
+                            (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
+                } else {
+                    assertFalse("The application should not be installed forward locked",
+                            (info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0);
+                }
+                assertTrue("Application flags (" + info.flags
+                        + ") should contain FLAG_EXTERNAL_STORAGE",
+                        (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0);
+                // Might need to check:
+                // ((info.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0)
+                assertTrue("The APK path (" + srcPath + ") should start with "
+                        + SECURE_CONTAINERS_PREFIX, srcPath.startsWith(SECURE_CONTAINERS_PREFIX));
+                assertTrue("The public APK path (" + publicSrcPath + ") should start with "
+                        + SECURE_CONTAINERS_PREFIX,
+                        publicSrcPath.startsWith(SECURE_CONTAINERS_PREFIX));
+                assertTrue("The native library path (" + info.nativeLibraryDir
+                        + ") should start with " + SECURE_CONTAINERS_PREFIX,
+                        info.nativeLibraryDir.startsWith(SECURE_CONTAINERS_PREFIX));
+
+                // Make sure the native library in /data/data/<app>/lib is a
+                // symlink to the ASEC
+                final File nativeLibSymLink = new File(info.dataDir, "lib");
+                assertTrue("Native library symlink should exist at " + nativeLibSymLink.getPath(),
+                        nativeLibSymLink.exists());
+                try {
+                    assertEquals(nativeLibSymLink.getPath() + " should be a symlink to "
+                            + info.nativeLibraryDir, info.nativeLibraryDir, nativeLibSymLink
+                            .getCanonicalPath());
+                } catch (IOException e) {
+                    fail("Can't read " + nativeLibSymLink.getPath());
+                }
+            } else {
+                // TODO handle error. Install should have failed.
+                fail("Install should have failed");
             }
         } catch (NameNotFoundException e) {
             failStr("failed with exception : " + e);
@@ -1774,15 +1787,17 @@
     }
 
     /*
-     * Install an app with both external and forward-lock flags set. should fail
+     * Install an app with both external and forward-lock flags set.
      */
     @LargeTest
     public void testFlagEF() {
-        installFromRawResource("install.apk", R.raw.install,
-                PackageManager.INSTALL_FORWARD_LOCK | PackageManager.INSTALL_EXTERNAL,
-                false,
-                true, PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
-                PackageInfo.INSTALL_LOCATION_AUTO);
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        sampleInstallFromRawResource(PackageManager.INSTALL_FORWARD_LOCK
+                | PackageManager.INSTALL_EXTERNAL, true);
     }
 
     /*
@@ -1899,15 +1914,20 @@
                 PackageManager.INSTALL_FORWARD_LOCK,
                 true,
                 false, -1,
-                PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
+                PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
     }
 
     /*
      * Install an app with fwd locked flag set and install location set to
-     * preferExternal. should install internally.
+     * preferExternal. Should install externally.
      */
     @LargeTest
     public void testFlagFManifestE() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         installFromRawResource("install.apk", R.raw.install_loc_sdcard,
                 PackageManager.INSTALL_FORWARD_LOCK,
                 true,
@@ -1916,11 +1936,16 @@
     }
 
     /*
-     * Install an app with fwd locked flag set and install location set to
-     * auto. should install internally.
+     * Install an app with fwd locked flag set and install location set to auto.
+     * should install externally.
      */
     @LargeTest
     public void testFlagFManifestA() {
+        // Do not run on devices with emulated external storage.
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         installFromRawResource("install.apk", R.raw.install_loc_auto,
                 PackageManager.INSTALL_FORWARD_LOCK,
                 true,
diff --git a/core/tests/coretests/src/android/os/storage/AsecTests.java b/core/tests/coretests/src/android/os/storage/AsecTests.java
index 5efbd88..abb8eae 100755
--- a/core/tests/coretests/src/android/os/storage/AsecTests.java
+++ b/core/tests/coretests/src/android/os/storage/AsecTests.java
@@ -27,20 +27,13 @@
 import java.io.File;
 import java.io.FileOutputStream;
 
-import junit.framework.Assert;
-
 public class AsecTests extends AndroidTestCase {
+    private static final String SECURE_CONTAINER_PREFIX = "com.android.unittests.AsecTests.";
     private static final boolean localLOGV = true;
     public static final String TAG="AsecTests";
 
-    void failStr(String errMsg) {
-        Log.w(TAG, "errMsg="+errMsg);
-    }
-
-    void failStr(Exception e) {
-        Log.w(TAG, "e.getMessage="+e.getMessage());
-        Log.w(TAG, "e="+e);
-    }
+    private static final String FS_FAT = "fat";
+    private static final String FS_EXT4 = "ext4";
 
     @Override
     protected void setUp() throws Exception {
@@ -61,7 +54,9 @@
         String[] containers = ms.getSecureContainerList();
 
         for (int i = 0; i < containers.length; i++) {
-            if (containers[i].startsWith("com.android.unittests.AsecTests.")) {
+            if (containers[i].startsWith(SECURE_CONTAINER_PREFIX)) {
+                if (localLOGV)
+                    Log.i(TAG, "Cleaning: " + containers[i]);
                 ms.destroySecureContainer(containers[i], true);
             }
         }
@@ -70,7 +65,7 @@
     private boolean containerExists(String localId) throws RemoteException {
         IMountService ms = getMs();
         String[] containers = ms.getSecureContainerList();
-        String fullId = "com.android.unittests.AsecTests." + localId;
+        String fullId = SECURE_CONTAINER_PREFIX + localId;
 
         for (int i = 0; i < containers.length; i++) {
             if (containers[i].equals(fullId)) {
@@ -80,50 +75,52 @@
         return false;
     }
 
-    private int createContainer(String localId, int size, String key) throws RemoteException {
-        Assert.assertTrue(isMediaMounted());
-        String fullId = "com.android.unittests.AsecTests." + localId;
+    private int createContainer(String localId, int size, String key, String filesystem,
+            boolean isExternal) throws Exception {
+        assertTrue("Media should be mounted", isMediaMounted());
+        String fullId = SECURE_CONTAINER_PREFIX + localId;
 
         IMountService ms = getMs();
-        return ms.createSecureContainer(fullId, size, "fat", key, android.os.Process.myUid());
+        return ms.createSecureContainer(fullId, size, filesystem, key, android.os.Process.myUid(),
+                isExternal);
     }
 
-    private int mountContainer(String localId, String key) throws RemoteException {
-        Assert.assertTrue(isMediaMounted());
-        String fullId = "com.android.unittests.AsecTests." + localId;
+    private int mountContainer(String localId, String key) throws Exception {
+        assertTrue("Media should be mounted", isMediaMounted());
+        String fullId = SECURE_CONTAINER_PREFIX + localId;
 
         IMountService ms = getMs();
         return ms.mountSecureContainer(fullId, key, android.os.Process.myUid());
     }
 
-    private int renameContainer(String localId1, String localId2) throws RemoteException {
-        Assert.assertTrue(isMediaMounted());
-        String fullId1 = "com.android.unittests.AsecTests." + localId1;
-        String fullId2 = "com.android.unittests.AsecTests." + localId2;
+    private int renameContainer(String localId1, String localId2) throws Exception {
+        assertTrue("Media should be mounted", isMediaMounted());
+        String fullId1 = SECURE_CONTAINER_PREFIX + localId1;
+        String fullId2 = SECURE_CONTAINER_PREFIX + localId2;
 
         IMountService ms = getMs();
         return ms.renameSecureContainer(fullId1, fullId2);
     }
 
-    private int unmountContainer(String localId, boolean force) throws RemoteException {
-        Assert.assertTrue(isMediaMounted());
-        String fullId = "com.android.unittests.AsecTests." + localId;
+    private int unmountContainer(String localId, boolean force) throws Exception {
+        assertTrue("Media should be mounted", isMediaMounted());
+        String fullId = SECURE_CONTAINER_PREFIX + localId;
 
         IMountService ms = getMs();
         return ms.unmountSecureContainer(fullId, force);
     }
 
-    private int destroyContainer(String localId, boolean force) throws RemoteException {
-        Assert.assertTrue(isMediaMounted());
-        String fullId = "com.android.unittests.AsecTests." + localId;
+    private int destroyContainer(String localId, boolean force) throws Exception {
+        assertTrue("Media should be mounted", isMediaMounted());
+        String fullId = SECURE_CONTAINER_PREFIX + localId;
 
         IMountService ms = getMs();
         return ms.destroySecureContainer(fullId, force);
     }
 
-    private boolean isContainerMounted(String localId) throws RemoteException {
-        Assert.assertTrue(isMediaMounted());
-        String fullId = "com.android.unittests.AsecTests." + localId;
+    private boolean isContainerMounted(String localId) throws Exception {
+        assertTrue("Media should be mounted", isMediaMounted());
+        String fullId = SECURE_CONTAINER_PREFIX + localId;
 
         IMountService ms = getMs();
         return ms.isSecureContainerMounted(fullId);
@@ -139,248 +136,392 @@
         return null;
     }
 
-    private boolean isMediaMounted() {
-        try {
+    private boolean isMediaMounted() throws Exception {
         String mPath = Environment.getExternalStorageDirectory().toString();
         String state = getMs().getVolumeState(mPath);
         return Environment.MEDIA_MOUNTED.equals(state);
-        } catch (RemoteException e) {
-            failStr(e);
-            return false;
-        }
     }
 
-    public void testCreateContainer() {
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testCreateContainer", 4, "none"));
-            Assert.assertEquals(true, containerExists("testCreateContainer"));
-        } catch (Exception e) {
-            failStr(e);
+
+    /*
+     * CREATE
+     */
+
+    public void test_Fat_External_Create_Success() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
         }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateContainer", 4, "none", FS_FAT, true));
+        assertTrue(containerExists("testCreateContainer"));
     }
 
-    public void testCreateMinSizeContainer() {
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testCreateContainer", 1, "none"));
-            Assert.assertEquals(true, containerExists("testCreateContainer"));
-        } catch (Exception e) {
-            failStr(e);
+    public void test_Ext4_External_Create_Success() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
         }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateContainer", 4, "none", FS_EXT4, true));
+        assertTrue(containerExists("testCreateContainer"));
     }
 
-    public void testCreateZeroSizeContainer() {
-        try {
-            Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
-                    createContainer("testCreateZeroContainer", 0, "none"));
-        } catch (Exception e) {
-            failStr(e);
-        }
+    public void test_Fat_Internal_Create_Success() throws Exception {
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateContainer", 4, "none", FS_FAT, false));
+        assertTrue(containerExists("testCreateContainer"));
     }
 
-    public void testCreateDuplicateContainer() {
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testCreateDupContainer", 4, "none"));
-
-            Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
-                    createContainer("testCreateDupContainer", 4, "none"));
-        } catch (Exception e) {
-            failStr(e);
-        }
+    public void test_Ext4_Internal_Create_Success() throws Exception {
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateContainer", 4, "none", FS_EXT4, false));
+        assertTrue(containerExists("testCreateContainer"));
     }
 
-    public void testDestroyContainer() {
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testDestroyContainer", 4, "none"));
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    destroyContainer("testDestroyContainer", false));
-        } catch (Exception e) {
-            failStr(e);
+
+    /*
+     * CREATE MIN SIZE
+     */
+
+    public void test_Fat_External_CreateMinSize_Success() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
         }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateContainer", 1, "none", FS_FAT, true));
+        assertTrue(containerExists("testCreateContainer"));
     }
 
-    public void testMountContainer() {
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testMountContainer", 4, "none"));
-
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    unmountContainer("testMountContainer", false));
-
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    mountContainer("testMountContainer", "none"));
-        } catch (Exception e) {
-            failStr(e);
+    public void test_Ext4_External_CreateMinSize_Success() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
         }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateContainer", 1, "none", FS_EXT4, true));
+        assertTrue(containerExists("testCreateContainer"));
     }
 
-    public void testMountBadKey() {
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testMountBadKey", 4, "00000000000000000000000000000000"));
-
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    unmountContainer("testMountBadKey", false));
-
-            Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
-                    mountContainer("testMountContainer", "000000000000000000000000000000001"));
-
-            Assert.assertEquals(StorageResultCode.OperationFailedInternalError,
-                    mountContainer("testMountContainer", "none"));
-        } catch (Exception e) {
-            failStr(e);
-        }
+    public void test_Fat_Internal_CreateMinSize_Success() throws Exception {
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateContainer", 1, "none", FS_FAT, false));
+        assertTrue(containerExists("testCreateContainer"));
     }
 
-    public void testNonExistPath() {
+    public void test_Ext4_Internal_CreateMinSize_Success() throws Exception {
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateContainer", 1, "none", FS_EXT4, false));
+        assertTrue(containerExists("testCreateContainer"));
+    }
+
+
+    /*
+     * CREATE ZERO SIZE - FAIL CASE
+     */
+
+    public void test_Fat_External_CreateZeroSize_Failure() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationFailedInternalError,
+                createContainer("testCreateZeroContainer", 0, "none", FS_FAT, true));
+    }
+
+    public void test_Ext4_External_CreateZeroSize_Failure() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationFailedInternalError,
+                createContainer("testCreateZeroContainer", 0, "none", FS_EXT4, true));
+    }
+
+    public void test_Fat_Internal_CreateZeroSize_Failure() throws Exception {
+        assertEquals(StorageResultCode.OperationFailedInternalError,
+                createContainer("testCreateZeroContainer", 0, "none", FS_FAT, false));
+    }
+
+    public void test_Ext4_Internal_CreateZeroSize_Failure() throws Exception {
+        assertEquals(StorageResultCode.OperationFailedInternalError,
+                createContainer("testCreateZeroContainer", 0, "none", FS_EXT4, false));
+    }
+
+
+    /*
+     * CREATE DUPLICATE - FAIL CASE
+     */
+
+    public void test_Fat_External_CreateDuplicate_Failure() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateDupContainer", 4, "none", FS_FAT, true));
+
+        assertEquals(StorageResultCode.OperationFailedInternalError,
+                createContainer("testCreateDupContainer", 4, "none", FS_FAT, true));
+    }
+
+    public void test_Ext4_External_CreateDuplicate_Failure() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateDupContainer", 4, "none", FS_EXT4, true));
+
+        assertEquals(StorageResultCode.OperationFailedInternalError,
+                createContainer("testCreateDupContainer", 4, "none", FS_EXT4, true));
+    }
+
+    public void test_Fat_Internal_CreateDuplicate_Failure() throws Exception {
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateDupContainer", 4, "none", FS_FAT, false));
+
+        assertEquals(StorageResultCode.OperationFailedInternalError,
+                createContainer("testCreateDupContainer", 4, "none", FS_FAT, false));
+    }
+
+    public void test_Ext4_Internal_CreateDuplicate_Failure() throws Exception {
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testCreateDupContainer", 4, "none", FS_EXT4, false));
+
+        assertEquals(StorageResultCode.OperationFailedInternalError,
+                createContainer("testCreateDupContainer", 4, "none", FS_EXT4, false));
+    }
+
+
+    /*
+     * DESTROY
+     */
+
+    public void test_Fat_External_Destroy_Success() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testDestroyContainer", 4, "none", FS_FAT, true));
+        assertEquals(StorageResultCode.OperationSucceeded,
+                destroyContainer("testDestroyContainer", false));
+    }
+
+    public void test_Ext4_External_Destroy_Success() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testDestroyContainer", 4, "none", FS_EXT4, true));
+        assertEquals(StorageResultCode.OperationSucceeded,
+                destroyContainer("testDestroyContainer", false));
+    }
+
+    public void test_Fat_Internal_Destroy_Success() throws Exception {
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testDestroyContainer", 4, "none", FS_FAT, false));
+        assertEquals(StorageResultCode.OperationSucceeded,
+                destroyContainer("testDestroyContainer", false));
+    }
+
+    public void test_Ext4_Internal_Destroy_Success() throws Exception {
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testDestroyContainer", 4, "none", FS_EXT4, false));
+        assertEquals(StorageResultCode.OperationSucceeded,
+                destroyContainer("testDestroyContainer", false));
+    }
+
+
+    /*
+     * MOUNT
+     */
+
+    public void test_Fat_External_Mount() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testMountContainer", 4, "none", FS_FAT, true));
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                unmountContainer("testMountContainer", false));
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                mountContainer("testMountContainer", "none"));
+    }
+
+
+    /*
+     * MOUNT BAD KEY - FAIL CASE
+     */
+
+    public void test_Fat_External_MountBadKey_Failure() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testMountBadKey", 4, "00000000000000000000000000000000", FS_FAT,
+                        true));
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                unmountContainer("testMountBadKey", false));
+
+        assertEquals(StorageResultCode.OperationFailedInternalError,
+                mountContainer("testMountContainer", "000000000000000000000000000000001"));
+
+        assertEquals(StorageResultCode.OperationFailedInternalError,
+                mountContainer("testMountContainer", "none"));
+    }
+
+
+    public void test_Fat_External_UnmountBusy_Success() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         IMountService ms = getMs();
-        try {
-            String path = ms.getSecureContainerPath("jparks.broke.it");
-            failStr(path);
-        } catch (IllegalArgumentException e) {
-        } catch (Exception e) {
-            failStr(e);
-        }
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testUnmountBusyContainer", 4, "none", FS_FAT, true));
+
+        String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX
+                + "testUnmountBusyContainer");
+
+        File f = new File(path, "reference");
+        FileOutputStream fos = new FileOutputStream(f);
+
+        assertEquals(StorageResultCode.OperationFailedStorageBusy,
+                unmountContainer("testUnmountBusyContainer", false));
+
+        fos.close();
+        assertEquals(StorageResultCode.OperationSucceeded,
+                unmountContainer("testUnmountBusyContainer", false));
     }
 
-    public void testUnmountBusyContainer() {
+    public void test_Fat_External_DestroyBusy() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         IMountService ms = getMs();
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testUnmountBusyContainer", 4, "none"));
 
-            String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer");
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testDestroyBusyContainer", 4, "none", FS_FAT, true));
 
-            File f = new File(path, "reference");
-            FileOutputStream fos = new FileOutputStream(f);
+        String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX
+                + "testDestroyBusyContainer");
 
-            Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy,
-                    unmountContainer("testUnmountBusyContainer", false));
+        File f = new File(path, "reference");
+        FileOutputStream fos = new FileOutputStream(f);
 
-            fos.close();
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    unmountContainer("testUnmountBusyContainer", false));
-        } catch (Exception e) {
-            failStr(e);
-        }
+        assertEquals(StorageResultCode.OperationFailedStorageBusy,
+                destroyContainer("testDestroyBusyContainer", false));
+
+        fos.close();
+        assertEquals(StorageResultCode.OperationSucceeded,
+                destroyContainer("testDestroyBusyContainer", false));
     }
 
-    public void testDestroyBusyContainer() {
+    public void test_Fat_External_Rename_Success() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testRenameContainer.1", 4, "none", FS_FAT, true));
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                unmountContainer("testRenameContainer.1", false));
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                renameContainer("testRenameContainer.1", "testRenameContainer.2"));
+
+        assertFalse(containerExists("testRenameContainer.1"));
+        assertTrue(containerExists("testRenameContainer.2"));
+    }
+
+    public void test_Fat_External_RenameSrcMounted_Failure() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testRenameContainer.1", 4, "none", FS_FAT, true));
+
+        assertEquals(StorageResultCode.OperationFailedStorageMounted,
+                renameContainer("testRenameContainer.1", "testRenameContainer.2"));
+    }
+
+    public void test_Fat_External_RenameDstMounted_Failure() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testRenameContainer.1", 4, "none", FS_FAT, true));
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                unmountContainer("testRenameContainer.1", false));
+
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testRenameContainer.2", 4, "none", FS_FAT, true));
+
+        assertEquals(StorageResultCode.OperationFailedStorageMounted,
+                renameContainer("testRenameContainer.1", "testRenameContainer.2"));
+    }
+
+    public void test_Fat_External_Size_Success() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         IMountService ms = getMs();
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testDestroyBusyContainer", 4, "none"));
+        assertEquals(StorageResultCode.OperationSucceeded,
+                createContainer("testContainerSize", 1, "none", FS_FAT, true));
+        String path = ms.getSecureContainerPath(SECURE_CONTAINER_PREFIX + "testContainerSize");
 
-            String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testDestroyBusyContainer");
-
-            File f = new File(path, "reference");
-            FileOutputStream fos = new FileOutputStream(f);
-
-            Assert.assertEquals(StorageResultCode.OperationFailedStorageBusy,
-                    destroyContainer("testDestroyBusyContainer", false));
-
-            fos.close();
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    destroyContainer("testDestroyBusyContainer", false));
-        } catch (Exception e) {
-            failStr(e);
+        byte[] buf = new byte[4096];
+        File f = new File(path, "reference");
+        FileOutputStream fos = new FileOutputStream(f);
+        for (int i = 0; i < (1024 * 1024); i += buf.length) {
+            fos.write(buf);
         }
+        fos.close();
     }
 
-    public void testRenameContainer() {
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testRenameContainer.1", 4, "none"));
-
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    unmountContainer("testRenameContainer.1", false));
-
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    renameContainer("testRenameContainer.1", "testRenameContainer.2"));
-
-            Assert.assertEquals(false, containerExists("testRenameContainer.1"));
-            Assert.assertEquals(true, containerExists("testRenameContainer.2"));
-        } catch (Exception e) {
-            failStr(e);
-        }
-    }
-
-    public void testRenameSrcMountedContainer() {
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testRenameContainer.1", 4, "none"));
-
-            Assert.assertEquals(StorageResultCode.OperationFailedStorageMounted,
-                    renameContainer("testRenameContainer.1", "testRenameContainer.2"));
-        } catch (Exception e) {
-            failStr(e);
-        }
-    }
-
-    public void testRenameDstMountedContainer() {
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testRenameContainer.1", 4, "none"));
-
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    unmountContainer("testRenameContainer.1", false));
-
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testRenameContainer.2", 4, "none"));
-
-            Assert.assertEquals(StorageResultCode.OperationFailedStorageMounted,
-                    renameContainer("testRenameContainer.1", "testRenameContainer.2"));
-        } catch (Exception e) {
-            failStr(e);
-        }
-    }
-
-    public void testContainerSize() {
+    public void testGetSecureContainerPath_NonExistPath_Failure() throws Exception {
         IMountService ms = getMs();
-        try {
-            Assert.assertEquals(StorageResultCode.OperationSucceeded,
-                    createContainer("testContainerSize", 1, "none"));
-            String path = ms.getSecureContainerPath("com.android.unittests.AsecTests.testUnmountBusyContainer");
-
-            byte[] buf = new byte[4096];
-            File f = new File(path, "reference");
-            FileOutputStream fos = new FileOutputStream(f);
-            for (int i = 0; i < (1024 * 1024); i+= buf.length) {
-                fos.write(buf);
-            }
-            fos.close();
-        } catch (Exception e) {
-            failStr(e);
-        }
+        assertNull("Getting the path for an invalid container should return null",
+                ms.getSecureContainerPath("jparks.broke.it"));
     }
 
     /*------------ Tests for unmounting volume ---*/
     public final long MAX_WAIT_TIME=120*1000;
     public final long WAIT_TIME_INCR=20*1000;
-    boolean getMediaState() {
-        try {
+
+    boolean getMediaState() throws Exception {
         String mPath = Environment.getExternalStorageDirectory().toString();
         String state = getMs().getVolumeState(mPath);
         return Environment.MEDIA_MOUNTED.equals(state);
-        } catch (RemoteException e) {
-            return false;
-        }
     }
 
-    boolean mountMedia() {
+    boolean mountMedia() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return true;
+        }
+
         if (getMediaState()) {
             return true;
         }
-        try {
+
         String mPath = Environment.getExternalStorageDirectory().toString();
         int ret = getMs().mountVolume(mPath);
         return ret == StorageResultCode.OperationSucceeded;
-        } catch (RemoteException e) {
-            return false;
-        }
     }
 
     class StorageListener extends StorageEventListener {
@@ -410,10 +551,15 @@
         }
     }
 
-    private boolean unmountMedia() {
-        if (!getMediaState()) {
-            return true;
+    private void unmountMedia() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
         }
+
+        if (!getMediaState()) {
+            return;
+        }
+
         String path = Environment.getExternalStorageDirectory().toString();
         StorageListener observer = new StorageListener();
         StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
@@ -428,17 +574,15 @@
                     waitTime += WAIT_TIME_INCR;
                 }
                 if(!observer.isDone()) {
-                    throw new Exception("Timed out waiting for packageInstalled callback");
+                    fail("Timed out waiting for packageInstalled callback");
                 }
-                return true;
             }
-        } catch (Exception e) {
-            return false;
         } finally {
             sm.unregisterListener(observer);
         }
     }
-    public void testUnmount() {
+
+    public void testUnmount() throws Exception {
         boolean oldStatus = getMediaState();
         Log.i(TAG, "oldStatus="+oldStatus);
         try {
@@ -446,7 +590,7 @@
             if (!getMediaState()) {
                 mountMedia();
             }
-            assertTrue(unmountMedia());
+            unmountMedia();
         } finally {
             // Restore old status
             boolean currStatus = getMediaState();
@@ -472,7 +616,11 @@
      * This test invokes unmount multiple time and expects the call back
      * to be invoked just once.
      */
-    public void testUnmountMultiple() {
+    public void testUnmountMultiple() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         boolean oldStatus = getMediaState();
         StorageManager sm = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
         MultipleStorageLis observer = new MultipleStorageLis();
@@ -494,12 +642,10 @@
                     waitTime += WAIT_TIME_INCR;
                 }
                 if(!observer.isDone()) {
-                    failStr("Timed out waiting for packageInstalled callback");
+                    fail("Timed out waiting for packageInstalled callback");
                 }
             }
             assertEquals(observer.count, 1);
-        } catch (Exception e) {
-            failStr(e);
         } finally {
             sm.unregisterListener(observer);
             // Restore old status
@@ -514,7 +660,7 @@
             }
         }
     }
-    
+
     class ShutdownObserver extends  IMountShutdownObserver.Stub{
         private boolean doneFlag = false;
         int statusCode;
@@ -536,28 +682,26 @@
         
     }
 
-    boolean invokeShutdown() {
+    void invokeShutdown() throws Exception {
         IMountService ms = getMs();
         ShutdownObserver observer = new ShutdownObserver();
         synchronized (observer) {
-            try {
-                ms.shutdown(observer);
-                return true;
-            } catch (RemoteException e) {
-                failStr(e);
-            }
+            ms.shutdown(observer);
         }
-        return false;
     }
 
-    public void testShutdown() {
+    public void testShutdown() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         boolean oldStatus = getMediaState();
         try {
             // Mount media firsts
             if (!getMediaState()) {
                 mountMedia();
             }
-            assertTrue(invokeShutdown());
+            invokeShutdown();
         } finally {
             // Restore old status
             boolean currStatus = getMediaState();
@@ -576,7 +720,11 @@
      * This test invokes unmount multiple time and expects the call back
      * to be invoked just once.
      */
-    public void testShutdownMultiple() {
+    public void testShutdownMultiple() throws Exception {
+        if (Environment.isExternalStorageEmulated()) {
+            return;
+        }
+
         boolean oldStatus = getMediaState();
         try {
             // Mount media firsts
@@ -586,13 +734,9 @@
             IMountService ms = getMs();
             ShutdownObserver observer = new ShutdownObserver();
             synchronized (observer) {
-                try {
-                    ms.shutdown(observer);
-                    for (int i = 0; i < 4; i++) {
-                        ms.shutdown(null);
-                    }
-                } catch (RemoteException e) {
-                    failStr(e);
+                ms.shutdown(observer);
+                for (int i = 0; i < 4; i++) {
+                    ms.shutdown(null);
                 }
             }
         } finally {
diff --git a/data/fonts/DroidNaskh-Regular-Shift.ttf b/data/fonts/DroidNaskh-Regular-Shift.ttf
index bb9c70c..de475ca 100644
--- a/data/fonts/DroidNaskh-Regular-Shift.ttf
+++ b/data/fonts/DroidNaskh-Regular-Shift.ttf
Binary files differ
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 768ee5e..225c11a 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -300,7 +300,7 @@
 
 
 # key 352 "KEY_OK"
-# key 353 "KEY_SELECT"
+key 353   DPAD_CENTER
 # key 354 "KEY_GOTO"
 # key 355 "KEY_CLEAR"
 # key 356 "KEY_POWER2"
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index f8bb70a..da2192f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -190,8 +190,17 @@
     while ((status = glGetError()) != GL_NO_ERROR) {
         ALOGD("GL error from OpenGLRenderer: 0x%x", status);
         switch (status) {
+            case GL_INVALID_ENUM:
+                ALOGE("  GL_INVALID_ENUM");
+                break;
+            case GL_INVALID_VALUE:
+                ALOGE("  GL_INVALID_VALUE");
+                break;
+            case GL_INVALID_OPERATION:
+                ALOGE("  GL_INVALID_OPERATION");
+                break;
             case GL_OUT_OF_MEMORY:
-                ALOGE("  OpenGLRenderer is out of memory!");
+                ALOGE("  Out of memory!");
                 break;
         }
     }
@@ -267,17 +276,24 @@
             Functor* f = functors.itemAt(i);
             result |= (*f)(DrawGlInfo::kModeProcess, &info);
 
-            if (result != DrawGlInfo::kStatusDone) {
+            if (result & DrawGlInfo::kStatusDraw) {
                 Rect localDirty(info.dirtyLeft, info.dirtyTop, info.dirtyRight, info.dirtyBottom);
                 dirty.unionWith(localDirty);
+            }
 
-                if (result & DrawGlInfo::kStatusInvoke) {
-                    mFunctors.add(f);
-                }
+            if (result & DrawGlInfo::kStatusInvoke) {
+                mFunctors.add(f);
             }
         }
     }
 
+    // Restore state possibly changed by the functors in process mode
+    GLboolean value;
+    glGetBooleanv(GL_BLEND, &value);
+    mCaches.blend = value;
+
+    mCaches.activeTexture(0);
+
     return result;
 }
 
@@ -2787,6 +2803,7 @@
 void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
         ProgramDescription& description, bool swapSrcDst) {
     blend = blend || mode != SkXfermode::kSrcOver_Mode;
+
     if (blend) {
         // These blend modes are not supported by OpenGL directly and have
         // to be implemented using shaders. Since the shader will perform
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 41d5c32..012e095 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -47,7 +47,6 @@
 
     private final Context mContext;
     private long mVolumeKeyUpTime;
-    private int  mVolumeControlStream = -1;
     private final boolean mUseMasterVolume;
     private static String TAG = "AudioManager";
 
@@ -304,13 +303,6 @@
     public static final int FLAG_VIBRATE = 1 << 4;
 
     /**
-     * forces use of specified stream
-     * @hide
-     */
-    public static final int FLAG_FORCE_STREAM = 1 << 5;
-
-
-    /**
      * Ringer mode that will be silent and will not vibrate. (This overrides the
      * vibrate setting.)
      *
@@ -458,10 +450,6 @@
                                     : ADJUST_LOWER,
                             flags);
                 } else {
-                    if (mVolumeControlStream != -1) {
-                        stream = mVolumeControlStream;
-                        flags |= FLAG_FORCE_STREAM;
-                    }
                     adjustSuggestedStreamVolume(
                             keyCode == KeyEvent.KEYCODE_VOLUME_UP
                                     ? ADJUST_RAISE
@@ -500,10 +488,6 @@
                     }
                 } else {
                     int flags = FLAG_PLAY_SOUND;
-                    if (mVolumeControlStream != -1) {
-                        stream = mVolumeControlStream;
-                        flags |= FLAG_FORCE_STREAM;
-                    }
                     adjustSuggestedStreamVolume(
                             ADJUST_SAME,
                             stream,
@@ -943,7 +927,12 @@
      * @hide
      */
     public void forceVolumeControlStream(int streamType) {
-        mVolumeControlStream = streamType;
+        IAudioService service = getService();
+        try {
+            service.forceVolumeControlStream(streamType, mICallBack);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in forceVolumeControlStream", e);
+        }
     }
 
     /**
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 48d3712..dcf72cc 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -149,6 +149,7 @@
     private int mMode;
     // protects mRingerMode
     private final Object mSettingsLock = new Object();
+
     private boolean mMediaServerOk;
 
     private SoundPool mSoundPool;
@@ -343,6 +344,14 @@
     // Keyguard manager proxy
     private KeyguardManager mKeyguardManager;
 
+    // mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
+    // is controlled by Vol keys.
+    private int  mVolumeControlStream = -1;
+    private final Object mForceControlStreamLock = new Object();
+    // VolumePanel is currently the only client of forceVolumeControlStream() and runs in system
+    // server process so in theory it is not necessary to monitor the client death.
+    // However it is good to be ready for future evolutions.
+    private ForceControlStreamClient mForceControlStreamClient = null;
 
     ///////////////////////////////////////////////////////////////////////////
     // Construction
@@ -538,8 +547,8 @@
     public void adjustSuggestedStreamVolume(int direction, int suggestedStreamType, int flags) {
 
         int streamType;
-        if ((flags & AudioManager.FLAG_FORCE_STREAM) != 0) {
-            streamType = suggestedStreamType;
+        if (mVolumeControlStream != -1) {
+            streamType = mVolumeControlStream;
         } else {
             streamType = getActiveStreamType(suggestedStreamType);
         }
@@ -682,6 +691,57 @@
         sendVolumeUpdate(streamType, oldIndex, index, flags);
     }
 
+    /** @see AudioManager#forceVolumeControlStream(int) */
+    public void forceVolumeControlStream(int streamType, IBinder cb) {
+        synchronized(mForceControlStreamLock) {
+            mVolumeControlStream = streamType;
+            if (mVolumeControlStream == -1) {
+                if (mForceControlStreamClient != null) {
+                    mForceControlStreamClient.release();
+                    mForceControlStreamClient = null;
+                }
+            } else {
+                mForceControlStreamClient = new ForceControlStreamClient(cb);
+            }
+        }
+    }
+
+    private class ForceControlStreamClient implements IBinder.DeathRecipient {
+        private IBinder mCb; // To be notified of client's death
+
+        ForceControlStreamClient(IBinder cb) {
+            if (cb != null) {
+                try {
+                    cb.linkToDeath(this, 0);
+                } catch (RemoteException e) {
+                    // Client has died!
+                    Log.w(TAG, "ForceControlStreamClient() could not link to "+cb+" binder death");
+                    cb = null;
+                }
+            }
+            mCb = cb;
+        }
+
+        public void binderDied() {
+            synchronized(mForceControlStreamLock) {
+                Log.w(TAG, "SCO client died");
+                if (mForceControlStreamClient != this) {
+                    Log.w(TAG, "unregistered control stream client died");
+                } else {
+                    mForceControlStreamClient = null;
+                    mVolumeControlStream = -1;
+                }
+            }
+        }
+
+        public void release() {
+            if (mCb != null) {
+                mCb.unlinkToDeath(this, 0);
+                mCb = null;
+            }
+        }
+    }
+
     private int findVolumeDelta(int direction, int volume) {
         int delta = 0;
         if (direction == AudioManager.ADJUST_RAISE) {
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index b775095..0311c59 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -115,4 +115,6 @@
     void startBluetoothSco(IBinder cb);
 
     void stopBluetoothSco(IBinder cb);
+
+    void forceVolumeControlStream(int streamType, IBinder cb);
 }
diff --git a/media/java/android/media/MediaExtractor.java b/media/java/android/media/MediaExtractor.java
index 9fdb81f..5fe58a8 100644
--- a/media/java/android/media/MediaExtractor.java
+++ b/media/java/android/media/MediaExtractor.java
@@ -191,17 +191,33 @@
 
     /** Subsequent calls to {@link #readSampleData}, {@link #getSampleTrackIndex} and
      *  {@link #getSampleTime} only retrieve information for the subset of tracks
-     *  selected by the call below.
-     *  Selecting the same track multiple times has no effect, the track
+     *  selected.
+     *  Selecting the same track multiple times has no effect, the track is
      *  only selected once.
-     *  Media data will be returned in the order of their timestamps.
     */
     public native void selectTrack(int index);
 
-    /** All selected tracks seek near the requested time. The next sample
-     *  returned for each selected track will be a sync sample.
+    /** Subsequent calls to {@link #readSampleData}, {@link #getSampleTrackIndex} and
+     *  {@link #getSampleTime} only retrieve information for the subset of tracks
+     *  selected.
     */
-    public native void seekTo(long timeUs);
+    public native void unselectTrack(int index);
+
+    /** If possible, seek to a sync sample at or before the specified time */
+    public static final int SEEK_TO_PREVIOUS_SYNC       = 0;
+    /** If possible, seek to a sync sample at or after the specified time */
+    public static final int SEEK_TO_NEXT_SYNC           = 1;
+    /** If possible, seek to the sync sample closest to the specified time */
+    public static final int SEEK_TO_CLOSEST_SYNC        = 2;
+    /** If possible, seek to a sample closest to the specified time, which may
+      * NOT be a sync sample!
+      */
+    public static final int SEEK_TO_CLOSEST             = 3;
+
+    /** All selected tracks seek near the requested time according to the
+      * specified mode.
+      */
+    public native void seekTo(long timeUs, int mode);
 
     /** Advance to the next sample. Returns false if no more sample data
      *  is available (end of stream).
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 2175131..e0b33cd 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -257,6 +257,8 @@
         public static final int AAC_PLUS = 4;
         /** @hide enhanced AAC plus audio codec */
         public static final int EAAC_PLUS = 5;
+        /** AAC-ELD audio codec */
+        public static final int AAC_ELD = 6;
     }
 
     /**
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index c41901b..821a251b 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -31,17 +31,16 @@
 import android.mtp.MtpConstants;
 import android.net.Uri;
 import android.os.Environment;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.provider.MediaStore;
-import android.provider.MediaStore.Files.FileColumns;
-import android.provider.Settings;
 import android.provider.MediaStore.Audio;
+import android.provider.MediaStore.Audio.Playlists;
 import android.provider.MediaStore.Files;
+import android.provider.MediaStore.Files.FileColumns;
 import android.provider.MediaStore.Images;
 import android.provider.MediaStore.Video;
-import android.provider.MediaStore.Audio.Playlists;
+import android.provider.Settings;
 import android.sax.Element;
 import android.sax.ElementListener;
 import android.sax.RootElement;
@@ -56,10 +55,8 @@
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.Locale;
 
 import libcore.io.ErrnoException;
@@ -372,6 +369,14 @@
         }
     }
 
+    private static class PlaylistEntry {
+        String path;
+        long bestmatchid;
+        int bestmatchlevel;
+    }
+
+    private ArrayList<PlaylistEntry> mPlaylistEntries = new ArrayList<PlaylistEntry>();
+
     private MediaInserter mMediaInserter;
 
     private ArrayList<FileEntry> mPlayLists;
@@ -1492,93 +1497,83 @@
         return result;
     }
 
-    private boolean addPlayListEntry(String entry, String playListDirectory,
-            Uri uri, ContentValues values, int index, Cursor fileList) {
+    private boolean matchEntries(long rowId, String data) {
 
+        int len = mPlaylistEntries.size();
+        boolean done = true;
+        for (int i = 0; i < len; i++) {
+            PlaylistEntry entry = mPlaylistEntries.get(i);
+            if (entry.bestmatchlevel == Integer.MAX_VALUE) {
+                continue; // this entry has been matched already
+            }
+            done = false;
+            if (data.equalsIgnoreCase(entry.path)) {
+                entry.bestmatchid = rowId;
+                entry.bestmatchlevel = Integer.MAX_VALUE;
+                continue; // no need for path matching
+            }
+
+            int matchLength = matchPaths(data, entry.path);
+            if (matchLength > entry.bestmatchlevel) {
+                entry.bestmatchid = rowId;
+                entry.bestmatchlevel = matchLength;
+            }
+        }
+        return done;
+    }
+
+    private void cachePlaylistEntry(String line, String playListDirectory) {
+        PlaylistEntry entry = new PlaylistEntry();
         // watch for trailing whitespace
-        int entryLength = entry.length();
-        while (entryLength > 0 && Character.isWhitespace(entry.charAt(entryLength - 1))) entryLength--;
+        int entryLength = line.length();
+        while (entryLength > 0 && Character.isWhitespace(line.charAt(entryLength - 1))) entryLength--;
         // path should be longer than 3 characters.
         // avoid index out of bounds errors below by returning here.
-        if (entryLength < 3) return false;
-        if (entryLength < entry.length()) entry = entry.substring(0, entryLength);
+        if (entryLength < 3) return;
+        if (entryLength < line.length()) line = line.substring(0, entryLength);
 
         // does entry appear to be an absolute path?
         // look for Unix or DOS absolute paths
-        char ch1 = entry.charAt(0);
+        char ch1 = line.charAt(0);
         boolean fullPath = (ch1 == '/' ||
-                (Character.isLetter(ch1) && entry.charAt(1) == ':' && entry.charAt(2) == '\\'));
+                (Character.isLetter(ch1) && line.charAt(1) == ':' && line.charAt(2) == '\\'));
         // if we have a relative path, combine entry with playListDirectory
         if (!fullPath)
-            entry = playListDirectory + entry;
-
+            line = playListDirectory + line;
+        entry.path = line;
         //FIXME - should we look for "../" within the path?
 
-        // best matching MediaFile for the play list entry
-        FileEntry bestMatch = null;
+        mPlaylistEntries.add(entry);
+    }
 
-        // number of rightmost file/directory names for bestMatch
-        int bestMatchLength = 0;
-
-        if (fileList != null) {
-            int count = fileList.getCount();
-            // Backing up a little in the cursor helps when the files in the
-            // playlist are not in the same order as they are in the database
-            // but are still close.
-            fileList.move(-1000);
-            while(--count >= 0) {
-                if (!fileList.moveToNext()) {
-                    fileList.moveToFirst();
-                }
-                long rowId = fileList.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
-                String path = fileList.getString(FILES_PRESCAN_PATH_COLUMN_INDEX);
-                int format = fileList.getInt(FILES_PRESCAN_FORMAT_COLUMN_INDEX);
-                long lastModified = fileList.getLong(FILES_PRESCAN_DATE_MODIFIED_COLUMN_INDEX);
-
-                if (path.equalsIgnoreCase(entry)) {
-                    bestMatch = new FileEntry(rowId, path, lastModified, format);
-                    break;    // don't bother continuing search
-                }
-
-                int matchLength = matchPaths(path, entry);
-                if (matchLength > bestMatchLength) {
-                    bestMatch = new FileEntry(rowId, path, lastModified, format);
-                    bestMatchLength = matchLength;
-                }
+    private void processCachedPlaylist(Cursor fileList, ContentValues values, Uri playlistUri) {
+        fileList.moveToPosition(-1);
+        while (fileList.moveToNext()) {
+            long rowId = fileList.getLong(FILES_PRESCAN_ID_COLUMN_INDEX);
+            String data = fileList.getString(FILES_PRESCAN_PATH_COLUMN_INDEX);
+            if (matchEntries(rowId, data)) {
+                break;
             }
         }
 
-        if (bestMatch == null) {
-            return false;
-        }
-
-        try {
-            // check rowid is set. Rowid may be missing if it is inserted by bulkInsert().
-            if (bestMatch.mRowId == 0) {
-                Cursor c = mMediaProvider.query(mAudioUri, ID_PROJECTION,
-                        MediaStore.Files.FileColumns.DATA + "=?",
-                        new String[] { bestMatch.mPath }, null, null);
-                if (c != null) {
-                    if (c.moveToNext()) {
-                        bestMatch.mRowId = c.getLong(0);
-                    }
-                    c.close();
-                }
-                if (bestMatch.mRowId == 0) {
-                    return false;
+        int len = mPlaylistEntries.size();
+        int index = 0;
+        for (int i = 0; i < len; i++) {
+            PlaylistEntry entry = mPlaylistEntries.get(i);
+            if (entry.bestmatchlevel > 0) {
+                try {
+                    values.clear();
+                    values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(index));
+                    values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, Long.valueOf(entry.bestmatchid));
+                    mMediaProvider.insert(playlistUri, values);
+                    index++;
+                } catch (RemoteException e) {
+                    Log.e(TAG, "RemoteException in MediaScanner.processCachedPlaylist()", e);
+                    return;
                 }
             }
-            // OK, now we are ready to add this to the database
-            values.clear();
-            values.put(MediaStore.Audio.Playlists.Members.PLAY_ORDER, Integer.valueOf(index));
-            values.put(MediaStore.Audio.Playlists.Members.AUDIO_ID, Long.valueOf(bestMatch.mRowId));
-            mMediaProvider.insert(uri, values);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException in MediaScanner.addPlayListEntry()", e);
-            return false;
         }
-
-        return true;
+        mPlaylistEntries.clear();
     }
 
     private void processM3uPlayList(String path, String playListDirectory, Uri uri,
@@ -1590,16 +1585,16 @@
                 reader = new BufferedReader(
                         new InputStreamReader(new FileInputStream(f)), 8192);
                 String line = reader.readLine();
-                int index = 0;
+                mPlaylistEntries.clear();
                 while (line != null) {
                     // ignore comment lines, which begin with '#'
                     if (line.length() > 0 && line.charAt(0) != '#') {
-                        values.clear();
-                        if (addPlayListEntry(line, playListDirectory, uri, values, index, fileList))
-                            index++;
+                        cachePlaylistEntry(line, playListDirectory);
                     }
                     line = reader.readLine();
                 }
+
+                processCachedPlaylist(fileList, values, uri);
             }
         } catch (IOException e) {
             Log.e(TAG, "IOException in MediaScanner.processM3uPlayList()", e);
@@ -1622,20 +1617,19 @@
                 reader = new BufferedReader(
                         new InputStreamReader(new FileInputStream(f)), 8192);
                 String line = reader.readLine();
-                int index = 0;
+                mPlaylistEntries.clear();
                 while (line != null) {
                     // ignore comment lines, which begin with '#'
                     if (line.startsWith("File")) {
                         int equals = line.indexOf('=');
                         if (equals > 0) {
-                            values.clear();
-                            if (addPlayListEntry(line.substring(equals + 1), playListDirectory,
-                                    uri, values, index, fileList))
-                                index++;
+                            cachePlaylistEntry(line, playListDirectory);
                         }
                     }
                     line = reader.readLine();
                 }
+
+                processCachedPlaylist(fileList, values, uri);
             }
         } catch (IOException e) {
             Log.e(TAG, "IOException in MediaScanner.processPlsPlayList()", e);
@@ -1653,15 +1647,9 @@
 
         final ContentHandler handler;
         String playListDirectory;
-        Uri uri;
-        Cursor fileList;
-        ContentValues values = new ContentValues();
-        int index = 0;
 
         public WplHandler(String playListDirectory, Uri uri, Cursor fileList) {
             this.playListDirectory = playListDirectory;
-            this.uri = uri;
-            this.fileList = fileList;
 
             RootElement root = new RootElement("smil");
             Element body = root.getChild("body");
@@ -1676,13 +1664,11 @@
         public void start(Attributes attributes) {
             String path = attributes.getValue("", "src");
             if (path != null) {
-                values.clear();
-                if (addPlayListEntry(path, playListDirectory, uri, values, index, fileList)) {
-                    index++;
-                }
+                cachePlaylistEntry(path, playListDirectory);
             }
         }
 
+       @Override
        public void end() {
        }
 
@@ -1692,15 +1678,18 @@
     }
 
     private void processWplPlayList(String path, String playListDirectory, Uri uri,
-            Cursor fileList) {
+            ContentValues values, Cursor fileList) {
         FileInputStream fis = null;
         try {
             File f = new File(path);
             if (f.exists()) {
                 fis = new FileInputStream(f);
 
+                mPlaylistEntries.clear();
                 Xml.parse(fis, Xml.findEncodingByName("UTF-8"),
                         new WplHandler(playListDirectory, uri, fileList).getContentHandler());
+
+                processCachedPlaylist(fileList, values, uri);
             }
         } catch (SAXException e) {
             e.printStackTrace();
@@ -1762,7 +1751,7 @@
         } else if (fileType == MediaFile.FILE_TYPE_PLS) {
             processPlsPlayList(path, playListDirectory, membersUri, values, fileList);
         } else if (fileType == MediaFile.FILE_TYPE_WPL) {
-            processWplPlayList(path, playListDirectory, membersUri, fileList);
+            processWplPlayList(path, playListDirectory, membersUri, values, fileList);
         }
     }
 
@@ -1800,7 +1789,7 @@
     private native final void native_finalize();
 
     /**
-     * Releases resouces associated with this MediaScanner object.
+     * Releases resources associated with this MediaScanner object.
      * It is considered good practice to call this method when
      * one is done using the MediaScanner object. After this method
      * is called, the MediaScanner object can no longer be used.
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 7aaf4aa..a5b1f45 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -393,13 +393,13 @@
      * @return A {@link Uri} pointing to the ringtone.
      */
     public Uri getRingtoneUri(int position) {
-        final Cursor cursor = getCursor();
-        
-        if (!cursor.moveToPosition(position)) {
+        // use cursor directly instead of requerying it, which could easily
+        // cause position to shuffle.
+        if (mCursor == null || !mCursor.moveToPosition(position)) {
             return null;
         }
         
-        return getUriFromCursor(cursor);
+        return getUriFromCursor(mCursor);
     }
     
     private static Uri getUriFromCursor(Cursor cursor) {
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 0518331..9e1920c 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -96,8 +96,13 @@
     return mImpl->selectTrack(index);
 }
 
-status_t JMediaExtractor::seekTo(int64_t timeUs) {
-    return mImpl->seekTo(timeUs);
+status_t JMediaExtractor::unselectTrack(size_t index) {
+    return mImpl->unselectTrack(index);
+}
+
+status_t JMediaExtractor::seekTo(
+        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode) {
+    return mImpl->seekTo(timeUs, mode);
 }
 
 status_t JMediaExtractor::advance() {
@@ -281,8 +286,8 @@
     }
 }
 
-static void android_media_MediaExtractor_seekTo(
-        JNIEnv *env, jobject thiz, jlong timeUs) {
+static void android_media_MediaExtractor_unselectTrack(
+        JNIEnv *env, jobject thiz, jint index) {
     sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
 
     if (extractor == NULL) {
@@ -290,7 +295,30 @@
         return;
     }
 
-    extractor->seekTo(timeUs);
+    status_t err = extractor->unselectTrack(index);
+
+    if (err != OK) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+}
+
+static void android_media_MediaExtractor_seekTo(
+        JNIEnv *env, jobject thiz, jlong timeUs, jint mode) {
+    sp<JMediaExtractor> extractor = getMediaExtractor(env, thiz);
+
+    if (extractor == NULL) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+        return;
+    }
+
+    if (mode < MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC
+            || mode > MediaSource::ReadOptions::SEEK_CLOSEST) {
+        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+        return;
+    }
+
+    extractor->seekTo(timeUs, (MediaSource::ReadOptions::SeekMode)mode);
 }
 
 static jboolean android_media_MediaExtractor_advance(
@@ -648,7 +676,10 @@
 
     { "selectTrack", "(I)V", (void *)android_media_MediaExtractor_selectTrack },
 
-    { "seekTo", "(J)V", (void *)android_media_MediaExtractor_seekTo },
+    { "unselectTrack", "(I)V",
+        (void *)android_media_MediaExtractor_unselectTrack },
+
+    { "seekTo", "(JI)V", (void *)android_media_MediaExtractor_seekTo },
 
     { "advance", "()Z", (void *)android_media_MediaExtractor_advance },
 
diff --git a/media/jni/android_media_MediaExtractor.h b/media/jni/android_media_MediaExtractor.h
index ef0c48b..2d4627e 100644
--- a/media/jni/android_media_MediaExtractor.h
+++ b/media/jni/android_media_MediaExtractor.h
@@ -18,6 +18,7 @@
 #define _ANDROID_MEDIA_MEDIAEXTRACTOR_H_
 
 #include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/MediaSource.h>
 #include <utils/Errors.h>
 #include <utils/KeyedVector.h>
 #include <utils/RefBase.h>
@@ -43,8 +44,9 @@
     status_t getTrackFormat(size_t index, jobject *format) const;
 
     status_t selectTrack(size_t index);
+    status_t unselectTrack(size_t index);
 
-    status_t seekTo(int64_t timeUs);
+    status_t seekTo(int64_t timeUs, MediaSource::ReadOptions::SeekMode mode);
 
     status_t advance();
     status_t readSampleData(jobject byteBuf, size_t offset, size_t *sampleSize);
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 8e3a3c5..3eec18c 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -81,13 +81,15 @@
          * @return Returns the new cache path where the resource has been copied into
          *
          */
-        public String copyResourceToContainer(final Uri packageURI,
-                final String cid,
-                final String key, final String resFileName) {
+        public String copyResourceToContainer(final Uri packageURI, final String cid,
+                final String key, final String resFileName, final String publicResFileName,
+                boolean isExternal, boolean isForwardLocked) {
             if (packageURI == null || cid == null) {
                 return null;
             }
-            return copyResourceInner(packageURI, cid, key, resFileName);
+
+            return copyResourceInner(packageURI, cid, key, resFileName, publicResFileName,
+                    isExternal, isForwardLocked);
         }
 
         /*
@@ -169,22 +171,23 @@
         }
 
         @Override
-        public boolean checkInternalFreeStorage(Uri packageUri, long threshold)
-                throws RemoteException {
+        public boolean checkInternalFreeStorage(Uri packageUri, boolean isForwardLocked,
+                long threshold) throws RemoteException {
             final File apkFile = new File(packageUri.getPath());
             try {
-                return isUnderInternalThreshold(apkFile, threshold);
-            } catch (FileNotFoundException e) {
+                return isUnderInternalThreshold(apkFile, isForwardLocked, threshold);
+            } catch (IOException e) {
                 return true;
             }
         }
 
         @Override
-        public boolean checkExternalFreeStorage(Uri packageUri) throws RemoteException {
+        public boolean checkExternalFreeStorage(Uri packageUri, boolean isForwardLocked)
+                throws RemoteException {
             final File apkFile = new File(packageUri.getPath());
             try {
-                return isUnderExternalThreshold(apkFile);
-            } catch (FileNotFoundException e) {
+                return isUnderExternalThreshold(apkFile, isForwardLocked);
+            } catch (IOException e) {
                 return true;
             }
         }
@@ -259,12 +262,16 @@
         return mBinder;
     }
 
-    private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName) {
-        // Make sure the sdcard is mounted.
-        String status = Environment.getExternalStorageState();
-        if (!status.equals(Environment.MEDIA_MOUNTED)) {
-            Slog.w(TAG, "Make sure sdcard is mounted.");
-            return null;
+    private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName,
+            String publicResFileName, boolean isExternal, boolean isForwardLocked) {
+
+        if (isExternal) {
+            // Make sure the sdcard is mounted.
+            String status = Environment.getExternalStorageState();
+            if (!status.equals(Environment.MEDIA_MOUNTED)) {
+                Slog.w(TAG, "Make sure sdcard is mounted.");
+                return null;
+            }
         }
 
         // The .apk file
@@ -272,17 +279,18 @@
         File codeFile = new File(codePath);
 
         // Calculate size of container needed to hold base APK.
-        int sizeMb;
+        final int sizeMb;
         try {
-            sizeMb = calculateContainerSize(codeFile);
-        } catch (FileNotFoundException e) {
-            Slog.w(TAG, "File does not exist when trying to copy " + codeFile.getPath());
+            sizeMb = calculateContainerSize(codeFile, isForwardLocked);
+        } catch (IOException e) {
+            Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath());
             return null;
         }
 
         // Create new container
-        final String newCachePath;
-        if ((newCachePath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid())) == null) {
+        final String newCachePath = PackageHelper.createSdDir(sizeMb, newCid, key, Process.myUid(),
+                isExternal);
+        if (newCachePath == null) {
             Slog.e(TAG, "Failed to create container " + newCid);
             return null;
         }
@@ -303,6 +311,30 @@
             return null;
         }
 
+        if (isForwardLocked) {
+            File publicZipFile = new File(newCachePath, publicResFileName);
+            try {
+                PackageHelper.extractPublicFiles(resFile.getAbsolutePath(), publicZipFile);
+                if (localLOGV) {
+                    Slog.i(TAG, "Copied resources to " + publicZipFile);
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "Could not chown public APK " + publicZipFile.getAbsolutePath() + ": "
+                        + e.getMessage());
+                PackageHelper.destroySdDir(newCid);
+                return null;
+            }
+
+            try {
+                Libcore.os.chmod(resFile.getAbsolutePath(), 0640);
+                Libcore.os.chmod(publicZipFile.getAbsolutePath(), 0644);
+            } catch (ErrnoException e) {
+                Slog.e(TAG, "Could not chown APK or resource file: " + e.getMessage());
+                PackageHelper.destroySdDir(newCid);
+                return null;
+            }
+        }
+
         final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);
         if (sharedLibraryDir.mkdir()) {
             int ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(codeFile, sharedLibraryDir);
@@ -412,18 +444,13 @@
         int prefer;
         boolean checkBoth = false;
 
+        final boolean isForwardLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
+
         check_inner : {
             /*
              * Explicit install flags should override the manifest settings.
              */
-            if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) {
-                /*
-                 * Forward-locked applications cannot be installed on SD card,
-                 * so only allow checking internal storage.
-                 */
-                prefer = PREFER_INTERNAL;
-                break check_inner;
-            } else if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
+            if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
                 prefer = PREFER_INTERNAL;
                 break check_inner;
             } else if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
@@ -473,8 +500,8 @@
         boolean fitsOnInternal = false;
         if (checkBoth || prefer == PREFER_INTERNAL) {
             try {
-                fitsOnInternal = isUnderInternalThreshold(apkFile, threshold);
-            } catch (FileNotFoundException e) {
+                fitsOnInternal = isUnderInternalThreshold(apkFile, isForwardLocked, threshold);
+            } catch (IOException e) {
                 return PackageHelper.RECOMMEND_FAILED_INVALID_URI;
             }
         }
@@ -482,8 +509,8 @@
         boolean fitsOnSd = false;
         if (!emulated && (checkBoth || prefer == PREFER_EXTERNAL)) {
             try {
-                fitsOnSd = isUnderExternalThreshold(apkFile);
-            } catch (FileNotFoundException e) {
+                fitsOnSd = isUnderExternalThreshold(apkFile, isForwardLocked);
+            } catch (IOException e) {
                 return PackageHelper.RECOMMEND_FAILED_INVALID_URI;
             }
         }
@@ -527,13 +554,17 @@
      * @return true if file fits under threshold
      * @throws FileNotFoundException when APK does not exist
      */
-    private boolean isUnderInternalThreshold(File apkFile, long threshold)
-            throws FileNotFoundException {
-        final long size = apkFile.length();
+    private boolean isUnderInternalThreshold(File apkFile, boolean isForwardLocked, long threshold)
+            throws IOException {
+        long size = apkFile.length();
         if (size == 0 && !apkFile.exists()) {
             throw new FileNotFoundException();
         }
 
+        if (isForwardLocked) {
+            size += PackageHelper.extractPublicFiles(apkFile.getAbsolutePath(), null);
+        }
+
         final StatFs internalStats = new StatFs(Environment.getDataDirectory().getPath());
         final long availInternalSize = (long) internalStats.getAvailableBlocks()
                 * (long) internalStats.getBlockSize();
@@ -549,12 +580,13 @@
      * @return true if file fits
      * @throws IOException when file does not exist
      */
-    private boolean isUnderExternalThreshold(File apkFile) throws FileNotFoundException {
+    private boolean isUnderExternalThreshold(File apkFile, boolean isForwardLocked)
+            throws IOException {
         if (Environment.isExternalStorageEmulated()) {
             return false;
         }
 
-        final int sizeMb = calculateContainerSize(apkFile);
+        final int sizeMb = calculateContainerSize(apkFile, isForwardLocked);
 
         final int availSdMb;
         if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
@@ -573,9 +605,9 @@
      * 
      * @param apkFile file from which to calculate size
      * @return size in megabytes (2^20 bytes)
-     * @throws FileNotFoundException when file does not exist
+     * @throws IOException when there is a problem reading the file
      */
-    private int calculateContainerSize(File apkFile) throws FileNotFoundException {
+    private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException {
         // Calculate size of container needed to hold base APK.
         long sizeBytes = apkFile.length();
         if (sizeBytes == 0 && !apkFile.exists()) {
@@ -586,6 +618,10 @@
         // container size.
         sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkFile);
 
+        if (forwardLocked) {
+            sizeBytes += PackageHelper.extractPublicFiles(apkFile.getPath(), null);
+        }
+
         int sizeMb = (int) (sizeBytes >> 20);
         if ((sizeBytes - (sizeMb * 1024 * 1024)) > 0) {
             sizeMb++;
diff --git a/packages/InputDevices/res/raw/keyboard_layout_croatian_and_slovenian.kcm b/packages/InputDevices/res/raw/keyboard_layout_croatian_and_slovenian.kcm
new file mode 100644
index 0000000..eec9d27
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_croatian_and_slovenian.kcm
@@ -0,0 +1,352 @@
+# 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.
+
+#
+# Croatian and Slovenian keyboard layout, QWERTZ style.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 21 Z
+map key 44 Y
+map key 53 MINUS
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '\u00b8'
+    base:                               '\u0327'
+    shift:                              '\u0308'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+    ralt:                               '\u0303'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+    ralt:                               '\u030c'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+    ralt:                               '\u0302'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '$'
+    ralt:                               '\u0306'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+    ralt:                               '\u030a'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+    ralt:                               '\u0328'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+    ralt:                               '\u0300'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '\u0307'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               '\u0301'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+    ralt:                               '\u030b'
+}
+
+key SLASH {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '?'
+    ralt:                               '\u0308'
+}
+
+key EQUALS {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '*'
+    ralt:                               '\u0327'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+    ralt:                               '\\'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+    ralt:                               '|'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u0160'
+    base:                               '\u0161'
+    shift, capslock:                    '\u0160'
+    ralt:                               '\u00f7'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u0110'
+    base:                               '\u0111'
+    shift, capslock:                    '\u0110'
+    ralt:                               '\u00d7'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+    ralt:                               '['
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+    ralt:                               ']'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+    ralt:                               '\u0268'
+    ralt+shift, ralt+capslock:          '\u0197'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+    ralt:                               '\u0142'
+    ralt+shift, ralt+capslock:          '\u0141'
+}
+
+key SEMICOLON {
+    label:                              '\u010d'
+    base:                               '\u010c'
+    shift, capslock:                    '\u010d'
+}
+
+key APOSTROPHE {
+    label:                              '\u0106'
+    base:                               '\u0107'
+    shift, capslock:                    '\u0106'
+    ralt:                               '\u00df'
+}
+
+key BACKSLASH {
+    label:                              '\u017d'
+    base:                               '\u017e'
+    shift, capslock:                    '\u017d'
+    ralt:                               '\u00a4'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+    ralt:                               '@'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+    ralt:                               '{'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+    ralt:                               '}'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+    ralt:                               '\u00a7'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+    ralt:                               '<'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+    ralt:                               '>'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_czech.kcm b/packages/InputDevices/res/raw/keyboard_layout_czech.kcm
new file mode 100644
index 0000000..f710a8e
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_czech.kcm
@@ -0,0 +1,348 @@
+# 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.
+
+#
+# Czech keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              ';'
+    base:                               ';'
+    shift:                              '\u00b0'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '+'
+    shift:                              '1'
+    ralt:                               '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '\u011b'
+    shift:                              '2'
+    ralt:                               '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '\u0161'
+    shift:                              '3'
+    ralt:                               '#'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '\u010d'
+    shift:                              '4'
+    ralt:                               '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '\u0159'
+    shift:                              '5'
+    ralt:                               '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '\u017e'
+    shift:                              '6'
+    ralt:                               '^'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '\u00fd'
+    shift:                              '7'
+    ralt:                               '&'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '\u00e1'
+    shift:                              '8'
+    ralt:                               '*'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '\u00ed'
+    shift:                              '9'
+    ralt:                               '('
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '\u00e9'
+    shift:                              '0'
+    ralt:                               ')'
+}
+
+key MINUS {
+    label:                              '='
+    base:                               '='
+    shift:                              '%'
+    ralt:                               '-'
+    ralt+shift:                         '_'
+}
+
+key EQUALS {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\u030c'
+    ralt:                               '='
+    ralt+shift:                         '+'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00fa'
+    base:                               '\u00fa'
+    shift:                              '/'
+    ralt:                               '['
+    ralt+shift:                         '{'
+}
+
+key RIGHT_BRACKET {
+    label:                              ')'
+    base:                               ')'
+    shift:                              '('
+    ralt:                               ']'
+    ralt+shift:                         '}'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u016f'
+    base:                               '\u016f'
+    shift:                              '"'
+    ralt:                               ';'
+    ralt+shift:                         ':'
+}
+
+key APOSTROPHE {
+    label:                              '\u00a7'
+    base:                               '\u00a7'
+    shift:                              '!'
+    ralt:                               '\''
+    ralt+shift:                         '"'
+}
+
+key BACKSLASH {
+    label:                              '\u0308'
+    base:                               '\u0308'
+    shift:                              '\''
+    ralt:                               '\\'
+    ralt+shift:                         '|'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+    ralt:                               '@'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+    ralt:                               '\u00b5'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              '?'
+    ralt:                               '<'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+    ralt:                               '>'
+}
+
+key SLASH {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+    ralt:                               '/'
+    ralt+shift:                         '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_danish.kcm b/packages/InputDevices/res/raw/keyboard_layout_danish.kcm
new file mode 100644
index 0000000..9386a45
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_danish.kcm
@@ -0,0 +1,331 @@
+# 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.
+
+#
+# Danish keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 53 MINUS
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '\u00bd'
+    base:                               '\u00bd'
+    shift:                              '\u00a7'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+    ralt:                               '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+    ralt:                               '\u00a3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '\u00a4'
+    ralt:                               '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+    ralt:                               '{'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '['
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               ']'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+    ralt:                               '}'
+}
+
+key SLASH {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '?'
+}
+
+key EQUALS {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\u0300'
+    ralt:                               '|'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00c5'
+    base:                               '\u00e5'
+    shift, capslock:                    '\u00c5'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u00a8'
+    base:                               '\u0308'
+    shift:                              '\u0302'
+    ralt:                               '\u0303'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00c6'
+    base:                               '\u00e6'
+    shift, capslock:                    '\u00c6'
+}
+
+key APOSTROPHE {
+    label:                              '\u00d8'
+    base:                               '\u00f8'
+    shift, capslock:                    '\u00d8'
+}
+
+key BACKSLASH {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '*'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+    ralt:                               '\\'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+    ralt:                               '\u00b5'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_estonian.kcm b/packages/InputDevices/res/raw/keyboard_layout_estonian.kcm
new file mode 100644
index 0000000..ef545b8
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_estonian.kcm
@@ -0,0 +1,336 @@
+# 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.
+
+#
+# Estonian keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 53 MINUS
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '\u02c7'
+    base:                               '\u030c'
+    shift:                              '\u0303'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+    ralt:                               '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+    ralt:                               '\u00a3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '\u00a4'
+    ralt:                               '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+    ralt:                               '{'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '['
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               ']'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+    ralt:                               '}'
+}
+
+key SLASH {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '?'
+    ralt:                               '\\'
+}
+
+key EQUALS {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\u0300'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00dc'
+    base:                               '\u00fc'
+    shift, capslock:                    '\u00dc'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u00d5'
+    base:                               '\u00f5'
+    shift, capslock:                    '\u00d5'
+    ralt:                               '\u00a7'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+    ralt:                               '\u0161'
+    ralt+shift, ralt+capslock:          '\u0160'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00d6'
+    base:                               '\u00f6'
+    shift, capslock:                    '\u00d6'
+}
+
+key APOSTROPHE {
+    label:                              '\u00c4'
+    base:                               '\u00e4'
+    shift, capslock:                    '\u00c4'
+    ralt:                               '\u0302'
+}
+
+key BACKSLASH {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '*'
+    ralt:                               '\u00bd'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+    ralt:                               '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+    ralt:                               '\u017e'
+    ralt+shift, ralt+capslock:          '\u017d'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_finnish.kcm b/packages/InputDevices/res/raw/keyboard_layout_finnish.kcm
new file mode 100644
index 0000000..c6e5ac4
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_finnish.kcm
@@ -0,0 +1,380 @@
+# 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.
+
+#
+# Finnish multilingual keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 53 MINUS
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '\u00a7'
+    base:                               '\u00a7'
+    shift:                              '\u00bd'
+    ralt:                               '\u0335'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+    ralt+shift:                         '\u00a1'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+    ralt:                               '@'
+    ralt+shift:                         '\u201d'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+    ralt:                               '\u00a3'
+    ralt+shift:                         '\u00bb'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '\u00a4'
+    ralt:                               '$'
+    ralt+shift:                         '\u00ab'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+    ralt:                               '\u2030'
+    ralt+shift:                         '\u201c'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+    ralt:                               '\u201a'
+    ralt+shift:                         '\u201e'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+    ralt:                               '{'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '['
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               ']'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+    ralt:                               '}'
+    ralt+shift:                         '\u00b0'
+}
+
+key SLASH {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '?'
+    ralt:                               '\\'
+    ralt+shift:                         '\u00bf'
+}
+
+key EQUALS {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\u0300'
+    ralt:                               '\u0327'
+    ralt+shift:                         '\u0328'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+    ralt:                               '\u00fe'
+    ralt+shift, ralt+capslock:          '\u00de'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+    ralt:                               '\u0131'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+    ralt:                               '\u0153'
+    ralt+shift, ralt+capslock:          '\u0152'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+    ralt:                               '\u031b'
+    ralt+shift:                         '\u0309'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00c5'
+    base:                               '\u00e5'
+    shift, capslock:                    '\u00c5'
+    ralt:                               '\u030b'
+    ralt+shift:                         '\u030a'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u00a8'
+    base:                               '\u0308'
+    shift:                              '\u0302'
+    ralt:                               '\u0303'
+    ralt+shift:                         '\u0304'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+    ralt:                               '\u0259'
+    ralt+shift, ralt+capslock:          '\u018f'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+    ralt:                               '\u00df'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+    ralt:                               '\u00f0'
+    ralt+shift, ralt+capslock:          '\u00d0'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+    ralt:                               '\u0138'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+    ralt:                               '\u0335'
+}
+
+key SEMICOLON {
+    label:                              '\u00d6'
+    base:                               '\u00f6'
+    shift, capslock:                    '\u00d6'
+    ralt:                               '\u00f8'
+    ralt+shift, ralt+capslock:          '\u00d8'
+}
+
+key APOSTROPHE {
+    label:                              '\u00c4'
+    base:                               '\u00e4'
+    shift, capslock:                    '\u00c4'
+    ralt:                               '\u00e6'
+    ralt+shift, ralt+capslock:          '\u00c6'
+}
+
+key BACKSLASH {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '*'
+    ralt:                               '\u030c'
+    ralt+shift:                         '\u0306'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+    ralt:                               '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+    ralt:                               '\u0292'
+    ralt+shift, ralt+capslock:          '\u01b7'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+    ralt:                               '\u00d7'
+    ralt+shift:                         '\u00b7'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+    ralt:                               '\u014b'
+    ralt+shift, ralt+capslock:          '\u014a'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+    ralt:                               '\u00b5'
+    ralt+shift:                         '\u2014'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+    ralt:                               '\u2019'
+    ralt+shift:                         '\u2018'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+    ralt:                               '\u0323'
+    ralt+shift:                         '\u0307'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+    ralt:                               '\u2013'
+    ralt+shift:                         '\u0307'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_hungarian.kcm b/packages/InputDevices/res/raw/keyboard_layout_hungarian.kcm
new file mode 100644
index 0000000..dafb50b
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_hungarian.kcm
@@ -0,0 +1,362 @@
+# 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.
+
+#
+# Hungarian keyboard layout, QWERTZ style.
+#
+
+type OVERLAY
+
+map key 41 0
+map key 11 GRAVE
+map key 12 SLASH
+map key 21 Z
+map key 44 Y
+map key 53 MINUS
+map key 86 PLUS
+
+### ROW 1
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '\u00a7'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+    ralt:                               '\u0303'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+    ralt:                               '\u030c'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '+'
+    ralt:                               '\u0302'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '!'
+    ralt:                               '\u0306'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+    ralt:                               '\u030a'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '/'
+    ralt:                               '\u0328'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '='
+    ralt:                               '\u0300'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '\u0307'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               '\u0301'
+}
+
+key GRAVE {
+    label:                              '\u00d6'
+    base:                               '\u00f6'
+    shift, capslock:                    '\u00d6'
+    ralt:                               '\u030b'
+}
+
+key SLASH {
+    label:                              '\u00dc'
+    base:                               '\u00fc'
+    shift, capslock:                    '\u00dc'
+    ralt:                               '\u0308'
+}
+
+key EQUALS {
+    label:                              '\u00d3'
+    base:                               '\u00f3'
+    shift, capslock:                    '\u00d3'
+    ralt:                               '\u0327'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+    ralt:                               '\\'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+    ralt:                               '|'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u00c4'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+    ralt:                               '\u20ac'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+    ralt:                               '\u00cd'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u0150'
+    base:                               '\u0151'
+    shift, capslock:                    '\u0150'
+    ralt:                               '\u00f7'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u00da'
+    base:                               '\u00fa'
+    shift, capslock:                    '\u00da'
+    ralt:                               '\u00d7'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+    ralt:                               '\u00e4'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+    ralt:                               '\u0111'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+    ralt:                               '\u0110'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+    ralt:                               '['
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+    ralt:                               ']'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+    ralt:                               '\u00ed'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+    ralt:                               '\u0197'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+    ralt:                               '\u0141'
+}
+
+key SEMICOLON {
+    label:                              '\u00c9'
+    base:                               '\u00e9'
+    shift, capslock:                    '\u00c9'
+    ralt:                               '$'
+}
+
+key APOSTROPHE {
+    label:                              '\u00c1'
+    base:                               '\u00e1'
+    shift, capslock:                    '\u00c1'
+    ralt:                               '\u00df'
+}
+
+key BACKSLASH {
+    label:                              '\u0170'
+    base:                               '\u0171'
+    shift, capslock:                    '\u0170'
+    ralt:                               '\u00a4'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '\u00cd'
+    base:                               '\u00ed'
+    shift, capslock:                    '\u00cd'
+    ralt:                               '<'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+    ralt:                               '>'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+    ralt:                               '#'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+    ralt:                               '&'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+    ralt:                               '@'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+    ralt:                               '{'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+    ralt:                               '}'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              '?'
+    ralt:                               ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+    ralt:                               '*'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_icelandic.kcm b/packages/InputDevices/res/raw/keyboard_layout_icelandic.kcm
new file mode 100644
index 0000000..117f58b
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_icelandic.kcm
@@ -0,0 +1,332 @@
+# 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.
+
+#
+# Icelandic keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 EQUALS
+map key 13 MINUS
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '\u02da'
+    base:                               '\u030a'
+    shift:                              '\u0308'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+    ralt:                               '\u20ac'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+    ralt:                               '{'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '['
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               ']'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+    ralt:                               '}'
+}
+
+key EQUALS {
+    label:                              '\u00d6'
+    base:                               '\u00f6'
+    shift, capslock:                    '\u00d6'
+    ralt:                               '\\'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+    ralt:                               '@'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u0110'
+    base:                               '\u0111'
+    shift, capslock:                    '\u0110'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '?'
+    ralt:                               '~'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00c6'
+    base:                               '\u00e6'
+    shift, capslock:                    '\u00c6'
+}
+
+key APOSTROPHE {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\''
+    ralt:                               '^'
+}
+
+key BACKSLASH {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '*'
+    ralt:                               '`'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+    ralt:                               '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+    ralt:                               '\u00b5'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key SLASH {
+    label:                              '\u00de'
+    base:                               '\u00fe'
+    shift, capslock:                    '\u00de'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_italian.kcm b/packages/InputDevices/res/raw/keyboard_layout_italian.kcm
new file mode 100644
index 0000000..bd2d25a
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_italian.kcm
@@ -0,0 +1,327 @@
+# 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.
+
+#
+# Italian keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 53 MINUS
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '\u00a3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+    ralt:                               '\u20ac'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+}
+
+key SLASH {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '?'
+}
+
+key EQUALS {
+    label:                              '\u00ec'
+    base:                               '\u00ec'
+    shift:                              '^'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00e8'
+    base:                               '\u00e8'
+    shift:                              '\u00e9'
+    ralt:                               '['
+    ralt+shift:                         '{'
+}
+
+key RIGHT_BRACKET {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '*'
+    ralt:                               ']'
+    ralt+shift:                         '}'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00f2'
+    base:                               '\u00f2'
+    shift:                              '\u00e7'
+    ralt:                               '@'
+}
+
+key APOSTROPHE {
+    label:                              '\u00e0'
+    base:                               '\u00e0'
+    shift:                              '\u00b0'
+    ralt:                               '#'
+}
+
+key BACKSLASH {
+    label:                              '\u00f9'
+    base:                               '\u00f9'
+    shift:                              '\u00a7'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_norwegian.kcm b/packages/InputDevices/res/raw/keyboard_layout_norwegian.kcm
new file mode 100644
index 0000000..d1be485
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_norwegian.kcm
@@ -0,0 +1,330 @@
+# 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.
+
+#
+# Norwegian keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 53 MINUS
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '|'
+    base:                               '|'
+    shift:                              '\u00a7'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+    ralt:                               '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+    ralt:                               '\u00a3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '\u00a4'
+    ralt:                               '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+    ralt:                               '{'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '['
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               ']'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+    ralt:                               '}'
+}
+
+key SLASH {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '?'
+}
+
+key EQUALS {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '\u0300'
+    ralt:                               '\u0301'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00c5'
+    base:                               '\u00e5'
+    shift, capslock:                    '\u00c5'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u00a8'
+    base:                               '\u0308'
+    shift:                              '\u0302'
+    ralt:                               '\u0303'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00d8'
+    base:                               '\u00f8'
+    shift, capslock:                    '\u00d8'
+}
+
+key APOSTROPHE {
+    label:                              '\u00c6'
+    base:                               '\u00e6'
+    shift, capslock:                    '\u00c6'
+}
+
+key BACKSLASH {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '*'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+    ralt:                               '\u00b5'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_portuguese.kcm b/packages/InputDevices/res/raw/keyboard_layout_portuguese.kcm
new file mode 100644
index 0000000..47ee867
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_portuguese.kcm
@@ -0,0 +1,329 @@
+# 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.
+
+#
+# Portuguese keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 53 MINUS
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+    ralt:                               '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+    ralt:                               '\u00a3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '$'
+    ralt:                               '\u00a7'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+    ralt:                               '{'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '['
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               ']'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+    ralt:                               '}'
+}
+
+key SLASH {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '?'
+}
+
+key EQUALS {
+    label:                              '\u00ab'
+    base:                               '\u00ab'
+    shift:                              '\u00bb'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '*'
+    ralt:                               '\u0308'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\u0300'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00c7'
+    base:                               '\u00e7'
+    shift, capslock:                    '\u00c7'
+}
+
+key APOSTROPHE {
+    label:                              '\u00ba'
+    base:                               '\u00ba'
+    shift:                              '\u00aa'
+}
+
+key BACKSLASH {
+    label:                              '\u02dc'
+    base:                               '\u0303'
+    shift:                              '\u0302'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+    ralt:                               '\\'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_russian_apple.kcm b/packages/InputDevices/res/raw/keyboard_layout_russian_mac.kcm
similarity index 98%
rename from packages/InputDevices/res/raw/keyboard_layout_russian_apple.kcm
rename to packages/InputDevices/res/raw/keyboard_layout_russian_mac.kcm
index 8c1d596..11c2ad4 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_russian_apple.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_russian_mac.kcm
@@ -15,7 +15,7 @@
 #
 # Russian keyboard layout.
 # This is a variant of the typical Russian PC keyboard layout that is presented
-# on Apple keyboards.  In contrast with the standard layout, some of the symbols and
+# on Mac keyboards.  In contrast with the standard layout, some of the symbols and
 # punctuation characters have been rearranged.
 # As an added convenience, English characters are accessible using ralt (Alt Gr).
 #
diff --git a/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm b/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm
new file mode 100644
index 0000000..70c1fa4
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm
@@ -0,0 +1,353 @@
+# 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.
+
+#
+# Slovak keyboard layout.
+#
+
+type OVERLAY
+
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              ';'
+    base:                               ';'
+    shift:                              '\u00b0'
+    ralt:                               '`'
+    ralt+shift:                         '~'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '+'
+    shift:                              '1'
+    ralt:                               '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '\u013e'
+    shift:                              '2'
+    ralt:                               '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '\u0161'
+    shift:                              '3'
+    ralt:                               '#'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '\u010d'
+    shift:                              '4'
+    ralt:                               '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '\u0165'
+    shift:                              '5'
+    ralt:                               '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '\u017e'
+    shift:                              '6'
+    ralt:                               '^'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '\u00fd'
+    shift:                              '7'
+    ralt:                               '&'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '\u00e1'
+    shift:                              '8'
+    ralt:                               '*'
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '\u00ed'
+    shift:                              '9'
+    ralt:                               '('
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '\u00e9'
+    shift:                              '0'
+    ralt:                               ')'
+}
+
+key MINUS {
+    label:                              '='
+    base:                               '='
+    shift:                              '%'
+    ralt:                               '-'
+    ralt+shift:                         '_'
+}
+
+key EQUALS {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\u030c'
+    ralt:                               '='
+    ralt+shift:                         '+'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+    ralt:                               '\\'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+    ralt:                               '|'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00fa'
+    base:                               '\u00fa'
+    shift:                              '/'
+    ralt:                               '['
+    ralt+shift:                         '{'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u00e4'
+    base:                               '\u00e4'
+    shift:                              '('
+    ralt:                               ']'
+    ralt+shift:                         '}'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00f4'
+    base:                               '\u00f4'
+    shift:                              '"'
+    ralt:                               ';'
+    ralt+shift:                         ':'
+}
+
+key APOSTROPHE {
+    label:                              '\u00a7'
+    base:                               '\u00a7'
+    shift:                              '!'
+    ralt:                               '\''
+    ralt+shift:                         '"'
+}
+
+key BACKSLASH {
+    label:                              '\u0148'
+    base:                               '\u0148'
+    shift:                              ')'
+    ralt:                               '\\'
+    ralt+shift:                         '|'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '|'
+    ralt:                               '&'
+    ralt+shift:                         '*'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+    ralt:                               '@'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              '?'
+    ralt:                               '<'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+    ralt:                               '>'
+}
+
+key SLASH {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+    ralt:                               '/'
+    ralt+shift:                         '?'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_swedish.kcm b/packages/InputDevices/res/raw/keyboard_layout_swedish.kcm
new file mode 100644
index 0000000..e42bd6c
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_swedish.kcm
@@ -0,0 +1,331 @@
+# 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.
+
+#
+# Swedish keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 53 MINUS
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '\u00a7'
+    base:                               '\u00a7'
+    shift:                              '\u00bd'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '"'
+    ralt:                               '@'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '#'
+    ralt:                               '\u00a3'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '\u00a4'
+    ralt:                               '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+    ralt:                               '{'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '['
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               ']'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+    ralt:                               '}'
+}
+
+key SLASH {
+    label:                              '+'
+    base:                               '+'
+    shift:                              '?'
+    ralt:                               '\\'
+}
+
+key EQUALS {
+    label:                              '\u00b4'
+    base:                               '\u0301'
+    shift:                              '\u0300'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               'i'
+    shift, capslock:                    'I'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u00c5'
+    base:                               '\u00e5'
+    shift, capslock:                    '\u00c5'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u00a8'
+    base:                               '\u0308'
+    shift:                              '\u0302'
+    ralt:                               '\u0303'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u00d6'
+    base:                               '\u00f6'
+    shift, capslock:                    '\u00d6'
+}
+
+key APOSTROPHE {
+    label:                              '\u00c4'
+    base:                               '\u00e4'
+    shift, capslock:                    '\u00c4'
+}
+
+key BACKSLASH {
+    label:                              '\''
+    base:                               '\''
+    shift:                              '*'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+    ralt:                               '|'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+    ralt:                               '\u00b5'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_turkish.kcm b/packages/InputDevices/res/raw/keyboard_layout_turkish.kcm
new file mode 100644
index 0000000..e193d34
--- /dev/null
+++ b/packages/InputDevices/res/raw/keyboard_layout_turkish.kcm
@@ -0,0 +1,347 @@
+# 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.
+
+#
+# Turkish keyboard layout.
+#
+
+type OVERLAY
+
+map key 12 SLASH
+map key 13 MINUS
+map key 43 COMMA
+map key 51 EQUALS
+map key 52 BACKSLASH
+map key 53 PERIOD
+map key 86 PLUS
+
+### ROW 1
+
+key GRAVE {
+    label:                              '"'
+    base:                               '"'
+    shift:                              '\u00e9'
+    ralt:                               '<'
+}
+
+key 1 {
+    label:                              '1'
+    base:                               '1'
+    shift:                              '!'
+    ralt:                               '>'
+}
+
+key 2 {
+    label:                              '2'
+    base:                               '2'
+    shift:                              '\''
+    ralt:                               '\u00a3'
+}
+
+key 3 {
+    label:                              '3'
+    base:                               '3'
+    shift:                              '\u0302'
+    ralt:                               '#'
+}
+
+key 4 {
+    label:                              '4'
+    base:                               '4'
+    shift:                              '+'
+    ralt:                               '$'
+}
+
+key 5 {
+    label:                              '5'
+    base:                               '5'
+    shift:                              '%'
+    ralt:                               '\u00bd'
+}
+
+key 6 {
+    label:                              '6'
+    base:                               '6'
+    shift:                              '&'
+}
+
+key 7 {
+    label:                              '7'
+    base:                               '7'
+    shift:                              '/'
+    ralt:                               '{'
+}
+
+key 8 {
+    label:                              '8'
+    base:                               '8'
+    shift:                              '('
+    ralt:                               '['
+}
+
+key 9 {
+    label:                              '9'
+    base:                               '9'
+    shift:                              ')'
+    ralt:                               ']'
+}
+
+key 0 {
+    label:                              '0'
+    base:                               '0'
+    shift:                              '='
+    ralt:                               '}'
+}
+
+key SLASH {
+    label:                              '*'
+    base:                               '*'
+    shift:                              '?'
+    ralt:                               '\\'
+}
+
+key MINUS {
+    label:                              '-'
+    base:                               '-'
+    shift:                              '_'
+    ralt:                               '|'
+}
+
+### ROW 2
+
+key Q {
+    label:                              'Q'
+    base:                               'q'
+    shift, capslock:                    'Q'
+    ralt:                               '@'
+}
+
+key W {
+    label:                              'W'
+    base:                               'w'
+    shift, capslock:                    'W'
+}
+
+key E {
+    label:                              'E'
+    base:                               'e'
+    shift, capslock:                    'E'
+    ralt:                               '\u20ac'
+}
+
+key R {
+    label:                              'R'
+    base:                               'r'
+    shift, capslock:                    'R'
+}
+
+key T {
+    label:                              'T'
+    base:                               't'
+    shift, capslock:                    'T'
+}
+
+key Y {
+    label:                              'Y'
+    base:                               'y'
+    shift, capslock:                    'Y'
+}
+
+key U {
+    label:                              'U'
+    base:                               'u'
+    shift, capslock:                    'U'
+}
+
+key I {
+    label:                              'I'
+    base:                               '\u0131'
+    shift, capslock:                    'I'
+    ralt:                               'i'
+    ralt+shift, ralt+capslock:          '\u0130'
+}
+
+key O {
+    label:                              'O'
+    base:                               'o'
+    shift, capslock:                    'O'
+}
+
+key P {
+    label:                              'P'
+    base:                               'p'
+    shift, capslock:                    'P'
+}
+
+key LEFT_BRACKET {
+    label:                              '\u011e'
+    base:                               '\u011f'
+    shift, capslock:                    '\u011e'
+    ralt:                               '\u0308'
+}
+
+key RIGHT_BRACKET {
+    label:                              '\u00dc'
+    base:                               '\u00fc'
+    shift, capslock:                    '\u00dc'
+    ralt:                               '\u0303'
+}
+
+### ROW 3
+
+key A {
+    label:                              'A'
+    base:                               'a'
+    shift, capslock:                    'A'
+    ralt:                               '\u00e6'
+    ralt+shift, ralt+capslock:          '\u00c6'
+}
+
+key S {
+    label:                              'S'
+    base:                               's'
+    shift, capslock:                    'S'
+    ralt:                               '\u00df'
+}
+
+key D {
+    label:                              'D'
+    base:                               'd'
+    shift, capslock:                    'D'
+}
+
+key F {
+    label:                              'F'
+    base:                               'f'
+    shift, capslock:                    'F'
+}
+
+key G {
+    label:                              'G'
+    base:                               'g'
+    shift, capslock:                    'G'
+}
+
+key H {
+    label:                              'H'
+    base:                               'h'
+    shift, capslock:                    'H'
+}
+
+key J {
+    label:                              'J'
+    base:                               'j'
+    shift, capslock:                    'J'
+}
+
+key K {
+    label:                              'K'
+    base:                               'k'
+    shift, capslock:                    'K'
+}
+
+key L {
+    label:                              'L'
+    base:                               'l'
+    shift, capslock:                    'L'
+}
+
+key SEMICOLON {
+    label:                              '\u015e'
+    base:                               '\u015f'
+    shift, capslock:                    '\u015e'
+    ralt:                               '\u0301'
+}
+
+key APOSTROPHE {
+    label:                              '\u0130'
+    base:                               'i'
+    shift, capslock:                    '\u0130'
+}
+
+key COMMA {
+    label:                              ','
+    base:                               ','
+    shift:                              ';'
+    ralt:                               '\u0300'
+}
+
+### ROW 4
+
+key PLUS {
+    label:                              '<'
+    base:                               '<'
+    shift:                              '>'
+    ralt:                               '\\'
+}
+
+key Z {
+    label:                              'Z'
+    base:                               'z'
+    shift, capslock:                    'Z'
+}
+
+key X {
+    label:                              'X'
+    base:                               'x'
+    shift, capslock:                    'X'
+}
+
+key C {
+    label:                              'C'
+    base:                               'c'
+    shift, capslock:                    'C'
+}
+
+key V {
+    label:                              'V'
+    base:                               'v'
+    shift, capslock:                    'V'
+}
+
+key B {
+    label:                              'B'
+    base:                               'b'
+    shift, capslock:                    'B'
+}
+
+key N {
+    label:                              'N'
+    base:                               'n'
+    shift, capslock:                    'N'
+}
+
+key M {
+    label:                              'M'
+    base:                               'm'
+    shift, capslock:                    'M'
+}
+
+key EQUALS {
+    label:                              '\u00d6'
+    base:                               '\u00f6'
+    shift, capslock:                    '\u00d6'
+}
+
+key BACKSLASH {
+    label:                              '\u00c7'
+    base:                               '\u00e7'
+    shift, capslock:                    '\u00c7'
+}
+
+key PERIOD {
+    label:                              '.'
+    base:                               '.'
+    shift:                              ':'
+}
diff --git a/packages/InputDevices/res/raw/keyboard_layout_russian_apple.kcm b/packages/InputDevices/res/raw/keyboard_layout_ukrainian.kcm
similarity index 90%
copy from packages/InputDevices/res/raw/keyboard_layout_russian_apple.kcm
copy to packages/InputDevices/res/raw/keyboard_layout_ukrainian.kcm
index 8c1d596..a802460 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_russian_apple.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_ukrainian.kcm
@@ -13,10 +13,8 @@
 # limitations under the License.
 
 #
-# Russian keyboard layout.
-# This is a variant of the typical Russian PC keyboard layout that is presented
-# on Apple keyboards.  In contrast with the standard layout, some of the symbols and
-# punctuation characters have been rearranged.
+# Ukrainian keyboard layout.
+# This is a typical Ukrainian PC keyboard layout.
 # As an added convenience, English characters are accessible using ralt (Alt Gr).
 #
 
@@ -27,11 +25,11 @@
 ### ROW 1
 
 key GRAVE {
-    label:                              '>'
-    base:                               '>'
-    shift:                              '<'
-    ralt:                               '\u00a7'
-    ralt+shift:                         '\u00b1'
+    label:                              '\u0401'
+    base:                               '\u0451'
+    shift, capslock:                    '\u0401'
+    ralt:                               '`'
+    ralt+shift:                         '~'
 }
 
 key 1 {
@@ -58,35 +56,35 @@
 key 4 {
     label:                              '4'
     base:                               '4'
-    shift:                              '%'
+    shift:                              ';'
     ralt:                               '$'
 }
 
 key 5 {
     label:                              '5'
     base:                               '5'
-    shift:                              ':'
+    shift:                              '%'
     ralt:                               '%'
 }
 
 key 6 {
     label:                              '6'
     base:                               '6'
-    shift:                              ','
+    shift:                              ':'
     ralt:                               '^'
 }
 
 key 7 {
     label:                              '7'
     base:                               '7'
-    shift:                              '.'
+    shift:                              '?'
     ralt:                               '&'
 }
 
 key 8 {
     label:                              '8'
     base:                               '8'
-    shift:                              ';'
+    shift:                              '*'
     ralt:                               '*'
 }
 
@@ -211,9 +209,9 @@
 }
 
 key RIGHT_BRACKET {
-    label:                              '\u042a'
-    base:                               '\u044a'
-    shift, capslock:                    '\u042a'
+    label:                              '\u0407'
+    base:                               '\u0457'
+    shift, capslock:                    '\u0407'
     ralt:                               ']'
     ralt+shift:                         '}'
 }
@@ -229,9 +227,9 @@
 }
 
 key S {
-    label:                              '\u042b'
-    base:                               '\u044b'
-    shift, capslock:                    '\u042b'
+    label:                              '\u0406'
+    base:                               '\u0456'
+    shift, capslock:                    '\u0406'
     ralt:                               's'
     ralt+shift, ralt+capslock:          'S'
 }
@@ -301,29 +299,28 @@
 }
 
 key APOSTROPHE {
-    label:                              '\u042d'
-    base:                               '\u044d'
-    shift, capslock:                    '\u042d'
+    label:                              '\u0404'
+    base:                               '\u0454'
+    shift, capslock:                    '\u0404'
     ralt:                               '\''
     ralt+shift:                         '"'
 }
 
 key BACKSLASH {
-    label:                              '\u0401'
-    base:                               '\u0451'
-    shift, capslock:                    '\u0401'
-    ralt:                               '\\'
-    ralt+shift:                         '|'
+    label:                              '\\'
+    base:                               '\\'
+    shift:                              '/'
+    ralt:                               '|'
 }
 
 ### ROW 4
 
 key PLUS {
-    label:                              '['
-    base:                               '['
-    shift:                              ']'
-    ralt:                               '`'
-    ralt+shift:                         '~'
+    label:                              '\u0490'
+    base:                               '\u0491'
+    shift, capslock:                    '\u0490'
+    ralt:                               '\\'
+    ralt+shift:                         '|'
 }
 
 key Z {
@@ -399,9 +396,9 @@
 }
 
 key SLASH {
-    label:                              '/'
-    base:                               '/'
-    shift:                              '?'
+    label:                              '.'
+    base:                               '.'
+    shift:                              ','
     ralt:                               '/'
     ralt+shift:                         '?'
 }
diff --git a/packages/InputDevices/res/values/strings.xml b/packages/InputDevices/res/values/strings.xml
index 95e7401..140c7d4 100644
--- a/packages/InputDevices/res/values/strings.xml
+++ b/packages/InputDevices/res/values/strings.xml
@@ -7,7 +7,7 @@
     <string name="keyboard_layout_english_us_label">English (US)</string>
 
     <!-- US English (Dvorak style) keyboard layout label. [CHAR LIMIT=35] -->
-    <string name="keyboard_layout_english_us_dvorak_label">English (US), Dvorak</string>
+    <string name="keyboard_layout_english_us_dvorak_label">English (US), Dvorak style</string>
 
     <!-- German keyboard layout label. [CHAR LIMIT=35] -->
     <string name="keyboard_layout_german_label">German</string>
@@ -21,8 +21,8 @@
     <!-- Russian keyboard layout label. [CHAR LIMIT=35] -->
     <string name="keyboard_layout_russian_label">Russian</string>
 
-    <!-- Russian (Apple style) keyboard layout label. [CHAR LIMIT=35] -->
-    <string name="keyboard_layout_russian_apple_label">Russian, Apple</string>
+    <!-- Russian (Mac style) keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_russian_mac_label">Russian, Mac style</string>
 
     <!-- Spanish keyboard layout label. [CHAR LIMIT=35] -->
     <string name="keyboard_layout_spanish_label">Spanish</string>
@@ -38,4 +38,49 @@
 
     <!-- Bulgarian keyboard layout label. [CHAR LIMIT=35] -->
     <string name="keyboard_layout_bulgarian">Bulgarian</string>
+
+    <!-- Italian keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_italian">Italian</string>
+
+    <!-- Danish keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_danish">Danish</string>
+
+    <!-- Norwegian keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_norwegian">Norwegian</string>
+
+    <!-- Swedish keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_swedish">Swedish</string>
+
+    <!-- Finnish keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_finnish">Finnish</string>
+
+    <!-- Croatian keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_croatian">Croatian</string>
+
+    <!-- Czech keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_czech">Czech</string>
+
+    <!-- Estonian keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_estonian">Estonian</string>
+
+    <!-- Hungarian keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_hungarian">Hungarian</string>
+
+    <!-- Icelandic keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_icelandic">Icelandic</string>
+
+    <!-- Portuguese keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_portuguese">Portuguese</string>
+
+    <!-- Slovak keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_slovak">Slovak</string>
+
+    <!-- Slovenian keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_slovenian">Slovenian</string>
+
+    <!-- Turkish keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_turkish">Turkish</string>
+
+    <!-- Ukrainian keyboard layout label. [CHAR LIMIT=35] -->
+    <string name="keyboard_layout_ukrainian">Ukrainian</string>
 </resources>
diff --git a/packages/InputDevices/res/xml/keyboard_layouts.xml b/packages/InputDevices/res/xml/keyboard_layouts.xml
index 50672a1..23f6bcb 100644
--- a/packages/InputDevices/res/xml/keyboard_layouts.xml
+++ b/packages/InputDevices/res/xml/keyboard_layouts.xml
@@ -24,9 +24,9 @@
             android:label="@string/keyboard_layout_russian_label"
             android:kcm="@raw/keyboard_layout_russian" />
 
-    <keyboard-layout android:name="keyboard_layout_russian_apple"
-            android:label="@string/keyboard_layout_russian_apple_label"
-            android:kcm="@raw/keyboard_layout_russian_apple" />
+    <keyboard-layout android:name="keyboard_layout_russian_mac"
+            android:label="@string/keyboard_layout_russian_mac_label"
+            android:kcm="@raw/keyboard_layout_russian_mac" />
 
     <keyboard-layout android:name="keyboard_layout_spanish"
             android:label="@string/keyboard_layout_spanish_label"
@@ -47,4 +47,64 @@
     <keyboard-layout android:name="keyboard_layout_bulgarian"
             android:label="@string/keyboard_layout_bulgarian"
             android:kcm="@raw/keyboard_layout_bulgarian" />
+
+    <keyboard-layout android:name="keyboard_layout_italian"
+            android:label="@string/keyboard_layout_italian"
+            android:kcm="@raw/keyboard_layout_italian" />
+
+    <keyboard-layout android:name="keyboard_layout_danish"
+            android:label="@string/keyboard_layout_danish"
+            android:kcm="@raw/keyboard_layout_danish" />
+
+    <keyboard-layout android:name="keyboard_layout_norwegian"
+            android:label="@string/keyboard_layout_norwegian"
+            android:kcm="@raw/keyboard_layout_norwegian" />
+
+    <keyboard-layout android:name="keyboard_layout_swedish"
+            android:label="@string/keyboard_layout_swedish"
+            android:kcm="@raw/keyboard_layout_swedish" />
+
+    <keyboard-layout android:name="keyboard_layout_finnish"
+            android:label="@string/keyboard_layout_finnish"
+            android:kcm="@raw/keyboard_layout_finnish" />
+
+    <keyboard-layout android:name="keyboard_layout_croatian"
+            android:label="@string/keyboard_layout_croatian"
+            android:kcm="@raw/keyboard_layout_croatian_and_slovenian" />
+
+    <keyboard-layout android:name="keyboard_layout_czech"
+            android:label="@string/keyboard_layout_czech"
+            android:kcm="@raw/keyboard_layout_czech" />
+
+    <keyboard-layout android:name="keyboard_layout_estonian"
+            android:label="@string/keyboard_layout_estonian"
+            android:kcm="@raw/keyboard_layout_estonian" />
+
+    <keyboard-layout android:name="keyboard_layout_hungarian"
+            android:label="@string/keyboard_layout_hungarian"
+            android:kcm="@raw/keyboard_layout_hungarian" />
+
+    <keyboard-layout android:name="keyboard_layout_icelandic"
+            android:label="@string/keyboard_layout_icelandic"
+            android:kcm="@raw/keyboard_layout_icelandic" />
+
+    <keyboard-layout android:name="keyboard_layout_portuguese"
+            android:label="@string/keyboard_layout_portuguese"
+            android:kcm="@raw/keyboard_layout_portuguese" />
+
+    <keyboard-layout android:name="keyboard_layout_slovak"
+            android:label="@string/keyboard_layout_slovak"
+            android:kcm="@raw/keyboard_layout_slovak" />
+
+    <keyboard-layout android:name="keyboard_layout_slovenian"
+            android:label="@string/keyboard_layout_slovenian"
+            android:kcm="@raw/keyboard_layout_croatian_and_slovenian" />
+
+    <keyboard-layout android:name="keyboard_layout_turkish"
+            android:label="@string/keyboard_layout_turkish"
+            android:kcm="@raw/keyboard_layout_turkish" />
+
+    <keyboard-layout android:name="keyboard_layout_ukrainian"
+            android:label="@string/keyboard_layout_ukrainian"
+            android:kcm="@raw/keyboard_layout_ukrainian" />
 </keyboard-layouts>
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index cd6da85..3fa79b6 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -114,14 +114,21 @@
         mDeviceProvisioned = isDeviceProvisioned;
         if (mDialog != null) {
             mDialog.dismiss();
+            mDialog = null;
+            // Show delayed, so that the dismiss of the previous dialog completes
+            mHandler.sendEmptyMessage(MESSAGE_SHOW);
+        } else {
+            handleShow();
         }
+    }
+
+    private void handleShow() {
         mDialog = createDialog();
         prepareDialog();
 
         mDialog.show();
         mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND);
     }
-
     /**
      * Create the global actions dialog.
      * @return A new dialog.
@@ -280,7 +287,6 @@
         }
     }
 
-
     /** {@inheritDoc} */
     public void onDismiss(DialogInterface dialog) {
         if (SHOW_SILENT_TOGGLE) {
@@ -694,16 +700,23 @@
 
     private static final int MESSAGE_DISMISS = 0;
     private static final int MESSAGE_REFRESH = 1;
+    private static final int MESSAGE_SHOW = 2;
     private static final int DIALOG_DISMISS_DELAY = 300; // ms
 
     private Handler mHandler = new Handler() {
         public void handleMessage(Message msg) {
-            if (msg.what == MESSAGE_DISMISS) {
+            switch (msg.what) {
+            case MESSAGE_DISMISS:
                 if (mDialog != null) {
                     mDialog.dismiss();
                 }
-            } else if (msg.what == MESSAGE_REFRESH) {
+                break;
+            case MESSAGE_REFRESH:
                 mAdapter.notifyDataSetChanged();
+                break;
+            case MESSAGE_SHOW:
+                handleShow();
+                break;
             }
         }
     };
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index faa8d3c..dd650bf 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2422,15 +2422,15 @@
                     }
 
                     // Connectivity state changed:
-                    // [31-13] Reserved for future use
-                    // [12-9] Network subtype (for mobile network, as defined
+                    // [31-14] Reserved for future use
+                    // [13-10] Network subtype (for mobile network, as defined
                     //         by TelephonyManager)
-                    // [8-3] Detailed state ordinal (as defined by
+                    // [9-4] Detailed state ordinal (as defined by
                     //         NetworkInfo.DetailedState)
-                    // [2-0] Network type (as defined by ConnectivityManager)
-                    int eventLogParam = (info.getType() & 0x7) |
-                            ((info.getDetailedState().ordinal() & 0x3f) << 3) |
-                            (info.getSubtype() << 9);
+                    // [3-0] Network type (as defined by ConnectivityManager)
+                    int eventLogParam = (info.getType() & 0xf) |
+                            ((info.getDetailedState().ordinal() & 0x3f) << 4) |
+                            (info.getSubtype() << 10);
                     EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
                             eventLogParam);
 
diff --git a/services/java/com/android/server/EventLogTags.logtags b/services/java/com/android/server/EventLogTags.logtags
index 249513f..41f7335 100644
--- a/services/java/com/android/server/EventLogTags.logtags
+++ b/services/java/com/android/server/EventLogTags.logtags
@@ -134,10 +134,10 @@
 # ConnectivityService.java
 # ---------------------------
 # Connectivity state changed:
-# [31-13] Reserved for future use
-# [12- 9] Network subtype (for mobile network, as defined by TelephonyManager)
-# [ 8- 3] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
-# [ 2- 0] Network type (as defined by ConnectivityManager)
+# [31-14] Reserved for future use
+# [13-10] Network subtype (for mobile network, as defined by TelephonyManager)
+# [ 9- 4] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
+# [ 3- 0] Network type (as defined by ConnectivityManager)
 50020 connectivity_state_changed (custom|1|5)
 
 
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 510bdb2..d6606f6 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -668,6 +668,9 @@
                     updatePublicVolumeState(mExternalStoragePath, Environment.MEDIA_REMOVED);
                 }
 
+                // Let package manager load internal ASECs.
+                mPms.updateExternalMediaStatus(true, false);
+
                 /*
                  * Now that we've done our initialization, release
                  * the hounds!
@@ -1435,15 +1438,16 @@
         }
     }
 
-    public int createSecureContainer(String id, int sizeMb, String fstype,
-                                    String key, int ownerUid) {
+    public int createSecureContainer(String id, int sizeMb, String fstype, String key,
+            int ownerUid, boolean external) {
         validatePermission(android.Manifest.permission.ASEC_CREATE);
         waitForReady();
         warnOnNotMounted();
 
         int rc = StorageResultCode.OperationSucceeded;
         try {
-            mConnector.execute("asec", "create", id, sizeMb, fstype, key, ownerUid);
+            mConnector.execute("asec", "create", id, sizeMb, fstype, key, ownerUid,
+                    external ? "1" : "0");
         } catch (NativeDaemonConnectorException e) {
             rc = StorageResultCode.OperationFailedInternalError;
         }
@@ -1473,6 +1477,23 @@
         return rc;
     }
 
+    public int fixPermissionsSecureContainer(String id, int gid, String filename) {
+        validatePermission(android.Manifest.permission.ASEC_CREATE);
+        warnOnNotMounted();
+
+        int rc = StorageResultCode.OperationSucceeded;
+        try {
+            mConnector.execute("asec", "fixperms", id, gid, filename);
+            /*
+             * Fix permissions does a remount, so no need to update
+             * mAsecMountSet
+             */
+        } catch (NativeDaemonConnectorException e) {
+            rc = StorageResultCode.OperationFailedInternalError;
+        }
+        return rc;
+    }
+
     public int destroySecureContainer(String id, boolean force) {
         validatePermission(android.Manifest.permission.ASEC_DESTROY);
         waitForReady();
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 00d86e3..21ae624 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -723,7 +723,7 @@
                     }
                     if (msg.obj != null) {
                         @SuppressWarnings("unchecked")
-                        Set<SdInstallArgs> args = (Set<SdInstallArgs>) msg.obj;
+                        Set<AsecInstallArgs> args = (Set<AsecInstallArgs>) msg.obj;
                         if (DEBUG_SD_INSTALL) Log.i(TAG, "Unloading all containers");
                         // Unload containers
                         unloadAllContainers(args);
@@ -830,17 +830,6 @@
         }
     }
 
-    static boolean installOnSd(int flags) {
-        if (((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0) ||
-                ((flags & PackageManager.INSTALL_INTERNAL) != 0)) {
-            return false;
-        }
-        if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
-            return true;
-        }
-        return false;
-    }
-
     public static final IPackageManager main(Context context, boolean factoryTest,
             boolean onlyCore) {
         PackageManagerService m = new PackageManagerService(context, factoryTest, onlyCore);
@@ -5396,7 +5385,7 @@
                     synchronized (mInstallLock) {
                         installPackageLI(args, true, res);
                     }
-                    args.doPostInstall(res.returnCode);
+                    args.doPostInstall(res.returnCode, res.uid);
                 }
 
                 // A restore should be performed at this point if (a) the install
@@ -5646,7 +5635,6 @@
          */
         public void handleStartCopy() throws RemoteException {
             int ret = PackageManager.INSTALL_SUCCEEDED;
-            final boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
             final boolean onSd = (flags & PackageManager.INSTALL_EXTERNAL) != 0;
             final boolean onInt = (flags & PackageManager.INSTALL_INTERNAL) != 0;
             PackageInfoLite pkgLite = null;
@@ -5655,10 +5643,6 @@
                 // Check if both bits are set.
                 Slog.w(TAG, "Conflicting flags specified for installing on both internal and external");
                 ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
-            } else if (fwdLocked && onSd) {
-                // Check for forward locked apps
-                Slog.w(TAG, "Cannot install fwd locked apps on sdcard");
-                ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
             } else {
                 final long lowThreshold;
 
@@ -5835,6 +5819,10 @@
             mArgs = createInstallArgs(this);
             mRet = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
         }
+
+        public boolean isForwardLocked() {
+            return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
+        }
     }
 
     /*
@@ -5850,14 +5838,16 @@
         final String packageName;
         final InstallArgs srcArgs;
         final InstallArgs targetArgs;
+        int uid;
         int mRet;
 
         MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
-                String packageName, String dataDir) {
+                String packageName, String dataDir, int uid) {
             this.srcArgs = srcArgs;
             this.observer = observer;
             this.flags = flags;
             this.packageName = packageName;
+            this.uid = uid;
             if (srcArgs != null) {
                 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
                 targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
@@ -5892,7 +5882,7 @@
 
         @Override
         void handleReturnCode() {
-            targetArgs.doPostInstall(mRet);
+            targetArgs.doPostInstall(mRet, uid);
             int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
             if (mRet == PackageManager.INSTALL_SUCCEEDED) {
                 currentStatus = PackageManager.MOVE_SUCCEEDED;
@@ -5908,9 +5898,35 @@
         }
     }
 
+    /**
+     * Used during creation of InstallArgs
+     *
+     * @param flags package installation flags
+     * @return true if should be installed on external storage
+     */
+    private static boolean installOnSd(int flags) {
+        if ((flags & PackageManager.INSTALL_INTERNAL) != 0) {
+            return false;
+        }
+        if ((flags & PackageManager.INSTALL_EXTERNAL) != 0) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Used during creation of InstallArgs
+     *
+     * @param flags package installation flags
+     * @return true if should be installed as forward locked
+     */
+    private static boolean installForwardLocked(int flags) {
+        return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
+    }
+
     private InstallArgs createInstallArgs(InstallParams params) {
-        if (installOnSd(params.flags)) {
-            return new SdInstallArgs(params);
+        if (installOnSd(params.flags) || params.isForwardLocked()) {
+            return new AsecInstallArgs(params);
         } else {
             return new FileInstallArgs(params);
         }
@@ -5918,8 +5934,9 @@
 
     private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
             String nativeLibraryPath) {
-        if (installOnSd(flags)) {
-            return new SdInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
+        if (installOnSd(flags) || installForwardLocked(flags)) {
+            return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
+                    (flags & PackageManager.INSTALL_EXTERNAL) != 0);
         } else {
             return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
         }
@@ -5927,9 +5944,10 @@
 
     // Used by package mover
     private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
-        if (installOnSd(flags)) {
-            String cid = getNextCodePath(null, pkgName, "/" + SdInstallArgs.RES_FILE_NAME);
-            return new SdInstallArgs(packageURI, cid);
+        if (installOnSd(flags) || installForwardLocked(flags)) {
+            String cid = getNextCodePath(null, pkgName, "/" + AsecInstallArgs.RES_FILE_NAME);
+            return new AsecInstallArgs(packageURI, cid,
+                    (flags & PackageManager.INSTALL_EXTERNAL) != 0);
         } else {
             return new FileInstallArgs(packageURI, pkgName, dataDir);
         }
@@ -5956,7 +5974,8 @@
         abstract int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException;
         abstract int doPreInstall(int status);
         abstract boolean doRename(int status, String pkgName, String oldCodePath);
-        abstract int doPostInstall(int status);
+
+        abstract int doPostInstall(int status, int uid);
         abstract String getCodePath();
         abstract String getResourcePath();
         abstract String getNativeLibraryPath();
@@ -5964,6 +5983,10 @@
         abstract void cleanUpResourcesLI();
         abstract boolean doPostDeleteLI(boolean delete);
         abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
+
+        protected boolean isFwdLocked() {
+            return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
+        }
     }
 
     class FileInstallArgs extends InstallArgs {
@@ -6016,7 +6039,7 @@
             try {
                 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
                         Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                return imcs.checkInternalFreeStorage(packageURI, lowThreshold);
+                return imcs.checkInternalFreeStorage(packageURI, isFwdLocked(), lowThreshold);
             } finally {
                 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
             }
@@ -6126,7 +6149,7 @@
             }
         }
 
-        int doPostInstall(int status) {
+        int doPostInstall(int status, int uid) {
             if (status != PackageManager.INSTALL_SUCCEEDED) {
                 cleanUp();
             }
@@ -6229,10 +6252,6 @@
             cleanUpResourcesLI();
             return true;
         }
-
-        private boolean isFwdLocked() {
-            return (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
-        }
     }
 
     /**
@@ -6246,20 +6265,23 @@
         return subStr1.substring(sidx+1, eidx);
     }
 
-    class SdInstallArgs extends InstallArgs {
+    class AsecInstallArgs extends InstallArgs {
         static final String RES_FILE_NAME = "pkg.apk";
+        static final String PUBLIC_RES_FILE_NAME = "res.zip";
 
         String cid;
         String packagePath;
+        String resourcePath;
         String libraryPath;
 
-        SdInstallArgs(InstallParams params) {
+        AsecInstallArgs(InstallParams params) {
             super(params.packageURI, params.observer, params.flags, params.installerPackageName,
                     params.manifestDigest);
         }
 
-        SdInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
-            super(null, null, PackageManager.INSTALL_EXTERNAL, null, null);
+        AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
+                boolean isExternal) {
+            super(null, null, isExternal ? PackageManager.INSTALL_EXTERNAL : 0, null, null);
             // Extract cid from fullCodePath
             int eidx = fullCodePath.lastIndexOf("/");
             String subStr1 = fullCodePath.substring(0, eidx);
@@ -6268,14 +6290,14 @@
             setCachePath(subStr1);
         }
 
-        SdInstallArgs(String cid) {
-            super(null, null, PackageManager.INSTALL_EXTERNAL, null, null);
+        AsecInstallArgs(String cid) {
+            super(null, null, 0, null, null);
             this.cid = cid;
             setCachePath(PackageHelper.getSdDir(cid));
         }
 
-        SdInstallArgs(Uri packageURI, String cid) {
-            super(packageURI, null, PackageManager.INSTALL_EXTERNAL, null, null);
+        AsecInstallArgs(Uri packageURI, String cid, boolean isExternal) {
+            super(packageURI, null, isExternal ? PackageManager.INSTALL_EXTERNAL : 0, null, null);
             this.cid = cid;
         }
 
@@ -6287,12 +6309,16 @@
             try {
                 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
                         Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                return imcs.checkExternalFreeStorage(packageURI);
+                return imcs.checkExternalFreeStorage(packageURI, isFwdLocked());
             } finally {
                 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
             }
         }
 
+        private final boolean isExternal() {
+            return (flags & PackageManager.INSTALL_EXTERNAL) != 0;
+        }
+
         int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
             if (temp) {
                 createCopyFile();
@@ -6308,8 +6334,8 @@
             try {
                 mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
                         Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                newCachePath = imcs.copyResourceToContainer(packageURI, cid,
-                        getEncryptKey(), RES_FILE_NAME);
+                newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
+                        RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked());
             } finally {
                 mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
             }
@@ -6329,7 +6355,7 @@
 
         @Override
         String getResourcePath() {
-            return packagePath;
+            return resourcePath;
         }
 
         @Override
@@ -6405,22 +6431,36 @@
             File cachePath = new File(newCachePath);
             libraryPath = new File(cachePath, LIB_DIR_NAME).getPath();
             packagePath = new File(cachePath, RES_FILE_NAME).getPath();
+
+            if (isFwdLocked()) {
+                resourcePath = new File(cachePath, PUBLIC_RES_FILE_NAME).getPath();
+            } else {
+                resourcePath = packagePath;
+            }
         }
 
-        int doPostInstall(int status) {
+        int doPostInstall(int status, int uid) {
             if (status != PackageManager.INSTALL_SUCCEEDED) {
                 cleanUp();
             } else {
+                if (uid < Process.FIRST_APPLICATION_UID
+                        || !PackageHelper.fixSdPermissions(cid, uid, RES_FILE_NAME)) {
+                    Slog.e(TAG, "Failed to finalize " + cid);
+                    PackageHelper.destroySdDir(cid);
+                    return PackageManager.INSTALL_FAILED_CONTAINER_ERROR;
+                }
+
                 boolean mounted = PackageHelper.isContainerMounted(cid);
                 if (!mounted) {
-                    PackageHelper.mountSdDir(cid,
-                            getEncryptKey(), Process.myUid());
+                    PackageHelper.mountSdDir(cid, getEncryptKey(), Process.myUid());
                 }
             }
             return status;
         }
 
         private void cleanUp() {
+            if (DEBUG_SD_INSTALL) Slog.i(TAG, "cleanUp");
+
             // Destroy secure container
             PackageHelper.destroySdDir(cid);
         }
@@ -6749,8 +6789,7 @@
                 // We didn't need to disable the .apk as a current system package,
                 // which means we are replacing another update that is already
                 // installed.  We need to make sure to delete the older one's .apk.
-                res.removedInfo.args = createInstallArgs(isExternal(pkg)
-                        ? PackageManager.INSTALL_EXTERNAL : PackageManager.INSTALL_INTERNAL,
+                res.removedInfo.args = createInstallArgs(0,
                         deletedPackage.applicationInfo.sourceDir,
                         deletedPackage.applicationInfo.publicSourceDir,
                         deletedPackage.applicationInfo.nativeLibraryDir);
@@ -6836,13 +6875,9 @@
             // Discontinue if moving dex files failed.
             return;
         }
-        if((res.returnCode = setPermissionsLI(newPackage))
-                != PackageManager.INSTALL_SUCCEEDED) {
-            mInstaller.rmdex(newPackage.mScanPath);
-            return;
-        } else {
-            Log.d(TAG, "New package installed in " + newPackage.mPath);
-        }
+
+        Log.d(TAG, "New package installed in " + newPackage.mPath);
+
         synchronized (mPackages) {
             updatePermissionsLPw(newPackage.packageName, newPackage,
                     UPDATE_PERMISSIONS_REPLACE_PKG | (newPackage.permissions.size() > 0
@@ -6872,10 +6907,9 @@
         res.returnCode = PackageManager.INSTALL_SUCCEEDED;
 
         // Retrieve PackageSettings and parse package
-        int parseFlags = PackageParser.PARSE_CHATTY |
-        (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0) |
-        (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
-        parseFlags |= mDefParseFlags;
+        int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
+                | (forwardLocked ? PackageParser.PARSE_FORWARD_LOCK : 0)
+                | (onSd ? PackageParser.PARSE_ON_SDCARD : 0);
         PackageParser pp = new PackageParser(tmpPackageFile.getPath());
         pp.setSeparateProcesses(mSeparateProcesses);
         final PackageParser.Package pkg = pp.parsePackage(tmpPackageFile,
@@ -6972,27 +7006,6 @@
         }
     }
 
-    private int setPermissionsLI(PackageParser.Package newPackage) {
-        int retCode = 0;
-        // TODO Gross hack but fix later. Ideally move this to be a post installation
-        // check after alloting uid.
-        if (isForwardLocked(newPackage)) {
-            retCode = mInstaller.setForwardLockPerm(getApkName(newPackage.mPath),
-                    newPackage.applicationInfo.uid);
-        } else {
-            // The permissions on the resource file was set when it was copied for
-            // non forward locked apps and apps on sdcard
-        }
-
-        if (retCode != 0) {
-            Slog.e(TAG, "Couldn't set new package file permissions for " + newPackage.mPath
-                    + ". The return code was: " + retCode);
-            // TODO Define new internal error
-            return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
-        }
-        return PackageManager.INSTALL_SUCCEEDED;
-    }
-
     private static boolean isForwardLocked(PackageParser.Package pkg) {
         return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FORWARD_LOCK) != 0;
     }
@@ -7001,6 +7014,10 @@
         return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
     }
 
+    private static boolean isExternal(PackageSetting ps) {
+        return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
+    }
+
     private static boolean isSystemApp(PackageParser.Package pkg) {
         return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
@@ -8359,8 +8376,6 @@
         // little while.
         mHandler.post(new Runnable() {
             public void run() {
-                // TODO fix this; this does nothing.
-                mHandler.removeCallbacks(this);
                 updateExternalMediaStatusInner(mediaStatus, reportStatus);
             }
         });
@@ -8372,13 +8387,13 @@
      * Please note that we always have to report status if reportStatus has been
      * set to true especially when unloading packages.
      */
-    private void updateExternalMediaStatusInner(boolean mediaStatus, boolean reportStatus) {
+    private void updateExternalMediaStatusInner(boolean isMounted, boolean reportStatus) {
         // Collection of uids
         int uidArr[] = null;
         // Collection of stale containers
         HashSet<String> removeCids = new HashSet<String>();
         // Collection of packages on external media with valid containers.
-        HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
+        HashMap<AsecInstallArgs, String> processCids = new HashMap<AsecInstallArgs, String>();
         // Get list of secure containers.
         final String list[] = PackageHelper.getSecureContainerList();
         if (list == null || list.length == 0) {
@@ -8391,7 +8406,7 @@
             // reader
             synchronized (mPackages) {
                 for (String cid : list) {
-                    SdInstallArgs args = new SdInstallArgs(cid);
+                    AsecInstallArgs args = new AsecInstallArgs(cid);
                     if (DEBUG_SD_INSTALL)
                         Log.i(TAG, "Processing container " + cid);
                     String pkgName = args.getPackageName();
@@ -8441,7 +8456,7 @@
             }
         }
         // Process packages with valid entries.
-        if (mediaStatus) {
+        if (isMounted) {
             if (DEBUG_SD_INSTALL)
                 Log.i(TAG, "Loading packages");
             loadMediaPackages(processCids, uidArr, removeCids);
@@ -8476,12 +8491,12 @@
      * the cid is added to list of removeCids. We currently don't delete stale
      * containers.
      */
-   private void loadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[],
+   private void loadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
             HashSet<String> removeCids) {
         ArrayList<String> pkgList = new ArrayList<String>();
-        Set<SdInstallArgs> keys = processCids.keySet();
+        Set<AsecInstallArgs> keys = processCids.keySet();
         boolean doGc = false;
-        for (SdInstallArgs args : keys) {
+        for (AsecInstallArgs args : keys) {
             String codePath = processCids.get(args);
             if (DEBUG_SD_INSTALL)
                 Log.i(TAG, "Loading container : " + args.cid);
@@ -8517,7 +8532,8 @@
                             retCode = PackageManager.INSTALL_SUCCEEDED;
                             pkgList.add(pkg.packageName);
                             // Post process args
-                            args.doPostInstall(PackageManager.INSTALL_SUCCEEDED);
+                            args.doPostInstall(PackageManager.INSTALL_SUCCEEDED,
+                                    pkg.applicationInfo.uid);
                         }
                     } else {
                         Slog.i(TAG, "Failed to install pkg from  " + codePath + " from sdcard");
@@ -8580,9 +8596,9 @@
    /*
      * Utility method to unload a list of specified containers
      */
-    private void unloadAllContainers(Set<SdInstallArgs> cidArgs) {
+    private void unloadAllContainers(Set<AsecInstallArgs> cidArgs) {
         // Just unmount all valid containers.
-        for (SdInstallArgs arg : cidArgs) {
+        for (AsecInstallArgs arg : cidArgs) {
             synchronized (mInstallLock) {
                 arg.doPostDeleteLI(false);
            }
@@ -8598,14 +8614,14 @@
      * that we always have to post this message if status has been requested no
      * matter what.
      */
-    private void unloadMediaPackages(HashMap<SdInstallArgs, String> processCids, int uidArr[],
+    private void unloadMediaPackages(HashMap<AsecInstallArgs, String> processCids, int uidArr[],
             final boolean reportStatus) {
         if (DEBUG_SD_INSTALL)
             Log.i(TAG, "unloading media packages");
         ArrayList<String> pkgList = new ArrayList<String>();
-        ArrayList<SdInstallArgs> failedList = new ArrayList<SdInstallArgs>();
-        final Set<SdInstallArgs> keys = processCids.keySet();
-        for (SdInstallArgs args : keys) {
+        ArrayList<AsecInstallArgs> failedList = new ArrayList<AsecInstallArgs>();
+        final Set<AsecInstallArgs> keys = processCids.keySet();
+        for (AsecInstallArgs args : keys) {
             String pkgName = args.getPackageName();
             if (DEBUG_SD_INSTALL)
                 Log.i(TAG, "Trying to unload pkg : " + pkgName);
@@ -8666,9 +8682,6 @@
                 if (pkg.applicationInfo != null && isSystemApp(pkg)) {
                     Slog.w(TAG, "Cannot move system application");
                     returnCode = PackageManager.MOVE_FAILED_SYSTEM_PACKAGE;
-                } else if (pkg.applicationInfo != null && isForwardLocked(pkg)) {
-                    Slog.w(TAG, "Cannot move forward locked app.");
-                    returnCode = PackageManager.MOVE_FAILED_FORWARD_LOCKED;
                 } else if (pkg.mOperationPending) {
                     Slog.w(TAG, "Attempt to move package which has pending operations");
                     returnCode = PackageManager.MOVE_FAILED_OPERATION_PENDING;
@@ -8700,13 +8713,14 @@
              * anyway.
              */
             if (returnCode != PackageManager.MOVE_SUCCEEDED) {
-                processPendingMove(new MoveParams(null, observer, 0, packageName, null), returnCode);
+                processPendingMove(new MoveParams(null, observer, 0, packageName, null, -1),
+                        returnCode);
             } else {
                 Message msg = mHandler.obtainMessage(INIT_COPY);
                 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
                         pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
                 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
-                        pkg.applicationInfo.dataDir);
+                        pkg.applicationInfo.dataDir, pkg.applicationInfo.uid);
                 msg.obj = mp;
                 mHandler.sendMessage(msg);
             }
@@ -8831,7 +8845,8 @@
                 if (returnCode != PackageManager.MOVE_SUCCEEDED) {
                     // Clean up failed installation
                     if (mp.targetArgs != null) {
-                        mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR);
+                        mp.targetArgs.doPostInstall(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
+                                -1);
                     }
                 } else {
                     // Force a gc to clear things up.
diff --git a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeBasicsTest.java b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeBasicsTest.java
index 07d7c34..1ecccf6 100644
--- a/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeBasicsTest.java
+++ b/tests/WebViewTests/src/com/android/webviewtests/JavaBridgeBasicsTest.java
@@ -186,6 +186,13 @@
         assertRaisesException("testController.foo()");
     }
 
+    public void testUncaughtJavaExceptionRaisesJavaException() throws Throwable {
+        injectObjectAndReload(new Object() {
+            public void method() { throw new RuntimeException("foo"); }
+        }, "testObject");
+        assertRaisesException("testObject.method()");
+    }
+
     // Note that this requires that we can pass a JavaScript string to Java.
     public void testTypeOfStaticMethod() throws Throwable {
         injectObjectAndReload(new ObjectWithStaticMethod(), "testObject");
@@ -394,7 +401,6 @@
         assertEquals("", mTestController.waitForStringValue());
     }
 
-    // java.lang.reflect only allows access to public methods and fields. See b/6386557.
     public void testReflectPublicMethod() throws Throwable {
         injectObjectAndReload(new Object() {
             public String method() { return "foo"; }
@@ -404,7 +410,6 @@
                 ".toString()"));
     }
 
-    // java.lang.reflect only allows access to public methods and fields. See b/6386557.
     public void testReflectPublicField() throws Throwable {
         injectObjectAndReload(new Object() {
             public String field = "foo";
@@ -412,4 +417,26 @@
         assertEquals("foo", executeJavaScriptAndGetStringResult(
                 "testObject.getClass().getField('field').get(testObject).toString()"));
     }
+
+    public void testReflectPrivateMethodRaisesException() throws Throwable {
+        injectObjectAndReload(new Object() {
+            private void method() {};
+        }, "testObject");
+        assertRaisesException("testObject.getClass().getMethod('method', null)");
+        // getDeclaredMethod() is able to access a private method, but invoke()
+        // throws a Java exception.
+        assertRaisesException(
+                "testObject.getClass().getDeclaredMethod('method', null).invoke(testObject, null)");
+    }
+
+    public void testReflectPrivateFieldRaisesException() throws Throwable {
+        injectObjectAndReload(new Object() {
+            private int field;
+        }, "testObject");
+        assertRaisesException("testObject.getClass().getField('field')");
+        // getDeclaredField() is able to access a private field, but getInt()
+        // throws a Java exception.
+        assertRaisesException(
+                "testObject.getClass().getDeclaredField('field').getInt(testObject)");
+    }
 }
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index a4473c8..d428fef 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -1740,20 +1740,6 @@
             // Write the R.java file into the appropriate class directory
             // e.g. gen/com/foo/app/R.java
             err = writeResourceSymbols(bundle, assets, assets->getPackage(), true);
-            // If we have library files, we're going to write our R.java file into
-            // the appropriate class directory for those libraries as well.
-            // e.g. gen/com/foo/app/lib/R.java
-            if (bundle->getExtraPackages() != NULL) {
-                // Split on colon
-                String8 libs(bundle->getExtraPackages());
-                char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
-                while (packageString != NULL) {
-                    // Write the R.java file out with the correct package name
-                    err = writeResourceSymbols(bundle, assets, String8(packageString), true);
-                    packageString = strtok(NULL, ":");
-                }
-                libs.unlockBuffer();
-            }
         } else {
             const String8 customPkg(bundle->getCustomPackage());
             err = writeResourceSymbols(bundle, assets, customPkg, true);
@@ -1761,6 +1747,23 @@
         if (err < 0) {
             goto bail;
         }
+        // If we have library files, we're going to write our R.java file into
+        // the appropriate class directory for those libraries as well.
+        // e.g. gen/com/foo/app/lib/R.java
+        if (bundle->getExtraPackages() != NULL) {
+            // Split on colon
+            String8 libs(bundle->getExtraPackages());
+            char* packageString = strtok(libs.lockBuffer(libs.length()), ":");
+            while (packageString != NULL) {
+                // Write the R.java file out with the correct package name
+                err = writeResourceSymbols(bundle, assets, String8(packageString), true);
+                if (err < 0) {
+                    goto bail;
+                }
+                packageString = strtok(NULL, ":");
+            }
+            libs.unlockBuffer();
+        }
     } else {
         err = writeResourceSymbols(bundle, assets, assets->getPackage(), false);
         if (err < 0) {