diff options
50 files changed, 1172 insertions, 475 deletions
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java index 238792bd35a4..60b406d36467 100644 --- a/core/java/android/content/ContentProviderOperation.java +++ b/core/java/android/content/ContentProviderOperation.java @@ -221,26 +221,30 @@ public class ContentProviderOperation implements Parcelable { } else if (mType == TYPE_UPDATE) { numRows = provider.update(mUri, values, mSelection, selectionArgs); } else if (mType == TYPE_ASSERT) { - // Build projection map from expected values - final ArrayList<String> projectionList = new ArrayList<String>(); - for (Map.Entry<String, Object> entry : values.valueSet()) { - projectionList.add(entry.getKey()); - } - // Assert that all rows match expected values - final String[] projection = projectionList.toArray(new String[projectionList.size()]); + String[] projection = null; + if (values != null) { + // Build projection map from expected values + final ArrayList<String> projectionList = new ArrayList<String>(); + for (Map.Entry<String, Object> entry : values.valueSet()) { + projectionList.add(entry.getKey()); + } + projection = projectionList.toArray(new String[projectionList.size()]); + } final Cursor cursor = provider.query(mUri, projection, mSelection, selectionArgs, null); - numRows = cursor.getCount(); try { - while (cursor.moveToNext()) { - for (int i = 0; i < projection.length; i++) { - final String cursorValue = cursor.getString(i); - final String expectedValue = values.getAsString(projection[i]); - if (!TextUtils.equals(cursorValue, expectedValue)) { - // Throw exception when expected values don't match - throw new OperationApplicationException("Found value " + cursorValue - + " when expected " + expectedValue + " for column " - + projection[i]); + numRows = cursor.getCount(); + if (projection != null) { + while (cursor.moveToNext()) { + for (int i = 0; i < projection.length; i++) { + final String cursorValue = cursor.getString(i); + final String expectedValue = values.getAsString(projection[i]); + if (!TextUtils.equals(cursorValue, expectedValue)) { + // Throw exception when expected values don't match + throw new OperationApplicationException("Found value " + cursorValue + + " when expected " + expectedValue + " for column " + + projection[i]); + } } } } @@ -395,12 +399,19 @@ public class ContentProviderOperation implements Parcelable { /** Create a ContentProviderOperation from this {@link Builder}. */ public ContentProviderOperation build() { - if (mType == TYPE_UPDATE || mType == TYPE_ASSERT) { + if (mType == TYPE_UPDATE) { if ((mValues == null || mValues.size() == 0) && (mValuesBackReferences == null || mValuesBackReferences.size() == 0)) { throw new IllegalArgumentException("Empty values"); } } + if (mType == TYPE_ASSERT) { + if ((mValues == null || mValues.size() == 0) + && (mValuesBackReferences == null || mValuesBackReferences.size() == 0) + && (mExpectedCount == null)) { + throw new IllegalArgumentException("Empty values"); + } + } return new ContentProviderOperation(this); } diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java index 38881d3f1a82..f736f85273ce 100644 --- a/core/java/android/text/method/QwertyKeyListener.java +++ b/core/java/android/text/method/QwertyKeyListener.java @@ -431,6 +431,7 @@ public class QwertyKeyListener extends BaseKeyListener { PICKER_SETS.put('z', "\u017A\u017C\u017E"); PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT, "\u2026\u00A5\u2022\u00AE\u00A9\u00B1[]{}\\"); + PICKER_SETS.put('/', "\\"); // From packages/inputmethods/LatinIME/res/xml/kbd_symbols.xml diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index 94acd3ffa7f7..e5985c179e9d 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -458,11 +458,12 @@ public abstract class LayoutInflater { public final View createView(String name, String prefix, AttributeSet attrs) throws ClassNotFoundException, InflateException { Constructor constructor = sConstructorMap.get(name); + Class clazz = null; try { if (constructor == null) { // Class not found in the cache, see if it's real, and try to add it - Class clazz = mContext.getClassLoader().loadClass( + clazz = mContext.getClassLoader().loadClass( prefix != null ? (prefix + name) : name); if (mFilter != null && clazz != null) { @@ -480,7 +481,7 @@ public abstract class LayoutInflater { Boolean allowedState = mFilterMap.get(name); if (allowedState == null) { // New class -- remember whether it is allowed - Class clazz = mContext.getClassLoader().loadClass( + clazz = mContext.getClassLoader().loadClass( prefix != null ? (prefix + name) : name); boolean allowed = clazz != null && mFilter.onLoadClass(clazz); @@ -511,7 +512,7 @@ public abstract class LayoutInflater { } catch (Exception e) { InflateException ie = new InflateException(attrs.getPositionDescription() + ": Error inflating class " - + (constructor == null ? "<unknown>" : constructor.getClass().getName())); + + (clazz == null ? "<unknown>" : clazz.getName())); ie.initCause(e); throw ie; } diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java index 95b3a12ad308..39a2470dd960 100644 --- a/core/java/android/webkit/WebTextView.java +++ b/core/java/android/webkit/WebTextView.java @@ -16,6 +16,8 @@ package android.webkit; +import com.android.internal.widget.EditableInputConnection; + import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; @@ -38,6 +40,7 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; @@ -346,6 +349,16 @@ import java.util.ArrayList; @Override protected void onSelectionChanged(int selStart, int selEnd) { + // This code is copied from TextView.onDraw(). That code does not get + // executed, however, because the WebTextView does not draw, allowing + // webkit's drawing to show through. + InputMethodManager imm = InputMethodManager.peekInstance(); + if (imm != null && imm.isActive(this)) { + Spannable sp = (Spannable) getText(); + int candStart = EditableInputConnection.getComposingSpanStart(sp); + int candEnd = EditableInputConnection.getComposingSpanEnd(sp); + imm.updateSelection(this, selStart, selEnd, candStart, candEnd); + } if (!mFromWebKit && mWebView != null) { if (DebugFlags.WEB_TEXT_VIEW) { Log.v(LOGTAG, "onSelectionChanged selStart=" + selStart @@ -430,18 +443,26 @@ import java.util.ArrayList; mGotTouchDown = true; break; case MotionEvent.ACTION_MOVE: + int slop = ViewConfiguration.get(mContext).getScaledTouchSlop(); Spannable buffer = getText(); int initialScrollX = Touch.getInitialScrollX(this, buffer); int initialScrollY = Touch.getInitialScrollY(this, buffer); super.onTouchEvent(event); - if (mScrollX != initialScrollX - || mScrollY != initialScrollY) { + if (Math.abs(mScrollX - initialScrollX) > slop + || Math.abs(mScrollY - initialScrollY) > slop) { if (mWebView != null) { mWebView.scrollFocusedTextInput(mScrollX, mScrollY); } mScrolled = true; return true; } + if (Math.abs((int) event.getX() - mDragStartX) < slop + && Math.abs((int) event.getY() - mDragStartY) < slop) { + // If the user has not scrolled further than slop, we should not + // send the drag. Instead, do nothing, and when the user lifts + // their finger, we will change the selection. + return true; + } if (mWebView != null) { // Only want to set the initial state once. if (!mDragSent) { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 4ca17ac73362..abbbc00e9020 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -420,6 +420,7 @@ public class WebView extends AbsoluteLayout private static final int STD_SPEED = 480; // pixels per second // time for the longest scroll animation private static final int MAX_DURATION = 750; // milliseconds + private static final int SLIDE_TITLE_DURATION = 300; // milliseconds private Scroller mScroller; private boolean mWrapContent; @@ -2416,10 +2417,18 @@ public class WebView extends AbsoluteLayout if ((dx | dy) == 0) { return false; } - - if (true && animate) { + // mobile sites prefer to scroll to (0, 1), thus the + 1 below + boolean slideTitle = getVisibleTitleHeight() > 0 + && y <= getTitleHeight() + 1; + if (DebugFlags.WEB_VIEW) { + Log.v(LOGTAG, "pinScrollTo slideTitle=" + slideTitle + + " getVisibleTitleHeight()=" + getVisibleTitleHeight() + + " animationDuration=" + animationDuration + " y=" + y); + } + if (slideTitle || animate) { // Log.d(LOGTAG, "startScroll: " + dx + " " + dy); - + if (slideTitle && animationDuration < SLIDE_TITLE_DURATION) + animationDuration = SLIDE_TITLE_DURATION; mScroller.startScroll(mScrollX, mScrollY, dx, dy, animationDuration > 0 ? animationDuration : computeDuration(dx, dy)); invalidate(); diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java index fe01866e4225..4ec597c6f0cb 100644 --- a/core/java/com/android/internal/widget/ContactHeaderWidget.java +++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java @@ -42,6 +42,7 @@ import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.CheckBox; +import android.widget.FasttrackBadgeWidget; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -64,15 +65,13 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList private TextView mDisplayNameView; private TextView mPhoneticNameView; private CheckBox mStarredView; - private ImageView mPhotoView; + private FasttrackBadgeWidget mPhotoView; private ImageView mPresenceView; private TextView mStatusView; private int mNoPhotoResource; private QueryHandler mQueryHandler; - protected long mContactId; protected Uri mContactUri; - protected Uri mStatusUri; protected String[] mExcludeMimes = null; @@ -94,6 +93,8 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList Contacts.STARRED, Contacts.PHOTO_ID, Contacts.PRESENCE_STATUS, + Contacts._ID, + Contacts.LOOKUP_KEY, }; protected static final int HEADER_DISPLAY_NAME_COLUMN_INDEX = 0; //TODO: We need to figure out how we're going to get the phonetic name. @@ -101,6 +102,8 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList protected static final int HEADER_STARRED_COLUMN_INDEX = 1; protected static final int HEADER_PHOTO_ID_COLUMN_INDEX = 2; protected static final int HEADER_PRESENCE_STATUS_COLUMN_INDEX = 3; + protected static final int HEADER_CONTACT_ID_COLUMN_INDEX = 4; + protected static final int HEADER_LOOKUP_KEY_COLUMN_INDEX = 5; //Projection used for finding the most recent social status. protected static final String[] SOCIAL_PROJECTION = new String[] { @@ -113,18 +116,29 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList //Projection used for looking up contact id from phone number protected static final String[] PHONE_LOOKUP_PROJECTION = new String[] { PhoneLookup._ID, + PhoneLookup.LOOKUP_KEY, }; protected static final int PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0; + protected static final int PHONE_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX = 1; //Projection used for looking up contact id from email address protected static final String[] EMAIL_LOOKUP_PROJECTION = new String[] { RawContacts.CONTACT_ID, + Contacts.LOOKUP_KEY, }; protected static final int EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0; + protected static final int EMAIL_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX = 1; + protected static final String[] CONTACT_LOOKUP_PROJECTION = new String[] { + Contacts._ID, + }; + protected static final int CONTACT_LOOKUP_ID_COLUMN_INDEX = 0; private static final int TOKEN_CONTACT_INFO = 0; private static final int TOKEN_SOCIAL = 1; + private static final int TOKEN_PHONE_LOOKUP = 2; + private static final int TOKEN_EMAIL_LOOKUP = 3; + private static final int TOKEN_LOOKUP_CONTACT_FOR_SOCIAL_QUERY = 4; public ContactHeaderWidget(Context context) { this(context, null); @@ -151,8 +165,7 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList mStarredView = (CheckBox)findViewById(R.id.star); mStarredView.setOnClickListener(this); - mPhotoView = (ImageView)findViewById(R.id.photo); - mPhotoView.setOnClickListener(this); + mPhotoView = (FasttrackBadgeWidget) findViewById(R.id.photo); mPhotoView.setOnLongClickListener(this); mPresenceView = (ImageView) findViewById(R.id.presence); @@ -217,12 +230,46 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList @Override protected void onQueryComplete(int token, Object cookie, Cursor cursor) { try{ - if (token == TOKEN_CONTACT_INFO) { - bindContactInfo(cursor); - invalidate(); - } else if (token == TOKEN_SOCIAL) { - bindSocial(cursor); - invalidate(); + switch (token) { + case TOKEN_CONTACT_INFO: { + bindContactInfo(cursor); + invalidate(); + break; + } + case TOKEN_SOCIAL: { + bindSocial(cursor); + invalidate(); + break; + } + case TOKEN_PHONE_LOOKUP: { + if (cursor != null && cursor.moveToFirst()) { + long contactId = cursor.getLong(PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX); + String lookupKey = cursor.getString( + PHONE_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX); + bindFromContactUri(Contacts.getLookupUri(contactId, lookupKey)); + } else { + setDisplayName((String) cookie, null); + } + break; + } + case TOKEN_EMAIL_LOOKUP: { + if (cursor != null && cursor.moveToFirst()) { + long contactId = cursor.getLong(EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX); + String lookupKey = cursor.getString( + EMAIL_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX); + bindFromContactUri(Contacts.getLookupUri(contactId, lookupKey)); + } else { + setDisplayName((String) cookie, null); + } + break; + } + case TOKEN_LOOKUP_CONTACT_FOR_SOCIAL_QUERY: { + if (cursor != null && cursor.moveToFirst()) { + long contactId = cursor.getLong(CONTACT_LOOKUP_ID_COLUMN_INDEX); + startSocialQuery(ContentUris.withAppendedId( + Activities.CONTENT_CONTACT_STATUS_URI, contactId)); + } + } } } finally { if (cursor != null) { @@ -300,33 +347,31 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList * Convenience method for binding all available data from an existing * contact. * - * @param contactId the contact id of the contact whose info should be displayed. + * @param conatctUri a {Contacts.CONTENT_LOOKUP_URI} style URI. */ - public void bindFromContactId(long contactId) { - mContactId = contactId; - mContactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, mContactId); + public void bindFromContactLookupUri(Uri contactLookupUri) { + mContactUri = contactLookupUri; - bindContactUri(mContactUri); - bindSocialUri(ContentUris.withAppendedId(Activities.CONTENT_CONTACT_STATUS_URI, mContactId)); - } + // Query for the contactId so we can do the social query. + mQueryHandler.startQuery(TOKEN_LOOKUP_CONTACT_FOR_SOCIAL_QUERY, null, contactLookupUri, + CONTACT_LOOKUP_PROJECTION, null, null, null); - /** - * Convenience method for binding {@link Contacts} header details from a - * {@link Contacts#CONTENT_URI} reference. - */ - public void bindContactUri(Uri contactUri) { - mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, contactUri, HEADER_PROJECTION, - null, null, null); + startContactQuery(contactLookupUri); } /** - * Convenience method for binding {@link Activities} header details from a - * {@link Activities#CONTENT_CONTACT_STATUS_URI}. + * Convenience method for binding all available data from an existing + * contact. + * + * @param conatctUri a {Contacts.CONTENT_URI} style URI. */ - public void bindSocialUri(Uri contactSocial) { - mStatusUri = contactSocial; - mQueryHandler.startQuery(TOKEN_SOCIAL, null, mStatusUri, SOCIAL_PROJECTION, null, null, - null); + public void bindFromContactUri(Uri contactUri) { + mContactUri = contactUri; + long contactId = ContentUris.parseId(contactUri); + + startContactQuery(contactUri); + startSocialQuery(ContentUris.withAppendedId( + Activities.CONTENT_CONTACT_STATUS_URI, contactId)); } /** @@ -338,21 +383,9 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList * address, one of them will be chosen to bind to. */ public void bindFromEmail(String emailAddress) { - Cursor c = null; - try { - c = mContentResolver.query(Uri.withAppendedPath(Email.CONTENT_FILTER_EMAIL_URI, Uri - .encode(emailAddress)), EMAIL_LOOKUP_PROJECTION, null, null, null); - if (c != null && c.moveToFirst()) { - long contactId = c.getLong(EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX); - bindFromContactId(contactId); - } else { - setDisplayName(emailAddress, null); - } - } finally { - if (c != null) { - c.close(); - } - } + mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP, emailAddress, + Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(emailAddress)), + EMAIL_LOOKUP_PROJECTION, null, null, null); } /** @@ -364,22 +397,19 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList * number, one of them will be chosen to bind to. */ public void bindFromPhoneNumber(String number) { - Cursor c = null; - try { - c = mContentResolver.query( - Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)), - PHONE_LOOKUP_PROJECTION, null, null, null); - if (c != null && c.moveToFirst()) { - long contactId = c.getLong(PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX); - bindFromContactId(contactId); - } else { - setDisplayName(number, null); - } - } finally { - if (c != null) { - c.close(); - } - } + mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP, number, + Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number), + PHONE_LOOKUP_PROJECTION, null, null, null); + } + + private void startSocialQuery(Uri contactSocial) { + mQueryHandler.startQuery(TOKEN_SOCIAL, null, contactSocial, SOCIAL_PROJECTION, null, null, + null); + } + + private void startContactQuery(Uri contactUri) { + mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, contactUri, HEADER_PROJECTION, + null, null, null); } /** @@ -390,6 +420,8 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList // TODO: Bring back phonetic name final String displayName = c.getString(HEADER_DISPLAY_NAME_COLUMN_INDEX); + final long contactId = c.getLong(HEADER_CONTACT_ID_COLUMN_INDEX); + final String lookupKey = c.getString(HEADER_LOOKUP_KEY_COLUMN_INDEX); final String phoneticName = null; this.setDisplayName(displayName, null); @@ -402,6 +434,7 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList photoBitmap = loadPlaceholderPhoto(null); } mPhotoView.setImageBitmap(photoBitmap); + mPhotoView.assignContactUri(Contacts.getLookupUri(contactId, lookupKey)); //Set the presence status int presence = c.getInt(HEADER_PRESENCE_STATUS_COLUMN_INDEX); @@ -423,27 +456,11 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList return; } - switch (view.getId()) { - case R.id.star: { - // Toggle "starred" state - final ContentValues values = new ContentValues(1); - values.put(Contacts.STARRED, mStarredView.isChecked()); - mContentResolver.update(mContactUri, values, null, null); - break; - } - case R.id.photo: { - // Photo launches contact detail action - final Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, mContactUri); - final Rect target = getTargetRect(view); - intent.putExtra(Intents.EXTRA_TARGET_RECT, target); - intent.putExtra(Intents.EXTRA_MODE, Intents.MODE_SMALL); - if (mExcludeMimes != null) { - // Exclude specific MIME-types when requested - intent.putExtra(Intents.EXTRA_EXCLUDE_MIMES, mExcludeMimes); - } - mContext.startActivity(intent); - break; - } + if (view.getId() == R.id.star) { + // Toggle "starred" state + final ContentValues values = new ContentValues(1); + values.put(Contacts.STARRED, mStarredView.isChecked()); + mContentResolver.update(mContactUri, values, null, null); } } diff --git a/core/java/com/android/internal/widget/RotarySelector.java b/core/java/com/android/internal/widget/RotarySelector.java index 7b940c9805a7..aff92b816c28 100644 --- a/core/java/com/android/internal/widget/RotarySelector.java +++ b/core/java/com/android/internal/widget/RotarySelector.java @@ -19,8 +19,6 @@ package com.android.internal.widget; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Vibrator; import android.util.AttributeSet; @@ -28,7 +26,7 @@ import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.AccelerateInterpolator; - +import static android.view.animation.AnimationUtils.currentAnimationTimeMillis; import com.android.internal.R; @@ -69,7 +67,7 @@ public class RotarySelector extends View { private boolean mAnimating = false; private long mAnimationEndTime; private int mAnimatingDelta; - AccelerateInterpolator mInterpolator; + private AccelerateInterpolator mInterpolator; /** * True after triggering an action if the user of {@link OnDialTriggerListener} wants to @@ -96,12 +94,6 @@ public class RotarySelector extends View { private static final long VIBRATE_SHORT = 60; // msec private static final long VIBRATE_LONG = 100; // msec - // Various tweakable layout or behavior parameters: - - // How close to the edge of the screen, we let the handle get before - // triggering an action: - private static final int EDGE_THRESHOLD_DIP = 70; - /** * The drawable for the arrows need to be scrunched this many dips towards the rotary bg below * it. @@ -122,6 +114,11 @@ public class RotarySelector extends View { private static final boolean DRAW_CENTER_DIMPLE = false; + public RotarySelector(Context context) { + this(context, null); + } + + /** * Constructor used when this widget is created from a layout file. */ @@ -132,8 +129,6 @@ public class RotarySelector extends View { Resources r = getResources(); mDensity = r.getDisplayMetrics().density; if (DBG) log("- Density: " + mDensity); - // Density is 1.0 on HVGA (like Dream), and 1.5 on WVGA. - // Usage: raw_pixel_value = (int) (dpi_value * mDensity + 0.5f) // Assets (all are BitmapDrawables). mBackground = r.getDrawable(R.drawable.jog_dial_bg_cropped); @@ -143,6 +138,15 @@ public class RotarySelector extends View { mArrowLongRight = r.getDrawable(R.drawable.jog_dial_arrow_long_right_red); mArrowShortLeftAndRight = r.getDrawable(R.drawable.jog_dial_arrow_short_left_and_right); + // Arrows: + // All arrow assets are the same size (they're the full width of + // the screen) regardless of which arrows are actually visible. + int arrowW = mArrowShortLeftAndRight.getIntrinsicWidth(); + int arrowH = mArrowShortLeftAndRight.getIntrinsicHeight(); + mArrowShortLeftAndRight.setBounds(0, 0, arrowW, arrowH); + mArrowLongLeft.setBounds(0, 0, arrowW, arrowH); + mArrowLongRight.setBounds(0, 0, arrowW, arrowH); + mInterpolator = new AccelerateInterpolator(); } @@ -237,7 +241,7 @@ public class RotarySelector extends View { // update animating state before we draw anything if (mAnimating && !mFrozen) { - long millisLeft = mAnimationEndTime - System.currentTimeMillis(); + long millisLeft = mAnimationEndTime - currentAnimationTimeMillis(); if (DBG) log("millisleft for animating: " + millisLeft); if (millisLeft <= 0) { reset(); @@ -259,11 +263,6 @@ public class RotarySelector extends View { if (DBG) log(" Background BOUNDS: " + mBackground.getBounds()); mBackground.draw(canvas); - // Arrows: - // All arrow assets are the same size (they're the full width of - // the screen) regardless of which arrows are actually visible. - int arrowW = mArrowShortLeftAndRight.getIntrinsicWidth(); - int arrowH = mArrowShortLeftAndRight.getIntrinsicHeight(); // Draw the correct arrow(s) depending on the current state: Drawable currentArrow; @@ -280,7 +279,6 @@ public class RotarySelector extends View { default: throw new IllegalStateException("invalid mGrabbedState: " + mGrabbedState); } - currentArrow.setBounds(0, 0, arrowW, arrowH); currentArrow.draw(canvas); // debug: draw circle that should match the outer arc (good sanity check) @@ -382,63 +380,70 @@ public class RotarySelector extends View { final int eventX = (int) event.getX(); final int hitWindow = mDimple.getIntrinsicWidth(); - if (event.getAction() == MotionEvent.ACTION_DOWN) { - if (DBG) log("touch-down"); - mTriggered = false; - if (mGrabbedState != RotarySelector.NOTHING_GRABBED) { - reset(); - invalidate(); - } - if (eventX < mLeftHandleX + hitWindow) { - mTouchDragOffset = eventX - mLeftHandleX; - mGrabbedState = RotarySelector.LEFT_HANDLE_GRABBED; - invalidate(); - vibrate(VIBRATE_SHORT); - } else if (eventX > mRightHandleX - hitWindow) { - mTouchDragOffset = eventX - mRightHandleX; - mGrabbedState = RotarySelector.RIGHT_HANDLE_GRABBED; - invalidate(); - vibrate(VIBRATE_SHORT); - } - } else if (event.getAction() == MotionEvent.ACTION_MOVE) { - if (DBG) log("touch-move"); - if (mGrabbedState == RotarySelector.LEFT_HANDLE_GRABBED) { - mTouchDragOffset = eventX - mLeftHandleX; - invalidate(); - if (eventX >= mRightHandleX - EDGE_PADDING_DIP && !mTriggered) { - mTriggered = true; - mFrozen = dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE); + final int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + if (DBG) log("touch-down"); + mTriggered = false; + if (mGrabbedState != NOTHING_GRABBED) { + reset(); + invalidate(); } - } else if (mGrabbedState == RotarySelector.RIGHT_HANDLE_GRABBED) { - mTouchDragOffset = eventX - mRightHandleX; - invalidate(); - if (eventX <= mLeftHandleX + EDGE_PADDING_DIP && !mTriggered) { - mTriggered = true; - mFrozen = dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE); + if (eventX < mLeftHandleX + hitWindow) { + mTouchDragOffset = eventX - mLeftHandleX; + mGrabbedState = LEFT_HANDLE_GRABBED; + invalidate(); + vibrate(VIBRATE_SHORT); + } else if (eventX > mRightHandleX - hitWindow) { + mTouchDragOffset = eventX - mRightHandleX; + mGrabbedState = RIGHT_HANDLE_GRABBED; + invalidate(); + vibrate(VIBRATE_SHORT); } - } - } else if ((event.getAction() == MotionEvent.ACTION_UP)) { - if (DBG) log("touch-up"); - // handle animating back to start if they didn't trigger - if (mGrabbedState == RotarySelector.LEFT_HANDLE_GRABBED - && Math.abs(eventX - mLeftHandleX) > 5) { - mAnimating = true; - mAnimationEndTime = System.currentTimeMillis() + ANIMATION_DURATION_MILLIS; - mAnimatingDelta = eventX - mLeftHandleX; - } else if (mGrabbedState == RotarySelector.RIGHT_HANDLE_GRABBED - && Math.abs(eventX - mRightHandleX) > 5) { - mAnimating = true; - mAnimationEndTime = System.currentTimeMillis() + ANIMATION_DURATION_MILLIS; - mAnimatingDelta = eventX - mRightHandleX; - } + break; - mTouchDragOffset = 0; - mGrabbedState = RotarySelector.NOTHING_GRABBED; - invalidate(); - } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { - if (DBG) log("touch-cancel"); - reset(); - invalidate(); + case MotionEvent.ACTION_MOVE: + if (DBG) log("touch-move"); + if (mGrabbedState == LEFT_HANDLE_GRABBED) { + mTouchDragOffset = eventX - mLeftHandleX; + invalidate(); + if (eventX >= mRightHandleX - EDGE_PADDING_DIP && !mTriggered) { + mTriggered = true; + mFrozen = dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE); + } + } else if (mGrabbedState == RIGHT_HANDLE_GRABBED) { + mTouchDragOffset = eventX - mRightHandleX; + invalidate(); + if (eventX <= mLeftHandleX + EDGE_PADDING_DIP && !mTriggered) { + mTriggered = true; + mFrozen = dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE); + } + } + break; + case MotionEvent.ACTION_UP: + if (DBG) log("touch-up"); + // handle animating back to start if they didn't trigger + if (mGrabbedState == LEFT_HANDLE_GRABBED + && Math.abs(eventX - mLeftHandleX) > 5) { + mAnimating = true; + mAnimationEndTime = currentAnimationTimeMillis() + ANIMATION_DURATION_MILLIS; + mAnimatingDelta = eventX - mLeftHandleX; + } else if (mGrabbedState == RIGHT_HANDLE_GRABBED + && Math.abs(eventX - mRightHandleX) > 5) { + mAnimating = true; + mAnimationEndTime = currentAnimationTimeMillis() + ANIMATION_DURATION_MILLIS; + mAnimatingDelta = eventX - mRightHandleX; + } + + mTouchDragOffset = 0; + mGrabbedState = NOTHING_GRABBED; + invalidate(); + break; + case MotionEvent.ACTION_CANCEL: + if (DBG) log("touch-cancel"); + reset(); + invalidate(); + break; } return true; } @@ -446,7 +451,7 @@ public class RotarySelector extends View { private void reset() { mAnimating = false; mTouchDragOffset = 0; - mGrabbedState = RotarySelector.NOTHING_GRABBED; + mGrabbedState = NOTHING_GRABBED; mTriggered = false; } diff --git a/core/res/res/drawable-hdpi/title_bar_medium.png b/core/res/res/drawable-hdpi/title_bar_medium.png Binary files differnew file mode 100644 index 000000000000..c13dd2698e5f --- /dev/null +++ b/core/res/res/drawable-hdpi/title_bar_medium.png diff --git a/core/res/res/drawable-mdpi/title_bar_medium.png b/core/res/res/drawable-mdpi/title_bar_medium.png Binary files differnew file mode 100644 index 000000000000..9d01f79bb0de --- /dev/null +++ b/core/res/res/drawable-mdpi/title_bar_medium.png diff --git a/core/res/res/layout/contact_header.xml b/core/res/res/layout/contact_header.xml index 8d7e470fb93d..e800dfa79903 100644 --- a/core/res/res/layout/contact_header.xml +++ b/core/res/res/layout/contact_header.xml @@ -19,17 +19,17 @@ android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:background="@drawable/title_bar_tall" + android:background="@drawable/title_bar_medium" android:paddingRight="5dip" android:gravity="center_vertical"> - <ImageView android:id="@+id/photo" - android:layout_width="56dip" - android:layout_height="62dip" + <android.widget.FasttrackBadgeWidget android:id="@+id/photo" + android:layout_alignParentLeft="true" + android:layout_centerVertical="true" android:layout_marginRight="10dip" android:layout_marginLeft="10dip" - android:scaleType="fitCenter" - android:background="@drawable/fasttrack_badge_middle_large"/> + style="@*android:style/Widget.FasttrackBadgeWidget.WindowSmall" /> + /> <LinearLayout android:layout_width="0dip" diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml index 62a230c548de..c967c4c09407 100644 --- a/core/res/res/values/colors.xml +++ b/core/res/res/values/colors.xml @@ -18,7 +18,7 @@ */ --> <resources> - <drawable name="screen_background_light">#fff9f9f9</drawable> + <drawable name="screen_background_light">#ffffffff</drawable> <drawable name="screen_background_dark">#ff202020</drawable> <drawable name="status_bar_closed_default_background">#ff000000</drawable> <drawable name="status_bar_opened_default_background">#ff000000</drawable> @@ -45,7 +45,7 @@ <color name="dim_foreground_dark_inverse">#323232</color> <color name="dim_foreground_dark_inverse_disabled">#80323232</color> <color name="hint_foreground_dark">#808080</color> - <color name="background_light">#fff9f9f9</color> + <color name="background_light">#ffffffff</color> <color name="bright_foreground_light">#ff000000</color> <color name="bright_foreground_light_inverse">#ffffffff</color> <color name="bright_foreground_light_disabled">#80000000</color> diff --git a/data/etc/Android.mk b/data/etc/Android.mk index a32d8ea8db36..041c5d3a273e 100644 --- a/data/etc/Android.mk +++ b/data/etc/Android.mk @@ -32,3 +32,20 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions LOCAL_SRC_FILES := $(LOCAL_MODULE) include $(BUILD_PREBUILT) + +######################## +include $(CLEAR_VARS) + +LOCAL_MODULE := required_hardware.xml + +LOCAL_MODULE_TAGS := user + +LOCAL_MODULE_CLASS := ETC + +# This will install the file in /system/etc/permissions +# +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions + +LOCAL_SRC_FILES := $(LOCAL_MODULE) + +include $(BUILD_PREBUILT) diff --git a/data/etc/android.hardware.camera.flash-autofocus.xml b/data/etc/android.hardware.camera.flash-autofocus.xml new file mode 100644 index 000000000000..55f1900a4e51 --- /dev/null +++ b/data/etc/android.hardware.camera.flash-autofocus.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<!-- This is the standard set of features for a camera with a flash. Note + that this currently requires having auto-focus as well. --> +<permissions> + <feature name="android.hardware.camera" /> + <feature name="android.hardware.camera.autofocus" /> + <feature name="android.hardware.camera.flash" /> +</permissions> diff --git a/data/etc/android.hardware.sensor.light.xml b/data/etc/android.hardware.sensor.light.xml new file mode 100644 index 000000000000..78b0fecb99ab --- /dev/null +++ b/data/etc/android.hardware.sensor.light.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<!-- Feature for devices with an ambient light sensor. --> +<permissions> + <feature name="android.hardware.sensor.light" /> +</permissions> diff --git a/data/etc/android.hardware.sensor.proximity.xml b/data/etc/android.hardware.sensor.proximity.xml new file mode 100644 index 000000000000..d1948dea98f4 --- /dev/null +++ b/data/etc/android.hardware.sensor.proximity.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<!-- Feature for devices with a proximity sensor. --> +<permissions> + <feature name="android.hardware.sensor.proximity" /> +</permissions> diff --git a/data/etc/android.hardware.telephony.cdma.xml b/data/etc/android.hardware.telephony.cdma.xml new file mode 100644 index 000000000000..72e0485d422f --- /dev/null +++ b/data/etc/android.hardware.telephony.cdma.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<!-- This is the standard set of features for a CDMA phone. --> +<permissions> + <feature name="android.hardware.telephony" /> + <feature name="android.hardware.telephony.cdma" /> +</permissions> diff --git a/data/etc/android.hardware.telephony.gsm.xml b/data/etc/android.hardware.telephony.gsm.xml new file mode 100644 index 000000000000..ffde4333e1bc --- /dev/null +++ b/data/etc/android.hardware.telephony.gsm.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<!-- This is the standard set of features for a GSM phone. --> +<permissions> + <feature name="android.hardware.telephony" /> + <feature name="android.hardware.telephony.gsm" /> +</permissions> diff --git a/data/etc/required_hardware.xml b/data/etc/required_hardware.xml new file mode 100644 index 000000000000..896a148d6dea --- /dev/null +++ b/data/etc/required_hardware.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2009 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. +--> + +<!-- These are the hardware features that all devices must possess. + These are always added for you by the build system, you do not need + to add them yourself. --> +<permissions> + <feature name="android.hardware.sensor.compass" /> + <feature name="android.hardware.sensor.accelerometer" /> + <feature name="android.hardware.bluetooth" /> + <feature name="android.hardware.wifi" /> +</permissions> diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index 3266f1e21102..c6f57d4c482a 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -36,7 +36,6 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { private Drawable mCurrDrawable; private int mAlpha = 0xFF; private ColorFilter mColorFilter; - private boolean mDither = DEFAULT_DITHER; private int mCurIndex = -1; private boolean mMutated; @@ -83,10 +82,10 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @Override public void setDither(boolean dither) { - if (mDither != dither) { - mDither = dither; + if (mDrawableContainerState.mDither != dither) { + mDrawableContainerState.mDither = dither; if (mCurrDrawable != null) { - mCurrDrawable.setDither(mDither); + mCurrDrawable.setDither(mDrawableContainerState.mDither); } } } @@ -212,7 +211,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { if (d != null) { d.setVisible(isVisible(), true); d.setAlpha(mAlpha); - d.setDither(mDither); + d.setDither(mDrawableContainerState.mDither); d.setColorFilter(mColorFilter); d.setState(getState()); d.setLevel(getLevel()); @@ -285,6 +284,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { boolean mCanConstantState; boolean mPaddingChecked = false; + + boolean mDither = DEFAULT_DITHER; DrawableContainerState(DrawableContainerState orig, DrawableContainer owner, Resources res) { @@ -323,6 +324,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { mOpacity = orig.mOpacity; mHaveStateful = orig.mHaveStateful; mStateful = orig.mStateful; + + mDither = orig.mDither; } else { mDrawables = new Drawable[10]; diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java index 89db4fa6b4ec..d35c5e302207 100644 --- a/graphics/java/android/renderscript/RenderScript.java +++ b/graphics/java/android/renderscript/RenderScript.java @@ -140,6 +140,8 @@ public class RenderScript { native void nScriptSetTimeZone(int script, byte[] timeZone); native void nScriptSetType(int type, boolean writable, String name, int slot); native void nScriptSetRoot(boolean isRoot); + native void nScriptSetInvokable(String name, int slot); + native void nScriptInvoke(int id, int slot); native void nScriptCBegin(); native void nScriptCSetScript(byte[] script, int offset, int length); diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java index a402471e39bc..35791a3bc91e 100644 --- a/graphics/java/android/renderscript/Script.java +++ b/graphics/java/android/renderscript/Script.java @@ -25,6 +25,22 @@ public class Script extends BaseObj { boolean mIsRoot; Type[] mTypes; boolean[] mWritable; + Invokable[] mInvokables; + + public static class Invokable { + RenderScript mRS; + Script mScript; + int mSlot; + String mName; + + Invokable() { + mSlot = -1; + } + + public void execute() { + mRS.nScriptInvoke(mScript.mID, mSlot); + } + } Script(int id, RenderScript rs) { super(rs); @@ -61,12 +77,15 @@ public class Script extends BaseObj { Type[] mTypes; String[] mNames; boolean[] mWritable; + int mInvokableCount = 0; + Invokable[] mInvokables; Builder(RenderScript rs) { mRS = rs; mTypes = new Type[MAX_SLOT]; mNames = new String[MAX_SLOT]; mWritable = new boolean[MAX_SLOT]; + mInvokables = new Invokable[MAX_SLOT]; } public void setType(Type t, int slot) { @@ -79,6 +98,15 @@ public class Script extends BaseObj { mNames[slot] = name; } + public Invokable addInvokable(String func) { + Invokable i = new Invokable(); + i.mName = func; + i.mRS = mRS; + i.mSlot = mInvokableCount; + mInvokables[mInvokableCount++] = i; + return i; + } + public void setType(boolean writable, int slot) { mWritable[slot] = writable; } @@ -90,11 +118,20 @@ public class Script extends BaseObj { mRS.nScriptSetType(mTypes[ct].mID, mWritable[ct], mNames[ct], ct); } } + for(int ct=0; ct < mInvokableCount; ct++) { + mRS.nScriptSetInvokable(mInvokables[ct].mName, ct); + } } void transferObject(Script s) { s.mIsRoot = mIsRoot; s.mTypes = mTypes; + s.mInvokables = new Invokable[mInvokableCount]; + for(int ct=0; ct < mInvokableCount; ct++) { + s.mInvokables[ct] = mInvokables[ct]; + s.mInvokables[ct].mScript = s; + } + s.mInvokables = null; } public void setRoot(boolean r) { diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp index 90b5958ccf77..eae6f2431fbb 100644 --- a/graphics/jni/android_renderscript_RenderScript.cpp +++ b/graphics/jni/android_renderscript_RenderScript.cpp @@ -891,6 +891,29 @@ nScriptSetType(JNIEnv *_env, jobject _this, jint type, jboolean writable, jstrin } static void +nScriptSetInvoke(JNIEnv *_env, jobject _this, jstring _str, jint slot) +{ + RsContext con = (RsContext)(_env->GetIntField(_this, gContextId)); + LOG_API("nScriptSetInvoke, con(%p)", con); + const char* n = NULL; + if (_str) { + n = _env->GetStringUTFChars(_str, NULL); + } + rsScriptSetInvoke(con, n, slot); + if (n) { + _env->ReleaseStringUTFChars(_str, n); + } +} + +static void +nScriptInvoke(JNIEnv *_env, jobject _this, jint obj, jint slot) +{ + RsContext con = (RsContext)(_env->GetIntField(_this, gContextId)); + LOG_API("nScriptInvoke, con(%p), script(%p)", con, (void *)obj); + rsScriptInvoke(con, (RsScript)obj, slot); +} + +static void nScriptSetRoot(JNIEnv *_env, jobject _this, jboolean isRoot) { RsContext con = (RsContext)(_env->GetIntField(_this, gContextId)); @@ -1366,6 +1389,8 @@ static JNINativeMethod methods[] = { {"nScriptSetTimeZone", "(I[B)V", (void*)nScriptSetTimeZone }, {"nScriptSetType", "(IZLjava/lang/String;I)V", (void*)nScriptSetType }, {"nScriptSetRoot", "(Z)V", (void*)nScriptSetRoot }, +{"nScriptSetInvokable", "(Ljava/lang/String;I)V", (void*)nScriptSetInvoke }, +{"nScriptInvoke", "(II)V", (void*)nScriptInvoke }, {"nScriptCBegin", "()V", (void*)nScriptCBegin }, {"nScriptCSetScript", "([BII)V", (void*)nScriptCSetScript }, diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec index ac2e738b027c..87ad97cfcede 100644 --- a/libs/rs/rs.spec +++ b/libs/rs/rs.spec @@ -297,6 +297,16 @@ ScriptSetType { param const char * name } +ScriptSetInvoke { + param const char * name + param uint32_t slot + } + +ScriptInvoke { + param RsScript s + param uint32_t slot + } + ScriptSetRoot { param bool isRoot } diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp index fde31a1b90cc..99a085d87856 100644 --- a/libs/rs/rsScript.cpp +++ b/libs/rs/rsScript.cpp @@ -27,6 +27,8 @@ Script::Script() mEnviroment.mClearColor[2] = 0; mEnviroment.mClearColor[3] = 1; mEnviroment.mClearDepth = 1; + mEnviroment.mClearStencil = 0; + mEnviroment.mIsRoot = false; } Script::~Script() @@ -83,10 +85,23 @@ void rsi_ScriptSetType(Context * rsc, RsType vt, uint32_t slot, bool writable, c } } +void rsi_ScriptSetInvoke(Context *rsc, const char *name, uint32_t slot) +{ + ScriptCState *ss = &rsc->mScriptC; + ss->mInvokableNames[slot] = name; +} + +void rsi_ScriptInvoke(Context *rsc, RsScript vs, uint32_t slot) +{ + Script *s = static_cast<Script *>(vs); + s->mEnviroment.mInvokables[slot](); +} + + void rsi_ScriptSetRoot(Context * rsc, bool isRoot) { ScriptCState *ss = &rsc->mScriptC; - ss->mEnviroment.mIsRoot = isRoot; + ss->mScript->mEnviroment.mIsRoot = isRoot; } diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h index 60f83a63c696..e40531ede37e 100644 --- a/libs/rs/rsScript.h +++ b/libs/rs/rsScript.h @@ -34,6 +34,7 @@ class ProgramFragmentStore; class Script : public ObjectBase { public: + typedef void (* InvokeFunc_t)(void); Script(); virtual ~Script(); @@ -52,17 +53,22 @@ public: ObjectBaseRef<ProgramFragment> mFragment; //ObjectBaseRef<ProgramRaster> mRaster; ObjectBaseRef<ProgramFragmentStore> mFragmentStore; - + InvokeFunc_t mInvokables[MAX_SCRIPT_BANKS]; + const char * mScriptText; + uint32_t mScriptTextLength; }; Enviroment_t mEnviroment; uint32_t mCounstantBufferCount; + ObjectBaseRef<Allocation> mSlots[MAX_SCRIPT_BANKS]; ObjectBaseRef<const Type> mTypes[MAX_SCRIPT_BANKS]; String8 mSlotNames[MAX_SCRIPT_BANKS]; bool mSlotWritable[MAX_SCRIPT_BANKS]; + + virtual bool run(Context *, uint32_t launchID) = 0; }; diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp index 8230cbcf4009..108ae5a911c6 100644 --- a/libs/rs/rsScriptC.cpp +++ b/libs/rs/rsScriptC.cpp @@ -82,36 +82,27 @@ bool ScriptC::run(Context *rsc, uint32_t launchIndex) ScriptCState::ScriptCState() { + mScript = NULL; clear(); } ScriptCState::~ScriptCState() { - if (mAccScript) { - accDeleteScript(mAccScript); - } + delete mScript; + mScript = NULL; } void ScriptCState::clear() { - memset(&mProgram, 0, sizeof(mProgram)); - for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) { mConstantBufferTypes[ct].clear(); mSlotNames[ct].setTo(""); + mInvokableNames[ct].setTo(""); mSlotWritable[ct] = false; } - memset(&mEnviroment, 0, sizeof(mEnviroment)); - mEnviroment.mClearColor[0] = 0; - mEnviroment.mClearColor[1] = 0; - mEnviroment.mClearColor[2] = 0; - mEnviroment.mClearColor[3] = 1; - mEnviroment.mClearDepth = 1; - mEnviroment.mClearStencil = 0; - mEnviroment.mIsRoot = false; - - mAccScript = NULL; + delete mScript; + mScript = new ScriptC(); mInt32Defines.clear(); mFloatDefines.clear(); @@ -127,9 +118,9 @@ static ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) return NULL; } -void ScriptCState::runCompiler(Context *rsc) +void ScriptCState::runCompiler(Context *rsc, ScriptC *s) { - mAccScript = accCreateScript(); + s->mAccScript = accCreateScript(); String8 tmp; rsc->appendNameDefines(&tmp); @@ -139,44 +130,51 @@ void ScriptCState::runCompiler(Context *rsc) appendTypes(&tmp); tmp.append("#line 1\n"); - const char* scriptSource[] = {tmp.string(), mProgram.mScriptText}; - int scriptLength[] = {tmp.length(), mProgram.mScriptTextLength} ; - accScriptSource(mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength); - accRegisterSymbolCallback(mAccScript, symbolLookup, NULL); - accCompileScript(mAccScript); - accGetScriptLabel(mAccScript, "main", (ACCvoid**) &mProgram.mScript); - accGetScriptLabel(mAccScript, "init", (ACCvoid**) &mProgram.mInit); - rsAssert(mProgram.mScript); + const char* scriptSource[] = {tmp.string(), s->mEnviroment.mScriptText}; + int scriptLength[] = {tmp.length(), s->mEnviroment.mScriptTextLength} ; + accScriptSource(s->mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength); + accRegisterSymbolCallback(s->mAccScript, symbolLookup, NULL); + accCompileScript(s->mAccScript); + accGetScriptLabel(s->mAccScript, "main", (ACCvoid**) &s->mProgram.mScript); + accGetScriptLabel(s->mAccScript, "init", (ACCvoid**) &s->mProgram.mInit); + rsAssert(s->mProgram.mScript); - if (!mProgram.mScript) { + if (!s->mProgram.mScript) { ACCchar buf[4096]; ACCsizei len; - accGetScriptInfoLog(mAccScript, sizeof(buf), &len, buf); + accGetScriptInfoLog(s->mAccScript, sizeof(buf), &len, buf); LOGE(buf); } - if (mProgram.mInit) { - mProgram.mInit(); + if (s->mProgram.mInit) { + s->mProgram.mInit(); } for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) { if (mSlotNames[ct].length() > 0) { - accGetScriptLabel(mAccScript, + accGetScriptLabel(s->mAccScript, mSlotNames[ct].string(), - (ACCvoid**) &mProgram.mSlotPointers[ct]); - LOGE("var %s %p", mSlotNames[ct].string(), mProgram.mSlotPointers[ct]); + (ACCvoid**) &s->mProgram.mSlotPointers[ct]); + } + } + + for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) { + if (mInvokableNames[ct].length() > 0) { + accGetScriptLabel(s->mAccScript, + mInvokableNames[ct].string(), + (ACCvoid**) &s->mEnviroment.mInvokables[ct]); } } - mEnviroment.mFragment.set(rsc->getDefaultProgramFragment()); - mEnviroment.mVertex.set(rsc->getDefaultProgramVertex()); - mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore()); + s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment()); + s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex()); + s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore()); - if (mProgram.mScript) { + if (s->mProgram.mScript) { const static int pragmaMax = 16; ACCsizei pragmaCount; ACCchar * str[pragmaMax]; - accGetPragmas(mAccScript, &pragmaCount, pragmaMax, &str[0]); + accGetPragmas(s->mAccScript, &pragmaCount, pragmaMax, &str[0]); for (int ct=0; ct < pragmaCount; ct+=2) { if (!strcmp(str[ct], "version")) { @@ -188,12 +186,12 @@ void ScriptCState::runCompiler(Context *rsc) continue; } if (!strcmp(str[ct+1], "parent")) { - mEnviroment.mVertex.clear(); + s->mEnviroment.mVertex.clear(); continue; } ProgramVertex * pv = (ProgramVertex *)rsc->lookupName(str[ct+1]); if (pv != NULL) { - mEnviroment.mVertex.set(pv); + s->mEnviroment.mVertex.set(pv); continue; } LOGE("Unreconized value %s passed to stateVertex", str[ct+1]); @@ -208,12 +206,12 @@ void ScriptCState::runCompiler(Context *rsc) continue; } if (!strcmp(str[ct+1], "parent")) { - mEnviroment.mFragment.clear(); + s->mEnviroment.mFragment.clear(); continue; } ProgramFragment * pf = (ProgramFragment *)rsc->lookupName(str[ct+1]); if (pf != NULL) { - mEnviroment.mFragment.set(pf); + s->mEnviroment.mFragment.set(pf); continue; } LOGE("Unreconized value %s passed to stateFragment", str[ct+1]); @@ -224,13 +222,13 @@ void ScriptCState::runCompiler(Context *rsc) continue; } if (!strcmp(str[ct+1], "parent")) { - mEnviroment.mFragmentStore.clear(); + s->mEnviroment.mFragmentStore.clear(); continue; } ProgramFragmentStore * pfs = (ProgramFragmentStore *)rsc->lookupName(str[ct+1]); if (pfs != NULL) { - mEnviroment.mFragmentStore.set(pfs); + s->mEnviroment.mFragmentStore.set(pfs); continue; } LOGE("Unreconized value %s passed to stateFragmentStore", str[ct+1]); @@ -351,33 +349,6 @@ void ScriptCState::appendTypes(String8 *str) s.append(";\n"); LOGD(s); str->append(s); -#if 0 - for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) { - const Component *c = e->getComponent(ct2); - tmp.setTo("#define "); - tmp.append(mSlotNames[ct]); - tmp.append("_"); - tmp.append(c->getComponentName()); - switch (c->getType()) { - case Component::FLOAT: - tmp.append(" loadF("); - break; - case Component::SIGNED: - sprintf(buf, " loadI%i(", c->getBits()); - tmp.append(buf); - break; - case Component::UNSIGNED: - sprintf(buf, " loadU%i(", c->getBits()); - tmp.append(buf); - break; - } - sprintf(buf, "%i, %i)\n", ct, ct2); - tmp.append(buf); - - LOGD(tmp); - str->append(tmp); - } -#endif } } } @@ -394,15 +365,16 @@ void rsi_ScriptCBegin(Context * rsc) void rsi_ScriptCSetScript(Context * rsc, void *vp) { - ScriptCState *ss = &rsc->mScriptC; - ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp); + rsAssert(0); + //ScriptCState *ss = &rsc->mScriptC; + //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp); } void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len) { ScriptCState *ss = &rsc->mScriptC; - ss->mProgram.mScriptText = text; - ss->mProgram.mScriptTextLength = len; + ss->mScript->mEnviroment.mScriptText = text; + ss->mScript->mEnviroment.mScriptTextLength = len; } @@ -410,14 +382,11 @@ RsScript rsi_ScriptCCreate(Context * rsc) { ScriptCState *ss = &rsc->mScriptC; - ss->runCompiler(rsc); + ScriptC *s = ss->mScript; + ss->mScript = NULL; - ScriptC *s = new ScriptC(); + ss->runCompiler(rsc, s); s->incUserRef(); - s->mAccScript = ss->mAccScript; - ss->mAccScript = NULL; - s->mEnviroment = ss->mEnviroment; - s->mProgram = ss->mProgram; for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) { s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get()); s->mSlotNames[ct] = ss->mSlotNames[ct]; diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h index 8aa99eff49de..355f0c38319f 100644 --- a/libs/rs/rsScriptC.h +++ b/libs/rs/rsScriptC.h @@ -67,17 +67,15 @@ public: ScriptCState(); ~ScriptCState(); - ACCscript* mAccScript; - - ScriptC::Program_t mProgram; - Script::Enviroment_t mEnviroment; + ScriptC *mScript; ObjectBaseRef<const Type> mConstantBufferTypes[MAX_SCRIPT_BANKS]; String8 mSlotNames[MAX_SCRIPT_BANKS]; bool mSlotWritable[MAX_SCRIPT_BANKS]; + String8 mInvokableNames[MAX_SCRIPT_BANKS]; void clear(); - void runCompiler(Context *rsc); + void runCompiler(Context *rsc, ScriptC *s); void appendVarDefines(String8 *str); void appendTypes(String8 *str); diff --git a/libs/surfaceflinger/BlurFilter.cpp b/libs/surfaceflinger/BlurFilter.cpp index 5dc0ba057c8f..1ffbd5b6c8d7 100644 --- a/libs/surfaceflinger/BlurFilter.cpp +++ b/libs/surfaceflinger/BlurFilter.cpp @@ -111,6 +111,50 @@ struct BlurColor565 } }; +template <int FACTOR = 0> +struct BlurColor888X +{ + typedef uint32_t type; + int r, g, b; + inline BlurColor888X() { } + inline BlurColor888X(uint32_t v) { + v = BLUR_RGBA_TO_HOST(v); + r = v & 0xFF; + g = (v >> 8) & 0xFF; + b = (v >> 16) & 0xFF; + } + inline void clear() { r=g=b=0; } + inline uint32_t to(int shift, int last, int dither) const { + int R = r; + int G = g; + int B = b; + if (UNLIKELY(last)) { + if (FACTOR>0) { + int L = (R+G+G+B)>>2; + R += ((L - R) * FACTOR) >> 8; + G += ((L - G) * FACTOR) >> 8; + B += ((L - B) * FACTOR) >> 8; + } + } + R >>= shift; + G >>= shift; + B >>= shift; + return BLUR_HOST_TO_RGBA((0xFF<<24) | (B<<16) | (G<<8) | R); + } + inline BlurColor888X& operator += (const BlurColor888X& rhs) { + r += rhs.r; + g += rhs.g; + b += rhs.b; + return *this; + } + inline BlurColor888X& operator -= (const BlurColor888X& rhs) { + r -= rhs.r; + g -= rhs.g; + b -= rhs.b; + return *this; + } +}; + struct BlurGray565 { typedef uint16_t type; @@ -316,7 +360,13 @@ status_t blurFilter( int kernelSizeUser, int repeat) { - return blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat); + status_t err = BAD_VALUE; + if (image->format == GGL_PIXEL_FORMAT_RGB_565) { + err = blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat); + } else if (image->format == GGL_PIXEL_FORMAT_RGBX_8888) { + err = blurFilter< BlurColor888X<0x80> >(image, image, kernelSizeUser, repeat); + } + return err; } } // namespace android diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp index e14f35b7e09a..0ef663fe73e5 100644 --- a/libs/surfaceflinger/LayerBlur.cpp +++ b/libs/surfaceflinger/LayerBlur.cpp @@ -40,9 +40,9 @@ const char* const LayerBlur::typeID = "LayerBlur"; LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display, const sp<Client>& client, int32_t i) - : LayerBaseClient(flinger, display, client, i), mCacheDirty(true), - mRefreshCache(true), mCacheAge(0), mTextureName(-1U), - mWidthScale(1.0f), mHeightScale(1.0f) +: LayerBaseClient(flinger, display, client, i), mCacheDirty(true), +mRefreshCache(true), mCacheAge(0), mTextureName(-1U), +mWidthScale(1.0f), mHeightScale(1.0f) { } @@ -136,6 +136,13 @@ void LayerBlur::onDraw(const Region& clip) const // create the texture name the first time // can't do that in the ctor, because it runs in another thread. glGenTextures(1, &mTextureName); + glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat); + glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType); + if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) { + mReadFormat = GL_RGBA; + mReadType = GL_UNSIGNED_BYTE; + mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888; + } } Region::const_iterator it = clip.begin(); @@ -143,33 +150,39 @@ void LayerBlur::onDraw(const Region& clip) const if (it != end) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, mTextureName); - + if (mRefreshCache) { mRefreshCache = false; mAutoRefreshPending = false; - - // allocate enough memory for 4-bytes (2 pixels) aligned data - const int32_t s = (w + 1) & ~1; - uint16_t* const pixels = (uint16_t*)malloc(s*h*2); + + int32_t pixelSize = 4; + int32_t s = w; + if (mReadType == GL_UNSIGNED_SHORT_5_6_5) { + // allocate enough memory for 4-bytes (2 pixels) aligned data + s = (w + 1) & ~1; + pixelSize = 2; + } + + uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize); // This reads the frame-buffer, so a h/w GL would have to // finish() its rendering first. we don't want to do that // too often. Read data is 4-bytes aligned. - glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); - + glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels); + // blur that texture. GGLSurface bl; bl.version = sizeof(GGLSurface); bl.width = w; bl.height = h; bl.stride = s; - bl.format = GGL_PIXEL_FORMAT_RGB_565; + bl.format = mBlurFormat; bl.data = (GGLubyte*)pixels; blurFilter(&bl, 8, 2); if (mFlags & (DisplayHardware::NPOT_EXTENSION)) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); + glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0, + mReadFormat, mReadType, pixels); mWidthScale = 1.0f / w; mHeightScale =-1.0f / h; mYOffset = 0; @@ -178,10 +191,10 @@ void LayerBlur::onDraw(const Region& clip) const GLuint th = 1 << (31 - clz(h)); if (tw < w) tw <<= 1; if (th < h) th <<= 1; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0, + mReadFormat, mReadType, NULL); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, - GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels); + mReadFormat, mReadType, pixels); mWidthScale = 1.0f / tw; mHeightScale =-1.0f / th; mYOffset = th-h; @@ -189,7 +202,7 @@ void LayerBlur::onDraw(const Region& clip) const free((void*)pixels); } - + const State& s = drawingState(); if (UNLIKELY(s.alpha < 0xFF)) { const GGLfixed alpha = (s.alpha << 16)/255; diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h index bf36ae4e170f..2e9d7c67bec1 100644 --- a/libs/surfaceflinger/LayerBlur.h +++ b/libs/surfaceflinger/LayerBlur.h @@ -59,6 +59,9 @@ private: mutable GLfloat mWidthScale; mutable GLfloat mHeightScale; mutable GLfloat mYOffset; + mutable GLint mReadFormat; + mutable GLint mReadType; + mutable uint32_t mBlurFormat; }; // --------------------------------------------------------------------------- diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 60496d67fe54..d53f00242f18 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -7056,7 +7056,7 @@ public class WindowManagerService extends IWindowManager.Stub + " attHidden=" + mAttachedHidden + " tok.hiddenRequested=" + (mAppToken != null ? mAppToken.hiddenRequested : false) - + " tok.idden=" + + " tok.hidden=" + (mAppToken != null ? mAppToken.hidden : false) + " animating=" + mAnimating + " tok animating=" @@ -7085,10 +7085,20 @@ public class WindowManagerService extends IWindowManager.Stub if (mAttrs.type != TYPE_APPLICATION_STARTING && mAppToken != null) { mAppToken.firstWindowDrawn = true; - if (mAnimation == null && mAppToken.startingData != null) { + + if (mAppToken.startingData != null) { if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Finish starting " + mToken + ": first real window is shown, no animation"); + // If this initial window is animating, stop it -- we + // will do an animation to reveal it from behind the + // starting window, so there is no need for it to also + // be doing its own stuff. + if (mAnimation != null) { + mAnimation = null; + // Make sure we clean up the animation. + mAnimating = true; + } mFinishedStarting.add(mAppToken); mH.sendEmptyMessage(H.FINISHED_STARTING); } diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index 4368464eea1f..2672c6d5cb45 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -129,6 +129,8 @@ public class PhoneNumberUtils return uri.getSchemeSpecificPart(); } + // TODO: We don't check for SecurityException here (requires + // READ_PHONE_STATE permission). if (scheme.equals("voicemail")) { return TelephonyManager.getDefault().getVoiceMailNumber(); } @@ -1179,6 +1181,35 @@ public class PhoneNumberUtils } /** + * isVoiceMailNumber: checks a given number against the voicemail + * number provided by the RIL and SIM card. The caller must have + * the READ_PHONE_STATE credential. + * + * @param number the number to look up. + * @return true if the number is in the list of voicemail. False + * otherwise, including if the caller does not have the permission + * to read the VM number. + * @hide TODO: pending API Council approval + */ + public static boolean isVoiceMailNumber(String number) { + String vmNumber; + + try { + vmNumber = TelephonyManager.getDefault().getVoiceMailNumber(); + } catch (SecurityException ex) { + return false; + } + + // Strip the separators from the number before comparing it + // to the list. + number = extractNetworkPortion(number); + + // compare tolerates null so we need to make sure that we + // don't return true when both are null. + return !TextUtils.isEmpty(number) && compare(number, vmNumber); + } + + /** * Translates any alphabetic letters (i.e. [A-Za-z]) in the * specified phone number into the equivalent numeric digits, * according to the phone keypad letter mapping described in diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java index c8490e9cfeea..01b1746f9430 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfo.java +++ b/telephony/java/com/android/internal/telephony/CallerInfo.java @@ -101,13 +101,12 @@ public class CallerInfo { public boolean isCachedPhotoCurrent; private boolean mIsEmergency; - - // Don't keep checking VM if it's going to throw an exception for this proc. - private static boolean sSkipVmCheck = false; + private boolean mIsVoiceMail; public CallerInfo() { // TODO: Move all the basic initialization here? mIsEmergency = false; + mIsVoiceMail = false; } /** @@ -220,32 +219,15 @@ public class CallerInfo { public static CallerInfo getCallerInfo(Context context, String number) { if (TextUtils.isEmpty(number)) { return null; - } else { - // Change the callerInfo number ONLY if it is an emergency number - // or if it is the voicemail number. If it is either, take a - // shortcut and skip the query. - if (PhoneNumberUtils.isEmergencyNumber(number)) { - return new CallerInfo().markAsEmergency(context); - } else { - try { - if (!sSkipVmCheck && PhoneNumberUtils.compare(number, - TelephonyManager.getDefault().getVoiceMailNumber())) { - CallerInfo ci = new CallerInfo(); - - // Note we're setting the phone number here (refer to javadoc - // comments at the top of CallerInfo class). - ci.phoneNumber = TelephonyManager.getDefault().getVoiceMailAlphaTag(); - // TODO: FIND ANOTHER ICON - //info.photoResource = android.R.drawable.badge_voicemail; - return ci; - } - } catch (SecurityException ex) { - // Don't crash if this process doesn't have permission to - // retrieve VM number. It's still allowed to look up caller info. - // But don't try it again. - sSkipVmCheck = true; - } - } + } + + // Change the callerInfo number ONLY if it is an emergency number + // or if it is the voicemail number. If it is either, take a + // shortcut and skip the query. + if (PhoneNumberUtils.isEmergencyNumber(number)) { + return new CallerInfo().markAsEmergency(context); + } else if (PhoneNumberUtils.isVoiceMailNumber(number)) { + return new CallerInfo().markAsVoiceMail(); } Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)); @@ -304,6 +286,13 @@ public class CallerInfo { } /** + * @return true if the caller info is a voicemail number. + */ + public boolean isVoiceMailNumber() { + return mIsVoiceMail; + } + + /** * Mark this CallerInfo as an emergency call. * @param context To lookup the localized 'Emergency Number' string. * @return this instance. @@ -323,6 +312,37 @@ public class CallerInfo { return this; } + + /** + * Mark this CallerInfo as a voicemail call. The voicemail label + * is obtained from the telephony manager. Caller must hold the + * READ_PHONE_STATE permission otherwise the phoneNumber will be + * set to null. + * @return this instance. + */ + // TODO: As in the emergency number handling, we end up writing a + // string in the phone number field. + /* package */ CallerInfo markAsVoiceMail() { + mIsVoiceMail = true; + + try { + String voiceMailLabel = TelephonyManager.getDefault().getVoiceMailAlphaTag(); + + phoneNumber = voiceMailLabel; + } catch (SecurityException se) { + // Should never happen: if this process does not have + // permission to retrieve VM tag, it should not have + // permission to retrieve VM number and would not call + // this method. + // Leave phoneNumber untouched. + Log.e(TAG, "Cannot access VoiceMail.", se); + } + // TODO: There is no voicemail picture? + // FIXME: FIND ANOTHER ICON + // photoResource = android.R.drawable.badge_voicemail; + return this; + } + private static String normalize(String s) { if (s == null || s.length() > 0) { return s; @@ -330,4 +350,31 @@ public class CallerInfo { return null; } } + + /** + * @return a string debug representation of this instance. + */ + public String toString() { + return new StringBuilder(384) + .append("\nname: " + name) + .append("\nphoneNumber: " + phoneNumber) + .append("\ncnapName: " + cnapName) + .append("\nnumberPresentation: " + numberPresentation) + .append("\nnamePresentation: " + namePresentation) + .append("\ncontactExits: " + contactExists) + .append("\nphoneLabel: " + phoneLabel) + .append("\nnumberType: " + numberType) + .append("\nnumberLabel: " + numberLabel) + .append("\nphotoResource: " + photoResource) + .append("\nperson_id: " + person_id) + .append("\nneedUpdate: " + needUpdate) + .append("\ncontactRefUri: " + contactRefUri) + .append("\ncontactRingtoneUri: " + contactRefUri) + .append("\nshouldSendToVoicemail: " + shouldSendToVoicemail) + .append("\ncachedPhoto: " + cachedPhoto) + .append("\nisCachedPhotoCurrent: " + isCachedPhotoCurrent) + .append("\nemergency: " + mIsEmergency) + .append("\nvoicemail " + mIsVoiceMail) + .toString(); + } } diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java index 4227a84a9e33..802e79b2cadd 100644 --- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java +++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java @@ -47,9 +47,6 @@ public class CallerInfoAsyncQuery { private CallerInfoAsyncQueryHandler mHandler; - // Don't keep checking VM if it's going to throw an exception for this proc. - private static boolean sSkipVmCheck = false; - /** * Interface for a CallerInfoAsyncQueryHandler result return. */ @@ -227,18 +224,7 @@ public class CallerInfoAsyncQuery { // comments at the top of CallerInfo class). mCallerInfo = new CallerInfo().markAsEmergency(mQueryContext); } else if (cw.event == EVENT_VOICEMAIL_NUMBER) { - mCallerInfo = new CallerInfo(); - try { - // Note we're setting the phone number here (refer to javadoc - // comments at the top of CallerInfo class). - mCallerInfo.phoneNumber = - TelephonyManager.getDefault().getVoiceMailAlphaTag(); - } catch (SecurityException ex) { - // Should never happen: if this process does not have - // permission to retrieve VM tag, it should not have - // permission to retrieve VM number and would not generate - // an EVENT_VOICEMAIL_NUMBER. But if it happens, don't crash. - } + mCallerInfo = new CallerInfo().markAsVoiceMail(); } else { mCallerInfo = CallerInfo.getCallerInfo(mQueryContext, mQueryUri, cursor); // Use the number entered by the user for display. @@ -258,7 +244,7 @@ public class CallerInfoAsyncQuery { //notify the listener that the query is complete. if (cw.listener != null) { if (DBG) log("notifying listener: " + cw.listener.getClass().toString() + - " for token: " + token); + " for token: " + token + mCallerInfo); cw.listener.onQueryComplete(token, cw.cookie, mCallerInfo); } } @@ -315,23 +301,10 @@ public class CallerInfoAsyncQuery { // check to see if these are recognized numbers, and use shortcuts if we can. if (PhoneNumberUtils.isEmergencyNumber(number)) { cw.event = EVENT_EMERGENCY_NUMBER; + } else if (PhoneNumberUtils.isVoiceMailNumber(number)) { + cw.event = EVENT_VOICEMAIL_NUMBER; } else { - String vmNumber = null; - if (!sSkipVmCheck){ - try { - vmNumber = TelephonyManager.getDefault().getVoiceMailNumber(); - } catch (SecurityException ex) { - // Don't crash if this process doesn't have permission to - // retrieve VM number. It's still allowed to look up caller info. - // But don't try it again. - sSkipVmCheck = true; - } - } - if (PhoneNumberUtils.compare(number, vmNumber)) { - cw.event = EVENT_VOICEMAIL_NUMBER; - } else { - cw.event = EVENT_NEW_QUERY; - } + cw.event = EVENT_NEW_QUERY; } c.mHandler.startQuery (token, cw, contactRef, null, null, null, null); diff --git a/telephony/tests/TelephonyTest/AndroidManifest.xml b/telephony/tests/TelephonyTest/AndroidManifest.xml index c0cc0d58f63f..b2a481bee5d3 100644 --- a/telephony/tests/TelephonyTest/AndroidManifest.xml +++ b/telephony/tests/TelephonyTest/AndroidManifest.xml @@ -28,8 +28,9 @@ </intent-filter> </activity> </application> - <instrumentation android:name=".TelephonyUnitTestRunner" - android:targetPackage="com.android.telephonytest" - android:label="Telephony unit tests InstrumentationRunner"> - </instrumentation> + <instrumentation android:name=".TelephonyUnitTestRunner" + android:targetPackage="com.android.telephonytest" + android:label="Telephony unit tests InstrumentationRunner"> + </instrumentation> + <uses-permission android:name="android.permission.READ_PHONE_STATE" /> </manifest> diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java index 5da940d801a4..9e1af3134343 100644 --- a/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java +++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java @@ -37,6 +37,7 @@ public class TelephonyUnitTestRunner extends InstrumentationTestRunner { public TestSuite getAllTests() { TestSuite suite = new InstrumentationTestSuite(this); suite.addTestSuite(com.android.telephonytest.unit.CallerInfoUnitTest.class); + suite.addTestSuite(com.android.telephonytest.unit.PhoneNumberUtilsUnitTest.class); return suite; } diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java index 4cd026609068..0f24f155046a 100644 --- a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java +++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java @@ -107,6 +107,16 @@ public class CallerInfoUnitTest extends AndroidTestCase { assertIsValidEmergencyCallerInfo(); } + // TODO: Add more tests: + /** + * Check if the voice mail number cannot be retrieved that the + * original phone number is preserved. + */ + /** + * Check the markAs* methods work. + */ + + // // Helpers // diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java new file mode 100644 index 000000000000..2d3c548d02a4 --- /dev/null +++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2009 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 com.android.telephonytest.unit; +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; + +import android.telephony.PhoneNumberUtils; +import android.telephony.TelephonyManager; + +/* + * Check the PhoneNumberUtils utility class works as expected. + * + */ + +public class PhoneNumberUtilsUnitTest extends AndroidTestCase { + private String mVoiceMailNumber; + private static final String TAG = "PhoneNumberUtilsUnitTest"; + + @Override + protected void setUp() throws Exception { + super.setUp(); + // FIXME: Why are we getting a security exception here? The + // permission is declared in the manifest.... + // mVoiceMailNumber = TelephonyManager.getDefault().getVoiceMailNumber(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + /** + * Basic checks for the VoiceMail number. + * Assumes READ_PHONE_STATE permission and we don't have it. + */ + // TODO: Figure out why we don't have the permission declared in the manifest. + @SmallTest + public void testWithNumberNotEqualToVoiceMail() throws Exception { + assertFalse(PhoneNumberUtils.isVoiceMailNumber("911")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber("tel:911")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber("+18001234567")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber("")); + assertFalse(PhoneNumberUtils.isVoiceMailNumber(null)); + // FIXME: + // assertTrue(PhoneNumberUtils.isVoiceMailNumber(mVoiceMailNumber)); + } + +} diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java index c62f94f4fcf9..f2025c6b91db 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java @@ -36,8 +36,11 @@ public class HandlerThreadTest extends TestCase { public void testHandlerThread() throws Exception { HandlerThread th1 = new HandlerThread("HandlerThreadTest") { protected void onLooperPrepared() { - mDidSetup = true; - mLooperTid = Process.myTid(); + synchronized (HandlerThreadTest.this) { + mDidSetup = true; + mLooperTid = Process.myTid(); + HandlerThreadTest.this.notify(); + } } }; @@ -49,14 +52,23 @@ public class HandlerThreadTest extends TestCase { assertTrue(th1.isAlive()); assertNotNull(th1.getLooper()); - /* - * Since getLooper() will block until the HandlerThread is setup, we are guaranteed - * that mDidSetup and mLooperTid will have been initalized. If they have not, then - * this test should fail - */ + // The call to getLooper() internally blocks until the looper is + // available, but will call onLooperPrepared() after that. So we + // need to block here to wait for our onLooperPrepared() to complete + // and fill in the values we expect. + synchronized (this) { + while (!mDidSetup) { + try { + wait(); + } catch (InterruptedException e) { + } + } + } + + // Make sure that the process was set. + assertNotSame(-1, mLooperTid); // Make sure that the onLooperPrepared() was called on a different thread. assertNotSame(Process.myTid(), mLooperTid); - assertTrue(mDidSetup); final Handler h1 = new Handler(th1.getLooper()) { public void handleMessage(Message msg) { diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java index 8fea967be9a4..395e57208310 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java @@ -96,7 +96,9 @@ public class FileFilter { // Android layout tests are stored in "layout_tests". The following two // tests expect "LayoutTests" in their output. "storage/domstorage/localstorage/iframe-events.html", - "storage/domstorage/sessionstorage/iframe-events.html" + "storage/domstorage/sessionstorage/iframe-events.html", + // below tests (failed or crashes) are filtered out temporarily due to prioritizing + "editing/selection/move-left-right.html", }; static void fillIgnoreResultSet() { diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java index cc2f1f5936a7..85e0422014f0 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java @@ -1,5 +1,23 @@ +/* + * Copyright (C) 2009 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 com.android.dumprendertree; +import com.android.dumprendertree.forwarder.ForwardService; + import android.util.Log; import java.io.BufferedOutputStream; @@ -12,6 +30,12 @@ import java.io.IOException; public class FsUtils { private static final String LOGTAG = "FsUtils"; + static final String HTTP_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/"; + static final String HTTPS_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/ssl/"; + static final String HTTP_LOCAL_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/local/"; + static final String HTTP_MEDIA_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/media/"; + static final String HTTP_WML_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/wml/"; + private FsUtils() { //no creation of instances } @@ -77,4 +101,24 @@ public class FsUtils { return status; } + public static String getTestUrl(String path) { + String url = null; + if (!path.startsWith(HTTP_TESTS_PREFIX)) { + url = "file://" + path; + } else { + ForwardService.getForwardService().startForwardService(); + if (path.startsWith(HTTPS_TESTS_PREFIX)) { + // still cut the URL after "http/tests/" + url = "https://127.0.0.1:8443/" + path.substring(HTTP_TESTS_PREFIX.length()); + } else if (!path.startsWith(HTTP_LOCAL_TESTS_PREFIX) + && !path.startsWith(HTTP_MEDIA_TESTS_PREFIX) + && !path.startsWith(HTTP_WML_TESTS_PREFIX)) { + url = "http://127.0.0.1:8000/" + path.substring(HTTP_TESTS_PREFIX.length()); + } else { + url = "file://" + path; + } + } + return url; + } + } diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java index e4c871630c63..235e10ee023d 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java @@ -19,6 +19,7 @@ package com.android.dumprendertree; import com.android.dumprendertree.TestShellActivity.DumpDataType; import com.android.dumprendertree.forwarder.AdbUtils; import com.android.dumprendertree.forwarder.ForwardServer; +import com.android.dumprendertree.forwarder.ForwardService; import android.app.Instrumentation; import android.content.Intent; @@ -143,17 +144,6 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh static final String LAYOUT_RESULTS_CRASHED_RESULT_FILE = "results/layout_tests_crashed.txt"; static final String LAYOUT_TESTS_RUNNER = "run_layout_tests.py"; - static final String HTTP_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/"; - static final String HTTPS_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/ssl/"; - static final String HTTP_LOCAL_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/local/"; - static final String HTTP_MEDIA_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/media/"; - static final String HTTP_WML_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/wml/"; - - - static final String DEFAULT_TEST_HOST = "android-browser-test.mtv.corp.google.com"; - static final String FORWARD_HOST_CONF = "/sdcard/drt_forward_host.txt"; - private ForwardServer fs8000, fs8080, fs8443; - private MyTestRecorder mResultRecorder; private Vector<String> mTestList; private boolean mRebaselineResults; @@ -162,45 +152,6 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh public LayoutTestsAutoTest() { super("com.android.dumprendertree", TestShellActivity.class); - - int addr = getForwardHostAddr(); - if(addr != -1) { - fs8000 = new ForwardServer(8000, addr, 8000); - fs8080 = new ForwardServer(8080, addr, 8080); - fs8443 = new ForwardServer(8443, addr, 8443); - } - } - - private int getForwardHostAddr() { - int addr = -1; - String host = null; - File forwardHostConf = new File(FORWARD_HOST_CONF); - if (forwardHostConf.isFile()) { - BufferedReader hostReader = null; - try { - hostReader = new BufferedReader(new FileReader(forwardHostConf)); - host = hostReader.readLine(); - Log.v(LOGTAG, "read forward host from file: " + host); - } catch (IOException ioe) { - Log.v(LOGTAG, "cannot read forward host from file", ioe); - } finally { - if (hostReader != null) { - try { - hostReader.close(); - } catch (IOException ioe) { - // burn!!! - } - } - } - } - if (host == null || host.length() == 0) - host = DEFAULT_TEST_HOST; - try { - addr = AdbUtils.resolve(host); - } catch (IOException ioe) { - Log.e(LOGTAG, "failed to resolve server address", ioe); - } - return addr; } // This function writes the result of the layout test to @@ -366,7 +317,7 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh Intent intent = new Intent(Intent.ACTION_VIEW); intent.setClass(activity, TestShellActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra(TestShellActivity.TEST_URL, getTestUrl(test)); + intent.putExtra(TestShellActivity.TEST_URL, FsUtils.getTestUrl(test)); intent.putExtra(TestShellActivity.RESULT_FILE, resultFile); intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout); activity.startActivity(intent); @@ -450,49 +401,10 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh } FsUtils.updateTestStatus(TEST_STATUS_FILE, "#DONE"); - if(fs8000 != null) - fs8000.stop(); - if(fs8080 != null) - fs8080.stop(); - if(fs8443 != null) - fs8443.stop(); - + ForwardService.getForwardService().stopForwardService(); activity.finish(); } - private void startForwardServerIfNeeded() { - try { - if(fs8000 != null) - fs8000.start(); - if(fs8080 != null) - fs8080.start(); - if(fs8443 != null) - fs8443.start(); - } catch (IOException ioe) { - Log.w(LOGTAG, "failed to start forwarder. http tests will fail.", ioe); - } - } - - private String getTestUrl(String path) { - String url = null; - if (!path.startsWith(HTTP_TESTS_PREFIX)) { - url = "file://" + path; - } else { - startForwardServerIfNeeded(); - if (path.startsWith(HTTPS_TESTS_PREFIX)) { - // still cut the URL after "http/tests/" - url = "https://127.0.0.1:8443/" + path.substring(HTTP_TESTS_PREFIX.length()); - } else if (!path.startsWith(HTTP_LOCAL_TESTS_PREFIX) - && !path.startsWith(HTTP_MEDIA_TESTS_PREFIX) - && !path.startsWith(HTTP_WML_TESTS_PREFIX)) { - url = "http://127.0.0.1:8000/" + path.substring(HTTP_TESTS_PREFIX.length()); - } else { - url = "file://" + path; - } - } - return url; - } - private String getTestPath() { LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation(); diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java index 71d9758e182d..50b7c3f86872 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2009 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 com.android.dumprendertree; import android.app.Activity; diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java index 995c129e4398..fbce78afa41b 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2009 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 com.android.dumprendertree; import android.app.Activity; diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java index 663df83a5eb7..074d90f7f513 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java @@ -16,6 +16,8 @@ package com.android.dumprendertree; +import com.android.dumprendertree.forwarder.ForwardService; + import android.app.Activity; import android.app.AlertDialog; import android.content.Context; @@ -184,6 +186,7 @@ public class TestShellActivity extends Activity implements LayoutTestController } catch (IOException ioe) { Log.w(LOGTAG, "Failed to close test list file.", ioe); } + ForwardService.getForwardService().stopForwardService(); finished(); } @@ -215,10 +218,9 @@ public class TestShellActivity extends Activity implements LayoutTestController builder.create().show(); return; } - url = "file://" + url; Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.putExtra(TestShellActivity.TEST_URL, url); + intent.putExtra(TestShellActivity.TEST_URL, FsUtils.getTestUrl(url)); intent.putExtra(TIMEOUT_IN_MILLIS, 10000); executeIntent(intent); } diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java index 9a3e9c202c2f..c2ecf3af47e7 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2009 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 com.android.dumprendertree.forwarder; import android.util.Log; @@ -44,7 +60,6 @@ public class AdbUtils { DataInputStream dis = new DataInputStream(localSocket.getInputStream()); OutputStream os = localSocket.getOutputStream(); int count_read = 0; - byte[] buf = new byte[128]; if (localSocket == null || dis == null || os == null) return -1; diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java index 74e018eada1f..14f8fbeaec95 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2009 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 com.android.dumprendertree.forwarder; import android.util.Log; diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java new file mode 100644 index 000000000000..8b7de6ea205f --- /dev/null +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2009 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 com.android.dumprendertree.forwarder; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +import android.util.Log; + +public class ForwardService { + + private ForwardServer fs8000, fs8080, fs8443; + + private static ForwardService inst; + + private static final String LOGTAG = "ForwardService"; + + private static final String DEFAULT_TEST_HOST = "android-browser-test.mtv.corp.google.com"; + + private static final String FORWARD_HOST_CONF = "/sdcard/drt_forward_host.txt"; + + private ForwardService() { + int addr = getForwardHostAddr(); + if (addr != -1) { + fs8000 = new ForwardServer(8000, addr, 8000); + fs8080 = new ForwardServer(8080, addr, 8080); + fs8443 = new ForwardServer(8443, addr, 8443); + } + } + + public static ForwardService getForwardService() { + if (inst == null) { + inst = new ForwardService(); + } + return inst; + } + + public void startForwardService() { + try { + if (fs8000 != null) + fs8000.start(); + if (fs8080 != null) + fs8080.start(); + if (fs8443 != null) + fs8443.start(); + } catch (IOException ioe) { + Log.w(LOGTAG, "failed to start forwarder. http tests will fail.", ioe); + return; + } + } + + public void stopForwardService() { + if (fs8000 != null) { + fs8000.stop(); + fs8000 = null; + } + if (fs8080 != null) { + fs8080.stop(); + fs8080 = null; + } + if (fs8443 != null) { + fs8443.stop(); + fs8443 = null; + } + Log.v(LOGTAG, "forwarders stopped."); + } + + private static int getForwardHostAddr() { + int addr = -1; + String host = null; + File forwardHostConf = new File(FORWARD_HOST_CONF); + if (forwardHostConf.isFile()) { + BufferedReader hostReader = null; + try { + hostReader = new BufferedReader(new FileReader(forwardHostConf)); + host = hostReader.readLine(); + Log.v(LOGTAG, "read forward host from file: " + host); + } catch (IOException ioe) { + Log.v(LOGTAG, "cannot read forward host from file", ioe); + } finally { + if (hostReader != null) { + try { + hostReader.close(); + } catch (IOException ioe) { + // burn!!! + } + } + } + } + if (host == null || host.length() == 0) + host = DEFAULT_TEST_HOST; + try { + addr = AdbUtils.resolve(host); + } catch (IOException ioe) { + Log.e(LOGTAG, "failed to resolve server address", ioe); + } + return addr; + } +} diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java index e1e04a7e538c..a1f3cdf582c8 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java @@ -1,3 +1,19 @@ +/* + * Copyright (C) 2009 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 com.android.dumprendertree.forwarder; import android.util.Log; diff --git a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java index dc959f5e174e..aea124b08658 100644 --- a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java +++ b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java @@ -29,7 +29,6 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; -import java.util.Hashtable; import java.util.Set; import java.util.Map; import java.util.Map.Entry; @@ -145,7 +144,7 @@ public class ContentProviderOperationTest extends TestCase { public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { // Return cursor over specific set of values - return getCursor(sTestValues1); + return getCursor(sTestValues1, 1); } }, null, 0); } catch (OperationApplicationException e) { @@ -153,11 +152,62 @@ public class ContentProviderOperationTest extends TestCase { } } + public void testAssertNoValues() { + // Build an operation to assert values match provider + ContentProviderOperation op1 = ContentProviderOperation.newAssertQuery(sTestUri1) + .withExpectedCount(1).build(); + + try { + // Assert that values match from cursor + ContentProviderResult result = op1.apply(new TestContentProvider() { + public Cursor query(Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { + // Return cursor over specific set of values + return getCursor(sTestValues1, 1); + } + }, null, 0); + } catch (OperationApplicationException e) { + fail("newAssert() failed"); + } + + ContentProviderOperation op2 = ContentProviderOperation.newAssertQuery(sTestUri1) + .withExpectedCount(0).build(); + + try { + // Assert that values match from cursor + ContentProviderResult result = op2.apply(new TestContentProvider() { + public Cursor query(Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { + // Return cursor over specific set of values + return getCursor(sTestValues1, 0); + } + }, null, 0); + } catch (OperationApplicationException e) { + fail("newAssert() failed"); + } + + ContentProviderOperation op3 = ContentProviderOperation.newAssertQuery(sTestUri1) + .withExpectedCount(2).build(); + + try { + // Assert that values match from cursor + ContentProviderResult result = op3.apply(new TestContentProvider() { + public Cursor query(Uri uri, String[] projection, String selection, + String[] selectionArgs, String sortOrder) { + // Return cursor over specific set of values + return getCursor(sTestValues1, 5); + } + }, null, 0); + fail("we expect the exception to be thrown"); + } catch (OperationApplicationException e) { + } + } + /** * Build a {@link Cursor} with a single row that contains all values * provided through the given {@link ContentValues}. */ - private Cursor getCursor(ContentValues contentValues) { + private Cursor getCursor(ContentValues contentValues, int numRows) { final Set<Entry<String, Object>> valueSet = contentValues.valueSet(); final String[] keys = new String[valueSet.size()]; final Object[] values = new Object[valueSet.size()]; @@ -170,7 +220,9 @@ public class ContentProviderOperationTest extends TestCase { } final MatrixCursor cursor = new MatrixCursor(keys); - cursor.addRow(values); + for (i = 0; i < numRows; i++) { + cursor.addRow(values); + } return cursor; } |