diff options
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/app/Dialog.java | 24 | ||||
-rw-r--r-- | core/java/android/app/LoaderManager.java | 13 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothAdapter.java | 40 | ||||
-rw-r--r-- | core/java/android/content/ContentProvider.java | 41 | ||||
-rw-r--r-- | core/java/android/content/CursorLoader.java | 2 | ||||
-rw-r--r-- | core/java/android/database/DatabaseUtils.java | 14 | ||||
-rw-r--r-- | core/java/android/net/Uri.java | 20 | ||||
-rw-r--r-- | core/java/android/provider/Mtp.java | 7 | ||||
-rw-r--r-- | core/java/android/view/View.java | 159 | ||||
-rw-r--r-- | core/java/android/view/ViewDebug.java | 118 | ||||
-rw-r--r-- | core/java/android/view/ViewGroup.java | 17 | ||||
-rw-r--r-- | core/java/android/webkit/DeviceOrientationManager.java | 55 | ||||
-rw-r--r-- | core/java/android/webkit/WebView.java | 21 | ||||
-rw-r--r-- | core/java/android/webkit/WebViewCore.java | 11 | ||||
-rw-r--r-- | core/java/com/android/internal/app/ActionBarImpl.java | 33 |
15 files changed, 461 insertions, 114 deletions
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java index a9420b4..b4c138e 100644 --- a/core/java/android/app/Dialog.java +++ b/core/java/android/app/Dialog.java @@ -16,6 +16,7 @@ package android.app; +import com.android.internal.app.ActionBarImpl; import com.android.internal.policy.PolicyManager; import android.content.ComponentName; @@ -27,9 +28,9 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.view.ActionMode; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; -import android.view.ActionMode; import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.KeyEvent; @@ -77,6 +78,7 @@ public class Dialog implements DialogInterface, Window.Callback, final WindowManager mWindowManager; Window mWindow; View mDecor; + private ActionBarImpl mActionBar; /** * This field should be made private, so it is hidden from the SDK. * {@hide} @@ -178,6 +180,15 @@ public class Dialog implements DialogInterface, Window.Callback, } /** + * Retrieve the {@link ActionBar} attached to this dialog, if present. + * + * @return The ActionBar attached to the dialog or null if no ActionBar is present. + */ + public ActionBar getActionBar() { + return mActionBar; + } + + /** * Sets the Activity that owns this dialog. An example use: This Dialog will * use the suggested volume control stream of the Activity. * @@ -228,6 +239,11 @@ public class Dialog implements DialogInterface, Window.Callback, onStart(); mDecor = mWindow.getDecorView(); + + if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) { + mActionBar = new ActionBarImpl(this); + } + WindowManager.LayoutParams l = mWindow.getAttributes(); if ((l.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) { @@ -834,12 +850,14 @@ public class Dialog implements DialogInterface, Window.Callback, } public ActionMode onStartActionMode(ActionMode.Callback callback) { - // TODO Support context modes in dialogs + if (mActionBar != null) { + return mActionBar.startActionMode(callback); + } return null; } /** - * @return The activity associated with this dialog, or null if there is no assocaited activity. + * @return The activity associated with this dialog, or null if there is no associated activity. */ private ComponentName getAssociatedActivity() { Activity activity = mOwnerActivity; diff --git a/core/java/android/app/LoaderManager.java b/core/java/android/app/LoaderManager.java index e7bdd8b..28abcaa 100644 --- a/core/java/android/app/LoaderManager.java +++ b/core/java/android/app/LoaderManager.java @@ -185,11 +185,14 @@ class LoaderManagerImpl implements LoaderManager { void stop() { if (DEBUG) Log.v(TAG, " Stopping: " + this); mStarted = false; - if (mLoader != null && mListenerRegistered) { - // Let the loader know we're done with it - mListenerRegistered = false; - mLoader.unregisterListener(this); - mLoader.stopLoading(); + if (!mRetaining) { + if (mLoader != null && mListenerRegistered) { + // Let the loader know we're done with it + mListenerRegistered = false; + mLoader.unregisterListener(this); + mLoader.stopLoading(); + } + mData = null; } } diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index 8eda844..03bcadc 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -468,12 +468,17 @@ public final class BluetoothAdapter { * <p>Valid Bluetooth names are a maximum of 248 UTF-8 characters, however * many remote devices can only display the first 40 characters, and some * may be limited to just 20. + * <p>If Bluetooth state is not {@link #STATE_ON}, this API + * will return false. After turning on Bluetooth, + * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} + * to get the updated value. * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} * * @param name a valid Bluetooth name * @return true if the name was set, false otherwise */ public boolean setName(String name) { + if (getState() != STATE_ON) return false; try { return mService.setName(name); } catch (RemoteException e) {Log.e(TAG, "", e);} @@ -488,11 +493,16 @@ public final class BluetoothAdapter { * {@link #SCAN_MODE_NONE}, * {@link #SCAN_MODE_CONNECTABLE}, * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. + * <p>If Bluetooth state is not {@link #STATE_ON}, this API + * will return {@link #SCAN_MODE_NONE}. After turning on Bluetooth, + * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} + * to get the updated value. * <p>Requires {@link android.Manifest.permission#BLUETOOTH} * * @return scan mode */ public int getScanMode() { + if (getState() != STATE_ON) return SCAN_MODE_NONE; try { return mService.getScanMode(); } catch (RemoteException e) {Log.e(TAG, "", e);} @@ -511,6 +521,10 @@ public final class BluetoothAdapter { * {@link #SCAN_MODE_NONE}, * {@link #SCAN_MODE_CONNECTABLE}, * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}. + * <p>If Bluetooth state is not {@link #STATE_ON}, this API + * will return false. After turning on Bluetooth, + * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} + * to get the updated value. * <p>Requires {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} * <p>Applications cannot set the scan mode. They should use * <code>startActivityForResult( @@ -524,6 +538,7 @@ public final class BluetoothAdapter { * @hide */ public boolean setScanMode(int mode, int duration) { + if (getState() != STATE_ON) return false; try { return mService.setScanMode(mode, duration); } catch (RemoteException e) {Log.e(TAG, "", e);} @@ -532,11 +547,13 @@ public final class BluetoothAdapter { /** @hide */ public boolean setScanMode(int mode) { + if (getState() != STATE_ON) return false; return setScanMode(mode, 120); } /** @hide */ public int getDiscoverableTimeout() { + if (getState() != STATE_ON) return -1; try { return mService.getDiscoverableTimeout(); } catch (RemoteException e) {Log.e(TAG, "", e);} @@ -545,6 +562,7 @@ public final class BluetoothAdapter { /** @hide */ public void setDiscoverableTimeout(int timeout) { + if (getState() != STATE_ON) return; try { mService.setDiscoverableTimeout(timeout); } catch (RemoteException e) {Log.e(TAG, "", e);} @@ -572,11 +590,16 @@ public final class BluetoothAdapter { * <p>Device discovery will only find remote devices that are currently * <i>discoverable</i> (inquiry scan enabled). Many Bluetooth devices are * not discoverable by default, and need to be entered into a special mode. + * <p>If Bluetooth state is not {@link #STATE_ON}, this API + * will return false. After turning on Bluetooth, + * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} + * to get the updated value. * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}. * * @return true on success, false on error */ public boolean startDiscovery() { + if (getState() != STATE_ON) return false; try { return mService.startDiscovery(); } catch (RemoteException e) {Log.e(TAG, "", e);} @@ -593,10 +616,15 @@ public final class BluetoothAdapter { * the Activity, but is run as a system service, so an application should * always call cancel discovery even if it did not directly request a * discovery, just to be sure. + * <p>If Bluetooth state is not {@link #STATE_ON}, this API + * will return false. After turning on Bluetooth, + * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} + * to get the updated value. * * @return true on success, false on error */ public boolean cancelDiscovery() { + if (getState() != STATE_ON) return false; try { mService.cancelDiscovery(); } catch (RemoteException e) {Log.e(TAG, "", e);} @@ -614,11 +642,16 @@ public final class BluetoothAdapter { * <p>Applications can also register for {@link #ACTION_DISCOVERY_STARTED} * or {@link #ACTION_DISCOVERY_FINISHED} to be notified when discovery * starts or completes. + * <p>If Bluetooth state is not {@link #STATE_ON}, this API + * will return false. After turning on Bluetooth, + * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} + * to get the updated value. * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * * @return true if discovering */ public boolean isDiscovering() { + if (getState() != STATE_ON) return false; try { return mService.isDiscovering(); } catch (RemoteException e) {Log.e(TAG, "", e);} @@ -628,11 +661,18 @@ public final class BluetoothAdapter { /** * Return the set of {@link BluetoothDevice} objects that are bonded * (paired) to the local adapter. + * <p>If Bluetooth state is not {@link #STATE_ON}, this API + * will return an empty set. After turning on Bluetooth, + * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON} + * to get the updated value. * <p>Requires {@link android.Manifest.permission#BLUETOOTH}. * * @return unmodifiable set of {@link BluetoothDevice}, or null on error */ public Set<BluetoothDevice> getBondedDevices() { + if (getState() != STATE_ON) { + return toDeviceSet(new String[0]); + } try { return toDeviceSet(mService.listBonds()); } catch (RemoteException e) {Log.e(TAG, "", e);} diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 1163add..e1d431f 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -1001,7 +1001,7 @@ public abstract class ContentProvider implements ComponentCallbacks { /** * @hide -- until interface has proven itself * - * Call an provider-defined method. This can be used to implement + * Call a provider-defined method. This can be used to implement * interfaces that are cheaper than using a Cursor. * * @param method Method name to call. Opaque to framework. @@ -1013,29 +1013,26 @@ public abstract class ContentProvider implements ComponentCallbacks { } /** - * Shuts down this instance of the ContentProvider. It is useful when writing tests that use - * the ContentProvider. + * Implement this to shut down the ContentProvider instance. You can then + * invoke this method in unit tests. + * * <p> - * If a unittest starts the ContentProvider in its test(..() methods, it could run into sqlite - * errors "disk I/O error" or "corruption" in the following scenario: - * <ul> - * <li>Say, there are 2 test methods in the unittest</li> - * <li>test1() (or setUp()) causes ContentProvider object to be initialized and - * assume it opens a database connection to "foo.db"</li> - * <li>est1() completes and test2() starts</li> - * <li>During the execution of test2() there will be 2 connections to "foo.db"</li> - * <li>Different threads in the ContentProvider may have one of these two connection - * handles. This is not a problem per se</li> - * <li>But if the two threads with 2 database connections don't interact correctly, - * there could be unexpected errors from sqlite</li> - * <li>Some of those unexpected errros are "disk I/O error" or "corruption" error</li> - * <li>Common practice in tearDown() is to delete test directory (and the database files)</li> - * <li>If this is done while some threads are still holding unclosed database connections, - * sqlite quite easily gets into corruption and disk I/O errors</li> - * </ul> + * Android normally handles ContentProvider startup and shutdown + * automatically. You do not need to start up or shut down a + * ContentProvider. When you invoke a test method on a ContentProvider, + * however, a ContentProvider instance is started and keeps running after + * the test finishes, even if a succeeding test instantiates another + * ContentProvider. A conflict develops because the two instances are + * usually running against the same underlying data source (for example, an + * sqlite database). + * </p> * <p> - * tearDown() in the unittests should call this method to have ContentProvider gracefully - * shutdown all database connections. + * Implementing shutDown() avoids this conflict by providing a way to + * terminate the ContentProvider. This method can also prevent memory leaks + * from multiple instantiations of the ContentProvider, and it can ensure + * unit test isolation by allowing you to completely clean up the test + * fixture before moving on to the next test. + * </p> */ public void shutdown() { Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " + diff --git a/core/java/android/content/CursorLoader.java b/core/java/android/content/CursorLoader.java index 850ff7f..42599ed 100644 --- a/core/java/android/content/CursorLoader.java +++ b/core/java/android/content/CursorLoader.java @@ -100,8 +100,8 @@ public class CursorLoader extends AsyncTaskLoader<Cursor> { public void stopLoading() { if (mCursor != null && !mCursor.isClosed()) { mCursor.close(); - mCursor = null; } + mCursor = null; // Attempt to cancel the current load task if possible. cancelLoad(); diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java index 9ac45d8..c07c3c6 100644 --- a/core/java/android/database/DatabaseUtils.java +++ b/core/java/android/database/DatabaseUtils.java @@ -1203,4 +1203,18 @@ public class DatabaseUtils { } return STATEMENT_OTHER; } + + /** + * Appends one set of selection args to another. This is useful when adding a selection + * argument to a user provided set. + */ + public static String[] appendSelectionArgs(String[] originalValues, String[] newValues) { + if (originalValues == null || originalValues.length == 0) { + return newValues; + } + String[] result = new String[originalValues.length + newValues.length ]; + System.arraycopy(originalValues, 0, result, 0, originalValues.length); + System.arraycopy(newValues, 0, result, originalValues.length, newValues.length); + return result; + } } diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java index 47faaba..63adcd0 100644 --- a/core/java/android/net/Uri.java +++ b/core/java/android/net/Uri.java @@ -1568,7 +1568,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { throw new UnsupportedOperationException(NOT_HIERARCHICAL); } if (key == null) { - throw new NullPointerException("key"); + throw new NullPointerException("key"); } final String query = getEncodedQuery(); @@ -1608,6 +1608,24 @@ public abstract class Uri implements Parcelable, Comparable<Uri> { return null; } + /** + * Searches the query string for the first value with the given key and interprets it + * as a boolean value. "false" and "0" are interpreted as <code>false</code>, everything + * else is interpreted as <code>true</code>. + * + * @param key which will be decoded + * @param defaultValue the default value to return if there is no query parameter for key + * @return the boolean interpretation of the query parameter key + */ + public boolean getBooleanQueryParameter(String key, boolean defaultValue) { + String flag = getQueryParameter(key); + if (flag == null) { + return defaultValue; + } + flag = flag.toLowerCase(); + return (!"false".equals(flag) && !"0".equals(flag)); + } + /** Identifies a null parcelled Uri. */ private static final int NULL_TYPE_ID = 0; diff --git a/core/java/android/provider/Mtp.java b/core/java/android/provider/Mtp.java index 15f8666..bc764ac 100644 --- a/core/java/android/provider/Mtp.java +++ b/core/java/android/provider/Mtp.java @@ -308,6 +308,13 @@ public final class Mtp public static final int FORMAT_ABSTRACT_CONTACT = 0xBB81; public static final int FORMAT_VCARD_2 = 0xBB82; + // Object properties we support + public static final int PROPERTY_STORAGE_ID = 0xDC01; + public static final int PROPERTY_OBJECT_FORMAT = 0xDC02; + public static final int PROPERTY_OBJECT_SIZE = 0xDC04; + public static final int PROPERTY_OBJECT_FILE_NAME = 0xDC07; + public static final int PROPERTY_PARENT_OBJECT = 0xDC0B; + /** * Object is not protected. It may be modified and deleted, and its properties * may be modified. diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 735b35a..603ad89 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -16,6 +16,7 @@ package android.view; +import android.graphics.Camera; import com.android.internal.R; import com.android.internal.view.menu.MenuBuilder; @@ -1436,8 +1437,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility static final int MEASURED_DIMENSION_SET = 0x00000800; /** {@hide} */ static final int FORCE_LAYOUT = 0x00001000; - - private static final int LAYOUT_REQUIRED = 0x00002000; + /** {@hide} */ + static final int LAYOUT_REQUIRED = 0x00002000; private static final int PRESSED = 0x00004000; @@ -1537,6 +1538,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility private static final int AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000; /** + * Indicates that pivotX or pivotY were explicitly set and we should not assume the center + * for transform operations + * + * @hide + */ + private static final int PIVOT_EXPLICITLY_SET = 0x10000000; + + /** * The parent this view is attached to. * {@hide} * @@ -1627,6 +1636,42 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility private boolean mMatrixIsIdentity = true; /** + * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set. + */ + private Camera mCamera = null; + + /** + * This matrix is used when computing the matrix for 3D rotations. + */ + private Matrix matrix3D = null; + + /** + * These prev values are used to recalculate a centered pivot point when necessary. The + * pivot point is only used in matrix operations (when rotation, scale, or translation are + * set), so thes values are only used then as well. + */ + private int mPrevWidth = -1; + private int mPrevHeight = -1; + + /** + * Convenience value to check for float values that are close enough to zero to be considered + * zero. + */ + private static float NONZERO_EPSILON = .001f; + + /** + * The degrees rotation around the vertical axis through the pivot point. + */ + @ViewDebug.ExportedProperty + private float mRotationY = 0f; + + /** + * The degrees rotation around the horizontal axis through the pivot point. + */ + @ViewDebug.ExportedProperty + private float mRotationX = 0f; + + /** * The degrees rotation around the pivot point. */ @ViewDebug.ExportedProperty @@ -4888,6 +4933,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } /** + * Utility function to determine if the value is far enough away from zero to be + * considered non-zero. + * @param value A floating point value to check for zero-ness + * @return whether the passed-in value is far enough away from zero to be considered non-zero + */ + private static boolean nonzero(float value) { + return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON); + } + + /** * Recomputes the transform matrix if necessary. * * @return True if the transform matrix is the identity matrix, false otherwise. @@ -4896,10 +4951,34 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility if (mMatrixDirty) { // transform-related properties have changed since the last time someone // asked for the matrix; recalculate it with the current values + + // Figure out if we need to update the pivot point + if ((mPrivateFlags & PIVOT_EXPLICITLY_SET) == 0) { + if ((mRight - mLeft) != mPrevWidth && (mBottom - mTop) != mPrevHeight) { + mPrevWidth = mRight - mLeft; + mPrevHeight = mBottom - mTop; + mPivotX = (float) mPrevWidth / 2f; + mPivotY = (float) mPrevHeight / 2f; + } + } mMatrix.reset(); mMatrix.setTranslate(mTranslationX, mTranslationY); mMatrix.preRotate(mRotation, mPivotX, mPivotY); mMatrix.preScale(mScaleX, mScaleY, mPivotX, mPivotY); + if (nonzero(mRotationX) || nonzero(mRotationY)) { + if (mCamera == null) { + mCamera = new Camera(); + matrix3D = new Matrix(); + } + mCamera.save(); + mCamera.rotateX(mRotationX); + mCamera.rotateY(mRotationY); + mCamera.getMatrix(matrix3D); + matrix3D.preTranslate(-mPivotX, -mPivotY); + matrix3D.postTranslate(mPivotX, mPivotY); + mMatrix.postConcat(matrix3D); + mCamera.restore(); + } mMatrixDirty = false; mMatrixIsIdentity = mMatrix.isIdentity(); mInverseMatrixDirty = true; @@ -4955,6 +5034,64 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility } /** + * The degrees that the view is rotated around the vertical axis through the pivot point. + * + * @see #getPivotX() + * @see #getPivotY() + * @return The degrees of Y rotation. + */ + public float getRotationY() { + return mRotationY; + } + + /** + * Sets the degrees that the view is rotated around the vertical axis through pivot point. + * + * @param rotationY The degrees of Y rotation. + * @see #getPivotX() + * @see #getPivotY() + */ + public void setRotationY(float rotationY) { + if (mRotationY != rotationY) { + // Double-invalidation is necessary to capture view's old and new areas + invalidate(); + mRotationY = rotationY; + mMatrixDirty = true; + mPrivateFlags |= DRAWN; // force another invalidation with the new orientation + invalidate(); + } + } + + /** + * The degrees that the view is rotated around the horizontal axis through the pivot point. + * + * @see #getPivotX() + * @see #getPivotY() + * @return The degrees of X rotation. + */ + public float getRotationX() { + return mRotationX; + } + + /** + * Sets the degrees that the view is rotated around the horizontal axis through pivot point. + * + * @param rotationX The degrees of X rotation. + * @see #getPivotX() + * @see #getPivotY() + */ + public void setRotationX(float rotationX) { + if (mRotationX != rotationX) { + // Double-invalidation is necessary to capture view's old and new areas + invalidate(); + mRotationX = rotationX; + mMatrixDirty = true; + mPrivateFlags |= DRAWN; // force another invalidation with the new orientation + invalidate(); + } + } + + /** * The amount that the view is scaled in x around the pivot point, as a proportion of * the view's unscaled width. A value of 1, the default, means that no scaling is applied. * @@ -5035,6 +5172,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility /** * Sets the x location of the point around which the view is * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}. + * By default, the pivot point is centered on the object. + * Setting this property disables this behavior and causes the view to use only the + * explicitly set pivotX and pivotY values. * * @param pivotX The x location of the pivot point. * @see #getRotation() @@ -5043,6 +5183,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * @see #getPivotY() */ public void setPivotX(float pivotX) { + mPrivateFlags |= PIVOT_EXPLICITLY_SET; if (mPivotX != pivotX) { // Double-invalidation is necessary to capture view's old and new areas invalidate(); @@ -5069,7 +5210,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility /** * Sets the y location of the point around which the view is {@link #setRotation(float) rotated} - * and {@link #setScaleY(float) scaled}. + * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object. + * Setting this property disables this behavior and causes the view to use only the + * explicitly set pivotX and pivotY values. * * @param pivotY The y location of the pivot point. * @see #getRotation() @@ -5078,6 +5221,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * @see #getPivotY() */ public void setPivotY(float pivotY) { + mPrivateFlags |= PIVOT_EXPLICITLY_SET; if (mPivotY != pivotY) { // Double-invalidation is necessary to capture view's old and new areas invalidate(); @@ -5312,15 +5456,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility * is still within the view. */ private boolean pointInView(float localX, float localY, float slop) { - if (!hasIdentityMatrix() && mAttachInfo != null) { - // non-identity matrix: transform the point into the view's coordinates - final float[] localXY = mAttachInfo.mTmpTransformLocation; - localXY[0] = localX; - localXY[1] = localY; - getInverseMatrix().mapPoints(localXY); - localX = localXY[0]; - localY = localXY[1]; - } return localX > -slop && localY > -slop && localX < ((mRight - mLeft) + slop) && localY < ((mBottom - mTop) + slop); } diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 5dd45f9..09939a6 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -934,65 +934,76 @@ public class ViewDebug { private static void profileViewAndChildren(final View view, BufferedWriter out) throws IOException { - final long durationMeasure = profileViewOperation(view, new ViewOperation<Void>() { - public Void[] pre() { - forceLayout(view); - return null; - } - - private void forceLayout(View view) { - view.forceLayout(); - if (view instanceof ViewGroup) { - ViewGroup group = (ViewGroup) view; - final int count = group.getChildCount(); - for (int i = 0; i < count; i++) { - forceLayout(group.getChildAt(i)); - } - } - } + profileViewAndChildren(view, out, true); + } - public void run(Void... data) { - view.measure(view.mOldWidthMeasureSpec, view.mOldHeightMeasureSpec); - } + private static void profileViewAndChildren(final View view, BufferedWriter out, boolean root) + throws IOException { - public void post(Void... data) { - } - }); + long durationMeasure = + (root || (view.mPrivateFlags & View.MEASURED_DIMENSION_SET) != 0) ? profileViewOperation( + view, new ViewOperation<Void>() { + public Void[] pre() { + forceLayout(view); + return null; + } - final long durationLayout = profileViewOperation(view, new ViewOperation<Void>() { - public Void[] pre() { - return null; - } + private void forceLayout(View view) { + view.forceLayout(); + if (view instanceof ViewGroup) { + ViewGroup group = (ViewGroup) view; + final int count = group.getChildCount(); + for (int i = 0; i < count; i++) { + forceLayout(group.getChildAt(i)); + } + } + } - public void run(Void... data) { - view.layout(view.mLeft, view.mTop, view.mRight, view.mBottom); - } + public void run(Void... data) { + view.measure(view.mOldWidthMeasureSpec, view.mOldHeightMeasureSpec); + } - public void post(Void... data) { - } - }); + public void post(Void... data) { + } + }) + : 0; + long durationLayout = + (root || (view.mPrivateFlags & View.LAYOUT_REQUIRED) != 0) ? profileViewOperation( + view, new ViewOperation<Void>() { + public Void[] pre() { + return null; + } - final long durationDraw = profileViewOperation(view, new ViewOperation<Object>() { - public Object[] pre() { - final DisplayMetrics metrics = view.getResources().getDisplayMetrics(); - final Bitmap bitmap = - Bitmap.createBitmap(metrics.widthPixels, metrics.heightPixels, - Bitmap.Config.RGB_565); - final Canvas canvas = new Canvas(bitmap); - return new Object[] { - bitmap, canvas - }; - } + public void run(Void... data) { + view.layout(view.mLeft, view.mTop, view.mRight, view.mBottom); + } - public void run(Object... data) { - view.draw((Canvas) data[1]); - } + public void post(Void... data) { + } + }) : 0; + long durationDraw = + (root || (view.mPrivateFlags & View.DRAWN) != 0) ? profileViewOperation(view, + new ViewOperation<Object>() { + public Object[] pre() { + final DisplayMetrics metrics = + view.getResources().getDisplayMetrics(); + final Bitmap bitmap = + Bitmap.createBitmap(metrics.widthPixels, + metrics.heightPixels, Bitmap.Config.RGB_565); + final Canvas canvas = new Canvas(bitmap); + return new Object[] { + bitmap, canvas + }; + } - public void post(Object... data) { - ((Bitmap) data[0]).recycle(); - } - }); + public void run(Object... data) { + view.draw((Canvas) data[1]); + } + public void post(Object... data) { + ((Bitmap) data[0]).recycle(); + } + }) : 0; out.write(String.valueOf(durationMeasure)); out.write(' '); out.write(String.valueOf(durationLayout)); @@ -1003,7 +1014,7 @@ public class ViewDebug { ViewGroup group = (ViewGroup) view; final int count = group.getChildCount(); for (int i = 0; i < count; i++) { - profileViewAndChildren(group.getChildAt(i), out); + profileViewAndChildren(group.getChildAt(i), out, false); } } } @@ -1033,7 +1044,10 @@ public class ViewDebug { }); try { - latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS); + if (!latch.await(CAPTURE_TIMEOUT, TimeUnit.MILLISECONDS)) { + Log.w("View", "Could not complete the profiling of the view " + view); + return -1; + } } catch (InterruptedException e) { Log.w("View", "Could not complete the profiling of the view " + view); Thread.currentThread().interrupt(); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 9da5637..fa86a68 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -905,19 +905,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } // Calculate the offset point into the target's local coordinates - float xc; - float yc; - if (target.hasIdentityMatrix() || mAttachInfo == null) { - xc = scrolledXFloat - (float) target.mLeft; - yc = scrolledYFloat - (float) target.mTop; - } else { + float xc = scrolledXFloat - (float) target.mLeft; + float yc = scrolledYFloat - (float) target.mTop; + if (!target.hasIdentityMatrix() && mAttachInfo != null) { // non-identity matrix: transform the point into the view's coordinates final float[] localXY = mAttachInfo.mTmpTransformLocation; - localXY[0] = scrolledXFloat; - localXY[1] = scrolledYFloat; + localXY[0] = xc; + localXY[1] = yc; target.getInverseMatrix().mapPoints(localXY); - xc = localXY[0] - (float) target.mLeft; - yc = localXY[1] - (float) target.mTop; + xc = localXY[0]; + yc = localXY[1]; } // if have a target, see if we're allowed to and want to intercept its diff --git a/core/java/android/webkit/DeviceOrientationManager.java b/core/java/android/webkit/DeviceOrientationManager.java new file mode 100644 index 0000000..778b043 --- /dev/null +++ b/core/java/android/webkit/DeviceOrientationManager.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.webkit; + +import android.util.Log; + +/** + * This class is simply a container for the methods used to configure WebKit's + * mock DeviceOrientationClient for use in LayoutTests. + * + * This could be part of WebViewCore, but have moved it to its own class to + * avoid bloat there. + * @hide + */ +public final class DeviceOrientationManager { + /** + * Sets whether the Page for the specified WebViewCore should use a mock DeviceOrientation + * client. + */ + public static void useMock(WebViewCore webViewCore) { + assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); + nativeUseMock(webViewCore); + } + + /** + * Set the position for the mock DeviceOrientation service for the supplied WebViewCore. + */ + public static void setMockOrientation(WebViewCore webViewCore, boolean canProvideAlpha, + double alpha, boolean canProvideBeta, double beta, boolean canProvideGamma, + double gamma) { + assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName()); + nativeSetMockOrientation(webViewCore, canProvideAlpha, alpha, canProvideBeta, beta, + canProvideGamma, gamma); + } + + // Native functions + private static native void nativeUseMock(WebViewCore webViewCore); + private static native void nativeSetMockOrientation(WebViewCore webViewCore, + boolean canProvideAlpha, double alpha, boolean canProvideBeta, double beta, + boolean canProvideGamma, double gamma); +} diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index d1b0902..44f036b 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -66,6 +66,7 @@ import android.view.accessibility.AccessibilityManager; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; +import android.webkit.DeviceOrientationManager; import android.webkit.WebTextView.AutoCompleteAdapter; import android.webkit.WebViewCore.EventHub; import android.webkit.WebViewCore.TouchEventData; @@ -3747,6 +3748,26 @@ public class WebView extends AbsoluteLayout } /** + * Called by DRT on UI thread, need to proxy to WebCore thread. + * + * @hide debug only + */ + public void useMockDeviceOrientation() { + mWebViewCore.sendMessage(EventHub.USE_MOCK_DEVICE_ORIENTATION); + } + + /** + * Called by DRT on WebCore thread. + * + * @hide debug only + */ + public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha, + boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) { + DeviceOrientationManager.setMockOrientation(mWebViewCore, canProvideAlpha, alpha, + canProvideBeta, beta, canProvideGamma, gamma); + } + + /** * Dump the V8 counters to standard output. * Note that you need a build with V8 and WEBCORE_INSTRUMENTATION set to * true. Otherwise, this will do nothing. diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java index 3c28c94..9ec97cd 100644 --- a/core/java/android/webkit/WebViewCore.java +++ b/core/java/android/webkit/WebViewCore.java @@ -33,6 +33,7 @@ import android.util.SparseBooleanArray; import android.view.KeyEvent; import android.view.SurfaceView; import android.view.View; +import android.webkit.DeviceOrientationManager; import java.util.ArrayList; import java.util.Collection; @@ -878,6 +879,8 @@ final class WebViewCore { // accessibility support static final int MODIFY_SELECTION = 190; + static final int USE_MOCK_DEVICE_ORIENTATION = 191; + // private message ids private static final int DESTROY = 200; @@ -1409,6 +1412,10 @@ final class WebViewCore { WebView.SET_TOUCH_HIGHLIGHT_RECTS, null) .sendToTarget(); break; + + case USE_MOCK_DEVICE_ORIENTATION: + useMockDeviceOrientation(); + break; } } }; @@ -2481,6 +2488,10 @@ final class WebViewCore { hMode, vMode).sendToTarget(); } + private void useMockDeviceOrientation() { + DeviceOrientationManager.useMock(this); + } + private native void nativePause(); private native void nativeResume(); private native void nativeFreeMemory(); diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java index 281f32c..6b52409 100644 --- a/core/java/com/android/internal/app/ActionBarImpl.java +++ b/core/java/com/android/internal/app/ActionBarImpl.java @@ -24,8 +24,10 @@ import com.android.internal.widget.ActionBarView; import android.app.ActionBar; import android.app.Activity; +import android.app.Dialog; import android.app.Fragment; import android.app.FragmentTransaction; +import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Handler; import android.view.ActionMode; @@ -54,7 +56,9 @@ public class ActionBarImpl extends ActionBar { private static final int TAB_SWITCH_SHOW_HIDE = 0; private static final int TAB_SWITCH_ADD_REMOVE = 1; + private Context mContext; private Activity mActivity; + private Dialog mDialog; private ViewAnimator mAnimatorView; private ActionBarView mActionView; @@ -88,8 +92,17 @@ public class ActionBarImpl extends ActionBar { }; public ActionBarImpl(Activity activity) { - final View decor = activity.getWindow().getDecorView(); mActivity = activity; + init(activity.getWindow().getDecorView()); + } + + public ActionBarImpl(Dialog dialog) { + mDialog = dialog; + init(dialog.getWindow().getDecorView()); + } + + private void init(View decor) { + mContext = decor.getContext(); mActionView = (ActionBarView) decor.findViewById(com.android.internal.R.id.action_bar); mUpperContextView = (ActionBarContextView) decor.findViewById( com.android.internal.R.id.action_context_bar); @@ -109,23 +122,23 @@ public class ActionBarImpl extends ActionBar { @Override public void setStandardNavigationMode(int titleResId, int subtitleResId) { - setStandardNavigationMode(mActivity.getString(titleResId), - mActivity.getString(subtitleResId)); + setStandardNavigationMode(mContext.getString(titleResId), + mContext.getString(subtitleResId)); } @Override public void setStandardNavigationMode(int titleResId) { - setStandardNavigationMode(mActivity.getString(titleResId)); + setStandardNavigationMode(mContext.getString(titleResId)); } @Override public void setTitle(int resId) { - setTitle(mActivity.getString(resId)); + setTitle(mContext.getString(resId)); } @Override public void setSubtitle(int resId) { - setSubtitle(mActivity.getString(resId)); + setSubtitle(mContext.getString(resId)); } public void setCustomNavigationMode(View view) { @@ -345,6 +358,10 @@ public class ActionBarImpl extends ActionBar { @Override public void setTabNavigationMode() { + if (mActivity == null) { + throw new IllegalStateException( + "Tab navigation mode cannot be used outside of an Activity"); + } mActionView.setNavigationMode(NAVIGATION_MODE_TABS); } @@ -396,7 +413,7 @@ public class ActionBarImpl extends ActionBar { @Override public MenuInflater getMenuInflater() { - return new MenuInflater(mActivity); + return new MenuInflater(mContext); } @Override @@ -485,7 +502,7 @@ public class ActionBarImpl extends ActionBar { return true; } - new MenuPopupHelper(mActivity, subMenu).show(); + new MenuPopupHelper(mContext, subMenu).show(); return true; } |