diff options
Diffstat (limited to 'core')
28 files changed, 490 insertions, 282 deletions
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 42eda02..8e2d360 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -168,6 +168,7 @@ public class SearchDialog extends Dialog { SearchBar searchBar = (SearchBar) findViewById(com.android.internal.R.id.search_bar); searchBar.setSearchDialog(this); mSearchView = (SearchView) findViewById(com.android.internal.R.id.search_view); + mSearchView.setIconified(false); mSearchView.setOnCloseListener(mOnCloseListener); mSearchView.setOnQueryTextListener(mOnQueryChangeListener); mSearchView.setOnSuggestionListener(mOnSuggestionSelectionListener); @@ -633,31 +634,6 @@ public class SearchDialog extends Dialog { } /** - * Overrides the handling of the back key to move back to the previous - * sources or dismiss the search dialog, instead of dismissing the input - * method. - */ - @Override - public boolean dispatchKeyEventPreIme(KeyEvent event) { - if (DBG) - Log.d(LOG_TAG, "onKeyPreIme(" + event + ")"); - if (mSearchDialog != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) { - KeyEvent.DispatcherState state = getKeyDispatcherState(); - if (state != null) { - if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { - state.startTracking(event, this); - return true; - } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled() - && state.isTracking(event)) { - mSearchDialog.onBackPressed(); - return true; - } - } - } - return super.dispatchKeyEventPreIme(event); - } - - /** * Don't allow action modes in a SearchBar, it looks silly. */ @Override diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index c179b35..4c21d04 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -662,12 +662,6 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { writer.println("nothing to dump"); } - - @Override - protected void finalize() throws Throwable { - super.finalize(); - //Log.i("Service", "Finalizing Service: " + this); - } // ------------------ Internal API ------------------ diff --git a/core/java/android/content/SearchRecentSuggestionsProvider.java b/core/java/android/content/SearchRecentSuggestionsProvider.java index 3d89e92..e1a8d21 100644 --- a/core/java/android/content/SearchRecentSuggestionsProvider.java +++ b/core/java/android/content/SearchRecentSuggestionsProvider.java @@ -186,6 +186,9 @@ public class SearchRecentSuggestionsProvider extends ContentProvider { mSuggestionProjection = new String [] { "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT, + "'android.resource://system/" + + com.android.internal.R.drawable.ic_menu_recent_history + "' AS " + + SearchManager.SUGGEST_COLUMN_ICON_1, "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1, "display2 AS " + SearchManager.SUGGEST_COLUMN_TEXT_2, "query AS " + SearchManager.SUGGEST_COLUMN_QUERY, @@ -196,6 +199,9 @@ public class SearchRecentSuggestionsProvider extends ContentProvider { mSuggestionProjection = new String [] { "0 AS " + SearchManager.SUGGEST_COLUMN_FORMAT, + "'android.resource://system/" + + com.android.internal.R.drawable.ic_menu_recent_history + "' AS " + + SearchManager.SUGGEST_COLUMN_ICON_1, "display1 AS " + SearchManager.SUGGEST_COLUMN_TEXT_1, "query AS " + SearchManager.SUGGEST_COLUMN_QUERY, "_id" diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java index 5c1b968..6e68b6b 100644 --- a/core/java/android/database/MatrixCursor.java +++ b/core/java/android/database/MatrixCursor.java @@ -272,6 +272,12 @@ public class MatrixCursor extends AbstractCursor { } @Override + public byte[] getBlob(int column) { + Object value = get(column); + return (byte[]) value; + } + + @Override public int getType(int column) { return DatabaseUtils.getTypeOfObject(get(column)); } diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 7d67e11..a168260 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -16,6 +16,8 @@ package android.hardware; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; import android.graphics.ImageFormat; import android.graphics.Rect; import android.graphics.SurfaceTexture; @@ -142,6 +144,22 @@ public class Camera { private boolean mWithBuffer; /** + * Broadcast Action: A new picture is taken by the camera, and the entry of + * the picture has been added to the media store. + * {@link android.content.Intent#getData} is URI of the picture. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_NEW_PICTURE = "android.hardware.action.NEW_PICTURE"; + + /** + * Broadcast Action: A new video is recorded by the camera, and the entry + * of the video has been added to the media store. + * {@link android.content.Intent#getData} is URI of the video. + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_NEW_VIDEO = "android.hardware.action.NEW_VIDEO"; + + /** * Returns the number of physical cameras available on this device. */ public native static int getNumberOfCameras(); diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index ae605fb..73e8d98 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -357,20 +357,11 @@ public class RecoverySystem { } /** - * Reboot into the recovery system to wipe the /data partition and toggle - * Encrypted File Systems on/off. - * @param extras to add to the RECOVERY_COMPLETED intent after rebooting. + * Reboot into the recovery system to wipe the /cache partition. * @throws IOException if something goes wrong. - * - * @hide */ - public static void rebootToggleEFS(Context context, boolean efsEnabled) - throws IOException { - if (efsEnabled) { - bootCommand(context, "--set_encrypted_filesystem=on"); - } else { - bootCommand(context, "--set_encrypted_filesystem=off"); - } + public static void rebootWipeCache(Context context) throws IOException { + bootCommand(context, "--wipe_cache"); } /** diff --git a/core/java/android/speech/tts/AudioPlaybackHandler.java b/core/java/android/speech/tts/AudioPlaybackHandler.java index 96864c4..255b333 100644 --- a/core/java/android/speech/tts/AudioPlaybackHandler.java +++ b/core/java/android/speech/tts/AudioPlaybackHandler.java @@ -418,22 +418,30 @@ class AudioPlaybackHandler { if (DBG) Log.d(TAG, "handleSynthesisDone()"); final AudioTrack audioTrack = params.getAudioTrack(); - try { - if (audioTrack != null) { - if (DBG) Log.d(TAG, "Waiting for audio track to complete : " + - audioTrack.hashCode()); - blockUntilDone(params); - if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]"); - // The last call to AudioTrack.write( ) will return only after - // all data from the audioTrack has been sent to the mixer, so - // it's safe to release at this point. - audioTrack.release(); - } - } finally { + if (audioTrack == null) { + return; + } + + if (DBG) Log.d(TAG, "Waiting for audio track to complete : " + + audioTrack.hashCode()); + blockUntilDone(params); + if (DBG) Log.d(TAG, "Releasing audio track [" + audioTrack.hashCode() + "]"); + + // The last call to AudioTrack.write( ) will return only after + // all data from the audioTrack has been sent to the mixer, so + // it's safe to release at this point. Make sure release() and the call + // that set the audio track to null are performed atomically. + synchronized (this) { + // Never allow the audioTrack to be observed in a state where + // it is released but non null. The only case this might happen + // is in the various stopFoo methods that call AudioTrack#stop from + // different threads, but they are synchronized on AudioPlayBackHandler#this + // too. + audioTrack.release(); params.setAudioTrack(null); - params.getDispatcher().dispatchUtteranceCompleted(); - mLastSynthesisRequest = null; } + params.getDispatcher().dispatchUtteranceCompleted(); + mLastSynthesisRequest = null; } private static void blockUntilDone(SynthesisMessageParams params) { diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java index 3bcd266..152827d 100644 --- a/core/java/android/util/Patterns.java +++ b/core/java/android/util/Patterns.java @@ -25,9 +25,9 @@ import java.util.regex.Pattern; public class Patterns { /** * Regular expression to match all IANA top-level domains. - * List accurate as of 2010/05/06. List taken from: + * List accurate as of 2011/07/18. List taken from: * http://data.iana.org/TLD/tlds-alpha-by-domain.txt - * This pattern is auto-generated by frameworks/base/common/tools/make-iana-tld-pattern.py + * This pattern is auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py */ public static final String TOP_LEVEL_DOMAIN_STR = "((aero|arpa|asia|a[cdefgilmnoqrstuwxz])" @@ -53,7 +53,7 @@ public class Patterns { + "|u[agksyz]" + "|v[aceginu]" + "|w[fs]" - + "|(xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-mgbaam7a8h|xn\\-\\-mgberp4a5d4ar|xn\\-\\-wgbh1c|xn\\-\\-zckzah)" + + "|(\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)" + "|y[et]" + "|z[amw])"; @@ -65,9 +65,9 @@ public class Patterns { /** * Regular expression to match all IANA top-level domains for WEB_URL. - * List accurate as of 2010/05/06. List taken from: + * List accurate as of 2011/07/18. List taken from: * http://data.iana.org/TLD/tlds-alpha-by-domain.txt - * This pattern is auto-generated by frameworks/base/common/tools/make-iana-tld-pattern.py + * This pattern is auto-generated by frameworks/ex/common/tools/make-iana-tld-pattern.py */ public static final String TOP_LEVEL_DOMAIN_STR_FOR_WEB_URL = "(?:" @@ -94,7 +94,7 @@ public class Patterns { + "|u[agksyz]" + "|v[aceginu]" + "|w[fs]" - + "|(?:xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-80akhbyknj4f|xn\\-\\-9t4b11yi5a|xn\\-\\-deba0ad|xn\\-\\-g6w251d|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-mgbaam7a8h|xn\\-\\-mgberp4a5d4ar|xn\\-\\-wgbh1c|xn\\-\\-zckzah)" + + "|(?:\u03b4\u03bf\u03ba\u03b9\u03bc\u03ae|\u0438\u0441\u043f\u044b\u0442\u0430\u043d\u0438\u0435|\u0440\u0444|\u0441\u0440\u0431|\u05d8\u05e2\u05e1\u05d8|\u0622\u0632\u0645\u0627\u06cc\u0634\u06cc|\u0625\u062e\u062a\u0628\u0627\u0631|\u0627\u0644\u0627\u0631\u062f\u0646|\u0627\u0644\u062c\u0632\u0627\u0626\u0631|\u0627\u0644\u0633\u0639\u0648\u062f\u064a\u0629|\u0627\u0644\u0645\u063a\u0631\u0628|\u0627\u0645\u0627\u0631\u0627\u062a|\u0628\u06be\u0627\u0631\u062a|\u062a\u0648\u0646\u0633|\u0633\u0648\u0631\u064a\u0629|\u0641\u0644\u0633\u0637\u064a\u0646|\u0642\u0637\u0631|\u0645\u0635\u0631|\u092a\u0930\u0940\u0915\u094d\u0937\u093e|\u092d\u093e\u0930\u0924|\u09ad\u09be\u09b0\u09a4|\u0a2d\u0a3e\u0a30\u0a24|\u0aad\u0abe\u0ab0\u0aa4|\u0b87\u0ba8\u0bcd\u0ba4\u0bbf\u0baf\u0bbe|\u0b87\u0bb2\u0b99\u0bcd\u0b95\u0bc8|\u0b9a\u0bbf\u0b99\u0bcd\u0b95\u0baa\u0bcd\u0baa\u0bc2\u0bb0\u0bcd|\u0baa\u0bb0\u0bbf\u0b9f\u0bcd\u0b9a\u0bc8|\u0c2d\u0c3e\u0c30\u0c24\u0c4d|\u0dbd\u0d82\u0d9a\u0dcf|\u0e44\u0e17\u0e22|\u30c6\u30b9\u30c8|\u4e2d\u56fd|\u4e2d\u570b|\u53f0\u6e7e|\u53f0\u7063|\u65b0\u52a0\u5761|\u6d4b\u8bd5|\u6e2c\u8a66|\u9999\u6e2f|\ud14c\uc2a4\ud2b8|\ud55c\uad6d|xn\\-\\-0zwm56d|xn\\-\\-11b5bs3a9aj6g|xn\\-\\-3e0b707e|xn\\-\\-45brj9c|xn\\-\\-80akhbyknj4f|xn\\-\\-90a3ac|xn\\-\\-9t4b11yi5a|xn\\-\\-clchc0ea0b2g2a9gcd|xn\\-\\-deba0ad|xn\\-\\-fiqs8s|xn\\-\\-fiqz9s|xn\\-\\-fpcrj9c3d|xn\\-\\-fzc2c9e2c|xn\\-\\-g6w251d|xn\\-\\-gecrj9c|xn\\-\\-h2brj9c|xn\\-\\-hgbk6aj7f53bba|xn\\-\\-hlcj6aya9esc7a|xn\\-\\-j6w193g|xn\\-\\-jxalpdlp|xn\\-\\-kgbechtv|xn\\-\\-kprw13d|xn\\-\\-kpry57d|xn\\-\\-lgbbat1ad8j|xn\\-\\-mgbaam7a8h|xn\\-\\-mgbayh7gpa|xn\\-\\-mgbbh1a71e|xn\\-\\-mgbc0a9azcg|xn\\-\\-mgberp4a5d4ar|xn\\-\\-o3cw4h|xn\\-\\-ogbpf8fl|xn\\-\\-p1ai|xn\\-\\-pgbs0dh|xn\\-\\-s9brj9c|xn\\-\\-wgbh1c|xn\\-\\-wgbl6a|xn\\-\\-xkc2al3hye2a|xn\\-\\-xkc2dl3a5ee0h|xn\\-\\-yfro4i67o|xn\\-\\-ygbi2ammx|xn\\-\\-zckzah|xxx)" + "|y[et]" + "|z[amw]))"; diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java index bfafa98..e954983 100644 --- a/core/java/android/view/ActionMode.java +++ b/core/java/android/view/ActionMode.java @@ -23,6 +23,36 @@ package android.view; * Examples of good action modes include selection modes, search, content editing, etc. */ public abstract class ActionMode { + private Object mTag; + + /** + * Set a tag object associated with this ActionMode. + * + * <p>Like the tag available to views, this allows applications to associate arbitrary + * data with an ActionMode for later reference. + * + * @param tag Tag to associate with this ActionMode + * + * @see #getTag() + */ + public void setTag(Object tag) { + mTag = tag; + } + + /** + * Retrieve the tag object associated with this ActionMode. + * + * <p>Like the tag available to views, this allows applications to associate arbitrary + * data with an ActionMode for later reference. + * + * @return Tag associated with this ActionMode + * + * @see #setTag(Object) + */ + public Object getTag() { + return mTag; + } + /** * Set the title of the action mode. This method will have no visible effect if * a custom view has been set. diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 4e9c0b7..59cb216 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10756,12 +10756,14 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit // Remember our drawn bit int drawn = mPrivateFlags & DRAWN; - // Invalidate our old position - invalidate(true); - - int oldWidth = mRight - mLeft; int oldHeight = mBottom - mTop; + int newWidth = right - left; + int newHeight = bottom - top; + boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight); + + // Invalidate our old position + invalidate(sizeChanged); mLeft = left; mTop = top; @@ -10770,10 +10772,8 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit mPrivateFlags |= HAS_BOUNDS; - int newWidth = right - left; - int newHeight = bottom - top; - if (newWidth != oldWidth || newHeight != oldHeight) { + if (sizeChanged) { if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) { // A change in dimension means an auto-centered pivot point changes, too mMatrixDirty = true; @@ -10788,7 +10788,7 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit // before this call to setFrame came in, thereby clearing // the DRAWN bit. mPrivateFlags |= DRAWN; - invalidate(true); + invalidate(sizeChanged); // parent display list may need to be recreated based on a change in the bounds // of any child invalidateParentCaches(); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 5f7673a..5624eb4 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3183,6 +3183,24 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** + * @hide + */ + protected void onViewAdded(View child) { + if (mOnHierarchyChangeListener != null) { + mOnHierarchyChangeListener.onChildViewAdded(this, child); + } + } + + /** + * @hide + */ + protected void onViewRemoved(View child) { + if (mOnHierarchyChangeListener != null) { + mOnHierarchyChangeListener.onChildViewRemoved(this, child); + } + } + + /** * Adds a view during layout. This is useful if in your onLayout() method, * you need to add more views (as does the list view for example). * @@ -3283,9 +3301,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager ai.mKeepScreenOn = lastKeepOn; } - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewAdded(this, child); - } + onViewAdded(child); if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) { mGroupFlags |= FLAG_NOTIFY_CHILDREN_ON_DRAWABLE_STATE_CHANGE; @@ -3486,9 +3502,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager view.dispatchDetachedFromWindow(); } - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewRemoved(this, view); - } + onViewRemoved(view); needGlobalAttributesUpdate(false); @@ -3533,8 +3547,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } private void removeViewsInternal(int start, int count) { - final OnHierarchyChangeListener onHierarchyChangeListener = mOnHierarchyChangeListener; - final boolean notifyListener = onHierarchyChangeListener != null; final View focused = mFocused; final boolean detach = mAttachInfo != null; View clearChildFocus = null; @@ -3563,9 +3575,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager needGlobalAttributesUpdate(false); - if (notifyListener) { - onHierarchyChangeListener.onChildViewRemoved(this, view); - } + onViewRemoved(view); } removeFromArray(start, count); @@ -3603,8 +3613,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final View[] children = mChildren; mChildrenCount = 0; - final OnHierarchyChangeListener listener = mOnHierarchyChangeListener; - final boolean notify = listener != null; final View focused = mFocused; final boolean detach = mAttachInfo != null; View clearChildFocus = null; @@ -3630,9 +3638,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager view.dispatchDetachedFromWindow(); } - if (notify) { - listener.onChildViewRemoved(this, view); - } + onViewRemoved(view); view.mParent = null; children[i] = null; @@ -3672,9 +3678,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager child.dispatchDetachedFromWindow(); } - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewRemoved(this, child); - } + onViewRemoved(child); } /** @@ -3960,7 +3964,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager final int left = mLeft; final int top = mTop; - if (dirty.intersect(0, 0, mRight - left, mBottom - top) || + if ((mGroupFlags & FLAG_CLIP_CHILDREN) != FLAG_CLIP_CHILDREN || + dirty.intersect(0, 0, mRight - left, mBottom - top) || (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) { mPrivateFlags &= ~DRAWING_CACHE_VALID; @@ -3978,8 +3983,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager location[CHILD_LEFT_INDEX] = mLeft; location[CHILD_TOP_INDEX] = mTop; - - dirty.set(0, 0, mRight - mLeft, mBottom - mTop); + if ((mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) { + dirty.set(0, 0, mRight - mLeft, mBottom - mTop); + } else { + // in case the dirty rect extends outside the bounds of this container + dirty.union(0, 0, mRight - mLeft, mBottom - mTop); + } if (mLayerType != LAYER_TYPE_NONE) { mLocalDirtyRect.union(dirty); diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index e5f3fc9..da5baf8 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -26,6 +26,7 @@ import com.android.internal.view.IInputMethodSession; import com.android.internal.view.InputBindResult; import android.content.Context; +import android.content.pm.PackageManager; import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; @@ -1580,16 +1581,16 @@ public final class InputMethodManager { } /** - * Set additional input method subtypes. - * @param imeToken Supplies the identifying token given to an input method. + * Set additional input method subtypes. Only a process which shares the same uid with the IME + * can add additional input method subtypes to the IME. + * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to. * @param subtypes subtypes will be added as additional subtypes of the current input method. * @return true if the additional input method subtypes are successfully added. */ - public boolean setAdditionalInputMethodSubtypes( - IBinder imeToken, InputMethodSubtype[] subtypes) { + public boolean setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) { synchronized (mH) { try { - return mService.setAdditionalInputMethodSubtypes(imeToken, subtypes); + return mService.setAdditionalInputMethodSubtypes(imiId, subtypes); } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); return false; diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 5414b79..d7a2526 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -2344,7 +2344,9 @@ public final class WebViewCore { webViewWidth = mWebView.getViewWidth(); viewportWidth = (int) (webViewWidth / adjust); if (viewportWidth == 0) { - Log.w(LOGTAG, "Can't get the viewWidth after the first layout"); + if (DebugFlags.WEB_VIEW_CORE) { + Log.v(LOGTAG, "Can't get the viewWidth yet"); + } } } else { webViewWidth = Math.round(viewportWidth * mCurrentViewScale); diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java index 0ffd087..3f5b571 100644 --- a/core/java/android/widget/Gallery.java +++ b/core/java/android/widget/Gallery.java @@ -16,28 +16,28 @@ package android.widget; -import com.android.internal.R; - import android.annotation.Widget; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; +import android.view.ContextMenu.ContextMenuInfo; import android.view.GestureDetector; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.SoundEffectConstants; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.view.SoundEffectConstants; -import android.view.ContextMenu.ContextMenuInfo; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.Transformation; +import com.android.internal.R; + /** * A view that shows items in a center-locked, horizontally scrolling list. * <p> @@ -122,6 +122,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList * in the future. It will also trigger a selection changed. */ private Runnable mDisableSuppressSelectionChangedRunnable = new Runnable() { + @Override public void run() { mSuppressSelectionChanged = false; selectionChanged(); @@ -171,6 +172,12 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList * drag sends many onScrolls). */ private boolean mIsFirstScroll; + + /** + * If true, mFirstPosition is the position of the rightmost child, and + * the children are ordered right to left. + */ + private boolean mIsRtl = true; public Gallery(Context context) { this(context, null); @@ -418,7 +425,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList } int getLimitedMotionScrollAmount(boolean motionToLeft, int deltaX) { - int extremeItemPosition = motionToLeft ? mItemCount - 1 : 0; + int extremeItemPosition = motionToLeft != mIsRtl ? mItemCount - 1 : 0; View extremeChild = getChildAt(extremeItemPosition - mFirstPosition); if (extremeChild == null) { @@ -490,31 +497,40 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList if (toLeft) { final int galleryLeft = mPaddingLeft; for (int i = 0; i < numChildren; i++) { - final View child = getChildAt(i); + int n = mIsRtl ? (numChildren - 1 - i) : i; + final View child = getChildAt(n); if (child.getRight() >= galleryLeft) { break; } else { + start = n; count++; - mRecycler.put(firstPosition + i, child); + mRecycler.put(firstPosition + n, child); } } + if (!mIsRtl) { + start = 0; + } } else { final int galleryRight = getWidth() - mPaddingRight; for (int i = numChildren - 1; i >= 0; i--) { - final View child = getChildAt(i); + int n = mIsRtl ? numChildren - 1 - i : i; + final View child = getChildAt(n); if (child.getLeft() <= galleryRight) { break; } else { - start = i; + start = n; count++; - mRecycler.put(firstPosition + i, child); + mRecycler.put(firstPosition + n, child); } } + if (mIsRtl) { + start = 0; + } } detachViewsFromParent(start, count); - if (toLeft) { + if (toLeft != mIsRtl) { mFirstPosition += count; } } @@ -614,6 +630,8 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList @Override void layout(int delta, boolean animate) { + mIsRtl = isLayoutRtl(); + int childrenLeft = mSpinnerPadding.left; int childrenWidth = mRight - mLeft - mSpinnerPadding.left - mSpinnerPadding.right; @@ -676,6 +694,45 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList } private void fillToGalleryLeft() { + if (mIsRtl) { + fillToGalleryLeftRtl(); + } else { + fillToGalleryLeftLtr(); + } + } + + private void fillToGalleryLeftRtl() { + int itemSpacing = mSpacing; + int galleryLeft = mPaddingLeft; + int numChildren = getChildCount(); + int numItems = mItemCount; + + // Set state for initial iteration + View prevIterationView = getChildAt(numChildren - 1); + int curPosition; + int curRightEdge; + + if (prevIterationView != null) { + curPosition = mFirstPosition + numChildren; + curRightEdge = prevIterationView.getLeft() - itemSpacing; + } else { + // No children available! + mFirstPosition = curPosition = mItemCount - 1; + curRightEdge = mRight - mLeft - mPaddingRight; + mShouldStopFling = true; + } + + while (curRightEdge > galleryLeft && curPosition < mItemCount) { + prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition, + curRightEdge, false); + + // Set state for next iteration + curRightEdge = prevIterationView.getLeft() - itemSpacing; + curPosition++; + } + } + + private void fillToGalleryLeftLtr() { int itemSpacing = mSpacing; int galleryLeft = mPaddingLeft; @@ -708,6 +765,45 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList } private void fillToGalleryRight() { + if (mIsRtl) { + fillToGalleryRightRtl(); + } else { + fillToGalleryRightLtr(); + } + } + + private void fillToGalleryRightRtl() { + int itemSpacing = mSpacing; + int galleryRight = mRight - mLeft - mPaddingRight; + + // Set state for initial iteration + View prevIterationView = getChildAt(0); + int curPosition; + int curLeftEdge; + + if (prevIterationView != null) { + curPosition = mFirstPosition -1; + curLeftEdge = prevIterationView.getRight() + itemSpacing; + } else { + curPosition = 0; + curLeftEdge = mPaddingLeft; + mShouldStopFling = true; + } + + while (curLeftEdge < galleryRight && curPosition >= 0) { + prevIterationView = makeAndAddView(curPosition, curPosition - mSelectedPosition, + curLeftEdge, true); + + // Remember some state + mFirstPosition = curPosition; + + // Set state for next iteration + curLeftEdge = prevIterationView.getRight() + itemSpacing; + curPosition--; + } + } + + private void fillToGalleryRightLtr() { int itemSpacing = mSpacing; int galleryRight = mRight - mLeft - mPaddingRight; int numChildren = getChildCount(); @@ -745,18 +841,16 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList * * @param position Position in the gallery for the view to obtain * @param offset Offset from the selected position - * @param x X-coordintate indicating where this view should be placed. This + * @param x X-coordinate indicating where this view should be placed. This * will either be the left or right edge of the view, depending on - * the fromLeft paramter - * @param fromLeft Are we posiitoning views based on the left edge? (i.e., + * the fromLeft parameter + * @param fromLeft Are we positioning views based on the left edge? (i.e., * building from left to right)? * @return A view that has been added to the gallery */ - private View makeAndAddView(int position, int offset, int x, - boolean fromLeft) { + private View makeAndAddView(int position, int offset, int x, boolean fromLeft) { View child; - if (!mDataChanged) { child = mRecycler.get(position); if (child != null) { @@ -786,27 +880,26 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList /** * Helper for makeAndAddView to set the position of a view and fill out its - * layout paramters. + * layout parameters. * * @param child The view to position * @param offset Offset from the selected position - * @param x X-coordintate indicating where this view should be placed. This + * @param x X-coordinate indicating where this view should be placed. This * will either be the left or right edge of the view, depending on - * the fromLeft paramter - * @param fromLeft Are we posiitoning views based on the left edge? (i.e., + * the fromLeft parameter + * @param fromLeft Are we positioning views based on the left edge? (i.e., * building from left to right)? */ private void setUpChild(View child, int offset, int x, boolean fromLeft) { // Respect layout params that are already in the view. Otherwise // make some up... - Gallery.LayoutParams lp = (Gallery.LayoutParams) - child.getLayoutParams(); + Gallery.LayoutParams lp = (Gallery.LayoutParams) child.getLayoutParams(); if (lp == null) { lp = (Gallery.LayoutParams) generateDefaultLayoutParams(); } - addViewInLayout(child, fromLeft ? -1 : 0, lp); + addViewInLayout(child, fromLeft != mIsRtl ? -1 : 0, lp); child.setSelected(offset == 0); @@ -883,9 +976,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList return retValue; } - /** - * {@inheritDoc} - */ + @Override public boolean onSingleTapUp(MotionEvent e) { if (mDownTouchPosition >= 0) { @@ -905,9 +996,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList return false; } - /** - * {@inheritDoc} - */ + @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (!mShouldCallbackDuringFling) { @@ -926,9 +1015,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList return true; } - /** - * {@inheritDoc} - */ + @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (localLOGV) Log.v(TAG, String.valueOf(e2.getX() - e1.getX())); @@ -967,9 +1054,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList return true; } - /** - * {@inheritDoc} - */ + @Override public boolean onDown(MotionEvent e) { // Kill any existing fling/scroll @@ -1009,9 +1094,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList onUp(); } - /** - * {@inheritDoc} - */ + @Override public void onLongPress(MotionEvent e) { if (mDownTouchPosition < 0) { @@ -1025,9 +1108,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList // Unused methods from GestureDetector.OnGestureListener below - /** - * {@inheritDoc} - */ + @Override public void onShowPress(MotionEvent e) { } @@ -1164,6 +1245,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList dispatchPress(mSelectedChild); postDelayed(new Runnable() { + @Override public void run() { dispatchUnpress(); } @@ -1278,10 +1360,10 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList // Draw the selected child last return selectedIndex; } else if (i >= selectedIndex) { - // Move the children to the right of the selected child earlier one + // Move the children after the selected child earlier one return i + 1; } else { - // Keep the children to the left of the selected child the same + // Keep the children before the selected child the same return i; } } @@ -1306,7 +1388,6 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList * Responsible for fling behavior. Use {@link #startUsingVelocity(int)} to * initiate a fling. Each frame of the fling is handled in {@link #run()}. * A FlingRunnable will keep re-posting itself until the fling is done. - * */ private class FlingRunnable implements Runnable { /** @@ -1365,6 +1446,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList if (scrollIntoSlots) scrollIntoSlots(); } + @Override public void run() { if (mItemCount == 0) { @@ -1384,15 +1466,17 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList // Pretend that each frame of a fling scroll is a touch scroll if (delta > 0) { - // Moving towards the left. Use first view as mDownTouchPosition - mDownTouchPosition = mFirstPosition; + // Moving towards the left. Use leftmost view as mDownTouchPosition + mDownTouchPosition = mIsRtl ? (mFirstPosition + getChildCount() - 1) : + mFirstPosition; // Don't fling more than 1 screen delta = Math.min(getWidth() - mPaddingLeft - mPaddingRight - 1, delta); } else { - // Moving towards the right. Use last view as mDownTouchPosition + // Moving towards the right. Use rightmost view as mDownTouchPosition int offsetToLast = getChildCount() - 1; - mDownTouchPosition = mFirstPosition + offsetToLast; + mDownTouchPosition = mIsRtl ? mFirstPosition : + (mFirstPosition + getChildCount() - 1); // Don't fling more than 1 screen delta = Math.max(-(getWidth() - mPaddingRight - mPaddingLeft - 1), delta); @@ -1414,7 +1498,6 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList * Gallery extends LayoutParams to provide a place to hold current * Transformation information along with previous position/transformation * info. - * */ public static class LayoutParams extends ViewGroup.LayoutParams { public LayoutParams(Context c, AttributeSet attrs) { diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index f82c61a..46fe407 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -757,39 +757,21 @@ public class GridLayout extends ViewGroup { // Add/remove + /** + * @hide + */ @Override - public void addView(View child, int index, ViewGroup.LayoutParams params) { - super.addView(child, index, params); - invalidateStructure(); - } - - @Override - public void removeView(View view) { - super.removeView(view); - invalidateStructure(); - } - - @Override - public void removeViewInLayout(View view) { - super.removeViewInLayout(view); - invalidateStructure(); - } - - @Override - public void removeViewsInLayout(int start, int count) { - super.removeViewsInLayout(start, count); - invalidateStructure(); - } - - @Override - public void removeViewAt(int index) { - super.removeViewAt(index); + protected void onViewAdded(View child) { + super.onViewAdded(child); invalidateStructure(); } + /** + * @hide + */ @Override - public void removeAllViews() { - super.removeAllViews(); + protected void onViewRemoved(View child) { + super.onViewRemoved(child); invalidateStructure(); } @@ -2301,25 +2283,6 @@ public class GridLayout extends ViewGroup { } /** - * Temporary backward compatibility class for Launcher - to avoid - * dependent multi-project commit. This class will be deleted after - * AppsCustomizePagedView is updated to new API. - * - * @hide - */ - @Deprecated - public static class Group extends Spec { - /** - * @deprecated Please replace with {@link #spec(int, int, Alignment)} - * @hide - */ - @Deprecated - public Group(int start, int size, Alignment alignment) { - super(start, size, alignment, UNDEFINED_FLEXIBILITY); - } - } - - /** * Return a Spec, {@code spec}, where: * <ul> * <li> {@code spec.span = [start, start + size]} </li> diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index f3bda43..b2d1a1e 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -18,8 +18,6 @@ package android.widget; import static android.widget.SuggestionsAdapter.getColumnString; -import com.android.internal.R; - import android.app.PendingIntent; import android.app.SearchManager; import android.app.SearchableInfo; @@ -39,10 +37,14 @@ import android.net.Uri; import android.os.Bundle; import android.speech.RecognizerIntent; import android.text.Editable; +import android.text.Spannable; +import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.TextWatcher; +import android.text.style.ImageSpan; import android.util.AttributeSet; import android.util.Log; +import android.util.TypedValue; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; @@ -51,6 +53,8 @@ import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.TextView.OnEditorActionListener; +import com.android.internal.R; + import java.util.WeakHashMap; /** @@ -87,6 +91,8 @@ public class SearchView extends LinearLayout { private View mSearchEditFrame; private View mVoiceButton; private SearchAutoComplete mQueryTextView; + private View mDropDownAnchor; + private ImageView mSearchHintIcon; private boolean mSubmitButtonEnabled; private CharSequence mQueryHint; private boolean mQueryRefinement; @@ -195,6 +201,7 @@ public class SearchView extends LinearLayout { mSubmitButton = findViewById(R.id.search_go_btn); mCloseButton = (ImageView) findViewById(R.id.search_close_btn); mVoiceButton = findViewById(R.id.search_voice_btn); + mSearchHintIcon = (ImageView) findViewById(R.id.search_mag_icon); mSearchButton.setOnClickListener(mOnClickListener); mCloseButton.setOnClickListener(mOnClickListener); @@ -244,7 +251,20 @@ public class SearchView extends LinearLayout { mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mDropDownAnchor = findViewById(mQueryTextView.getDropDownAnchor()); + if (mDropDownAnchor != null) { + mDropDownAnchor.addOnLayoutChangeListener(new OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int left, int top, int right, int bottom, + int oldLeft, int oldTop, int oldRight, int oldBottom) { + adjustDropDownSizeAndPosition(); + } + + }); + } + updateViewsVisibility(mIconifiedByDefault); + updateQueryHint(); } /** @@ -263,7 +283,7 @@ public class SearchView extends LinearLayout { } // Cache the voice search capability mVoiceButtonEnabled = hasVoiceSearch(); - updateViewsVisibility(mIconifiedByDefault); + updateViewsVisibility(isIconified()); } /** @@ -300,7 +320,6 @@ public class SearchView extends LinearLayout { mQueryTextView.clearFocus(); setImeVisibility(false); mClearingFocus = false; - updateViewsVisibility(mIconifiedByDefault); } /** @@ -555,6 +574,7 @@ public class SearchView extends LinearLayout { mSearchButton.setVisibility(visCollapsed); updateSubmitButton(hasText); mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE); + mSearchHintIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE); updateCloseButton(); updateVoiceButton(!hasText); updateSubmitArea(); @@ -822,9 +842,29 @@ public class SearchView extends LinearLayout { return result; } + private int getSearchIconId() { + TypedValue outValue = new TypedValue(); + getContext().getTheme().resolveAttribute(com.android.internal.R.attr.searchViewSearchIcon, + outValue, true); + return outValue.resourceId; + } + + private CharSequence getDecoratedHint(CharSequence hintText) { + // If the field is always expanded, then don't add the search icon to the hint + if (!mIconifiedByDefault) return hintText; + + SpannableStringBuilder ssb = new SpannableStringBuilder(" "); // for the icon + ssb.append(hintText); + Drawable searchIcon = getContext().getResources().getDrawable(getSearchIconId()); + int textSize = (int) (mQueryTextView.getTextSize() * 1.25); + searchIcon.setBounds(0, 0, textSize, textSize); + ssb.setSpan(new ImageSpan(searchIcon), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + return ssb; + } + private void updateQueryHint() { if (mQueryHint != null) { - mQueryTextView.setHint(mQueryHint); + mQueryTextView.setHint(getDecoratedHint(mQueryHint)); } else if (mSearchable != null) { CharSequence hint = null; int hintId = mSearchable.getHintId(); @@ -832,8 +872,10 @@ public class SearchView extends LinearLayout { hint = getContext().getString(hintId); } if (hint != null) { - mQueryTextView.setHint(hint); + mQueryTextView.setHint(getDecoratedHint(hint)); } + } else { + mQueryTextView.setHint(getDecoratedHint("")); } } @@ -922,9 +964,13 @@ public class SearchView extends LinearLayout { CharSequence text = mQueryTextView.getText(); if (TextUtils.isEmpty(text)) { if (mIconifiedByDefault) { - // query field already empty, hide the keyboard and remove focus - clearFocus(); - setImeVisibility(false); + // If the app doesn't override the close behavior + if (mOnCloseListener == null || !mOnCloseListener.onClose()) { + // hide the keyboard and remove focus + clearFocus(); + // collapse the search field + updateViewsVisibility(true); + } } } else { mQueryTextView.setText(""); @@ -932,10 +978,6 @@ public class SearchView extends LinearLayout { setImeVisibility(true); } - if (mIconifiedByDefault && (mOnCloseListener == null || !mOnCloseListener.onClose())) { - updateViewsVisibility(mIconifiedByDefault); - setImeVisibility(false); - } } private void onSearchClicked() { @@ -975,6 +1017,28 @@ public class SearchView extends LinearLayout { updateFocusedState(mQueryTextView.hasFocus()); } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + } + + private void adjustDropDownSizeAndPosition() { + if (mDropDownAnchor.getWidth() > 1) { + Resources res = getContext().getResources(); + int anchorPadding = mSearchPlate.getPaddingLeft(); + Rect dropDownPadding = new Rect(); + int iconOffset = mIconifiedByDefault + ? res.getDimensionPixelSize(R.dimen.dropdownitem_icon_width) + + res.getDimensionPixelSize(R.dimen.dropdownitem_text_padding_left) + : 0; + mQueryTextView.getDropDownBackground().getPadding(dropDownPadding); + mQueryTextView.setDropDownHorizontalOffset(-(dropDownPadding.left + iconOffset) + + anchorPadding); + mQueryTextView.setDropDownWidth(mDropDownAnchor.getWidth() + dropDownPadding.left + + dropDownPadding.right + iconOffset - (anchorPadding)); + } + } + private boolean onItemClicked(int position, int actionKey, String actionMsg) { if (mOnSuggestionListener == null || !mOnSuggestionListener.onSuggestionClick(position)) { @@ -1393,5 +1457,32 @@ public class SearchView extends LinearLayout { public boolean enoughToFilter() { return mThreshold <= 0 || super.enoughToFilter(); } + + @Override + public boolean onKeyPreIme(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + // special case for the back key, we do not even try to send it + // to the drop down list but instead, consume it immediately + if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.startTracking(event, this); + } + return true; + } else if (event.getAction() == KeyEvent.ACTION_UP) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.handleUpEvent(event); + } + if (event.isTracking() && !event.isCanceled()) { + mSearchView.clearFocus(); + mSearchView.setImeVisibility(false); + return true; + } + } + } + return super.onKeyPreIme(keyCode, event); + } + } } diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java index 2cfc016..9e32c9a 100644 --- a/core/java/android/widget/SuggestionsAdapter.java +++ b/core/java/android/widget/SuggestionsAdapter.java @@ -16,8 +16,6 @@ package android.widget; -import com.android.internal.R; - import android.app.SearchDialog; import android.app.SearchManager; import android.app.SearchableInfo; @@ -47,6 +45,8 @@ import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; +import com.android.internal.R; + import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -88,8 +88,8 @@ class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListene private int mIconName2Col = INVALID_INDEX; private int mFlagsCol = INVALID_INDEX; - private final Runnable mStartSpinnerRunnable; - private final Runnable mStopSpinnerRunnable; + // private final Runnable mStartSpinnerRunnable; + // private final Runnable mStopSpinnerRunnable; /** * The amount of time we delay in the filter when the user presses the delete key. @@ -113,17 +113,18 @@ class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListene mOutsideDrawablesCache = outsideDrawablesCache; - mStartSpinnerRunnable = new Runnable() { - public void run() { - // mSearchView.setWorking(true); // TODO: - } - }; - mStopSpinnerRunnable = new Runnable() { - public void run() { - // mSearchView.setWorking(false); // TODO: - } - }; + // mStartSpinnerRunnable = new Runnable() { + // public void run() { + // // mSearchView.setWorking(true); // TODO: + // } + // }; + // + // mStopSpinnerRunnable = new Runnable() { + // public void run() { + // // mSearchView.setWorking(false); // TODO: + // } + // }; // delay 500ms when deleting getFilter().setDelayer(new Filter.Delayer() { @@ -341,10 +342,10 @@ class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListene } if (views.mIcon1 != null) { - setViewDrawable(views.mIcon1, getIcon1(cursor)); + setViewDrawable(views.mIcon1, getIcon1(cursor), View.INVISIBLE); } if (views.mIcon2 != null) { - setViewDrawable(views.mIcon2, getIcon2(cursor)); + setViewDrawable(views.mIcon2, getIcon2(cursor), View.GONE); } if (mQueryRefinement == REFINE_ALL || (mQueryRefinement == REFINE_BY_ENTRY @@ -414,13 +415,13 @@ class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListene * Sets the drawable in an image view, makes sure the view is only visible if there * is a drawable. */ - private void setViewDrawable(ImageView v, Drawable drawable) { + private void setViewDrawable(ImageView v, Drawable drawable, int nullVisibility) { // Set the icon even if the drawable is null, since we need to clear any // previous icon. v.setImageDrawable(drawable); if (drawable == null) { - v.setVisibility(View.GONE); + v.setVisibility(nullVisibility); } else { v.setVisibility(View.VISIBLE); diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 812f92b..ce0299c 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -68,5 +68,5 @@ interface IInputMethodManager { boolean setCurrentInputMethodSubtype(in InputMethodSubtype subtype); boolean switchToLastInputMethod(in IBinder token); boolean setInputMethodEnabled(String id, boolean enabled); - boolean setAdditionalInputMethodSubtypes(in IBinder token, in InputMethodSubtype[] subtypes); + boolean setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes); } diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp index 6a13876..30fe298 100644 --- a/core/jni/android/graphics/TextLayoutCache.cpp +++ b/core/jni/android/graphics/TextLayoutCache.cpp @@ -323,9 +323,7 @@ size_t TextLayoutCacheValue::getSize() { void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count, - size_t contextCount, int dirFlags) { - bool isRTL = dirFlags & 0x1; - + size_t contextCount, bool isRTL) { font->klass = &harfbuzzSkiaClass; font->userData = 0; // The values which harfbuzzSkiaClass returns are already scaled to @@ -374,10 +372,10 @@ void TextLayoutCacheValue::setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec void TextLayoutCacheValue::shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count, - size_t contextCount, int dirFlags) { + size_t contextCount, bool isRTL) { // Setup Harfbuzz Shaper setupShaperItem(shaperItem, font, fontData, paint, chars, start, count, - contextCount, dirFlags); + contextCount, isRTL); // Shape resetGlyphArrays(shaperItem); @@ -430,7 +428,7 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar LOGD("computeValuesWithHarfbuzz -- forcing run with LTR=%d RTL=%d", forceLTR, forceRTL); #endif - computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, + computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, forceRTL, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount); if (forceRTL && *outGlyphsCount > 1) { @@ -451,10 +449,15 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar LOGD("computeValuesWithHarfbuzz -- dirFlags=%d run-count=%d paraDir=%d", dirFlags, rc, paraDir); #endif if (rc == 1 || !U_SUCCESS(status)) { + bool isRTL = (paraDir == 1); +#if DEBUG_GLYPHS + LOGD("computeValuesWithHarfbuzz -- processing SINGLE run " + "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL); +#endif computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, - dirFlags, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount); + isRTL, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount); - if (dirFlags == 1 && *outGlyphsCount > 1) { + if (isRTL && *outGlyphsCount > 1) { reverseGlyphArray(*outGlyphs, *outGlyphsCount); } } else { @@ -485,14 +488,14 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar lengthRun = endRun - startRun; - int newFlags = (runDir == UBIDI_RTL) ? kDirection_RTL : kDirection_LTR; + bool isRTL = (runDir == UBIDI_RTL); jfloat runTotalAdvance = 0; #if DEBUG_GLYPHS - LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d newFlags=%d", - startRun, lengthRun, newFlags); + LOGD("computeValuesWithHarfbuzz -- run-start=%d run-len=%d isRTL=%d", + startRun, lengthRun, isRTL); #endif computeRunValuesWithHarfbuzz(paint, chars, startRun, - lengthRun, contextCount, newFlags, + lengthRun, contextCount, isRTL, outAdvances, &runTotalAdvance, &runGlyphs, &runGlyphsCount); @@ -506,7 +509,7 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar LOGD(" -- glyphs[%d]=%d", j, runGlyphs[j]); } #endif - glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, newFlags)); + glyphRuns.push(GlyphRun(runGlyphs, runGlyphsCount, isRTL)); } *outGlyphs = new jchar[*outGlyphsCount]; @@ -528,13 +531,15 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar ubidi_close(bidi); } else { // Cannot run BiDi, just consider one Run + bool isRTL = (bidiReq = 1) || (bidiReq = UBIDI_DEFAULT_RTL); #if DEBUG_GLYPHS - LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering only one Run"); + LOGD("computeValuesWithHarfbuzz -- cannot run BiDi, considering a SINGLE Run " + "-- run-start=%d run-len=%d isRTL=%d", start, count, isRTL); #endif - computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, dirFlags, + computeRunValuesWithHarfbuzz(paint, chars, start, count, contextCount, isRTL, outAdvances, outTotalAdvance, outGlyphs, outGlyphsCount); - if (dirFlags == 1 && *outGlyphsCount > 1) { + if (isRTL && *outGlyphsCount > 1) { reverseGlyphArray(*outGlyphs, *outGlyphsCount); } } @@ -545,17 +550,15 @@ void TextLayoutCacheValue::computeValuesWithHarfbuzz(SkPaint* paint, const UChar } void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, - size_t start, size_t count, size_t contextCount, int dirFlags, + size_t start, size_t count, size_t contextCount, bool isRTL, jfloat* outAdvances, jfloat* outTotalAdvance, jchar** outGlyphs, size_t* outGlyphsCount) { - bool isRTL = dirFlags & 0x1; - HB_ShaperItem shaperItem; HB_FontRec font; FontData fontData; shapeWithHarfbuzz(&shaperItem, &font, &fontData, paint, chars, start, count, - contextCount, dirFlags); + contextCount, isRTL); #if DEBUG_GLYPHS LOGD("HARFBUZZ -- num_glypth=%d - kerning_applied=%d", shaperItem.num_glyphs, diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h index 690caac..10dee87 100644 --- a/core/jni/android/graphics/TextLayoutCache.h +++ b/core/jni/android/graphics/TextLayoutCache.h @@ -128,11 +128,11 @@ public: static void setupShaperItem(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, - int dirFlags); + bool isRTL); static void shapeWithHarfbuzz(HB_ShaperItem* shaperItem, HB_FontRec* font, FontData* fontData, SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, - int dirFlags); + bool isRTL); static void computeValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, size_t count, size_t contextCount, int dirFlags, @@ -179,7 +179,7 @@ private: static void resetGlyphArrays(HB_ShaperItem* shaperItem); static void computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars, size_t start, - size_t count, size_t contextCount, int dirFlags, + size_t count, size_t contextCount, bool isRTL, jfloat* outAdvances, jfloat* outTotalAdvance, jchar** outGlyphs, size_t* outGlyphsCount); }; // TextLayoutCacheValue diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml index 790ac6b..f6b5b53 100644 --- a/core/res/res/layout/search_bar.xml +++ b/core/res/res/layout/search_bar.xml @@ -66,7 +66,6 @@ android:layout_height="wrap_content" android:layout_weight="1" android:maxWidth="600dip" - android:iconifiedByDefault="false" android:layout_gravity="center_vertical" /> diff --git a/core/res/res/layout/search_dropdown_item_icons_2line.xml b/core/res/res/layout/search_dropdown_item_icons_2line.xml index 53906f9..acef2cc 100644 --- a/core/res/res/layout/search_dropdown_item_icons_2line.xml +++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml @@ -19,21 +19,21 @@ --> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:paddingLeft="4dip" - android:paddingRight="2dip" + android:paddingLeft="@dimen/dropdownitem_text_padding_left" + android:paddingRight="4dip" android:layout_width="match_parent" android:layout_height="?android:attr/searchResultListItemHeight" > <!-- Icons come first in the layout, since their placement doesn't depend on the placement of the text views. --> <ImageView android:id="@android:id/icon1" - android:layout_width="48dip" + android:layout_width="@dimen/dropdownitem_icon_width" android:layout_height="48dip" android:scaleType="centerInside" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_alignParentBottom="true" - android:visibility="gone" /> + android:visibility="invisible" /> <ImageView android:id="@+id/edit_query" android:layout_width="48dip" diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml index fee27eb..6b70d8d 100644 --- a/core/res/res/layout/search_view.xml +++ b/core/res/res/layout/search_view.xml @@ -22,6 +22,8 @@ android:id="@+id/search_bar" android:layout_width="match_parent" android:layout_height="match_parent" + android:paddingLeft="8dip" + android:paddingRight="8dip" android:orientation="horizontal" > @@ -30,7 +32,7 @@ android:id="@+id/search_badge" android:layout_width="wrap_content" android:layout_height="match_parent" - android:layout_gravity="center_vertical" + android:gravity="center_vertical" android:layout_marginBottom="2dip" android:drawablePadding="0dip" android:textAppearance="?android:attr/textAppearanceMedium" @@ -54,12 +56,21 @@ android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" - android:layout_marginLeft="8dip" - android:layout_marginRight="8dip" android:layout_marginTop="4dip" android:layout_marginBottom="4dip" android:orientation="horizontal"> + <ImageView + android:id="@+id/search_mag_icon" + android:layout_width="@dimen/dropdownitem_icon_width" + android:layout_height="wrap_content" + android:scaleType="centerInside" + android:layout_marginLeft="@dimen/dropdownitem_text_padding_left" + android:layout_gravity="center_vertical" + android:src="?android:attr/searchViewSearchIcon" + android:visibility="gone" + /> + <!-- Inner layout contains the app icon, button(s) and EditText --> <LinearLayout android:id="@+id/search_plate" @@ -70,14 +81,6 @@ android:orientation="horizontal" android:background="?android:attr/searchViewTextField"> - <ImageView - android:id="@+id/search_app_icon" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_gravity="center_vertical" - android:src="?android:attr/searchViewSearchIcon" - /> - <view class="android.widget.SearchView$SearchAutoComplete" android:id="@+id/search_src_text" android:layout_height="36dip" @@ -85,8 +88,8 @@ android:layout_weight="1" android:minWidth="@dimen/search_view_text_min_width" android:layout_gravity="bottom" - android:paddingLeft="8dip" - android:paddingRight="6dip" + android:paddingLeft="@dimen/dropdownitem_text_padding_left" + android:paddingRight="@dimen/dropdownitem_text_padding_right" android:singleLine="true" android:ellipsize="end" android:background="@null" @@ -100,7 +103,7 @@ <ImageView android:id="@+id/search_close_btn" - android:layout_width="wrap_content" + android:layout_width="@dimen/dropdownitem_icon_width" android:layout_height="match_parent" android:paddingLeft="8dip" android:paddingRight="8dip" @@ -131,7 +134,7 @@ android:visibility="gone" android:focusable="true" /> - + <ImageView android:id="@+id/search_voice_btn" android:layout_width="wrap_content" diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 7aabf80..0ed8076 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -141,4 +141,13 @@ <!-- The default gap between components in a layout. --> <dimen name="default_gap">16dip</dimen> + <!-- Text padding for dropdown items --> + <dimen name="dropdownitem_text_padding_left">6dip</dimen> + + <!-- Text padding for dropdown items --> + <dimen name="dropdownitem_text_padding_right">6dip</dimen> + + <!-- Width of the icon in a dropdown list --> + <dimen name="dropdownitem_icon_width">48dip</dimen> + </resources> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 5b5e7c3..d647467 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -563,8 +563,8 @@ <style name="Widget.DropDownItem"> <item name="android:textAppearance">@style/TextAppearance.Widget.DropDownItem</item> - <item name="android:paddingLeft">6dip</item> - <item name="android:paddingRight">6dip</item> + <item name="android:paddingLeft">@dimen/dropdownitem_text_padding_left</item> + <item name="android:paddingRight">@dimen/dropdownitem_text_padding_right</item> <item name="android:gravity">center_vertical</item> </style> diff --git a/core/tests/coretests/src/android/database/MatrixCursorTest.java b/core/tests/coretests/src/android/database/MatrixCursorTest.java index cddc6c4..cdab638 100644 --- a/core/tests/coretests/src/android/database/MatrixCursorTest.java +++ b/core/tests/coretests/src/android/database/MatrixCursorTest.java @@ -16,6 +16,8 @@ package android.database; +import android.test.MoreAsserts; + import junit.framework.TestCase; import java.util.*; @@ -33,6 +35,7 @@ public class MatrixCursorTest extends TestCase { cursor.moveToNext(); assertTrue(cursor.isNull(0)); assertNull(cursor.getString(0)); + assertNull(cursor.getBlob(0)); assertEquals(0, cursor.getShort(0)); assertEquals(0, cursor.getInt(0)); assertEquals(0L, cursor.getLong(0)); @@ -49,7 +52,8 @@ public class MatrixCursorTest extends TestCase { .add(2) .add(3) .add(4) - .add(5); + .add(5) + .add(new byte[] {(byte) 0xaa, (byte) 0x55}); cursor.moveToNext(); @@ -61,7 +65,8 @@ public class MatrixCursorTest extends TestCase { .add("2") .add("3") .add("4") - .add("5"); + .add("5") + .add(new byte[] {(byte) 0xaa, (byte) 0x55}); cursor.moveToNext(); checkValues(cursor); @@ -73,7 +78,7 @@ public class MatrixCursorTest extends TestCase { public void testAddArray() { MatrixCursor cursor = newMatrixCursor(); - cursor.addRow(new Object[] { "a", 1, 2, 3, 4, 5 }); + cursor.addRow(new Object[] { "a", 1, 2, 3, 4, 5, new byte[] {(byte) 0xaa, (byte) 0x55} }); cursor.moveToNext(); checkValues(cursor); @@ -86,7 +91,7 @@ public class MatrixCursorTest extends TestCase { public void testAddIterable() { MatrixCursor cursor = newMatrixCursor(); - cursor.addRow(Arrays.asList("a", 1, 2, 3, 4, 5)); + cursor.addRow(Arrays.asList("a", 1, 2, 3, 4, 5, new byte[] {(byte) 0xaa, (byte) 0x55})); cursor.moveToNext(); checkValues(cursor); @@ -96,7 +101,8 @@ public class MatrixCursorTest extends TestCase { } catch (IllegalArgumentException e) { /* expected */ } try { - cursor.addRow(Arrays.asList("a", 1, 2, 3, 4, 5, "Too many!")); + cursor.addRow(Arrays.asList("a", 1, 2, 3, 4, 5, + new byte[] {(byte) 0xaa, (byte) 0x55}, "Too many!")); fail(); } catch (IllegalArgumentException e) { /* expected */ } } @@ -105,7 +111,7 @@ public class MatrixCursorTest extends TestCase { MatrixCursor cursor = newMatrixCursor(); cursor.addRow(new NonIterableArrayList<Object>( - Arrays.asList("a", 1, 2, 3, 4, 5))); + Arrays.asList("a", 1, 2, 3, 4, 5, new byte[] {(byte) 0xaa, (byte) 0x55}))); cursor.moveToNext(); checkValues(cursor); @@ -116,7 +122,8 @@ public class MatrixCursorTest extends TestCase { try { cursor.addRow(new NonIterableArrayList<Object>( - Arrays.asList("a", 1, 2, 3, 4, 5, "Too many!"))); + Arrays.asList("a", 1, 2, 3, 4, 5, + new byte[] {(byte) 0xaa, (byte) 0x55}, "Too many!"))); fail(); } catch (IllegalArgumentException e) { /* expected */ } } @@ -137,7 +144,7 @@ public class MatrixCursorTest extends TestCase { private MatrixCursor newMatrixCursor() { return new MatrixCursor(new String[] { - "string", "short", "int", "long", "float", "double" }); + "string", "short", "int", "long", "float", "double", "blob" }); } private void checkValues(MatrixCursor cursor) { @@ -147,6 +154,7 @@ public class MatrixCursorTest extends TestCase { assertEquals(3, cursor.getLong(3)); assertEquals(4.0f, cursor.getFloat(4)); assertEquals(5.0D, cursor.getDouble(5)); + MoreAsserts.assertEquals(new byte[] {(byte) 0xaa, (byte) 0x55}, cursor.getBlob(6)); } } diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java index 440aeb5..0b50af3 100644 --- a/core/tests/coretests/src/android/util/JsonReaderTest.java +++ b/core/tests/coretests/src/android/util/JsonReaderTest.java @@ -858,7 +858,7 @@ public final class JsonReaderTest extends TestCase { } public void testFailWithPosition() throws IOException { - testFailWithPosition("Expected literal value at line 6 column 3", + testFailWithPosition("Expected literal value at line 6 column 3", "[\n\n\n\n\n0,}]"); } diff --git a/core/tests/coretests/src/android/util/PatternsTest.java b/core/tests/coretests/src/android/util/PatternsTest.java index aad3fe1..9519b9f 100644 --- a/core/tests/coretests/src/android/util/PatternsTest.java +++ b/core/tests/coretests/src/android/util/PatternsTest.java @@ -39,6 +39,10 @@ public class PatternsTest extends TestCase { t = Patterns.TOP_LEVEL_DOMAIN.matcher("xn--0zwm56d").matches(); assertTrue("Missed valid TLD", t); + // One of the new top level internationalized domain. + t = Patterns.TOP_LEVEL_DOMAIN.matcher("\uD55C\uAD6D").matches(); + assertTrue("Missed valid TLD", t); + t = Patterns.TOP_LEVEL_DOMAIN.matcher("mem").matches(); assertFalse("Matched invalid TLD!", t); @@ -80,6 +84,9 @@ public class PatternsTest extends TestCase { assertTrue("Valid URL", t); t = Patterns.WEB_URL.matcher("\uD604\uAE08\uC601\uC218\uC99D.kr").matches(); assertTrue("Valid URL", t); + // URL with international TLD. + t = Patterns.WEB_URL.matcher("\uB3C4\uBA54\uC778.\uD55C\uAD6D").matches(); + assertTrue("Valid URL", t); t = Patterns.WEB_URL.matcher("http://brainstormtech.blogs.fortune.cnn.com/2010/03/11/" + "top-five-moments-from-eric-schmidt\u2019s-talk-in-abu-dhabi/").matches(); |