diff options
27 files changed, 272 insertions, 105 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 440cb5406b85..efe263336063 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1150,8 +1150,12 @@ public class DevicePolicyManager { * fail (most commonly returning {@link #ENCRYPTION_STATUS_ACTIVE}). * * <p>This policy controls encryption of the secure (application data) storage area. Data - * written to other areas (e.g. the directory returned by - * {@link android.os.Environment#getExternalStorageDirectory()} may or may not be encrypted. + * written to other storage areas may or may not be encrypted, and this policy does not require + * or control the encryption of any other storage areas. + * There is one exception: If {@link android.os.Environment#isExternalStorageEmulated()} is + * {@code true}, then the directory returned by + * {@link android.os.Environment#getExternalStorageDirectory()} must be written to disk + * within the encrypted storage area. * * <p>Important Note: On some devices, it is possible to encrypt storage without requiring * the user to create a device PIN or Password. In this case, the storage is encrypted, but diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index ec5030c7f5db..e308c2c48a8d 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -423,9 +423,16 @@ public class Environment { /** * Returns whether the device has an external storage device which is - * emulated. If true, the device does not have real external storage - * and certain system services such as the package manager use this + * emulated. If true, the device does not have real external storage, and the directory + * returned by {@link #getExternalStorageDirectory()} will be allocated using a portion of + * the internal storage system. + * + * <p>Certain system services, such as the package manager, use this * to determine where to install an application. + * + * <p>Emulated external storage may also be encrypted - see + * {@link android.app.admin.DevicePolicyManager#setStorageEncryption( + * android.content.ComponentName, boolean)} for additional details. */ public static boolean isExternalStorageEmulated() { if (mIsExternalStorageEmulated == null) { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 1316235670a5..9b1f157d9c72 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -4036,15 +4036,10 @@ public class WebView extends AbsoluteLayout } } - void setBaseLayer(int layer, Rect invalRect, boolean showVisualIndciator) { + void setBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator) { if (mNativeClass == 0) return; - if (invalRect == null) { - Rect rect = new Rect(0, 0, mContentWidth, mContentHeight); - nativeSetBaseLayer(layer, rect, showVisualIndciator); - } else { - nativeSetBaseLayer(layer, invalRect, showVisualIndciator); - } + nativeSetBaseLayer(layer, invalRegion, showVisualIndicator); } private void onZoomAnimationStart() { @@ -5571,7 +5566,7 @@ public class WebView extends AbsoluteLayout ted.mReprocess = mDeferTouchProcess; ted.mNativeLayer = nativeScrollableLayer( contentX, contentY, ted.mNativeLayerRect, null); - ted.mDontEnqueueResult = true; + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); if (mDeferTouchProcess) { // still needs to set them for compute deltaX/Y @@ -5618,7 +5613,7 @@ public class WebView extends AbsoluteLayout ted.mReprocess = mDeferTouchProcess; ted.mNativeLayer = mScrollingLayer; ted.mNativeLayerRect.set(mScrollingLayerRect); - ted.mDontEnqueueResult = true; + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mLastSentTouchTime = eventTime; if (mDeferTouchProcess) { @@ -5800,7 +5795,7 @@ public class WebView extends AbsoluteLayout ted.mReprocess = mDeferTouchProcess; ted.mNativeLayer = mScrollingLayer; ted.mNativeLayerRect.set(mScrollingLayerRect); - ted.mDontEnqueueResult = true; + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } mLastTouchUpTime = eventTime; @@ -5823,7 +5818,7 @@ public class WebView extends AbsoluteLayout ted.mNativeLayer = nativeScrollableLayer( contentX, contentY, ted.mNativeLayerRect, null); - ted.mDontEnqueueResult = true; + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } else if (mPreventDefault != PREVENT_DEFAULT_YES){ mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY); @@ -6041,7 +6036,7 @@ public class WebView extends AbsoluteLayout ted.mAction = MotionEvent.ACTION_CANCEL; ted.mNativeLayer = nativeScrollableLayer( x, y, ted.mNativeLayerRect, null); - ted.mDontEnqueueResult = true; + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mPreventDefault = PREVENT_DEFAULT_IGNORE; } @@ -7525,7 +7520,7 @@ public class WebView extends AbsoluteLayout ted.mNativeLayer = nativeScrollableLayer( ted.mPoints[0].x, ted.mPoints[0].y, ted.mNativeLayerRect, null); - ted.mDontEnqueueResult = true; + ted.mSequence = mTouchEventQueue.nextTouchSequence(); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } else if (mPreventDefault != PREVENT_DEFAULT_YES) { mTouchMode = TOUCH_DONE_MODE; @@ -7571,7 +7566,7 @@ public class WebView extends AbsoluteLayout case NEW_PICTURE_MSG_ID: { // called for new content final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj; - setBaseLayer(draw.mBaseLayer, draw.mInvalRegion.getBounds(), + setBaseLayer(draw.mBaseLayer, draw.mInvalRegion, getSettings().getShowVisualIndicator()); final Point viewSize = draw.mViewSize; WebViewCore.ViewState viewState = draw.mViewState; @@ -7741,9 +7736,12 @@ public class WebView extends AbsoluteLayout break; } TouchEventData ted = (TouchEventData) msg.obj; - if (!ted.mDontEnqueueResult) { - mTouchEventQueue.enqueueTouchEvent(ted); - } + + // WebCore is responding to us; remove pending timeout. + // It will be re-posted when needed. + removeMessages(PREVENT_DEFAULT_TIMEOUT); + + mTouchEventQueue.enqueueTouchEvent(ted); break; case REQUEST_KEYBOARD: @@ -8613,7 +8611,7 @@ public class WebView extends AbsoluteLayout private native void nativeSetFindIsEmpty(); private native void nativeSetFindIsUp(boolean isUp); private native void nativeSetHeightCanMeasure(boolean measure); - private native void nativeSetBaseLayer(int layer, Rect invalRect, + private native void nativeSetBaseLayer(int layer, Region invalRegion, boolean showVisualIndicator); private native void nativeShowCursorTimed(); private native void nativeReplaceBaseContent(int content); diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index f367b93820de..b920a30fd2a9 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -827,7 +827,6 @@ final class WebViewCore { Rect mNativeLayerRect = new Rect(); long mSequence; boolean mNativeResult; - boolean mDontEnqueueResult; } static class GeolocationPermissionsData { diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java index f27ced89cbf8..942425af8e3b 100644 --- a/core/java/android/webkit/ZoomManager.java +++ b/core/java/android/webkit/ZoomManager.java @@ -16,6 +16,9 @@ package android.webkit; +import java.util.LinkedList; +import java.util.Queue; + import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Canvas; @@ -23,6 +26,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; import android.os.SystemClock; +import android.util.FloatMath; import android.util.Log; import android.view.ScaleGestureDetector; import android.view.View; @@ -112,6 +116,24 @@ class ZoomManager { private float mZoomCenterY; /* + * Similar to mZoomCenterX(Y), these track the focus point of the scale + * gesture. The difference is these get updated every time when onScale is + * invoked no matter if a zooming really happens. + */ + private float mFocusX; + private float mFocusY; + + /* + * mFocusMovement keeps track of the total movement that the focus point + * has been through. Comparing to the difference of mCurrlen and mPrevLen, + * it determines if the gesture is for panning or zooming or both. + */ + private static final int FOCUS_QUEUE_SIZE = 5; + private float mFocusMovementSum; + private Queue<Float> mFocusMovementQueue; + + + /* * These values represent the point around which the screen should be * centered after zooming. In other words it is used to determine the center * point of the visible document after the page has finished zooming. This @@ -196,6 +218,8 @@ class ZoomManager { * viewport size is. */ setZoomOverviewWidth(WebView.DEFAULT_VIEWPORT_WIDTH); + + mFocusMovementQueue = new LinkedList<Float>(); } /** @@ -715,10 +739,11 @@ class ZoomManager { } private class ScaleDetectorListener implements ScaleGestureDetector.OnScaleGestureListener { - public boolean onScaleBegin(ScaleGestureDetector detector) { mInitialZoomOverview = false; dismissZoomPicker(); + mFocusMovementSum = 0; + mFocusMovementQueue.clear(); mWebView.mViewManager.startZoom(); mWebView.onPinchToZoomAnimationStart(); return true; @@ -729,6 +754,29 @@ class ZoomManager { float scale = Math.max( computeScaleWithLimits(detector.getScaleFactor() * mActualScale), getZoomOverviewScale()); + + float prevFocusX = mFocusX; + float prevFocusY = mFocusY; + mFocusX = detector.getFocusX(); + mFocusY = detector.getFocusY(); + float focusDelta = (prevFocusX == 0 && prevFocusY == 0) ? 0 : + FloatMath.sqrt((mFocusX - prevFocusX) * (mFocusX - prevFocusX) + + (mFocusY - prevFocusY) * (mFocusY - prevFocusY)); + mFocusMovementSum += focusDelta; + mFocusMovementQueue.add(focusDelta); + if (mFocusMovementQueue.size() > FOCUS_QUEUE_SIZE) { + mFocusMovementSum -= mFocusMovementQueue.remove(); + } + float deltaSpan = Math.abs(detector.getCurrentSpan() - detector.getPreviousSpan()); + + // If the user moves the fingers but keeps the same distance between them, + // we should do panning only. + if (mFocusMovementSum > deltaSpan) { + mFocusMovementSum = 0; + mFocusMovementQueue.clear(); + return true; + } + if (mPinchToZoomAnimating || willScaleTriggerZoom(scale)) { mPinchToZoomAnimating = true; // limit the scale change per step diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java index 2d164fd75812..6088654a78c1 100644 --- a/core/java/android/widget/SearchView.java +++ b/core/java/android/widget/SearchView.java @@ -83,6 +83,7 @@ public class SearchView extends LinearLayout { private CursorAdapter mSuggestionsAdapter; private View mSearchButton; private View mSubmitButton; + private View mSearchPlate; private View mSubmitArea; private ImageView mCloseButton; private View mSearchEditFrame; @@ -190,6 +191,7 @@ public class SearchView extends LinearLayout { mQueryTextView.setSearchView(this); mSearchEditFrame = findViewById(R.id.search_edit_frame); + mSearchPlate = findViewById(R.id.search_plate); mSubmitArea = findViewById(R.id.submit_area); mSubmitButton = findViewById(R.id.search_go_btn); mCloseButton = (ImageView) findViewById(R.id.search_close_btn); @@ -258,6 +260,7 @@ public class SearchView extends LinearLayout { mSearchable = searchable; if (mSearchable != null) { updateSearchAutoComplete(); + updateQueryHint(); } // Cache the voice search capability mVoiceButtonEnabled = hasVoiceSearch(); @@ -575,19 +578,19 @@ public class SearchView extends LinearLayout { } private void updateSubmitButton(boolean hasText) { - mSubmitButton.setVisibility( - isSubmitAreaEnabled() ? (hasText ? VISIBLE : INVISIBLE) : GONE); + int visibility = GONE; + if (isSubmitAreaEnabled() && hasFocus() && (hasText || !mVoiceButtonEnabled)) { + visibility = VISIBLE; + } + mSubmitButton.setVisibility(visibility); } private void updateSubmitArea() { int visibility = GONE; - if (isSubmitAreaEnabled()) { - if (mSubmitButton.getVisibility() == VISIBLE - || mVoiceButton.getVisibility() == VISIBLE) { - visibility = VISIBLE; - } else { - visibility = INVISIBLE; - } + if (isSubmitAreaEnabled() + && (mSubmitButton.getVisibility() == VISIBLE + || mVoiceButton.getVisibility() == VISIBLE)) { + visibility = VISIBLE; } mSubmitArea.setVisibility(visibility); } @@ -601,6 +604,11 @@ public class SearchView extends LinearLayout { mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET); } + private void updateFocusedState(boolean focused) { + mSearchPlate.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET); + mSubmitArea.getBackground().setState(focused ? FOCUSED_STATE_SET : EMPTY_STATE_SET); + } + private void setImeVisibility(boolean visible) { InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); @@ -851,16 +859,11 @@ public class SearchView extends LinearLayout { * Update the visibility of the voice button. There are actually two voice search modes, * either of which will activate the button. * @param empty whether the search query text field is empty. If it is, then the other - * criteria apply to make the voice button visible. Otherwise the voice button will not - * be visible - i.e., if the user has typed a query, remove the voice button. + * criteria apply to make the voice button visible. */ private void updateVoiceButton(boolean empty) { - // If the voice button is to be visible, show it - // Else, make it gone if the submit button is enabled, otherwise invisible to - // avoid losing the real-estate - int visibility = mSubmitButtonEnabled ? GONE : INVISIBLE; - - if (mVoiceButtonEnabled && !isIconified() && empty) { + int visibility = GONE; + if (mVoiceButtonEnabled && !isIconified() && (empty || !mSubmitButtonEnabled)) { visibility = VISIBLE; mSubmitButton.setVisibility(GONE); } @@ -958,7 +961,8 @@ public class SearchView extends LinearLayout { } void onTextFocusChanged() { - updateCloseButton(); + updateViewsVisibility(isIconified()); + updateFocusedState(mQueryTextView.hasFocus()); } private boolean onItemClicked(int position, int actionKey, String actionMsg) { diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java index bab469b01cf9..21c61bdf67ab 100644 --- a/core/java/android/widget/StackView.java +++ b/core/java/android/widget/StackView.java @@ -531,6 +531,8 @@ public class StackView extends AdapterViewAnimator { @Override protected void dispatchDraw(Canvas canvas) { + boolean expandClipRegion = false; + canvas.getClipBounds(stackInvalidateRect); final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { @@ -540,12 +542,22 @@ public class StackView extends AdapterViewAnimator { child.getAlpha() == 0f || child.getVisibility() != VISIBLE) { lp.resetInvalidateRect(); } - stackInvalidateRect.union(lp.getInvalidateRect()); + Rect childInvalidateRect = lp.getInvalidateRect(); + if (!childInvalidateRect.isEmpty()) { + expandClipRegion = true; + stackInvalidateRect.union(childInvalidateRect); + } + } + + // We only expand the clip bounds if necessary. + if (expandClipRegion) { + canvas.save(Canvas.CLIP_SAVE_FLAG); + canvas.clipRect(stackInvalidateRect, Region.Op.UNION); + super.dispatchDraw(canvas); + canvas.restore(); + } else { + super.dispatchDraw(canvas); } - canvas.save(Canvas.CLIP_SAVE_FLAG); - canvas.clipRect(stackInvalidateRect, Region.Op.UNION); - super.dispatchDraw(canvas); - canvas.restore(); } private void onLayout() { diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png Binary files differindex b9435b645117..ae77fa0cadbc 100644 --- a/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png +++ b/core/res/res/drawable-hdpi/text_cursor_holo_dark.9.png diff --git a/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png Binary files differindex 477d820cc965..c6bdfcc6a3bd 100644 --- a/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png +++ b/core/res/res/drawable-hdpi/text_cursor_holo_light.9.png diff --git a/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png b/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png Binary files differindex b9435b645117..ae77fa0cadbc 100644 --- a/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png +++ b/core/res/res/drawable-mdpi/text_cursor_holo_dark.9.png diff --git a/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png b/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png Binary files differindex 477d820cc965..c6bdfcc6a3bd 100644 --- a/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png +++ b/core/res/res/drawable-mdpi/text_cursor_holo_light.9.png diff --git a/core/res/res/layout/search_view.xml b/core/res/res/layout/search_view.xml index 93b6deb6e57e..c52b73f874d2 100644 --- a/core/res/res/layout/search_view.xml +++ b/core/res/res/layout/search_view.xml @@ -54,6 +54,10 @@ android:layout_height="wrap_content" android:layout_weight="1" android:layout_gravity="center_vertical" + android:layout_marginLeft="4dip" + android:layout_marginRight="4dip" + android:layout_marginTop="4dip" + android:layout_marginBottom="4dip" android:orientation="horizontal"> <!-- Inner layout contains the app icon, button(s) and EditText --> diff --git a/core/res/res/raw-xlarge/incognito_mode_start_page.html b/core/res/res/raw-xlarge/incognito_mode_start_page.html new file mode 100644 index 000000000000..492658d29484 --- /dev/null +++ b/core/res/res/raw-xlarge/incognito_mode_start_page.html @@ -0,0 +1,24 @@ +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/> + <title>New incognito tab</title> + </head> + <body> + <p><strong>You've gone incognito</strong>. Pages you view in this tab + won't appear in your browser history or search history, and they won't + leave other traces, like cookies, on your device after you close the + incognito tab. Any files you download or bookmarks you create will be + preserved, however.</p> + + <p><strong>Going incognito doesn't affect the behavior of other people, + servers, or software. Be wary of:</strong></p> + + <ul> + <li>Websites that collect or share information about you</li> + <li>Internet service providers or employers that track the pages you visit</li> + <li>Malicious software that tracks your keystrokes in exchange for free smileys</li> + <li>Surveillance by secret agents</li> + <li>People standing behind you</li> + </ul> + </body> +</html> diff --git a/docs/html/images/avd-manager.png b/docs/html/images/avd-manager.png Binary files differindex 69ce972f8dbc..c33d8a885177 100644 --- a/docs/html/images/avd-manager.png +++ b/docs/html/images/avd-manager.png diff --git a/docs/html/images/billing_package.png b/docs/html/images/billing_package.png Binary files differindex ec04c2d98153..951e117d4446 100755..100644 --- a/docs/html/images/billing_package.png +++ b/docs/html/images/billing_package.png diff --git a/docs/html/images/developing/adt-props-isLib.png b/docs/html/images/developing/adt-props-isLib.png Binary files differindex 18bdb3392380..49c911175b96 100644 --- a/docs/html/images/developing/adt-props-isLib.png +++ b/docs/html/images/developing/adt-props-isLib.png diff --git a/docs/html/images/developing/adt-props-libRef.png b/docs/html/images/developing/adt-props-libRef.png Binary files differindex e61df51424e4..73bccbd0e6d4 100644 --- a/docs/html/images/developing/adt-props-libRef.png +++ b/docs/html/images/developing/adt-props-libRef.png diff --git a/docs/html/images/licensing_add_library.png b/docs/html/images/licensing_add_library.png Binary files differindex 90b4435ab017..3bbe6d5c6efc 100644 --- a/docs/html/images/licensing_add_library.png +++ b/docs/html/images/licensing_add_library.png diff --git a/docs/html/images/licensing_gapis_8.png b/docs/html/images/licensing_gapis_8.png Binary files differindex 43ad26233261..480d98992143 100644 --- a/docs/html/images/licensing_gapis_8.png +++ b/docs/html/images/licensing_gapis_8.png diff --git a/docs/html/images/licensing_package.png b/docs/html/images/licensing_package.png Binary files differindex 5da5632672b6..eb2c5cfd3f2c 100644 --- a/docs/html/images/licensing_package.png +++ b/docs/html/images/licensing_package.png diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml index bfa6c36a096e..3f172e68f3f8 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml @@ -38,8 +38,8 @@ android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" - android:layout_marginLeft="123dip" - android:layout_marginTop="16dip" + android:layout_marginLeft="131dip" + android:layout_marginTop="13dip" android:maxWidth="@dimen/status_bar_recents_thumbnail_max_width" android:maxHeight="@dimen/status_bar_recents_thumbnail_max_height" android:adjustViewBounds="true" diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml index eda19b742d17..42940be6f1b8 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml @@ -51,7 +51,7 @@ android:stackFromBottom="true" android:fadingEdge="vertical" android:scrollbars="none" - android:fadingEdgeLength="30dip" + android:fadingEdgeLength="20dip" android:listSelector="@drawable/recents_thumbnail_bg_selector" /> diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index eed41a0c0e9a..8ccfbbab68c7 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -4791,13 +4791,17 @@ public class WindowManagerService extends IWindowManager.Stub if (maxLayer < ws.mAnimLayer) { maxLayer = ws.mAnimLayer; } - final Rect wf = ws.mFrame; - final Rect cr = ws.mContentInsets; - int left = wf.left + cr.left; - int top = wf.top + cr.top; - int right = wf.right - cr.right; - int bottom = wf.bottom - cr.bottom; - frame.union(left, top, right, bottom); + + // Don't include wallpaper in bounds calculation + if (!ws.mIsWallpaper) { + final Rect wf = ws.mFrame; + final Rect cr = ws.mContentInsets; + int left = wf.left + cr.left; + int top = wf.top + cr.top; + int right = wf.right - cr.right; + int bottom = wf.bottom - cr.bottom; + frame.union(left, top, right, bottom); + } } Binder.restoreCallingIdentity(ident); @@ -5460,8 +5464,9 @@ public class WindowManagerService extends IWindowManager.Stub shortSize = (int)(shortSize/dm.density); // These semi-magic numbers define our compatibility modes for - // applications with different screens. Don't change unless you - // make sure to test lots and lots of apps! + // applications with different screens. These are guarantees to + // app developers about the space they can expect for a particular + // configuration. DO NOT CHANGE! if (longSize < 470) { // This is shorter than an HVGA normal density screen (which // is 480 pixels on its long side). @@ -5469,12 +5474,12 @@ public class WindowManagerService extends IWindowManager.Stub | Configuration.SCREENLAYOUT_LONG_NO; } else { // What size is this screen screen? - if (longSize >= 800 && shortSize >= 600) { - // SVGA or larger screens at medium density are the point + if (longSize >= 960 && shortSize >= 720) { + // 1.5xVGA or larger screens at medium density are the point // at which we consider it to be an extra large screen. mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE; - } else if (longSize >= 530 && shortSize >= 400) { - // SVGA or larger screens at high density are the point + } else if (longSize >= 640 && shortSize >= 480) { + // VGA or larger screens at medium density are the point // at which we consider it to be a large screen. mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE; } else { diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java index 6c9f48fb003c..db14e53b3aff 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java @@ -28,10 +28,12 @@ import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Arc2D; import java.awt.geom.Area; +import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; /** * Delegate implementing the native methods of android.graphics.Path @@ -331,58 +333,91 @@ public final class Path_Delegate { @LayoutlibDelegate /*package*/ static void native_addOval(int nPath, RectF oval, int dir) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addOval is not supported.", null, null /*data*/); + Path_Delegate pathDelegate = sManager.getDelegate(nPath); + if (pathDelegate == null) { + return; + } + + pathDelegate.mPath.append(new Ellipse2D.Float( + oval.left, oval.top, oval.width(), oval.height()), false); } @LayoutlibDelegate /*package*/ static void native_addCircle(int nPath, float x, float y, float radius, int dir) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addCircle is not supported.", null, null /*data*/); + Path_Delegate pathDelegate = sManager.getDelegate(nPath); + if (pathDelegate == null) { + return; + } + + // because x/y is the center of the circle, need to offset this by the radius + pathDelegate.mPath.append(new Ellipse2D.Float( + x - radius, y - radius, radius * 2, radius * 2), false); } @LayoutlibDelegate /*package*/ static void native_addArc(int nPath, RectF oval, float startAngle, float sweepAngle) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addArc is not supported.", null, null /*data*/); + Path_Delegate pathDelegate = sManager.getDelegate(nPath); + if (pathDelegate == null) { + return; + } + + // because x/y is the center of the circle, need to offset this by the radius + pathDelegate.mPath.append(new Arc2D.Float( + oval.left, oval.top, oval.width(), oval.height(), + startAngle, sweepAngle, Arc2D.OPEN), false); } @LayoutlibDelegate - /*package*/ static void native_addRoundRect(int nPath, RectF rect, - float rx, float ry, int dir) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addRoundRect is not supported.", null, null /*data*/); + /*package*/ static void native_addRoundRect( + int nPath, RectF rect, float rx, float ry, int dir) { + + Path_Delegate pathDelegate = sManager.getDelegate(nPath); + if (pathDelegate == null) { + return; + } + + pathDelegate.mPath.append(new RoundRectangle2D.Float( + rect.left, rect.top, rect.width(), rect.height(), rx * 2, ry * 2), false); } @LayoutlibDelegate - /*package*/ static void native_addRoundRect(int nPath, RectF r, float[] radii, int dir) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addRoundRect is not supported.", null, null /*data*/); + /*package*/ static void native_addRoundRect(int nPath, RectF rect, float[] radii, int dir) { + // Java2D doesn't support different rounded corners in each corner, so just use the + // first value. + native_addRoundRect(nPath, rect, radii[0], radii[1], dir); + + // there can be a case where this API is used but with similar values for all corners, so + // in that case we don't warn. + // we only care if 2 corners are different so just compare to the next one. + for (int i = 0 ; i < 3 ; i++) { + if (radii[i * 2] != radii[(i + 1) * 2] || radii[i * 2 + 1] != radii[(i + 1) * 2 + 1]) { + Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, + "Different corner sizes are not supported in Path.addRoundRect.", + null, null /*data*/); + break; + } + } } @LayoutlibDelegate /*package*/ static void native_addPath(int nPath, int src, float dx, float dy) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addPath is not supported.", null, null /*data*/); + addPath(nPath, src, AffineTransform.getTranslateInstance(dx, dy)); } @LayoutlibDelegate /*package*/ static void native_addPath(int nPath, int src) { - native_addPath(nPath, src, 0, 0); + addPath(nPath, src, null /*transform*/); } @LayoutlibDelegate /*package*/ static void native_addPath(int nPath, int src, int matrix) { - // FIXME - Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, - "Path.addPath is not supported.", null, null /*data*/); + Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(matrix); + if (matrixDelegate == null) { + return; + } + + addPath(nPath, src, matrixDelegate.getAffineTransform()); } @LayoutlibDelegate @@ -487,6 +522,26 @@ public final class Path_Delegate { return null; } + private static void addPath(int destPath, int srcPath, AffineTransform transform) { + Path_Delegate destPathDelegate = sManager.getDelegate(destPath); + if (destPathDelegate == null) { + return; + } + + Path_Delegate srcPathDelegate = sManager.getDelegate(srcPath); + if (srcPathDelegate == null) { + return; + } + + if (transform != null) { + destPathDelegate.mPath.append( + srcPathDelegate.mPath.getPathIterator(transform), false); + } else { + destPathDelegate.mPath.append(srcPathDelegate.mPath, false); + } + } + + /** * Returns whether the path is empty. * @return true if the path is empty. diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index acc7379990d4..e6e96476c18a 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -192,7 +192,7 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge { Capability.UNBOUND_RENDERING, Capability.CUSTOM_BACKGROUND_COLOR, Capability.RENDER, - Capability.LAYOUT_ONLY, + //Capability.LAYOUT_ONLY, // disable to run on ADT 10.0 which doesn't include this. Capability.EMBEDDED_LAYOUT, Capability.VIEW_MANIPULATION, Capability.PLAY_ANIMATION, diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java index c1d760069188..138a455004be 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java @@ -412,9 +412,7 @@ public final class BridgeTypedArray extends TypedArray { return LayoutParams.MATCH_PARENT; } else if (s.equals(BridgeConstants.WRAP_CONTENT)) { return LayoutParams.WRAP_CONTENT; - } - - if (RenderResources.REFERENCE_NULL.equals(s)) { + } else if (RenderResources.REFERENCE_NULL.equals(s)) { return defValue; } @@ -486,23 +484,32 @@ public final class BridgeTypedArray extends TypedArray { return LayoutParams.MATCH_PARENT; } else if (s.equals(BridgeConstants.WRAP_CONTENT)) { return LayoutParams.WRAP_CONTENT; - } - - if (RenderResources.REFERENCE_NULL.equals(s)) { + } else if (RenderResources.REFERENCE_NULL.equals(s)) { return defValue; } - // FIXME huh? + if (ResourceHelper.stringToFloat(s, mValue)) { + float f = mValue.getDimension(mBridgeResources.mMetrics); - float f = getDimension(index, defValue); - final int res = (int)(f+0.5f); - if (res != 0) return res; - if (f == 0) return 0; - if (f > 0) return 1; + if (f < 0) { + // negative values are not allowed in pixel dimensions + Bridge.getLog().error(LayoutLog.TAG_BROKEN, + "Negative pixel dimension: " + s, + null, null /*data*/); + return defValue; + } - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_FORMAT, - "Can't convert to dimension: " + Integer.toString(index), - null, null /*data*/); + if (f == 0) return 0; + if (f < 1) return 1; + + return (int)(f+0.5f); + } + + // looks like we were unable to resolve the dimension value + Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_FORMAT, + String.format( + "\"%1$s\" in attribute \"%2$s\" is not a valid format.", + s, mNames[index]), null /*data*/); return defValue; } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java index 69f46e6e335e..649160eb4501 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java @@ -377,7 +377,7 @@ public final class ResourceHelper { } // check the first character - if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.') { + if (buf[0] < '0' && buf[0] > '9' && buf[0] != '.' && buf[0] != '-') { return false; } |