diff options
Diffstat (limited to 'core/java')
18 files changed, 163 insertions, 132 deletions
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java index 6e589e4..bcab66e 100644 --- a/core/java/android/animation/AnimatorInflater.java +++ b/core/java/android/animation/AnimatorInflater.java @@ -215,7 +215,7 @@ public class AnimatorInflater { (toType <= TypedValue.TYPE_LAST_COLOR_INT))) { // special case for colors: ignore valueType and get ints getFloats = false; - anim.setEvaluator(new RGBEvaluator()); + anim.setEvaluator(new ArgbEvaluator()); } if (getFloats) { diff --git a/core/java/android/animation/RGBEvaluator.java b/core/java/android/animation/ArgbEvaluator.java index bae0af0..c3875be 100644 --- a/core/java/android/animation/RGBEvaluator.java +++ b/core/java/android/animation/ArgbEvaluator.java @@ -20,7 +20,7 @@ package android.animation; * This evaluator can be used to perform type interpolation between integer * values that represent ARGB colors. */ -public class RGBEvaluator implements TypeEvaluator { +public class ArgbEvaluator implements TypeEvaluator { /** * This function returns the calculated in-between value for a color diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index cfecec1..f884473 100755 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -862,7 +862,7 @@ public class ValueAnimator extends Animator { * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values * are not one of these primitive types, or if different evaluation is desired (such as is * necessary with int values that represent colors), a custom evaluator needs to be assigned. - * For example, when running an animation on color values, the {@link RGBEvaluator} + * For example, when running an animation on color values, the {@link ArgbEvaluator} * should be used to get correct RGB color interpolation. * * <p>If this ValueAnimator has only one set of values being animated between, this evaluator diff --git a/core/java/android/content/pm/ComponentInfo.java b/core/java/android/content/pm/ComponentInfo.java index f16c4ef..2812477 100644 --- a/core/java/android/content/pm/ComponentInfo.java +++ b/core/java/android/content/pm/ComponentInfo.java @@ -98,6 +98,13 @@ public class ComponentInfo extends PackageItemInfo { } return name; } + + /** + * Return whether this component and its enclosing application are enabled. + */ + public boolean isEnabled() { + return enabled && applicationInfo.enabled; + } /** * Return the icon resource identifier to use for this component. If diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java index 5e96928..c76cc6c 100644 --- a/core/java/android/database/sqlite/SQLiteStatement.java +++ b/core/java/android/database/sqlite/SQLiteStatement.java @@ -131,6 +131,10 @@ public class SQLiteStatement extends SQLiteProgram long retValue = native_1x1_long(); mDatabase.logTimeStat(mSql, timeStart); return retValue; + } catch (SQLiteDoneException e) { + throw new SQLiteDoneException( + "expected 1 row from this query but query returned no data. check the query: " + + mSql); } finally { releaseAndUnlock(); } @@ -150,6 +154,10 @@ public class SQLiteStatement extends SQLiteProgram String retValue = native_1x1_string(); mDatabase.logTimeStat(mSql, timeStart); return retValue; + } catch (SQLiteDoneException e) { + throw new SQLiteDoneException( + "expected 1 row from this query but query returned no data. check the query: " + + mSql); } finally { releaseAndUnlock(); } @@ -172,6 +180,10 @@ public class SQLiteStatement extends SQLiteProgram } catch (IOException ex) { Log.e(TAG, "simpleQueryForBlobFileDescriptor() failed", ex); return null; + } catch (SQLiteDoneException e) { + throw new SQLiteDoneException( + "expected 1 row from this query but query returned no data. check the query: " + + mSql); } finally { releaseAndUnlock(); } diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index 4688847..4f188f8 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -414,8 +414,6 @@ public class Environment { * emulated. If true, the device does not have real external storage * and certain system services such as the package manager use this * to determine where to install an application. - * - * @hide */ public static boolean isExternalStorageEmulated() { if (mIsExternalStorageEmulated == null) { diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java index d1ca0c9..ee091f0 100644 --- a/core/java/android/provider/ContactsContract.java +++ b/core/java/android/provider/ContactsContract.java @@ -3430,12 +3430,6 @@ public final class ContactsContract { * <th colspan='4'>PhoneLookup</th> * </tr> * <tr> - * <td>long</td> - * <td>{@link #_ID}</td> - * <td>read-only</td> - * <td>Data row ID.</td> - * </tr> - * <tr> * <td>String</td> * <td>{@link #NUMBER}</td> * <td>read-only</td> @@ -3462,6 +3456,12 @@ public final class ContactsContract { * <th colspan='4'>Join with {@link Contacts}</th> * </tr> * <tr> + * <td>long</td> + * <td>{@link #_ID}</td> + * <td>read-only</td> + * <td>Contact ID.</td> + * </tr> + * <tr> * <td>String</td> * <td>{@link #LOOKUP_KEY}</td> * <td>read-only</td> diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 366393c..7c55f7b 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -1073,11 +1073,6 @@ public final class ViewRoot extends Handler implements ViewParent, } } surfaceChanged = true; - - if (mAttachInfo.mHardwareRenderer != null) { - // This will bail out early if already initialized - mAttachInfo.mHardwareRenderer.initialize(mHolder); - } } if (surfaceChanged) { mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder, diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java index 4c2f0b4..1313fcc 100644 --- a/core/java/android/webkit/WebTextView.java +++ b/core/java/android/webkit/WebTextView.java @@ -204,11 +204,6 @@ import junit.framework.Assert; case KeyEvent.KEYCODE_DPAD_RIGHT: case KeyEvent.KEYCODE_DPAD_UP: case KeyEvent.KEYCODE_DPAD_DOWN: - if (!mWebView.nativeCursorMatchesFocus()) { - return down ? mWebView.onKeyDown(keyCode, event) : mWebView - .onKeyUp(keyCode, event); - - } isArrowKey = true; break; } @@ -258,10 +253,6 @@ import junit.framework.Assert; if (isPopupShowing()) { return super.dispatchKeyEvent(event); } - if (!mWebView.nativeCursorMatchesFocus()) { - return down ? mWebView.onKeyDown(keyCode, event) : mWebView - .onKeyUp(keyCode, event); - } // Center key should be passed to a potential onClick if (!down) { mWebView.centerKeyPressOnTextField(); @@ -753,12 +744,7 @@ import junit.framework.Assert; if (event.getAction() != MotionEvent.ACTION_MOVE) { return false; } - // If the Cursor is not on the text input, webview should handle the - // trackball - if (!mWebView.nativeCursorMatchesFocus()) { - return mWebView.onTrackballEvent(event); - } - Spannable text = (Spannable) getText(); + Spannable text = getText(); MovementMethod move = getMovementMethod(); if (move != null && getLayout() != null && move.onTrackballEvent(this, text, event)) { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index f98ad74..4a9e441 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -56,6 +56,7 @@ import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.os.SystemClock; import android.provider.Settings; import android.speech.tts.TextToSpeech; import android.text.Selection; @@ -2617,10 +2618,6 @@ public class WebView extends AbsoluteLayout private int computeRealHorizontalScrollRange() { if (mDrawHistory) { return mHistoryWidth; - } else if (mHorizontalScrollBarMode == SCROLLBAR_ALWAYSOFF - && !mZoomManager.canZoomOut()) { - // only honor the scrollbar mode when it is at minimum zoom level - return computeHorizontalScrollExtent(); } else { // to avoid rounding error caused unnecessary scrollbar, use floor return (int) Math.floor(mContentWidth * mZoomManager.getScale()); @@ -2651,10 +2648,6 @@ public class WebView extends AbsoluteLayout private int computeRealVerticalScrollRange() { if (mDrawHistory) { return mHistoryHeight; - } else if (mVerticalScrollBarMode == SCROLLBAR_ALWAYSOFF - && !mZoomManager.canZoomOut()) { - // only honor the scrollbar mode when it is at minimum zoom level - return computeVerticalScrollExtent(); } else { // to avoid rounding error caused unnecessary scrollbar, use floor return (int) Math.floor(mContentHeight * mZoomManager.getScale()); @@ -5329,17 +5322,10 @@ public class WebView extends AbsoluteLayout + " numPointers=" + ev.getPointerCount()); } - int action = ev.getAction(); - float x = ev.getX(); - float y = ev.getY(); - long eventTime = ev.getEventTime(); - - // mDeferMultitouch is a hack for layout tests, where it is used to - // force passing multi-touch events to webkit. - // FIXME: always pass multi-touch events to webkit and remove everything - // related to mDeferMultitouch. - if (ev.getPointerCount() > 1 && - (mDeferMultitouch || mZoomManager.isZoomScaleFixed())) { + // Always pass multi-touch event to WebKit first. + // If WebKit doesn't consume it and set preventDefault to true, + // WebView's private handler will handle it. + if (ev.getPointerCount() > 1) { if (DebugFlags.WEB_VIEW) { Log.v(LOGTAG, "passing " + ev.getPointerCount() + " points to webkit"); } @@ -5347,59 +5333,15 @@ public class WebView extends AbsoluteLayout return true; } - final ScaleGestureDetector detector = - mZoomManager.getMultiTouchGestureDetector(); - - if (mZoomManager.supportsMultiTouchZoom() && ev.getPointerCount() > 1) { - if (!detector.isInProgress() && - ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) { - // Insert a fake pointer down event in order to start - // the zoom scale detector. - MotionEvent temp = MotionEvent.obtain(ev); - // Clear the original event and set it to - // ACTION_POINTER_DOWN. - try { - temp.setAction(temp.getAction() & - ~MotionEvent.ACTION_MASK | - MotionEvent.ACTION_POINTER_DOWN); - detector.onTouchEvent(temp); - } finally { - temp.recycle(); - } - } - - detector.onTouchEvent(ev); + return handleTouchEventCommon(ev); + } - if (detector.isInProgress()) { - mLastTouchTime = eventTime; - cancelLongPress(); - mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); - if (!mZoomManager.supportsPanDuringZoom()) { - return true; - } - mTouchMode = TOUCH_DRAG_MODE; - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - } + private boolean handleTouchEventCommon(MotionEvent ev) { + int action = ev.getAction(); + float x = ev.getX(); + float y = ev.getY(); + long eventTime = ev.getEventTime(); - x = detector.getFocusX(); - y = detector.getFocusY(); - action = ev.getAction() & MotionEvent.ACTION_MASK; - if (action == MotionEvent.ACTION_POINTER_DOWN) { - cancelTouch(); - action = MotionEvent.ACTION_DOWN; - } else if (action == MotionEvent.ACTION_POINTER_UP) { - // set mLastTouchX/Y to the remaining point - mLastTouchX = x; - mLastTouchY = y; - } else if (action == MotionEvent.ACTION_MOVE) { - // negative x or y indicate it is on the edge, skip it. - if (x < 0 || y < 0) { - return true; - } - } - } // Due to the touch screen edge effect, a touch closer to the edge // always snapped to the edge. As getViewWidth() can be different from @@ -5612,22 +5554,6 @@ public class WebView extends AbsoluteLayout break; } - // Only lock dragging to one axis if we don't have a scale in progress. - // Scaling implies free-roaming movement. Note this is only ever a question - // if mZoomManager.supportsPanDuringZoom() is true. - if (detector != null && !detector.isInProgress()) { - // if it starts nearly horizontal or vertical, enforce it - int ax = Math.abs(deltaX); - int ay = Math.abs(deltaY); - if (ax > MAX_SLOPE_FOR_DIAG * ay) { - mSnapScrollMode = SNAP_X; - mSnapPositive = deltaX > 0; - } else if (ay > MAX_SLOPE_FOR_DIAG * ax) { - mSnapScrollMode = SNAP_Y; - mSnapPositive = deltaY > 0; - } - } - mTouchMode = TOUCH_DRAG_MODE; mLastTouchX = x; mLastTouchY = y; @@ -5884,13 +5810,82 @@ public class WebView extends AbsoluteLayout ted.mPoints[c] = new Point(x, y); } ted.mMetaState = ev.getMetaState(); - ted.mReprocess = mDeferTouchProcess; + ted.mReprocess = true; + ted.mMotionEvent = MotionEvent.obtain(ev); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); cancelLongPress(); mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); mPreventDefault = PREVENT_DEFAULT_IGNORE; } + private boolean handleMultiTouchInWebView(MotionEvent ev) { + if (DebugFlags.WEB_VIEW) { + Log.v(LOGTAG, "multi-touch: " + ev + " at " + ev.getEventTime() + + " mTouchMode=" + mTouchMode + + " numPointers=" + ev.getPointerCount() + + " scrolloffset=(" + mScrollX + "," + mScrollY + ")"); + } + + final ScaleGestureDetector detector = + mZoomManager.getMultiTouchGestureDetector(); + int action = ev.getAction(); + float x = ev.getX(); + float y = ev.getY(); + long eventTime = ev.getEventTime(); + + if (!detector.isInProgress() && + ev.getActionMasked() != MotionEvent.ACTION_POINTER_DOWN) { + // Insert a fake pointer down event in order to start + // the zoom scale detector. + MotionEvent temp = MotionEvent.obtain(ev); + // Clear the original event and set it to + // ACTION_POINTER_DOWN. + try { + temp.setAction(temp.getAction() & + ~MotionEvent.ACTION_MASK | + MotionEvent.ACTION_POINTER_DOWN); + detector.onTouchEvent(temp); + } finally { + temp.recycle(); + } + } + + detector.onTouchEvent(ev); + + if (detector.isInProgress()) { + if (DebugFlags.WEB_VIEW) { + Log.v(LOGTAG, "detector is in progress"); + } + mLastTouchTime = eventTime; + cancelLongPress(); + mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); + if (!mZoomManager.supportsPanDuringZoom()) { + return false; + } + mTouchMode = TOUCH_DRAG_MODE; + if (mVelocityTracker == null) { + mVelocityTracker = VelocityTracker.obtain(); + } + } + + action = ev.getAction() & MotionEvent.ACTION_MASK; + if (action == MotionEvent.ACTION_POINTER_DOWN) { + cancelTouch(); + action = MotionEvent.ACTION_DOWN; + } else if (action == MotionEvent.ACTION_POINTER_UP) { + // set mLastTouchX/Y to the remaining point + mLastTouchX = x; + mLastTouchY = y; + } else if (action == MotionEvent.ACTION_MOVE) { + // negative x or y indicate it is on the edge, skip it. + if (x < 0 || y < 0) { + return false; + } + } + + return handleTouchEventCommon(ev); + } + private void cancelWebCoreTouchEvent(int x, int y, boolean removeEvents) { if (shouldForwardTouchEvent()) { if (removeEvents) { @@ -7263,6 +7258,13 @@ public class WebView extends AbsoluteLayout // prevent default is not called in WebCore, so the // message needs to be reprocessed in UI TouchEventData ted = (TouchEventData) msg.obj; + + if (ted.mPoints.length > 1) { // for multi-touch. + handleMultiTouchInWebView(ted.mMotionEvent); + break; + } + + // Following is for single touch. switch (ted.mAction) { case MotionEvent.ACTION_DOWN: mLastDeferTouchX = contentToViewX(ted.mPoints[0].x) @@ -8088,7 +8090,6 @@ public class WebView extends AbsoluteLayout private native int nativeCursorFramePointer(); private native Rect nativeCursorNodeBounds(); private native int nativeCursorNodePointer(); - /* package */ native boolean nativeCursorMatchesFocus(); private native boolean nativeCursorIntersects(Rect visibleRect); private native boolean nativeCursorIsAnchor(); private native boolean nativeCursorIsTextInput(); diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index a482b74..c874160 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -33,6 +33,7 @@ import android.provider.MediaStore; import android.util.Log; import android.util.SparseBooleanArray; import android.view.KeyEvent; +import android.view.MotionEvent; import android.view.SurfaceView; import android.view.View; import android.webkit.DeviceMotionService; @@ -830,6 +831,7 @@ final class WebViewCore { Point[] mPoints; int mMetaState; boolean mReprocess; + MotionEvent mMotionEvent; } static class GeolocationPermissionsData { diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java index 7b9def0..e1392ae 100644 --- a/core/java/android/webkit/WebViewDatabase.java +++ b/core/java/android/webkit/WebViewDatabase.java @@ -223,6 +223,7 @@ public class WebViewDatabase { null); } } + mDatabase.enableWriteAheadLogging(); // mDatabase should not be null, // the only case is RequestAPI test has problem to create db @@ -233,7 +234,7 @@ public class WebViewDatabase { } if (mDatabase.getVersion() != DATABASE_VERSION) { - mDatabase.beginTransaction(); + mDatabase.beginTransactionNonExclusive(); try { upgradeDatabase(); mDatabase.setTransactionSuccessful(); @@ -261,6 +262,7 @@ public class WebViewDatabase { CACHE_DATABASE_FILE, 0, null); } } + mCacheDatabase.enableWriteAheadLogging(); // mCacheDatabase should not be null, // the only case is RequestAPI test has problem to create db @@ -271,7 +273,7 @@ public class WebViewDatabase { } if (mCacheDatabase.getVersion() != CACHE_DATABASE_VERSION) { - mCacheDatabase.beginTransaction(); + mCacheDatabase.beginTransactionNonExclusive(); try { upgradeCacheDatabase(); bootstrapCacheDatabase(); @@ -648,7 +650,7 @@ public class WebViewDatabase { + "WebViewWorkerThread instead of from " + Thread.currentThread().getName()); } - mCacheDatabase.beginTransaction(); + mCacheDatabase.beginTransactionNonExclusive(); return true; } return false; diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index b85670c..bccde8d 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -4810,7 +4810,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (mFiltered && mPopup != null && mPopup.isShowing()) { if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { - getKeyDispatcherState().startTracking(event, this); + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.startTracking(event, this); + } handled = true; } else if (event.getAction() == KeyEvent.ACTION_UP && event.isTracking() && !event.isCanceled()) { diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index ee037cd..4d8d21f 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -607,10 +607,16 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe // 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) { - getKeyDispatcherState().startTracking(event, this); + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.startTracking(event, this); + } return true; } else if (event.getAction() == KeyEvent.ACTION_UP) { - getKeyDispatcherState().handleUpEvent(event); + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + state.handleUpEvent(event); + } if (event.isTracking() && !event.isCanceled()) { dismissDropDown(); return true; diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java index 3bba816..444a163d 100644 --- a/core/java/android/widget/ListPopupWindow.java +++ b/core/java/android/widget/ListPopupWindow.java @@ -915,10 +915,16 @@ public class ListPopupWindow { // to the drop down list but instead, consume it immediately final View anchorView = mDropDownAnchorView; if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { - anchorView.getKeyDispatcherState().startTracking(event, this); + KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState(); + if (state != null) { + state.startTracking(event, this); + } return true; } else if (event.getAction() == KeyEvent.ACTION_UP) { - anchorView.getKeyDispatcherState().handleUpEvent(event); + KeyEvent.DispatcherState state = anchorView.getKeyDispatcherState(); + if (state != null) { + state.handleUpEvent(event); + } if (event.isTracking() && !event.isCanceled()) { dismiss(); return true; diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 5a5b6f4..79d6a81 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -1468,12 +1468,17 @@ public class PopupWindow { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { - getKeyDispatcherState().startTracking(event, this); - return true; - } else if (event.getAction() == KeyEvent.ACTION_UP - && getKeyDispatcherState().isTracking(event) && !event.isCanceled()) { - dismiss(); + 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.isTracking(event) && !event.isCanceled()) { + dismiss(); + return true; + } } return super.dispatchKeyEvent(event); } else { diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java index 9381675..463902f 100644 --- a/core/java/com/android/internal/view/menu/ActionMenuView.java +++ b/core/java/com/android/internal/view/menu/ActionMenuView.java @@ -139,6 +139,10 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo mReserveOverflow = reserveOverflow; } + public View getOverflowButton() { + return mOverflowButton; + } + @Override protected LayoutParams generateDefaultLayoutParams() { LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java index fe41f52..b93fac4 100644 --- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java +++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java @@ -68,6 +68,10 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On } } + public void setAnchorView(View anchor) { + mAnchorView = new WeakReference<View>(anchor); + } + public void show() { if (!tryShow()) { throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor"); |