diff options
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/app/DownloadManager.java | 110 | ||||
-rw-r--r-- | core/java/android/hardware/Camera.java | 54 | ||||
-rw-r--r-- | core/java/android/provider/Downloads.java | 54 | ||||
-rw-r--r-- | core/java/android/widget/PopupWindow.java | 30 | ||||
-rw-r--r-- | core/java/android/widget/TextView.java | 60 |
5 files changed, 215 insertions, 93 deletions
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java index c6fef4f..3ec21ff 100644 --- a/core/java/android/app/DownloadManager.java +++ b/core/java/android/app/DownloadManager.java @@ -100,16 +100,23 @@ public class DownloadManager { public final static String COLUMN_STATUS = "status"; /** - * Indicates the type of error that occurred, when {@link #COLUMN_STATUS} is - * {@link #STATUS_FAILED}. If an HTTP error occurred, this will hold the HTTP status code as - * defined in RFC 2616. Otherwise, it will hold one of the ERROR_* constants. + * Provides more detail on the status of the download. Its meaning depends on the value of + * {@link #COLUMN_STATUS}. * - * If {@link #COLUMN_STATUS} is not {@link #STATUS_FAILED}, this column's value is undefined. + * When {@link #COLUMN_STATUS} is {@link #STATUS_FAILED}, this indicates the type of error that + * occurred. If an HTTP error occurred, this will hold the HTTP status code as defined in RFC + * 2616. Otherwise, it will hold one of the ERROR_* constants. + * + * When {@link #COLUMN_STATUS} is {@link #STATUS_PAUSED}, this indicates why the download is + * paused. It will hold one of the PAUSED_* constants. + * + * If {@link #COLUMN_STATUS} is neither {@link #STATUS_FAILED} nor {@link #STATUS_PAUSED}, this + * column's value is undefined. * * @see <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1">RFC 2616 * status codes</a> */ - public final static String COLUMN_ERROR_CODE = "error_code"; + public final static String COLUMN_REASON = "reason"; /** * Number of bytes download so far. @@ -156,54 +163,77 @@ public class DownloadManager { public final static int ERROR_UNKNOWN = 1000; /** - * Value of {@link #COLUMN_ERROR_CODE} when a storage issue arises which doesn't fit under any + * Value of {@link #COLUMN_REASON} when a storage issue arises which doesn't fit under any * other error code. Use the more specific {@link #ERROR_INSUFFICIENT_SPACE} and * {@link #ERROR_DEVICE_NOT_FOUND} when appropriate. */ public final static int ERROR_FILE_ERROR = 1001; /** - * Value of {@link #COLUMN_ERROR_CODE} when an HTTP code was received that download manager + * Value of {@link #COLUMN_REASON} when an HTTP code was received that download manager * can't handle. */ public final static int ERROR_UNHANDLED_HTTP_CODE = 1002; /** - * Value of {@link #COLUMN_ERROR_CODE} when an error receiving or processing data occurred at + * Value of {@link #COLUMN_REASON} when an error receiving or processing data occurred at * the HTTP level. */ public final static int ERROR_HTTP_DATA_ERROR = 1004; /** - * Value of {@link #COLUMN_ERROR_CODE} when there were too many redirects. + * Value of {@link #COLUMN_REASON} when there were too many redirects. */ public final static int ERROR_TOO_MANY_REDIRECTS = 1005; /** - * Value of {@link #COLUMN_ERROR_CODE} when there was insufficient storage space. Typically, + * Value of {@link #COLUMN_REASON} when there was insufficient storage space. Typically, * this is because the SD card is full. */ public final static int ERROR_INSUFFICIENT_SPACE = 1006; /** - * Value of {@link #COLUMN_ERROR_CODE} when no external storage device was found. Typically, + * Value of {@link #COLUMN_REASON} when no external storage device was found. Typically, * this is because the SD card is not mounted. */ public final static int ERROR_DEVICE_NOT_FOUND = 1007; /** - * Value of {@link #COLUMN_ERROR_CODE} when some possibly transient error occurred but we can't + * Value of {@link #COLUMN_REASON} when some possibly transient error occurred but we can't * resume the download. */ public final static int ERROR_CANNOT_RESUME = 1008; /** - * Value of {@link #COLUMN_ERROR_CODE} when the requested destination file already exists (the + * Value of {@link #COLUMN_REASON} when the requested destination file already exists (the * download manager will not overwrite an existing file). */ public final static int ERROR_FILE_ALREADY_EXISTS = 1009; /** + * Value of {@link #COLUMN_REASON} when the download is paused because some network error + * occurred and the download manager is waiting before retrying the request. + */ + public final static int PAUSED_WAITING_TO_RETRY = 1; + + /** + * Value of {@link #COLUMN_REASON} when the download is waiting for network connectivity to + * proceed. + */ + public final static int PAUSED_WAITING_FOR_NETWORK = 2; + + /** + * Value of {@link #COLUMN_REASON} when the download exceeds a size limit for downloads over + * the mobile network and the download manager is waiting for a Wi-Fi connection to proceed. + */ + public final static int PAUSED_QUEUED_FOR_WIFI = 3; + + /** + * Value of {@link #COLUMN_REASON} when the download is paused for some other reason. + */ + public final static int PAUSED_UNKNOWN = 4; + + /** * Broadcast intent action sent by the download manager when a download completes. */ public final static String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE"; @@ -236,7 +266,7 @@ public class DownloadManager { COLUMN_TOTAL_SIZE_BYTES, COLUMN_LOCAL_URI, COLUMN_STATUS, - COLUMN_ERROR_CODE, + COLUMN_REASON, COLUMN_BYTES_DOWNLOADED_SO_FAR, COLUMN_LAST_MODIFIED_TIMESTAMP }; @@ -258,7 +288,7 @@ public class DownloadManager { }; private static final Set<String> LONG_COLUMNS = new HashSet<String>( - Arrays.asList(COLUMN_ID, COLUMN_TOTAL_SIZE_BYTES, COLUMN_STATUS, COLUMN_ERROR_CODE, + Arrays.asList(COLUMN_ID, COLUMN_TOTAL_SIZE_BYTES, COLUMN_STATUS, COLUMN_REASON, COLUMN_BYTES_DOWNLOADED_SO_FAR, COLUMN_LAST_MODIFIED_TIMESTAMP)); /** @@ -617,8 +647,10 @@ public class DownloadManager { parts.add(statusClause("=", Downloads.STATUS_RUNNING)); } if ((mStatusFlags & STATUS_PAUSED) != 0) { - parts.add(statusClause("=", Downloads.STATUS_PENDING_PAUSED)); - parts.add(statusClause("=", Downloads.STATUS_RUNNING_PAUSED)); + parts.add(statusClause("=", Downloads.Impl.STATUS_PAUSED_BY_APP)); + parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_TO_RETRY)); + parts.add(statusClause("=", Downloads.Impl.STATUS_WAITING_FOR_NETWORK)); + parts.add(statusClause("=", Downloads.Impl.STATUS_QUEUED_FOR_WIFI)); } if ((mStatusFlags & STATUS_SUCCESSFUL) != 0) { parts.add(statusClause("=", Downloads.STATUS_SUCCESS)); @@ -914,8 +946,8 @@ public class DownloadManager { if (column.equals(COLUMN_STATUS)) { return translateStatus((int) getUnderlyingLong(Downloads.COLUMN_STATUS)); } - if (column.equals(COLUMN_ERROR_CODE)) { - return translateErrorCode((int) getUnderlyingLong(Downloads.COLUMN_STATUS)); + if (column.equals(COLUMN_REASON)) { + return getReason((int) getUnderlyingLong(Downloads.COLUMN_STATUS)); } if (column.equals(COLUMN_BYTES_DOWNLOADED_SO_FAR)) { return getUnderlyingLong(Downloads.COLUMN_CURRENT_BYTES); @@ -924,10 +956,36 @@ public class DownloadManager { return getUnderlyingLong(Downloads.COLUMN_LAST_MODIFICATION); } - private long translateErrorCode(int status) { - if (translateStatus(status) != STATUS_FAILED) { - return 0; // arbitrary value when status is not an error + private long getReason(int status) { + switch (translateStatus(status)) { + case STATUS_FAILED: + return getErrorCode(status); + + case STATUS_PAUSED: + return getPausedReason(status); + + default: + return 0; // arbitrary value when status is not an error } + } + + private long getPausedReason(int status) { + switch (status) { + case Downloads.Impl.STATUS_WAITING_TO_RETRY: + return PAUSED_WAITING_TO_RETRY; + + case Downloads.Impl.STATUS_WAITING_FOR_NETWORK: + return PAUSED_WAITING_FOR_NETWORK; + + case Downloads.Impl.STATUS_QUEUED_FOR_WIFI: + return PAUSED_QUEUED_FOR_WIFI; + + default: + return PAUSED_UNKNOWN; + } + } + + private long getErrorCode(int status) { if ((400 <= status && status < Downloads.Impl.MIN_ARTIFICIAL_ERROR_STATUS) || (500 <= status && status < 600)) { // HTTP status code @@ -973,7 +1031,7 @@ public class DownloadManager { return super.getString(super.getColumnIndex(column)); } - private long translateStatus(int status) { + private int translateStatus(int status) { switch (status) { case Downloads.STATUS_PENDING: return STATUS_PENDING; @@ -981,8 +1039,10 @@ public class DownloadManager { case Downloads.STATUS_RUNNING: return STATUS_RUNNING; - case Downloads.STATUS_PENDING_PAUSED: - case Downloads.STATUS_RUNNING_PAUSED: + case Downloads.Impl.STATUS_PAUSED_BY_APP: + case Downloads.Impl.STATUS_WAITING_TO_RETRY: + case Downloads.Impl.STATUS_WAITING_FOR_NETWORK: + case Downloads.Impl.STATUS_QUEUED_FOR_WIFI: return STATUS_PAUSED; case Downloads.STATUS_SUCCESS: diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index 0d8228c..7b930d5 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -181,6 +181,7 @@ public class Camera { * value should be 90. * * @see #setDisplayOrientation(int) + * @see #setRotation(int) */ public int orientation; }; @@ -1716,23 +1717,46 @@ public class Camera { } /** - * Sets the orientation of the device in degrees. For example, suppose - * the natural position of the device is landscape. If the user takes a - * picture in landscape mode in 2048x1536 resolution, the rotation - * should be set to 0. If the user rotates the phone 90 degrees - * clockwise, the rotation should be set to 90. Applications can use - * {@link android.view.OrientationEventListener} to set this parameter. - * - * The camera driver may set orientation in the EXIF header without - * rotating the picture. Or the driver may rotate the picture and - * the EXIF thumbnail. If the Jpeg picture is rotated, the orientation - * in the EXIF header will be missing or 1 (row #0 is top and column #0 - * is left side). - * - * @param rotation The orientation of the device in degrees. Rotation - * can only be 0, 90, 180 or 270. + * Sets the rotation angle in degrees relative to the orientation of + * the camera. This affects the pictures returned from JPEG {@link + * PictureCallback}. The camera driver may set orientation in the + * EXIF header without rotating the picture. Or the driver may rotate + * the picture and the EXIF thumbnail. If the Jpeg picture is rotated, + * the orientation in the EXIF header will be missing or 1 (row #0 is + * top and column #0 is left side). + * + * If appplications want to rotate the picture to match the + * orientation of what users see, apps should use {@link + * android.view.OrientationEventListener} and {@link CameraInfo}. + * The value from OrientationEventListener is relative to the natural + * orientation of the device. CameraInfo.mOrientation is the angle + * between camera orientation and natural device orientation. The sum + * of the two is the angle for rotation. + * + * For example, suppose the natural orientation of the device is + * portrait. The device is rotated 270 degrees clockwise, so the device + * orientation is 270. Suppose the camera sensor is mounted in landscape + * and the top side of the camera sensor is aligned with the right edge + * of the display in natural orientation. So the camera orientation is + * 90. The rotation should be set to 0 (270 + 90). + * + * The reference code is as follows. + * + * public void public void onOrientationChanged(int orientation) { + * if (orientation == ORIENTATION_UNKNOWN) return; + * android.hardware.Camera.CameraInfo info = + * new android.hardware.Camera.CameraInfo(); + * android.hardware.Camera.getCameraInfo(cameraId, info); + * orientation = (orientation + 45) / 90 * 90; + * mParameters.setRotation((orientation + info.mOrientation) % 360); + * } + * + * @param rotation The rotation angle in degrees relative to the + * orientation of the camera. Rotation can only be 0, + * 90, 180 or 270. * @throws IllegalArgumentException if rotation value is invalid. * @see android.view.OrientationEventListener + * @see #getCameraInfo(int, CameraInfo) */ public void setRotation(int rotation) { if (rotation == 0 || rotation == 90 || rotation == 180 diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java index 1e358c9..8fd0e0a 100644 --- a/core/java/android/provider/Downloads.java +++ b/core/java/android/provider/Downloads.java @@ -378,16 +378,6 @@ public final class Downloads { } /** - * Returns whether the download is suspended. (i.e. whether the download - * won't complete without some action from outside the download - * manager). - * @hide - */ - public static boolean isStatusSuspended(int status) { - return (status == STATUS_PENDING_PAUSED || status == STATUS_RUNNING_PAUSED); - } - - /** * Returns whether the status is a success (i.e. 2xx). * @hide */ @@ -435,24 +425,12 @@ public final class Downloads { public static final int STATUS_PENDING = 190; /** - * This download hasn't stated yet and is paused - * @hide - */ - public static final int STATUS_PENDING_PAUSED = 191; - - /** * This download has started * @hide */ public static final int STATUS_RUNNING = 192; /** - * This download has started and is paused - * @hide - */ - public static final int STATUS_RUNNING_PAUSED = 193; - - /** * This download has successfully completed. * Warning: there might be other status values that indicate success * in the future. @@ -980,15 +958,6 @@ public final class Downloads { } /** - * Returns whether the download is suspended. (i.e. whether the download - * won't complete without some action from outside the download - * manager). - */ - public static boolean isStatusSuspended(int status) { - return (status == STATUS_PENDING_PAUSED || status == STATUS_RUNNING_PAUSED); - } - - /** * Returns whether the status is a success (i.e. 2xx). */ public static boolean isStatusSuccess(int status) { @@ -1030,19 +999,30 @@ public final class Downloads { public static final int STATUS_PENDING = 190; /** - * This download hasn't stated yet and is paused + * This download has started */ - public static final int STATUS_PENDING_PAUSED = 191; + public static final int STATUS_RUNNING = 192; /** - * This download has started + * This download has been paused by the owning app. */ - public static final int STATUS_RUNNING = 192; + public static final int STATUS_PAUSED_BY_APP = 193; + + /** + * This download encountered some network error and is waiting before retrying the request. + */ + public static final int STATUS_WAITING_TO_RETRY = 194; + + /** + * This download is waiting for network connectivity to proceed. + */ + public static final int STATUS_WAITING_FOR_NETWORK = 195; /** - * This download has started and is paused + * This download exceeded a size limit for mobile networks and is waiting for a Wi-Fi + * connection to proceed. */ - public static final int STATUS_RUNNING_PAUSED = 193; + public static final int STATUS_QUEUED_FOR_WIFI = 196; /** * This download has successfully completed. diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java index 7fe6190..ed15e25 100644 --- a/core/java/android/widget/PopupWindow.java +++ b/core/java/android/widget/PopupWindow.java @@ -86,6 +86,7 @@ public class PopupWindow { private boolean mOutsideTouchable = false; private boolean mClippingEnabled = true; private boolean mSplitTouchEnabled; + private boolean mLayoutInScreen; private OnTouchListener mTouchInterceptor; @@ -596,6 +597,29 @@ public class PopupWindow { } /** + * <p>Indicates whether the popup window will be forced into using absolute screen coordinates + * for positioning.</p> + * + * @return true if the window will always be positioned in screen coordinates. + * @hide + */ + public boolean isLayoutInScreenEnabled() { + return mLayoutInScreen; + } + + /** + * <p>Allows the popup window to force the flag + * {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN}, overriding default behavior. + * This will cause the popup to be positioned in absolute screen coordinates.</p> + * + * @param enabled true if the popup should always be positioned in screen coordinates + * @hide + */ + public void setLayoutInScreenEnabled(boolean enabled) { + mLayoutInScreen = enabled; + } + + /** * <p>Change the width and height measure specs that are given to the * window manager by the popup. By default these are 0, meaning that * the current width or height is requested as an explicit size from @@ -899,7 +923,8 @@ public class PopupWindow { WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS | - WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM | + WindowManager.LayoutParams.FLAG_SPLIT_TOUCH); if(mIgnoreCheekPress) { curFlags |= WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES; } @@ -923,6 +948,9 @@ public class PopupWindow { if (mSplitTouchEnabled) { curFlags |= WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; } + if (mLayoutInScreen) { + curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + } return curFlags; } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 6278192..8291d57 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -3768,6 +3768,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mError != null) { hideError(); } + + hideControllers(); } @Override @@ -4118,6 +4120,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ canvas.restore(); + + if (mInsertionPointCursorController != null && + mInsertionPointCursorController.isShowing()) { + mInsertionPointCursorController.updatePosition(); + } + if (mSelectionModifierCursorController != null && + mSelectionModifierCursorController.isShowing()) { + mSelectionModifierCursorController.updatePosition(); + } } @Override @@ -4736,6 +4747,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mInputMethodState != null) { mInputMethodState.mExtracting = req; } + hideControllers(); } /** @@ -6266,7 +6278,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener sendOnTextChanged(buffer, start, before, after); onTextChanged(buffer, start, before, after); - hideControllers(); + + // Hide the controller if the amount of content changed + if (before != after) { + hideControllers(); + } } /** @@ -6605,11 +6621,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mInputContentType != null) { mInputContentType.enterDown = false; } + hideControllers(); } startStopMarquee(hasWindowFocus); } + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + if (visibility != VISIBLE) { + hideControllers(); + } + } + /** * Use {@link BaseInputConnection#removeComposingSpans * BaseInputConnection.removeComposingSpans()} to remove any IME composing @@ -6679,8 +6704,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (hasSelection()) { startTextSelectionMode(); - } else if (mInsertionPointCursorController != null) { - mInsertionPointCursorController.show(); } } } @@ -7645,6 +7668,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private int mPositionY; private CursorController mController; private boolean mIsDragging; + private int mOffsetX; + private int mOffsetY; public HandleView(CursorController controller, Drawable handle) { super(TextView.this.mContext); @@ -7653,6 +7678,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener mContainer = new PopupWindow(TextView.this.mContext, null, com.android.internal.R.attr.textSelectHandleWindowStyle); mContainer.setSplitTouchEnabled(true); + mContainer.setClippingEnabled(false); + mContainer.setLayoutInScreenEnabled(true); } @Override @@ -7690,19 +7717,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int compoundPaddingRight = getCompoundPaddingRight(); final TextView hostView = TextView.this; - final int right = hostView.mRight; - final int left = hostView.mLeft; - final int bottom = hostView.mBottom; - final int top = hostView.mTop; + final int handleWidth = mDrawable.getIntrinsicWidth(); + final int left = 0; + final int right = hostView.getWidth(); + final int top = 0; + final int bottom = hostView.getHeight(); - final int clipLeft = left + compoundPaddingLeft; + final int clipLeft = left + compoundPaddingLeft - (int) (handleWidth * 0.75f); final int clipTop = top + extendedPaddingTop; - final int clipRight = right - compoundPaddingRight; + final int clipRight = right - compoundPaddingRight + (int) (handleWidth * 0.25f); final int clipBottom = bottom - extendedPaddingBottom; - final int handleWidth = mDrawable.getIntrinsicWidth(); - return mPositionX >= clipLeft - handleWidth * 0.75f && - mPositionX <= clipRight + handleWidth * 0.25f && + return mPositionX >= clipLeft && mPositionX <= clipRight && mPositionY >= clipTop && mPositionY <= clipBottom; } @@ -7741,6 +7767,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener public boolean onTouchEvent(MotionEvent ev) { switch (ev.getActionMasked()) { case MotionEvent.ACTION_DOWN: + mOffsetX = (int) (ev.getX() - mDrawable.getIntrinsicWidth() / 2.f + 0.5f); + mOffsetY = (int) (ev.getY() - mDrawable.getIntrinsicHeight() / 2.f + 0.5f); mIsDragging = true; break; @@ -7749,8 +7777,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final float rawY = ev.getRawY(); final int[] coords = mTempCoords; TextView.this.getLocationOnScreen(coords); - final int x = (int) (rawX - coords[0] + 0.5f); - final int y = (int) (rawY - coords[1] + 0.5f); + final int x = (int) (rawX - coords[0] + 0.5f) - mOffsetX; + final int y = (int) (rawY - coords[1] + 0.5f) - + (int) (mDrawable.getIntrinsicHeight() * 0.8f) - mOffsetY; + mController.updatePosition(this, x, y); break; @@ -8059,7 +8089,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int previousLine = layout.getLineForOffset(previousOffset); final int previousLineTop = layout.getLineTop(previousLine); final int previousLineBottom = layout.getLineBottom(previousLine); - final int hysteresisThreshold = (previousLineBottom - previousLineTop) / 2; + final int hysteresisThreshold = (previousLineBottom - previousLineTop) / 6; // If new line is just before or after previous line and y position is less than // hysteresisThreshold away from previous line, keep cursor on previous line. |