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.