Merge "Ensure we start every frame in the proper GL state Bug #6345013, #6314960" into jb-dev
diff --git a/api/current.txt b/api/current.txt
index f2b35a8..d04025c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -26608,7 +26608,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 +26650,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/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/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/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/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/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/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/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/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.