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