summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/accessibilityservice/AccessibilityService.java27
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java42
-rw-r--r--core/java/android/accessibilityservice/UiTestAutomationBridge.java2
-rw-r--r--core/java/android/app/ActivityManager.java13
-rw-r--r--core/java/android/app/ActivityOptions.java38
-rw-r--r--core/java/android/app/ActivityThread.java8
-rw-r--r--core/java/android/app/ContextImpl.java10
-rw-r--r--core/java/android/app/Notification.java38
-rw-r--r--core/java/android/content/ContentProviderClient.java11
-rw-r--r--core/java/android/content/ContentResolver.java208
-rw-r--r--core/java/android/content/Intent.java18
-rw-r--r--core/java/android/content/pm/ContainerEncryptionParams.java28
-rw-r--r--core/java/android/content/pm/LimitedLengthInputStream.java26
-rw-r--r--core/java/android/database/AbstractCursor.java10
-rwxr-xr-xcore/java/android/hardware/input/InputManager.java4
-rw-r--r--core/java/android/net/Uri.java6
-rw-r--r--core/java/android/net/nsd/DnsSdTxtRecord.java1
-rw-r--r--core/java/android/nfc/NdefRecord.java12
-rw-r--r--core/java/android/os/Build.java4
-rw-r--r--core/java/android/os/Process.java3
-rw-r--r--core/java/android/provider/Settings.java1
-rw-r--r--core/java/android/text/style/TextAppearanceSpan.java41
-rw-r--r--core/java/android/util/TimeUtils.java19
-rw-r--r--core/java/android/view/AccessibilityInteractionController.java2
-rw-r--r--core/java/android/view/GLES20DisplayList.java3
-rw-r--r--core/java/android/view/IWindowManager.aidl2
-rw-r--r--core/java/android/view/KeyCharacterMap.java55
-rw-r--r--core/java/android/view/TextureView.java12
-rw-r--r--core/java/android/view/VelocityTracker.java18
-rw-r--r--core/java/android/view/View.java140
-rw-r--r--core/java/android/view/ViewGroup.java7
-rw-r--r--core/java/android/view/ViewRootImpl.java43
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java24
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeProvider.java2
-rw-r--r--core/java/android/webkit/HTML5VideoFullScreen.java18
-rw-r--r--core/java/android/webkit/HTML5VideoInline.java14
-rw-r--r--core/java/android/webkit/HTML5VideoView.java86
-rw-r--r--core/java/android/webkit/HTML5VideoViewProxy.java23
-rw-r--r--core/java/android/webkit/WebViewCore.java9
-rw-r--r--core/java/android/webkit/WebViewInputDispatcher.java2
-rw-r--r--core/java/android/widget/AbsListView.java27
-rw-r--r--core/java/android/widget/HorizontalScrollView.java35
-rw-r--r--core/java/android/widget/NumberPicker.java204
-rw-r--r--core/java/android/widget/ScrollView.java35
-rw-r--r--core/java/android/widget/SpellChecker.java44
-rw-r--r--core/java/android/widget/TextView.java34
46 files changed, 1043 insertions, 366 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index c559e54..850fe48 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -284,16 +284,6 @@ public abstract class AccessibilityService extends Service {
public static final int GESTURE_SWIPE_DOWN_AND_RIGHT = 16;
/**
- * The user has performed a double tap gesture on the touch screen.
- */
- public static final int GESTURE_DOUBLE_TAP = 17;
-
- /**
- * The user has performed a tap and hold gesture on the touch screen.
- */
- public static final int GESTURE_TAP_AND_HOLD = 18;
-
- /**
* The {@link Intent} that must be declared as handled by the service.
*/
public static final String SERVICE_INTERFACE =
@@ -377,14 +367,12 @@ public abstract class AccessibilityService extends Service {
/**
* Called by the system when the user performs a specific gesture on the
- * touch screen. If the gesture is not handled in this callback the system
- * may provide default handing. Therefore, one should return true from this
- * function if overriding of default behavior is desired.
+ * touch screen.
*
- * <strong>Note:</strong> To receive gestures an accessibility service
- * must declare that it can handle such by specifying the
- * <code>&lt;{@link android.R.styleable#AccessibilityService_canHandleGestures
- * canHandleGestures}&gt;</code> attribute.
+ * <strong>Note:</strong> To receive gestures an accessibility service must
+ * request that the device is in touch exploration mode by setting the
+ * {@link android.accessibilityservice.AccessibilityServiceInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS}
+ * flag.
*
* @param gestureId The unique id of the performed gesture.
*
@@ -406,13 +394,8 @@ public abstract class AccessibilityService extends Service {
* @see #GESTURE_SWIPE_RIGHT_AND_UP
* @see #GESTURE_SWIPE_RIGHT_AND_LEFT
* @see #GESTURE_SWIPE_RIGHT_AND_DOWN
- * @see #GESTURE_CLOCKWISE_CIRCLE
- * @see #GESTURE_COUNTER_CLOCKWISE_CIRCLE
- * @see #GESTURE_DOUBLE_TAP
- * @see #GESTURE_TAP_AND_HOLD
*/
protected boolean onGesture(int gestureId) {
- // TODO: Describe the default gesture processing in the javaDoc once it is finalized.
return false;
}
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 7e6786b..10ea0fe 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -131,7 +131,19 @@ public class AccessibilityServiceInfo implements Parcelable {
* elements.
* </p>
*/
- public static final int INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002;
+ public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x0000002;
+
+ /**
+ * This flag requests that the system gets into touch exploration mode.
+ * In this mode a single finger moving on the screen behaves as a mouse
+ * pointer hovering over the user interface. The system will also detect
+ * certain gestures performed on the touch screen and notify this service.
+ * The system will enable touch exploration mode if there is at least one
+ * accessibility service that has this flag set. Hence, clearing this
+ * flag does not guarantee that the device will not be in touch exploration
+ * mode since there may be another enabled service that requested it.
+ */
+ public static final int FLAG_REQUEST_TOUCH_EXPLORATION_MODE= 0x0000004;
/**
* The event types an {@link AccessibilityService} is interested in.
@@ -198,7 +210,8 @@ public class AccessibilityServiceInfo implements Parcelable {
* <strong>Can be dynamically set at runtime.</strong>
* </p>
* @see #DEFAULT
- * @see #INCLUDE_NOT_IMPORTANT_VIEWS
+ * @see #FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
+ * @see #FLAG_REQUEST_TOUCH_EXPLORATION_MODE
*/
public int flags;
@@ -224,11 +237,6 @@ public class AccessibilityServiceInfo implements Parcelable {
private boolean mCanRetrieveWindowContent;
/**
- * Flag whether this accessibility service can handle gestures.
- */
- private boolean mCanHandleGestures;
-
- /**
* Resource id of the description of the accessibility service.
*/
private int mDescriptionResId;
@@ -308,8 +316,6 @@ public class AccessibilityServiceInfo implements Parcelable {
mCanRetrieveWindowContent = asAttributes.getBoolean(
com.android.internal.R.styleable.AccessibilityService_canRetrieveWindowContent,
false);
- mCanHandleGestures = asAttributes.getBoolean(
- com.android.internal.R.styleable.AccessibilityService_canHandleGestures, false);
TypedValue peekedValue = asAttributes.peekValue(
com.android.internal.R.styleable.AccessibilityService_description);
if (peekedValue != null) {
@@ -392,18 +398,6 @@ public class AccessibilityServiceInfo implements Parcelable {
}
/**
- * Whether this service can handle gestures.
- * <p>
- * <strong>Statically set from
- * {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
- * </p>
- * @return True if the service can handle gestures.
- */
- public boolean getCanHandleGestures() {
- return mCanHandleGestures;
- }
-
- /**
* Gets the non-localized description of the accessibility service.
* <p>
* <strong>Statically set from
@@ -614,8 +608,10 @@ public class AccessibilityServiceInfo implements Parcelable {
switch (flag) {
case DEFAULT:
return "DEFAULT";
- case INCLUDE_NOT_IMPORTANT_VIEWS:
- return "REGARD_VIEWS_NOT_IMPORTANT_FOR_ACCESSIBILITY";
+ case FLAG_INCLUDE_NOT_IMPORTANT_VIEWS:
+ return "FLAG_INCLUDE_NOT_IMPORTANT_VIEWS";
+ case FLAG_REQUEST_TOUCH_EXPLORATION_MODE:
+ return "FLAG_REQUEST_TOUCH_EXPLORATION_MODE";
default:
return null;
}
diff --git a/core/java/android/accessibilityservice/UiTestAutomationBridge.java b/core/java/android/accessibilityservice/UiTestAutomationBridge.java
index 30be374..6837386 100644
--- a/core/java/android/accessibilityservice/UiTestAutomationBridge.java
+++ b/core/java/android/accessibilityservice/UiTestAutomationBridge.java
@@ -189,7 +189,7 @@ public class UiTestAutomationBridge {
final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
- info.flags |= AccessibilityServiceInfo.INCLUDE_NOT_IMPORTANT_VIEWS;
+ info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
try {
manager.registerUiTestAutomationService(mListener, info);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7746ca9..4e61c3c 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1078,13 +1078,20 @@ public class ActivityManager {
*/
public static class MemoryInfo implements Parcelable {
/**
- * The total available memory on the system. This number should not
+ * The available memory on the system. This number should not
* be considered absolute: due to the nature of the kernel, a significant
* portion of this memory is actually in use and needed for the overall
* system to run well.
*/
public long availMem;
-
+
+ /**
+ * The total memory accessible by the kernel. This is basically the
+ * RAM size of the device, not including below-kernel fixed allocations
+ * like DMA buffers, RAM for the baseband CPU, etc.
+ */
+ public long totalMem;
+
/**
* The threshold of {@link #availMem} at which we consider memory to be
* low and start killing background services and other non-extraneous
@@ -1116,6 +1123,7 @@ public class ActivityManager {
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(availMem);
+ dest.writeLong(totalMem);
dest.writeLong(threshold);
dest.writeInt(lowMemory ? 1 : 0);
dest.writeLong(hiddenAppThreshold);
@@ -1126,6 +1134,7 @@ public class ActivityManager {
public void readFromParcel(Parcel source) {
availMem = source.readLong();
+ totalMem = source.readLong();
threshold = source.readLong();
lowMemory = source.readInt() != 0;
hiddenAppThreshold = source.readLong();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 3d0b7d8..523a78d 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -98,6 +98,8 @@ public class ActivityOptions {
public static final int ANIM_SCALE_UP = 2;
/** @hide */
public static final int ANIM_THUMBNAIL = 3;
+ /** @hide */
+ public static final int ANIM_THUMBNAIL_DELAYED = 4;
private String mPackageName;
private int mAnimationType = ANIM_NONE;
@@ -219,9 +221,38 @@ public class ActivityOptions {
*/
public static ActivityOptions makeThumbnailScaleUpAnimation(View source,
Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
+ return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, listener, false);
+ }
+
+ /**
+ * Create an ActivityOptions specifying an animation where a thumbnail
+ * is scaled from a given position to the new activity window that is
+ * being started. Before the animation, there is a short delay.
+ *
+ * @param source The View that this thumbnail is animating from. This
+ * defines the coordinate space for <var>startX</var> and <var>startY</var>.
+ * @param thumbnail The bitmap that will be shown as the initial thumbnail
+ * of the animation.
+ * @param startX The x starting location of the bitmap, relative to <var>source</var>.
+ * @param startY The y starting location of the bitmap, relative to <var>source</var>.
+ * @param listener Optional OnAnimationStartedListener to find out when the
+ * requested animation has started running. If for some reason the animation
+ * is not executed, the callback will happen immediately.
+ * @return Returns a new ActivityOptions object that you can use to
+ * supply these options as the options Bundle when starting an activity.
+ * @hide
+ */
+ public static ActivityOptions makeDelayedThumbnailScaleUpAnimation(View source,
+ Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener) {
+ return makeThumbnailScaleUpAnimation(source, thumbnail, startX, startY, listener, true);
+ }
+
+ private static ActivityOptions makeThumbnailScaleUpAnimation(View source,
+ Bitmap thumbnail, int startX, int startY, OnAnimationStartedListener listener,
+ boolean delayed) {
ActivityOptions opts = new ActivityOptions();
opts.mPackageName = source.getContext().getPackageName();
- opts.mAnimationType = ANIM_THUMBNAIL;
+ opts.mAnimationType = delayed ? ANIM_THUMBNAIL_DELAYED : ANIM_THUMBNAIL;
opts.mThumbnail = thumbnail;
int[] pts = new int[2];
source.getLocationOnScreen(pts);
@@ -258,7 +289,8 @@ public class ActivityOptions {
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
mStartWidth = opts.getInt(KEY_ANIM_START_WIDTH, 0);
mStartHeight = opts.getInt(KEY_ANIM_START_HEIGHT, 0);
- } else if (mAnimationType == ANIM_THUMBNAIL) {
+ } else if (mAnimationType == ANIM_THUMBNAIL ||
+ mAnimationType == ANIM_THUMBNAIL_DELAYED) {
mThumbnail = (Bitmap)opts.getParcelable(KEY_ANIM_THUMBNAIL);
mStartX = opts.getInt(KEY_ANIM_START_X, 0);
mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
@@ -359,6 +391,7 @@ public class ActivityOptions {
mStartHeight = otherOptions.mStartHeight;
break;
case ANIM_THUMBNAIL:
+ case ANIM_THUMBNAIL_DELAYED:
mAnimationType = otherOptions.mAnimationType;
mThumbnail = otherOptions.mThumbnail;
mStartX = otherOptions.mStartX;
@@ -401,6 +434,7 @@ public class ActivityOptions {
b.putInt(KEY_ANIM_START_HEIGHT, mStartHeight);
break;
case ANIM_THUMBNAIL:
+ case ANIM_THUMBNAIL_DELAYED:
b.putInt(KEY_ANIM_TYPE, mAnimationType);
b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
b.putInt(KEY_ANIM_START_X, mStartX);
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 8799194..e2ebeba 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4278,6 +4278,14 @@ public final class ActivityThread {
}
}
+ public final IContentProvider acquireUnstableProvider(Context c, String name) {
+ return acquireProvider(c, name);
+ }
+
+ public final boolean releaseUnstableProvider(IContentProvider provider) {
+ return releaseProvider(provider);
+ }
+
final void completeRemoveProvider(IContentProvider provider) {
IBinder jBinder = provider.asBinder();
String remoteProviderName = null;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4943c9a..299e408 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1692,6 +1692,16 @@ class ContextImpl extends Context {
return mMainThread.releaseProvider(provider);
}
+ @Override
+ protected IContentProvider acquireUnstableProvider(Context c, String name) {
+ return mMainThread.acquireUnstableProvider(c, name);
+ }
+
+ @Override
+ public boolean releaseUnstableProvider(IContentProvider icp) {
+ return mMainThread.releaseUnstableProvider(icp);
+ }
+
private final ActivityThread mMainThread;
}
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index f962259..0c47069 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -390,21 +390,25 @@ public class Notification implements Parcelable
public int priority;
/**
+ * @hide
* Notification type: incoming call (voice or video) or similar synchronous communication request.
*/
public static final String KIND_CALL = "android.call";
/**
+ * @hide
* Notification type: incoming direct message (SMS, instant message, etc.).
*/
public static final String KIND_MESSAGE = "android.message";
/**
+ * @hide
* Notification type: asynchronous bulk message (email).
*/
public static final String KIND_EMAIL = "android.email";
/**
+ * @hide
* Notification type: calendar event.
*/
public static final String KIND_EVENT = "android.event";
@@ -415,6 +419,7 @@ public class Notification implements Parcelable
public static final String KIND_PROMO = "android.promo";
/**
+ * @hide
* If this notification matches of one or more special types (see the <code>KIND_*</code>
* constants), add them here, best match first.
*/
@@ -796,6 +801,12 @@ public class Notification implements Parcelable
if (this.icon != 0) {
contentView.setImageViewResource(R.id.icon, this.icon);
}
+ if (priority < PRIORITY_LOW) {
+ contentView.setInt(R.id.icon,
+ "setBackgroundResource", R.drawable.notification_template_icon_low_bg);
+ contentView.setInt(R.id.status_bar_latest_event_content,
+ "setBackgroundResource", R.drawable.notification_bg_low);
+ }
if (contentTitle != null) {
contentView.setTextViewText(R.id.title, contentTitle);
}
@@ -971,8 +982,14 @@ public class Notification implements Parcelable
}
/**
- * Show the {@link Notification#when} field as a countdown (or count-up) timer instead of a timestamp.
+ * Show the {@link Notification#when} field as a stopwatch.
+ *
+ * Instead of presenting <code>when</code> as a timestamp, the notification will show an
+ * automatically updating display of the minutes and seconds since <code>when</code>.
*
+ * Useful when showing an elapsed time (like an ongoing phone call).
+ *
+ * @see android.widget.Chronometer
* @see Notification#when
*/
public Builder setUsesChronometer(boolean b) {
@@ -1297,6 +1314,8 @@ public class Notification implements Parcelable
}
/**
+ * @hide
+ *
* Add a kind (category) to this notification. Optional.
*
* @see Notification#kind
@@ -1364,6 +1383,12 @@ public class Notification implements Parcelable
contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
smallIconImageViewId = R.id.right_icon;
}
+ if (mPriority < PRIORITY_LOW) {
+ contentView.setInt(R.id.icon,
+ "setBackgroundResource", R.drawable.notification_template_icon_low_bg);
+ contentView.setInt(R.id.status_bar_latest_event_content,
+ "setBackgroundResource", R.drawable.notification_bg_low);
+ }
if (mSmallIcon != 0) {
contentView.setImageViewResource(smallIconImageViewId, mSmallIcon);
contentView.setViewVisibility(smallIconImageViewId, View.VISIBLE);
@@ -1478,7 +1503,16 @@ public class Notification implements Parcelable
RemoteViews button = new RemoteViews(mContext.getPackageName(), R.layout.notification_action);
button.setTextViewCompoundDrawables(R.id.action0, action.icon, 0, 0, 0);
button.setTextViewText(R.id.action0, action.title);
- button.setOnClickPendingIntent(R.id.action0, action.actionIntent);
+ if (action.actionIntent != null) {
+ button.setOnClickPendingIntent(R.id.action0, action.actionIntent);
+ //button.setBoolean(R.id.action0, "setEnabled", true);
+ button.setFloat(R.id.button0, "setAlpha", 1.0f);
+ button.setBoolean(R.id.button0, "setClickable", true);
+ } else {
+ //button.setBoolean(R.id.action0, "setEnabled", false);
+ button.setFloat(R.id.button0, "setAlpha", 0.5f);
+ button.setBoolean(R.id.button0, "setClickable", false);
+ }
button.setContentDescription(R.id.action0, action.title);
return button;
}
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index da2ab94..423f1f6 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -37,13 +37,16 @@ import java.util.ArrayList;
public class ContentProviderClient {
private final IContentProvider mContentProvider;
private final ContentResolver mContentResolver;
+ private final boolean mStable;
/**
* @hide
*/
- ContentProviderClient(ContentResolver contentResolver, IContentProvider contentProvider) {
+ ContentProviderClient(ContentResolver contentResolver,
+ IContentProvider contentProvider, boolean stable) {
mContentProvider = contentProvider;
mContentResolver = contentResolver;
+ mStable = stable;
}
/** See {@link ContentProvider#query ContentProvider.query} */
@@ -141,7 +144,11 @@ public class ContentProviderClient {
* @return true if this was release, false if it was already released
*/
public boolean release() {
- return mContentResolver.releaseProvider(mContentProvider);
+ if (mStable) {
+ return mContentResolver.releaseProvider(mContentProvider);
+ } else {
+ return mContentResolver.releaseUnstableProvider(mContentProvider);
+ }
}
/**
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index d4bca0a..f509fd8 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -198,6 +198,10 @@ public abstract class ContentResolver {
}
/** @hide */
public abstract boolean releaseProvider(IContentProvider icp);
+ /** @hide */
+ protected abstract IContentProvider acquireUnstableProvider(Context c, String name);
+ /** @hide */
+ public abstract boolean releaseUnstableProvider(IContentProvider icp);
/**
* Return the MIME type of the given content URL.
@@ -588,34 +592,48 @@ public abstract class ContentResolver {
if ("r".equals(mode)) {
return openTypedAssetFileDescriptor(uri, "*/*", null);
} else {
- IContentProvider provider = acquireProvider(uri);
- if (provider == null) {
- throw new FileNotFoundException("No content provider: " + uri);
- }
- try {
- AssetFileDescriptor fd = provider.openAssetFile(uri, mode);
- if(fd == null) {
- // The provider will be released by the finally{} clause
- return null;
+ int n = 0;
+ while (true) {
+ n++;
+ IContentProvider provider = acquireUnstableProvider(uri);
+ if (provider == null) {
+ throw new FileNotFoundException("No content provider: " + uri);
}
- ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
- fd.getParcelFileDescriptor(), provider);
-
- // Success! Don't release the provider when exiting, let
- // ParcelFileDescriptorInner do that when it is closed.
- provider = null;
-
- return new AssetFileDescriptor(pfd, fd.getStartOffset(),
- fd.getDeclaredLength());
- } catch (RemoteException e) {
- // Somewhat pointless, as Activity Manager will kill this
- // process shortly anyway if the depdendent ContentProvider dies.
- throw new FileNotFoundException("Dead content provider: " + uri);
- } catch (FileNotFoundException e) {
- throw e;
- } finally {
- if (provider != null) {
- releaseProvider(provider);
+ try {
+ AssetFileDescriptor fd = provider.openAssetFile(uri, mode);
+ if (fd == null) {
+ // The provider will be released by the finally{} clause
+ return null;
+ }
+ ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
+ fd.getParcelFileDescriptor(), provider);
+
+ // Success! Don't release the provider when exiting, let
+ // ParcelFileDescriptorInner do that when it is closed.
+ provider = null;
+
+ return new AssetFileDescriptor(pfd, fd.getStartOffset(),
+ fd.getDeclaredLength());
+ } catch (RemoteException e) {
+ // The provider died for some reason. Since we are
+ // acquiring it unstable, its process could have gotten
+ // killed and need to be restarted. We'll retry a couple
+ // times and if still can't succeed then fail.
+ if (n <= 2) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e1) {
+ }
+ continue;
+ }
+ // Whatever, whatever, we'll go away.
+ throw new FileNotFoundException("Dead content provider: " + uri);
+ } catch (FileNotFoundException e) {
+ throw e;
+ } finally {
+ if (provider != null) {
+ releaseUnstableProvider(provider);
+ }
}
}
}
@@ -652,32 +670,48 @@ public abstract class ContentResolver {
*/
public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
String mimeType, Bundle opts) throws FileNotFoundException {
- IContentProvider provider = acquireProvider(uri);
- if (provider == null) {
- throw new FileNotFoundException("No content provider: " + uri);
- }
- try {
- AssetFileDescriptor fd = provider.openTypedAssetFile(uri, mimeType, opts);
- if (fd == null) {
- // The provider will be released by the finally{} clause
- return null;
+ int n = 0;
+ while (true) {
+ n++;
+ IContentProvider provider = acquireUnstableProvider(uri);
+ if (provider == null) {
+ throw new FileNotFoundException("No content provider: " + uri);
}
- ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
- fd.getParcelFileDescriptor(), provider);
+ try {
+ AssetFileDescriptor fd = provider.openTypedAssetFile(uri, mimeType, opts);
+ if (fd == null) {
+ // The provider will be released by the finally{} clause
+ return null;
+ }
+ ParcelFileDescriptor pfd = new ParcelFileDescriptorInner(
+ fd.getParcelFileDescriptor(), provider);
- // Success! Don't release the provider when exiting, let
- // ParcelFileDescriptorInner do that when it is closed.
- provider = null;
+ // Success! Don't release the provider when exiting, let
+ // ParcelFileDescriptorInner do that when it is closed.
+ provider = null;
- return new AssetFileDescriptor(pfd, fd.getStartOffset(),
- fd.getDeclaredLength());
- } catch (RemoteException e) {
- throw new FileNotFoundException("Dead content provider: " + uri);
- } catch (FileNotFoundException e) {
- throw e;
- } finally {
- if (provider != null) {
- releaseProvider(provider);
+ return new AssetFileDescriptor(pfd, fd.getStartOffset(),
+ fd.getDeclaredLength());
+ } catch (RemoteException e) {
+ // The provider died for some reason. Since we are
+ // acquiring it unstable, its process could have gotten
+ // killed and need to be restarted. We'll retry a couple
+ // times and if still can't succeed then fail.
+ if (n <= 2) {
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e1) {
+ }
+ continue;
+ }
+ // Whatever, whatever, we'll go away.
+ throw new FileNotFoundException("Dead content provider: " + uri);
+ } catch (FileNotFoundException e) {
+ throw e;
+ } finally {
+ if (provider != null) {
+ releaseUnstableProvider(provider);
+ }
}
}
}
@@ -1003,6 +1037,34 @@ public abstract class ContentResolver {
}
/**
+ * Returns the content provider for the given content URI.
+ *
+ * @param uri The URI to a content provider
+ * @return The ContentProvider for the given URI, or null if no content provider is found.
+ * @hide
+ */
+ public final IContentProvider acquireUnstableProvider(Uri uri) {
+ if (!SCHEME_CONTENT.equals(uri.getScheme())) {
+ return null;
+ }
+ String auth = uri.getAuthority();
+ if (auth != null) {
+ return acquireUnstableProvider(mContext, uri.getAuthority());
+ }
+ return null;
+ }
+
+ /**
+ * @hide
+ */
+ public final IContentProvider acquireUnstableProvider(String name) {
+ if (name == null) {
+ return null;
+ }
+ return acquireProvider(mContext, name);
+ }
+
+ /**
* Returns a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
* that services the content at uri, starting the provider if necessary. Returns
* null if there is no provider associated wih the uri. The caller must indicate that they are
@@ -1016,7 +1078,7 @@ public abstract class ContentResolver {
public final ContentProviderClient acquireContentProviderClient(Uri uri) {
IContentProvider provider = acquireProvider(uri);
if (provider != null) {
- return new ContentProviderClient(this, provider);
+ return new ContentProviderClient(this, provider, true);
}
return null;
@@ -1036,7 +1098,47 @@ public abstract class ContentResolver {
public final ContentProviderClient acquireContentProviderClient(String name) {
IContentProvider provider = acquireProvider(name);
if (provider != null) {
- return new ContentProviderClient(this, provider);
+ return new ContentProviderClient(this, provider, true);
+ }
+
+ return null;
+ }
+
+ /**
+ * Like {@link #acquireContentProviderClient(Uri)}, but for use when you do
+ * not trust the stability of the target content provider. This turns off
+ * the mechanism in the platform clean up processes that are dependent on
+ * a content provider if that content provider's process goes away. Normally
+ * you can safely assume that once you have acquired a provider, you can freely
+ * use it as needed and it won't disappear, even if your process is in the
+ * background. If using this method, you need to take care to deal with any
+ * failures when communicating with the provider, and be sure to close it
+ * so that it can be re-opened later.
+ */
+ public final ContentProviderClient acquireUnstableContentProviderClient(Uri uri) {
+ IContentProvider provider = acquireProvider(uri);
+ if (provider != null) {
+ return new ContentProviderClient(this, provider, false);
+ }
+
+ return null;
+ }
+
+ /**
+ * Like {@link #acquireContentProviderClient(String)}, but for use when you do
+ * not trust the stability of the target content provider. This turns off
+ * the mechanism in the platform clean up processes that are dependent on
+ * a content provider if that content provider's process goes away. Normally
+ * you can safely assume that once you have acquired a provider, you can freely
+ * use it as needed and it won't disappear, even if your process is in the
+ * background. If using this method, you need to take care to deal with any
+ * failures when communicating with the provider, and be sure to close it
+ * so that it can be re-opened later.
+ */
+ public final ContentProviderClient acquireUnstableContentProviderClient(String name) {
+ IContentProvider provider = acquireProvider(name);
+ if (provider != null) {
+ return new ContentProviderClient(this, provider, false);
}
return null;
@@ -1690,7 +1792,7 @@ public abstract class ContentResolver {
public void close() throws IOException {
if(!mReleaseProviderFlag) {
super.close();
- ContentResolver.this.releaseProvider(mContentProvider);
+ ContentResolver.this.releaseUnstableProvider(mContentProvider);
mReleaseProviderFlag = true;
}
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 4ed6f25..c791e47 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -4573,7 +4573,7 @@ public class Intent implements Parcelable, Cloneable {
* <p><em>Note: scheme matching in the Android framework is
* case-sensitive, unlike the formal RFC. As a result,
* you should always write your Uri with a lower case scheme,
- * or use {@link Uri#normalize} or
+ * or use {@link Uri#normalizeScheme} or
* {@link #setDataAndNormalize}
* to ensure that the scheme is converted to lower case.</em>
*
@@ -4599,7 +4599,7 @@ public class Intent implements Parcelable, Cloneable {
* previously set (for example, by {@link #setType}).
*
* <p>The data Uri is normalized using
- * {@link android.net.Uri#normalize} before it is set,
+ * {@link android.net.Uri#normalizeScheme} before it is set,
* so really this is just a convenience method for
* <pre>
* setData(data.normalize())
@@ -4612,10 +4612,10 @@ public class Intent implements Parcelable, Cloneable {
*
* @see #getData
* @see #setType
- * @see android.net.Uri#normalize
+ * @see android.net.Uri#normalizeScheme
*/
public Intent setDataAndNormalize(Uri data) {
- return setData(data.normalize());
+ return setData(data.normalizeScheme());
}
/**
@@ -4687,7 +4687,7 @@ public class Intent implements Parcelable, Cloneable {
* <p><em>Note: MIME type and Uri scheme matching in the
* Android framework is case-sensitive, unlike the formal RFC definitions.
* As a result, you should always write these elements with lower case letters,
- * or use {@link #normalizeMimeType} or {@link android.net.Uri#normalize} or
+ * or use {@link #normalizeMimeType} or {@link android.net.Uri#normalizeScheme} or
* {@link #setDataAndTypeAndNormalize}
* to ensure that they are converted to lower case.</em>
*
@@ -4700,7 +4700,7 @@ public class Intent implements Parcelable, Cloneable {
* @see #setType
* @see #setData
* @see #normalizeMimeType
- * @see android.net.Uri#normalize
+ * @see android.net.Uri#normalizeScheme
* @see #setDataAndTypeAndNormalize
*/
public Intent setDataAndType(Uri data, String type) {
@@ -4716,7 +4716,7 @@ public class Intent implements Parcelable, Cloneable {
* data with your own type given here.
*
* <p>The data Uri and the MIME type are normalize using
- * {@link android.net.Uri#normalize} and {@link #normalizeMimeType}
+ * {@link android.net.Uri#normalizeScheme} and {@link #normalizeMimeType}
* before they are set, so really this is just a convenience method for
* <pre>
* setDataAndType(data.normalize(), Intent.normalizeMimeType(type))
@@ -4732,10 +4732,10 @@ public class Intent implements Parcelable, Cloneable {
* @see #setData
* @see #setDataAndType
* @see #normalizeMimeType
- * @see android.net.Uri#normalize
+ * @see android.net.Uri#normalizeScheme
*/
public Intent setDataAndTypeAndNormalize(Uri data, String type) {
- return setDataAndType(data.normalize(), normalizeMimeType(type));
+ return setDataAndType(data.normalizeScheme(), normalizeMimeType(type));
}
/**
diff --git a/core/java/android/content/pm/ContainerEncryptionParams.java b/core/java/android/content/pm/ContainerEncryptionParams.java
index 5b1440d..88112a7 100644
--- a/core/java/android/content/pm/ContainerEncryptionParams.java
+++ b/core/java/android/content/pm/ContainerEncryptionParams.java
@@ -70,16 +70,16 @@ public class ContainerEncryptionParams implements Parcelable {
private final byte[] mMacTag;
/** Offset into file where authenticated (e.g., MAC protected) data begins. */
- private final int mAuthenticatedDataStart;
+ private final long mAuthenticatedDataStart;
/** Offset into file where encrypted data begins. */
- private final int mEncryptedDataStart;
+ private final long mEncryptedDataStart;
/**
* Offset into file for the end of encrypted data (and, by extension,
* authenticated data) in file.
*/
- private final int mDataEnd;
+ private final long mDataEnd;
public ContainerEncryptionParams(String encryptionAlgorithm,
AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey)
@@ -99,6 +99,8 @@ public class ContainerEncryptionParams implements Parcelable {
* @param macAlgorithm MAC algorithm to use; format matches JCE
* @param macSpec algorithm parameters specification, may be {@code null}
* @param macKey key used for authentication (i.e., for the MAC tag)
+ * @param macTag message authentication code (MAC) tag for the authenticated
+ * data
* @param authenticatedDataStart offset of start of authenticated data in
* stream
* @param encryptedDataStart offset of start of encrypted data in stream
@@ -109,7 +111,7 @@ public class ContainerEncryptionParams implements Parcelable {
public ContainerEncryptionParams(String encryptionAlgorithm,
AlgorithmParameterSpec encryptionSpec, SecretKey encryptionKey, String macAlgorithm,
AlgorithmParameterSpec macSpec, SecretKey macKey, byte[] macTag,
- int authenticatedDataStart, int encryptedDataStart, int dataEnd)
+ long authenticatedDataStart, long encryptedDataStart, long dataEnd)
throws InvalidAlgorithmParameterException {
if (TextUtils.isEmpty(encryptionAlgorithm)) {
throw new NullPointerException("algorithm == null");
@@ -172,15 +174,15 @@ public class ContainerEncryptionParams implements Parcelable {
return mMacTag;
}
- public int getAuthenticatedDataStart() {
+ public long getAuthenticatedDataStart() {
return mAuthenticatedDataStart;
}
- public int getEncryptedDataStart() {
+ public long getEncryptedDataStart() {
return mEncryptedDataStart;
}
- public int getDataEnd() {
+ public long getDataEnd() {
return mDataEnd;
}
@@ -315,9 +317,9 @@ public class ContainerEncryptionParams implements Parcelable {
dest.writeByteArray(mMacTag);
- dest.writeInt(mAuthenticatedDataStart);
- dest.writeInt(mEncryptedDataStart);
- dest.writeInt(mDataEnd);
+ dest.writeLong(mAuthenticatedDataStart);
+ dest.writeLong(mEncryptedDataStart);
+ dest.writeLong(mDataEnd);
}
private ContainerEncryptionParams(Parcel source) throws InvalidAlgorithmParameterException {
@@ -333,9 +335,9 @@ public class ContainerEncryptionParams implements Parcelable {
mMacTag = source.createByteArray();
- mAuthenticatedDataStart = source.readInt();
- mEncryptedDataStart = source.readInt();
- mDataEnd = source.readInt();
+ mAuthenticatedDataStart = source.readLong();
+ mEncryptedDataStart = source.readLong();
+ mDataEnd = source.readLong();
switch (encParamType) {
case ENC_PARAMS_IV_PARAMETERS:
diff --git a/core/java/android/content/pm/LimitedLengthInputStream.java b/core/java/android/content/pm/LimitedLengthInputStream.java
index 25a490f..e787277 100644
--- a/core/java/android/content/pm/LimitedLengthInputStream.java
+++ b/core/java/android/content/pm/LimitedLengthInputStream.java
@@ -3,6 +3,7 @@ package android.content.pm;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Arrays;
/**
* A class that limits the amount of data that is read from an InputStream. When
@@ -15,20 +16,20 @@ public class LimitedLengthInputStream extends FilterInputStream {
/**
* The end of the stream where we don't want to allow more data to be read.
*/
- private final int mEnd;
+ private final long mEnd;
/**
* Current offset in the stream.
*/
- private int mOffset;
+ private long mOffset;
/**
* @param in underlying stream to wrap
* @param offset offset into stream where data starts
* @param length length of data at offset
- * @throws IOException if an error occured with the underlying stream
+ * @throws IOException if an error occurred with the underlying stream
*/
- public LimitedLengthInputStream(InputStream in, int offset, int length) throws IOException {
+ public LimitedLengthInputStream(InputStream in, long offset, long length) throws IOException {
super(in);
if (in == null) {
@@ -36,11 +37,15 @@ public class LimitedLengthInputStream extends FilterInputStream {
}
if (offset < 0) {
- throw new IOException("offset == " + offset);
+ throw new IOException("offset < 0");
}
if (length < 0) {
- throw new IOException("length must be non-negative; is " + length);
+ throw new IOException("length < 0");
+ }
+
+ if (length > Long.MAX_VALUE - offset) {
+ throw new IOException("offset + length > Long.MAX_VALUE");
}
mEnd = offset + length;
@@ -65,8 +70,15 @@ public class LimitedLengthInputStream extends FilterInputStream {
return -1;
}
+ final int arrayLength = buffer.length;
+ Arrays.checkOffsetAndCount(arrayLength, offset, byteCount);
+
+ if (mOffset > Long.MAX_VALUE - byteCount) {
+ throw new IOException("offset out of bounds: " + mOffset + " + " + byteCount);
+ }
+
if (mOffset + byteCount > mEnd) {
- byteCount = mEnd - mOffset;
+ byteCount = (int) (mEnd - mOffset);
}
final int numRead = super.read(buffer, offset, byteCount);
diff --git a/core/java/android/database/AbstractCursor.java b/core/java/android/database/AbstractCursor.java
index dd6692c..fb04817 100644
--- a/core/java/android/database/AbstractCursor.java
+++ b/core/java/android/database/AbstractCursor.java
@@ -44,14 +44,20 @@ public abstract class AbstractCursor implements CrossProcessCursor {
/**
* This must be set to the index of the row ID column by any
* subclass that wishes to support updates.
+ *
+ * @deprecated This field should not be used.
*/
+ @Deprecated
protected int mRowIdColumnIndex;
/**
* If {@link #mRowIdColumnIndex} is not -1 this contains contains the value of
* the column at {@link #mRowIdColumnIndex} for the current row this cursor is
* pointing at.
+ *
+ * @deprecated This field should not be used.
*/
+ @Deprecated
protected Long mCurrentRowID;
protected boolean mClosed;
@@ -62,8 +68,8 @@ public abstract class AbstractCursor implements CrossProcessCursor {
private ContentObserver mSelfObserver;
private boolean mSelfObserverRegistered;
- private DataSetObservable mDataSetObservable = new DataSetObservable();
- private ContentObservable mContentObservable = new ContentObservable();
+ private final DataSetObservable mDataSetObservable = new DataSetObservable();
+ private final ContentObservable mContentObservable = new ContentObservable();
private Bundle mExtras = Bundle.EMPTY;
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 5ba1850..6448b55 100755
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -96,14 +96,14 @@ public final class InputManager {
* &lt;keyboard-layouts xmlns:android="http://schemas.android.com/apk/res/android">
* &lt;keyboard-layout android:name="keyboard_layout_english_us"
* android:label="@string/keyboard_layout_english_us_label"
- * android:kcm="@raw/keyboard_layout_english_us" />
+ * android:keyboardLayout="@raw/keyboard_layout_english_us" />
* &lt;/keyboard-layouts>
* </p><p>
* The <code>android:name</code> attribute specifies an identifier by which
* the keyboard layout will be known in the package.
* The <code>android:label</code> attributes specifies a human-readable descriptive
* label to describe the keyboard layout in the user interface, such as "English (US)".
- * The <code>android:kcm</code> attribute refers to a
+ * The <code>android:keyboardLayout</code> attribute refers to a
* <a href="http://source.android.com/tech/input/key-character-map-files.html">
* key character map</a> resource that defines the keyboard layout.
* </p>
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index defe7aa..3b990e3 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1718,9 +1718,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
}
/**
- * Return a normalized representation of this Uri.
- *
- * <p>A normalized Uri has a lowercase scheme component.
+ * Return an equivalent URI with a lowercase scheme component.
* This aligns the Uri with Android best practices for
* intent filtering.
*
@@ -1740,7 +1738,7 @@ public abstract class Uri implements Parcelable, Comparable<Uri> {
* @see {@link android.content.Intent#setData}
* @see {@link #setNormalizedData}
*/
- public Uri normalize() {
+ public Uri normalizeScheme() {
String scheme = getScheme();
if (scheme == null) return this; // give up
String lowerScheme = scheme.toLowerCase(Locale.US);
diff --git a/core/java/android/net/nsd/DnsSdTxtRecord.java b/core/java/android/net/nsd/DnsSdTxtRecord.java
index ccb9a91..2f20d44 100644
--- a/core/java/android/net/nsd/DnsSdTxtRecord.java
+++ b/core/java/android/net/nsd/DnsSdTxtRecord.java
@@ -36,6 +36,7 @@ import java.util.Arrays;
*
* The DnsSdTxtRecord object stores the entire TXT data as a single byte array, traversing it
* as need be to implement its various methods.
+ * @hide
*
*/
public class DnsSdTxtRecord implements Parcelable {
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index 0e9e8f4..8872335 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -321,7 +321,7 @@ public final class NdefRecord implements Parcelable {
* and {@link #RTD_URI}. This is the most efficient encoding
* of a URI into NDEF.<p>
* The uri parameter will be normalized with
- * {@link Uri#normalize} to set the scheme to lower case to
+ * {@link Uri#normalizeScheme} to set the scheme to lower case to
* follow Android best practices for intent filtering.
* However the unchecked exception
* {@link IllegalArgumentException} may be thrown if the uri
@@ -338,7 +338,7 @@ public final class NdefRecord implements Parcelable {
public static NdefRecord createUri(Uri uri) {
if (uri == null) throw new NullPointerException("uri is null");
- uri = uri.normalize();
+ uri = uri.normalizeScheme();
String uriString = uri.toString();
if (uriString.length() == 0) throw new IllegalArgumentException("uri is empty");
@@ -364,7 +364,7 @@ public final class NdefRecord implements Parcelable {
* and {@link #RTD_URI}. This is the most efficient encoding
* of a URI into NDEF.<p>
* The uriString parameter will be normalized with
- * {@link Uri#normalize} to set the scheme to lower case to
+ * {@link Uri#normalizeScheme} to set the scheme to lower case to
* follow Android best practices for intent filtering.
* However the unchecked exception
* {@link IllegalArgumentException} may be thrown if the uriString
@@ -665,7 +665,7 @@ public final class NdefRecord implements Parcelable {
* actually valid: it always attempts to create and return a URI if
* this record appears to be a URI record by the above rules.<p>
* The returned URI will be normalized to have a lower case scheme
- * using {@link Uri#normalize}.<p>
+ * using {@link Uri#normalizeScheme}.<p>
*
* @return URI, or null if this is not a URI record
*/
@@ -688,13 +688,13 @@ public final class NdefRecord implements Parcelable {
}
} catch (FormatException e) { }
} else if (Arrays.equals(mType, RTD_URI)) {
- return parseWktUri().normalize();
+ return parseWktUri().normalizeScheme();
}
break;
case TNF_ABSOLUTE_URI:
Uri uri = Uri.parse(new String(mType, Charsets.UTF_8));
- return uri.normalize();
+ return uri.normalizeScheme();
case TNF_EXTERNAL_TYPE:
if (inSmartPoster) {
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 63275cf..2d5b625 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -370,7 +370,7 @@ public class Build {
public static final int ICE_CREAM_SANDWICH_MR1 = 15;
/**
- * Next up on Android!
+ * Android 4.1.
*
* <p>Applications targeting this or a later release will get these
* new changes in behavior:</p>
@@ -381,7 +381,7 @@ public class Build {
* exist in the application's manifest.
* </ul>
*/
- public static final int JELLY_BEAN = CUR_DEVELOPMENT;
+ public static final int JELLY_BEAN = 16;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 1df53e8..18fd3cb 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -897,6 +897,9 @@ public class Process {
public static final native long getFreeMemory();
/** @hide */
+ public static final native long getTotalMemory();
+
+ /** @hide */
public static final native void readProcLines(String path,
String[] reqFields, long[] outSizes);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ba8c4c9..497e66e8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1410,6 +1410,7 @@ public final class Settings {
/**
* Adjustment to auto-brightness to make it generally more (>0.0 <1.0)
* or less (<0.0 >-1.0) bright.
+ * @hide
*/
public static final String SCREEN_AUTO_BRIGHTNESS_ADJ = "screen_auto_brightness_adj";
diff --git a/core/java/android/text/style/TextAppearanceSpan.java b/core/java/android/text/style/TextAppearanceSpan.java
index 5fd7c57..ecbf4bc 100644
--- a/core/java/android/text/style/TextAppearanceSpan.java
+++ b/core/java/android/text/style/TextAppearanceSpan.java
@@ -68,24 +68,29 @@ public class TextAppearanceSpan extends MetricAffectingSpan implements Parcelabl
TextAppearance_textSize, -1);
mStyle = a.getInt(com.android.internal.R.styleable.TextAppearance_textStyle, 0);
- int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0);
-
- switch (tf) {
- case 1:
- mTypeface = "sans";
- break;
-
- case 2:
- mTypeface = "serif";
- break;
-
- case 3:
- mTypeface = "monospace";
- break;
-
- default:
- mTypeface = null;
- break;
+ String family = a.getString(com.android.internal.R.styleable.TextAppearance_fontFamily);
+ if (family != null) {
+ mTypeface = family;
+ } else {
+ int tf = a.getInt(com.android.internal.R.styleable.TextAppearance_typeface, 0);
+
+ switch (tf) {
+ case 1:
+ mTypeface = "sans";
+ break;
+
+ case 2:
+ mTypeface = "serif";
+ break;
+
+ case 3:
+ mTypeface = "monospace";
+ break;
+
+ default:
+ mTypeface = null;
+ break;
+ }
}
a.recycle();
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 2883eca..c4ebec4 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -26,6 +26,7 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Calendar;
import java.util.Collection;
import java.util.TimeZone;
import java.util.Date;
@@ -381,4 +382,22 @@ public class TimeUtils {
}
formatDuration(time-now, pw, 0);
}
+
+ /**
+ * Convert a System.currentTimeMillis() value to a time of day value like
+ * that printed in logs. MM-DD HH:MM:SS.MMM
+ *
+ * @param millis since the epoch (1/1/1970)
+ * @return String representation of the time.
+ * @hide
+ */
+ public static String logTimeOfDay(long millis) {
+ Calendar c = Calendar.getInstance();
+ if (millis >= 0) {
+ c.setTimeInMillis(millis);
+ return String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c);
+ } else {
+ return Long.toString(millis);
+ }
+ }
}
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 881594d..d42757d 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -413,7 +413,7 @@ final class AccessibilityInteractionController {
// focus instead fetching all provider nodes to do the search here.
AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
if (provider != null) {
- focused = provider.findAccessibilitiyFocus(virtualDescendantId);
+ focused = provider.findAccessibilityFocus(virtualDescendantId);
} else if (virtualDescendantId == View.NO_ID) {
focused = host.createAccessibilityNodeInfo();
}
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index f3618eb..0154556 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -131,7 +131,8 @@ class GLES20DisplayList extends DisplayList {
@Override
public void setAnimationMatrix(Matrix matrix) {
try {
- nSetAnimationMatrix(getNativeDisplayList(), matrix.native_instance);
+ nSetAnimationMatrix(getNativeDisplayList(),
+ (matrix != null) ? matrix.native_instance : 0);
} catch (IllegalStateException e) {
// invalid DisplayList okay: we'll set current values the next time we render to it
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index e1f01db..c5a687a 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -84,7 +84,7 @@ interface IWindowManager
void overridePendingAppTransitionScaleUp(int startX, int startY, int startWidth,
int startHeight);
void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
- IRemoteCallback startedCallback);
+ IRemoteCallback startedCallback, boolean delayed);
void executeAppTransition();
void setAppStartingWindow(IBinder token, String pkg, int theme,
in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index 5b371eb..2cb724f 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -386,19 +386,19 @@ public class KeyCharacterMap implements Parcelable {
*
* @param keyCode The key code.
* @param metaState The meta key modifier state.
- * @param outFallbackAction The fallback action object to populate.
- * @return True if a fallback action was found, false otherwise.
+ * @return The fallback action, or null if none. Remember to recycle the fallback action.
*
* @hide
*/
- public boolean getFallbackAction(int keyCode, int metaState,
- FallbackAction outFallbackAction) {
- if (outFallbackAction == null) {
- throw new IllegalArgumentException("fallbackAction must not be null");
- }
-
+ public FallbackAction getFallbackAction(int keyCode, int metaState) {
+ FallbackAction action = FallbackAction.obtain();
metaState = KeyEvent.normalizeMetaState(metaState);
- return nativeGetFallbackAction(mPtr, keyCode, metaState, outFallbackAction);
+ if (nativeGetFallbackAction(mPtr, keyCode, metaState, action)) {
+ action.metaState = KeyEvent.normalizeMetaState(action.metaState);
+ return action;
+ }
+ action.recycle();
+ return null;
}
/**
@@ -727,7 +727,44 @@ public class KeyCharacterMap implements Parcelable {
* @hide
*/
public static final class FallbackAction {
+ private static final int MAX_RECYCLED = 10;
+ private static final Object sRecycleLock = new Object();
+ private static FallbackAction sRecycleBin;
+ private static int sRecycledCount;
+
+ private FallbackAction next;
+
public int keyCode;
public int metaState;
+
+ private FallbackAction() {
+ }
+
+ public static FallbackAction obtain() {
+ final FallbackAction target;
+ synchronized (sRecycleLock) {
+ if (sRecycleBin == null) {
+ target = new FallbackAction();
+ } else {
+ target = sRecycleBin;
+ sRecycleBin = target.next;
+ sRecycledCount--;
+ target.next = null;
+ }
+ }
+ return target;
+ }
+
+ public void recycle() {
+ synchronized (sRecycleLock) {
+ if (sRecycledCount < MAX_RECYCLED) {
+ next = sRecycleBin;
+ sRecycleBin = this;
+ sRecycledCount += 1;
+ } else {
+ next = null;
+ }
+ }
+ }
}
}
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 651be2e..2048de2 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -561,7 +561,17 @@ public class TextureView extends View {
applyUpdate();
applyTransformMatrix();
- mLayer.copyInto(bitmap);
+ // This case can happen if the app invokes setSurfaceTexture() before
+ // we are able to create the hardware layer. We can safely initialize
+ // the layer here thanks to the validate() call at the beginning of
+ // this method
+ if (mLayer == null && mUpdateSurface) {
+ getHardwareLayer();
+ }
+
+ if (mLayer != null) {
+ mLayer.copyInto(bitmap);
+ }
}
return bitmap;
}
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 1c35e31..f703e34 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -298,6 +298,24 @@ public final class VelocityTracker implements Poolable<VelocityTracker> {
return estimate(time, yCoeff);
}
+ /**
+ * Gets the X coefficient with the specified index.
+ * @param index The index of the coefficient to return.
+ * @return The X coefficient, or 0 if the index is greater than the degree.
+ */
+ public float getXCoeff(int index) {
+ return index <= degree ? xCoeff[index] : 0;
+ }
+
+ /**
+ * Gets the Y coefficient with the specified index.
+ * @param index The index of the coefficient to return.
+ * @return The Y coefficient, or 0 if the index is greater than the degree.
+ */
+ public float getYCoeff(int index) {
+ return index <= degree ? yCoeff[index] : 0;
+ }
+
private float estimate(float time, float[] c) {
float a = 0;
float scale = 1;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index aad6756..55ea938 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2128,6 +2128,20 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*/
static final int ACCESSIBILITY_STATE_CHANGED = 0x00000080 << IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+ /**
+ * Flag indicating that view has an animation set on it. This is used to track whether an
+ * animation is cleared between successive frames, in order to tell the associated
+ * DisplayList to clear its animation matrix.
+ */
+ static final int VIEW_IS_ANIMATING_TRANSFORM = 0x10000000;
+
+ /**
+ * Flag indicating whether a view failed the quickReject() check in draw(). This condition
+ * is used to check whether later changes to the view's transform should invalidate the
+ * view to force the quickReject test to run again.
+ */
+ static final int VIEW_QUICK_REJECTED = 0x20000000;
+
/* End of masks for mPrivateFlags2 */
static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
@@ -5209,6 +5223,13 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* call to continue to your children, you must be sure to call the super
* implementation.
*
+ * <p>Here is a sample layout that makes use of fitting system windows
+ * to have controls for a video view placed inside of the window decorations
+ * that it hides and shows. This can be used with code like the second
+ * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
+ *
+ * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
+ *
* @param insets Current content insets of the window. Prior to
* {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
* the insets or else you and Android will be unhappy.
@@ -5251,7 +5272,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
/**
- * Check for the FITS_SYSTEM_WINDOWS flag. If this method returns true, this view
+ * Check for state of {@link #setFitsSystemWindows(boolean). If this method
+ * returns true, this view
* will account for system screen decorations such as the status bar and inset its
* content. This allows the view to be positioned in absolute screen coordinates
* and remain visible to the user.
@@ -5260,10 +5282,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*
* @attr ref android.R.styleable#View_fitsSystemWindows
*/
- public boolean fitsSystemWindows() {
+ public boolean getFitsSystemWindows() {
return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
}
+ /** @hide */
+ public boolean fitsSystemWindows() {
+ return getFitsSystemWindows();
+ }
+
/**
* Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
*/
@@ -8547,6 +8574,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mDisplayList != null) {
mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
}
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
/**
@@ -8589,6 +8620,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mDisplayList != null) {
mDisplayList.setRotation(rotation);
}
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -8636,6 +8671,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mDisplayList != null) {
mDisplayList.setRotationY(rotationY);
}
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -8683,6 +8722,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mDisplayList != null) {
mDisplayList.setRotationX(rotationX);
}
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -8722,6 +8765,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mDisplayList != null) {
mDisplayList.setScaleX(scaleX);
}
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -8761,6 +8808,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mDisplayList != null) {
mDisplayList.setScaleY(scaleY);
}
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -8808,6 +8859,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mDisplayList != null) {
mDisplayList.setPivotX(pivotX);
}
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -8854,6 +8909,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mDisplayList != null) {
mDisplayList.setPivotY(pivotY);
}
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -9012,6 +9071,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
mBackgroundSizeChanged = true;
invalidateParentIfNeeded();
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -9081,6 +9144,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
mBackgroundSizeChanged = true;
invalidateParentIfNeeded();
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -9144,6 +9211,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
mBackgroundSizeChanged = true;
invalidateParentIfNeeded();
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -9204,6 +9275,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
mBackgroundSizeChanged = true;
invalidateParentIfNeeded();
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -9288,6 +9363,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mDisplayList != null) {
mDisplayList.setTranslationX(translationX);
}
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -9325,6 +9404,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (mDisplayList != null) {
mDisplayList.setTranslationY(translationY);
}
+ if ((mPrivateFlags2 & VIEW_QUICK_REJECTED) == VIEW_QUICK_REJECTED) {
+ // View was rejected last time it was drawn by its parent; this may have changed
+ invalidateParentIfNeeded();
+ }
}
}
@@ -12764,16 +12847,27 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (a != null) {
more = drawAnimation(parent, drawingTime, a, scalingRequired);
concatMatrix = a.willChangeTransformationMatrix();
+ if (concatMatrix) {
+ mPrivateFlags2 |= VIEW_IS_ANIMATING_TRANSFORM;
+ }
transformToApply = parent.mChildTransformation;
- } else if (!useDisplayListProperties &&
- (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
- final boolean hasTransform =
- parent.getChildStaticTransformation(this, parent.mChildTransformation);
- if (hasTransform) {
- final int transformType = parent.mChildTransformation.getTransformationType();
- transformToApply = transformType != Transformation.TYPE_IDENTITY ?
- parent.mChildTransformation : null;
- concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
+ } else {
+ if ((mPrivateFlags2 & VIEW_IS_ANIMATING_TRANSFORM) == VIEW_IS_ANIMATING_TRANSFORM &&
+ mDisplayList != null) {
+ // No longer animating: clear out old animation matrix
+ mDisplayList.setAnimationMatrix(null);
+ mPrivateFlags2 &= ~VIEW_IS_ANIMATING_TRANSFORM;
+ }
+ if (!useDisplayListProperties &&
+ (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
+ final boolean hasTransform =
+ parent.getChildStaticTransformation(this, parent.mChildTransformation);
+ if (hasTransform) {
+ final int transformType = parent.mChildTransformation.getTransformationType();
+ transformToApply = transformType != Transformation.TYPE_IDENTITY ?
+ parent.mChildTransformation : null;
+ concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
+ }
}
}
@@ -12785,8 +12879,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
if (!concatMatrix && canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
(mPrivateFlags & DRAW_ANIMATION) == 0) {
+ mPrivateFlags2 |= VIEW_QUICK_REJECTED;
return more;
}
+ mPrivateFlags2 &= ~VIEW_QUICK_REJECTED;
if (hardwareAccelerated) {
// Clear INVALIDATED flag to allow invalidation to occur during rendering, but
@@ -15376,7 +15472,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* playing the application would like to go into a complete full-screen mode,
* to use as much of the display as possible for the video. When in this state
* the user can not interact with the application; the system intercepts
- * touching on the screen to pop the UI out of full screen mode.
+ * touching on the screen to pop the UI out of full screen mode. See
+ * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
*
* {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
* content}
@@ -15458,11 +15555,13 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
}
- void updateLocalSystemUiVisibility(int localValue, int localChanges) {
+ boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
if (val != mSystemUiVisibility) {
setSystemUiVisibility(val);
+ return true;
}
+ return false;
}
/** @hide */
@@ -16861,7 +16960,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Interface definition for a callback to be invoked when the status bar changes
* visibility. This reports <strong>global</strong> changes to the system UI
- * state, not just what the application is requesting.
+ * state, not what the application is requesting.
*
* @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
*/
@@ -16870,10 +16969,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Called when the status bar changes visibility because of a call to
* {@link View#setSystemUiVisibility(int)}.
*
- * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE} or
- * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}. This tells you the
- * <strong>global</strong> state of the UI visibility flags, not what your
- * app is currently applying.
+ * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
+ * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
+ * This tells you the <strong>global</strong> state of these UI visibility
+ * flags, not what your app is currently applying.
*/
public void onSystemUiVisibilityChange(int visibility);
}
@@ -17159,6 +17258,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
int mDisabledSystemUiVisibility;
/**
+ * Last global system UI visibility reported by the window manager.
+ */
+ int mGlobalSystemUiVisibility;
+
+ /**
* True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
* attached.
*/
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index acfca26..b3c8895 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1317,15 +1317,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
@Override
- void updateLocalSystemUiVisibility(int localValue, int localChanges) {
- super.updateLocalSystemUiVisibility(localValue, localChanges);
+ boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
+ boolean changed = super.updateLocalSystemUiVisibility(localValue, localChanges);
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i=0; i <count; i++) {
final View child = children[i];
- child.updateLocalSystemUiVisibility(localValue, localChanges);
+ changed |= child.updateLocalSystemUiVisibility(localValue, localChanges);
}
+ return changed;
}
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6e6fab2..1fcb2c3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -328,8 +328,6 @@ public final class ViewRootImpl implements ViewParent,
private final int mDensity;
- final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction();
-
/**
* Consistency verifier for debugging purposes.
*/
@@ -2384,7 +2382,7 @@ public final class ViewRootImpl implements ViewParent,
}
} else {
if (mAccessibilityFocusedVirtualView == null) {
- mAccessibilityFocusedVirtualView = provider.findAccessibilitiyFocus(View.NO_ID);
+ mAccessibilityFocusedVirtualView = provider.findAccessibilityFocus(View.NO_ID);
}
if (mAccessibilityFocusedVirtualView == null) {
return;
@@ -3797,13 +3795,15 @@ public final class ViewRootImpl implements ViewParent,
}
if (mView == null) return;
if (args.localChanges != 0) {
- if (mAttachInfo != null) {
- mAttachInfo.mRecomputeGlobalAttributes = true;
- }
mView.updateLocalSystemUiVisibility(args.localValue, args.localChanges);
- scheduleTraversals();
}
- mView.dispatchSystemUiVisibilityChanged(args.globalVisibility);
+ if (mAttachInfo != null) {
+ int visibility = args.globalVisibility&View.SYSTEM_UI_CLEARABLE_FLAGS;
+ if (visibility != mAttachInfo.mGlobalSystemUiVisibility) {
+ mAttachInfo.mGlobalSystemUiVisibility = visibility;
+ mView.dispatchSystemUiVisibilityChanged(visibility);
+ }
+ }
}
public void handleDispatchDoneAnimating() {
@@ -4481,20 +4481,19 @@ public final class ViewRootImpl implements ViewParent,
final int keyCode = event.getKeyCode();
final int metaState = event.getMetaState();
- KeyEvent fallbackEvent = null;
- synchronized (mFallbackAction) {
- // Check for fallback actions specified by the key character map.
- if (kcm.getFallbackAction(keyCode, metaState, mFallbackAction)) {
- int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
- fallbackEvent = KeyEvent.obtain(
- event.getDownTime(), event.getEventTime(),
- event.getAction(), mFallbackAction.keyCode,
- event.getRepeatCount(), mFallbackAction.metaState,
- event.getDeviceId(), event.getScanCode(),
- flags, event.getSource(), null);
- }
- }
- if (fallbackEvent != null) {
+ // Check for fallback actions specified by the key character map.
+ KeyCharacterMap.FallbackAction fallbackAction =
+ kcm.getFallbackAction(keyCode, metaState);
+ if (fallbackAction != null) {
+ final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
+ KeyEvent fallbackEvent = KeyEvent.obtain(
+ event.getDownTime(), event.getEventTime(),
+ event.getAction(), fallbackAction.keyCode,
+ event.getRepeatCount(), fallbackAction.metaState,
+ event.getDeviceId(), event.getScanCode(),
+ flags, event.getSource(), null);
+ fallbackAction.recycle();
+
dispatchKey(fallbackEvent);
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 6b14ba5..0517d4b 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -205,6 +205,16 @@ public class AccessibilityNodeInfo implements Parcelable {
public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
/**
+ * Action to scroll the node content forward.
+ */
+ public static final int ACTION_SCROLL_FORWARD = 0x00001000;
+
+ /**
+ * Action to scroll the node content backward.
+ */
+ public static final int ACTION_SCROLL_BACKWARD = 0x00002000;
+
+ /**
* Argument for which movement granularity to be used when traversing the node text.
* <p>
* <strong>Type:</strong> int<br>
@@ -569,6 +579,16 @@ public class AccessibilityNodeInfo implements Parcelable {
* @see AccessibilityNodeInfo#ACTION_CLEAR_FOCUS
* @see AccessibilityNodeInfo#ACTION_SELECT
* @see AccessibilityNodeInfo#ACTION_CLEAR_SELECTION
+ * @see AccessibilityNodeInfo#ACTION_ACCESSIBILITY_FOCUS
+ * @see AccessibilityNodeInfo#ACTION_CLEAR_ACCESSIBILITY_FOCUS
+ * @see AccessibilityNodeInfo#ACTION_CLICK
+ * @see AccessibilityNodeInfo#ACTION_LONG_CLICK
+ * @see AccessibilityNodeInfo#ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+ * @see AccessibilityNodeInfo#ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+ * @see AccessibilityNodeInfo#ACTION_NEXT_HTML_ELEMENT
+ * @see AccessibilityNodeInfo#ACTION_PREVIOUS_HTML_ELEMENT
+ * @see AccessibilityNodeInfo#ACTION_SCROLL_FORWARD
+ * @see AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD
*/
public int getActions() {
return mActions;
@@ -1578,6 +1598,10 @@ public class AccessibilityNodeInfo implements Parcelable {
return "ACTION_NEXT_HTML_ELEMENT";
case ACTION_PREVIOUS_HTML_ELEMENT:
return "ACTION_PREVIOUS_HTML_ELEMENT";
+ case ACTION_SCROLL_FORWARD:
+ return "ACTION_SCROLL_FORWARD";
+ case ACTION_SCROLL_BACKWARD:
+ return "ACTION_SCROLL_BACKWARD";
default:
throw new IllegalArgumentException("Unknown action: " + action);
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeProvider.java b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
index a2e0d88..e60716d 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeProvider.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeProvider.java
@@ -151,7 +151,7 @@ public abstract class AccessibilityNodeProvider {
* @see #createAccessibilityNodeInfo(int)
* @see AccessibilityNodeInfo
*/
- public AccessibilityNodeInfo findAccessibilitiyFocus(int virtualViewId) {
+ public AccessibilityNodeInfo findAccessibilityFocus(int virtualViewId) {
return null;
}
diff --git a/core/java/android/webkit/HTML5VideoFullScreen.java b/core/java/android/webkit/HTML5VideoFullScreen.java
index 730ad08..62bc502 100644
--- a/core/java/android/webkit/HTML5VideoFullScreen.java
+++ b/core/java/android/webkit/HTML5VideoFullScreen.java
@@ -104,7 +104,9 @@ public class HTML5VideoFullScreen extends HTML5VideoView
// After we return from this we can't use the surface any more.
// The current Video View will be destroy when we play a new video.
pauseAndDispatch(mProxy);
+ // TODO: handle full screen->inline mode transition without a reload.
mPlayer.release();
+ mPlayer = null;
mSurfaceHolder = null;
if (mMediaController != null) {
mMediaController.hide();
@@ -128,12 +130,12 @@ public class HTML5VideoFullScreen extends HTML5VideoView
return mVideoSurfaceView;
}
- HTML5VideoFullScreen(Context context, int videoLayerId, int position) {
+ HTML5VideoFullScreen(Context context, int videoLayerId, int position, boolean skipPrepare) {
mVideoSurfaceView = new VideoSurfaceView(context);
mFullScreenMode = FULLSCREEN_OFF;
mVideoWidth = 0;
mVideoHeight = 0;
- init(videoLayerId, position);
+ init(videoLayerId, position, skipPrepare);
}
private void setMediaController(MediaController m) {
@@ -156,8 +158,6 @@ public class HTML5VideoFullScreen extends HTML5VideoView
}
private void prepareForFullScreen() {
- // So in full screen, we reset the MediaPlayer
- mPlayer.reset();
MediaController mc = new FullScreenMediaController(mProxy.getContext(), mLayout);
mc.setSystemUiVisibility(mLayout.getSystemUiVisibility());
setMediaController(mc);
@@ -198,6 +198,7 @@ public class HTML5VideoFullScreen extends HTML5VideoView
// after reading the MetaData
if (mMediaController != null) {
mMediaController.setEnabled(true);
+ mMediaController.show();
}
if (mProgressView != null) {
@@ -243,7 +244,7 @@ public class HTML5VideoFullScreen extends HTML5VideoView
// Don't show the controller after exiting the full screen.
mMediaController = null;
- mCurrentState = STATE_RELEASED;
+ mCurrentState = STATE_RESETTED;
}
};
@@ -320,6 +321,13 @@ public class HTML5VideoFullScreen extends HTML5VideoView
return 0;
}
+ @Override
+ public void showControllerInFullScreen() {
+ if (mMediaController != null) {
+ mMediaController.show(0);
+ }
+ }
+
// Other listeners functions:
private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener =
new MediaPlayer.OnBufferingUpdateListener() {
diff --git a/core/java/android/webkit/HTML5VideoInline.java b/core/java/android/webkit/HTML5VideoInline.java
index 62e812e..2c7ea5d 100644
--- a/core/java/android/webkit/HTML5VideoInline.java
+++ b/core/java/android/webkit/HTML5VideoInline.java
@@ -21,7 +21,7 @@ public class HTML5VideoInline extends HTML5VideoView{
// associated with the surface texture can be used for showing the screen
// shot when paused, so they are not singleton.
private static SurfaceTexture mSurfaceTexture = null;
- private int[] mTextureNames;
+ private static int[] mTextureNames = null;
// Every time when the VideoLayer Id change, we need to recreate the
// SurfaceTexture in order to delete the old video's decoder memory.
private static int mVideoLayerUsingSurfaceTexture = -1;
@@ -35,8 +35,7 @@ public class HTML5VideoInline extends HTML5VideoView{
}
HTML5VideoInline(int videoLayerId, int position) {
- init(videoLayerId, position);
- mTextureNames = null;
+ init(videoLayerId, position, false);
}
@Override
@@ -69,15 +68,14 @@ public class HTML5VideoInline extends HTML5VideoView{
// Inline Video specific FUNCTIONS:
- @Override
- public SurfaceTexture getSurfaceTexture(int videoLayerId) {
+ public static SurfaceTexture getSurfaceTexture(int videoLayerId) {
// Create the surface texture.
if (videoLayerId != mVideoLayerUsingSurfaceTexture
|| mSurfaceTexture == null
|| mTextureNames == null) {
- if (mTextureNames != null) {
- GLES20.glDeleteTextures(1, mTextureNames, 0);
- }
+ // The GL texture will store in the VideoLayerManager at native side.
+ // They will be clean up when requested.
+ // The reason we recreated GL texture name is for screen shot support.
mTextureNames = new int[1];
GLES20.glGenTextures(1, mTextureNames, 0);
mSurfaceTexture = new SurfaceTexture(mTextureNames[0]);
diff --git a/core/java/android/webkit/HTML5VideoView.java b/core/java/android/webkit/HTML5VideoView.java
index 0d3b755..371feea 100644
--- a/core/java/android/webkit/HTML5VideoView.java
+++ b/core/java/android/webkit/HTML5VideoView.java
@@ -31,11 +31,10 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
// NOTE: these values are in sync with VideoLayerAndroid.h in webkit side.
// Please keep them in sync when changed.
static final int STATE_INITIALIZED = 0;
- static final int STATE_NOTPREPARED = 1;
+ static final int STATE_PREPARING = 1;
static final int STATE_PREPARED = 2;
static final int STATE_PLAYING = 3;
- static final int STATE_RELEASED = 4;
- protected int mCurrentState;
+ static final int STATE_RESETTED = 4;
protected HTML5VideoViewProxy mProxy;
@@ -46,11 +45,11 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
// This is used to find the VideoLayer on the native side.
protected int mVideoLayerId;
- // Every video will have one MediaPlayer. Given the fact we only have one
- // SurfaceTexture, there is only one MediaPlayer in action. Every time we
- // switch videos, a new instance of MediaPlayer will be created in reset().
- // Switching between inline and full screen will also create a new instance.
- protected MediaPlayer mPlayer;
+ // Given the fact we only have one SurfaceTexture, we cannot support multiple
+ // player at the same time. We may recreate a new one and abandon the old
+ // one at transition time.
+ protected static MediaPlayer mPlayer = null;
+ protected static int mCurrentState = -1;
// We need to save such info.
protected Uri mUri;
@@ -60,10 +59,12 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
// See http://www.whatwg.org/specs/web-apps/current-work/#event-media-timeupdate
protected static Timer mTimer;
+ protected boolean mPauseDuringPreparing;
+
// The spec says the timer should fire every 250 ms or less.
private static final int TIMEUPDATE_PERIOD = 250; // ms
+ private boolean mSkipPrepare = false;
- protected boolean mPauseDuringPreparing;
// common Video control FUNCTIONS:
public void start() {
if (mCurrentState == STATE_PREPARED) {
@@ -83,7 +84,7 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
public void pause() {
if (isPlaying()) {
mPlayer.pause();
- } else if (mCurrentState == STATE_NOTPREPARED) {
+ } else if (mCurrentState == STATE_PREPARING) {
mPauseDuringPreparing = true;
}
// Delete the Timer to stop it since there is no stop call.
@@ -124,11 +125,11 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
}
}
- public void release() {
- if (mCurrentState != STATE_RELEASED) {
- mPlayer.release();
+ public void reset() {
+ if (mCurrentState != STATE_RESETTED) {
+ mPlayer.reset();
}
- mCurrentState = STATE_RELEASED;
+ mCurrentState = STATE_RESETTED;
}
public void stopPlayback() {
@@ -142,9 +143,16 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
}
// Every time we start a new Video, we create a VideoView and a MediaPlayer
- public void init(int videoLayerId, int position) {
- mPlayer = new MediaPlayer();
- mCurrentState = STATE_INITIALIZED;
+ public void init(int videoLayerId, int position, boolean skipPrepare) {
+ if (mPlayer == null) {
+ mPlayer = new MediaPlayer();
+ mCurrentState = STATE_INITIALIZED;
+ }
+ mSkipPrepare = skipPrepare;
+ // If we want to skip the prepare, then we keep the state.
+ if (!mSkipPrepare) {
+ mCurrentState = STATE_INITIALIZED;
+ }
mProxy = null;
mVideoLayerId = videoLayerId;
mSaveSeekTime = position;
@@ -195,17 +203,28 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
}
public void prepareDataCommon(HTML5VideoViewProxy proxy) {
- try {
- mPlayer.setDataSource(proxy.getContext(), mUri, mHeaders);
- mPlayer.prepareAsync();
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- } catch (IllegalStateException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
+ if (!mSkipPrepare) {
+ try {
+ mPlayer.reset();
+ mPlayer.setDataSource(proxy.getContext(), mUri, mHeaders);
+ mPlayer.prepareAsync();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ mCurrentState = STATE_PREPARING;
+ } else {
+ // If we skip prepare and the onPrepared happened in inline mode, we
+ // don't need to call prepare again, we just need to call onPrepared
+ // to refresh the state here.
+ if (mCurrentState >= STATE_PREPARED) {
+ onPrepared(mPlayer);
+ }
+ mSkipPrepare = false;
}
- mCurrentState = STATE_NOTPREPARED;
}
public void reprepareData(HTML5VideoViewProxy proxy) {
@@ -294,10 +313,6 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
return false;
}
- public SurfaceTexture getSurfaceTexture(int videoLayerId) {
- return null;
- }
-
public void deleteSurfaceTexture() {
}
@@ -332,14 +347,17 @@ public class HTML5VideoView implements MediaPlayer.OnPreparedListener {
return false;
}
- private boolean m_startWhenPrepared = false;
+ private boolean mStartWhenPrepared = false;
public void setStartWhenPrepared(boolean willPlay) {
- m_startWhenPrepared = willPlay;
+ mStartWhenPrepared = willPlay;
}
public boolean getStartWhenPrepared() {
- return m_startWhenPrepared;
+ return mStartWhenPrepared;
+ }
+
+ public void showControllerInFullScreen() {
}
}
diff --git a/core/java/android/webkit/HTML5VideoViewProxy.java b/core/java/android/webkit/HTML5VideoViewProxy.java
index 5fa4bad..90db308 100644
--- a/core/java/android/webkit/HTML5VideoViewProxy.java
+++ b/core/java/android/webkit/HTML5VideoViewProxy.java
@@ -112,13 +112,14 @@ class HTML5VideoViewProxy extends Handler
mBaseLayer = layer;
int currentVideoLayerId = mHTML5VideoView.getVideoLayerId();
- SurfaceTexture surfTexture = mHTML5VideoView.getSurfaceTexture(currentVideoLayerId);
+ SurfaceTexture surfTexture =
+ HTML5VideoInline.getSurfaceTexture(currentVideoLayerId);
int textureName = mHTML5VideoView.getTextureName();
if (layer != 0 && surfTexture != null && currentVideoLayerId != -1) {
int playerState = mHTML5VideoView.getCurrentState();
if (mHTML5VideoView.getPlayerBuffering())
- playerState = HTML5VideoView.STATE_NOTPREPARED;
+ playerState = HTML5VideoView.STATE_PREPARING;
boolean foundInTree = nativeSendSurfaceTexture(surfTexture,
layer, currentVideoLayerId, textureName,
playerState);
@@ -145,6 +146,7 @@ class HTML5VideoViewProxy extends Handler
HTML5VideoViewProxy proxy, WebViewClassic webView) {
// Save the inline video info and inherit it in the full screen
int savePosition = 0;
+ boolean canSkipPrepare = false;
if (mHTML5VideoView != null) {
// We don't allow enter full screen mode while the previous
// full screen video hasn't finished yet.
@@ -156,15 +158,20 @@ class HTML5VideoViewProxy extends Handler
// save the current position.
if (layerId == mHTML5VideoView.getVideoLayerId()) {
savePosition = mHTML5VideoView.getCurrentPosition();
+ int playerState = mHTML5VideoView.getCurrentState();
+ canSkipPrepare = (playerState == HTML5VideoView.STATE_PREPARING
+ || playerState == HTML5VideoView.STATE_PREPARED
+ || playerState == HTML5VideoView.STATE_PLAYING)
+ && !mHTML5VideoView.isFullScreenMode();
+ }
+ if (!canSkipPrepare) {
+ mHTML5VideoView.reset();
}
- mHTML5VideoView.release();
}
mHTML5VideoView = new HTML5VideoFullScreen(proxy.getContext(),
- layerId, savePosition);
+ layerId, savePosition, canSkipPrepare);
mCurrentProxy = proxy;
-
mHTML5VideoView.setVideoURI(url, mCurrentProxy);
-
mHTML5VideoView.enterFullScreenVideoState(layerId, proxy, webView);
}
@@ -217,8 +224,7 @@ class HTML5VideoViewProxy extends Handler
if (!backFromFullScreenMode) {
mHTML5VideoView.pauseAndDispatch(mCurrentProxy);
}
- // release the media player to avoid finalize error
- mHTML5VideoView.release();
+ mHTML5VideoView.reset();
}
mCurrentProxy = proxy;
mHTML5VideoView = new HTML5VideoInline(videoLayerId, time);
@@ -273,6 +279,7 @@ class HTML5VideoViewProxy extends Handler
}
public static void end() {
+ mHTML5VideoView.showControllerInFullScreen();
if (mCurrentProxy != null) {
if (isVideoSelfEnded)
mCurrentProxy.dispatchOnEnded();
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 661bbf8..4adfd6a 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -2176,11 +2176,12 @@ public final class WebViewCore {
DrawData mLastDrawData = null;
- private Boolean m_skipDrawFlag = false;
+ private Object m_skipDrawFlagLock = new Object();
+ private boolean m_skipDrawFlag = false;
private boolean m_drawWasSkipped = false;
void pauseWebKitDraw() {
- synchronized (m_skipDrawFlag) {
+ synchronized (m_skipDrawFlagLock) {
if (!m_skipDrawFlag) {
m_skipDrawFlag = true;
}
@@ -2188,7 +2189,7 @@ public final class WebViewCore {
}
void resumeWebKitDraw() {
- synchronized (m_skipDrawFlag) {
+ synchronized (m_skipDrawFlagLock) {
if (m_skipDrawFlag && m_drawWasSkipped) {
// a draw was dropped, send a retry
m_drawWasSkipped = false;
@@ -2199,7 +2200,7 @@ public final class WebViewCore {
}
private void webkitDraw() {
- synchronized (m_skipDrawFlag) {
+ synchronized (m_skipDrawFlagLock) {
if (m_skipDrawFlag) {
m_drawWasSkipped = true;
return;
diff --git a/core/java/android/webkit/WebViewInputDispatcher.java b/core/java/android/webkit/WebViewInputDispatcher.java
index 9541435..9328d8c 100644
--- a/core/java/android/webkit/WebViewInputDispatcher.java
+++ b/core/java/android/webkit/WebViewInputDispatcher.java
@@ -334,6 +334,7 @@ final class WebViewInputDispatcher {
DispatchEvent d = obtainDispatchEventLocked(eventToEnqueue, eventType, 0,
webKitXOffset, webKitYOffset, webKitScale);
+ updateStateTrackersLocked(d, event);
enqueueEventLocked(d);
}
return true;
@@ -787,7 +788,6 @@ final class WebViewInputDispatcher {
flags = d.mFlags;
- updateStateTrackersLocked(d, event);
if (event == d.mEvent) {
d.mEvent = null; // retain ownership of event, don't recycle it yet
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3aafba5..c4e1bf5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1355,6 +1355,33 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(AbsListView.class.getName());
+ if (getFirstVisiblePosition() > 0) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ }
+ if (getLastVisiblePosition() < getCount() - 1) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ }
+ }
+
+ @Override
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ if (getLastVisiblePosition() < getCount() - 1) {
+ final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom;
+ smoothScrollBy(viewportHeight, PositionScroller.SCROLL_DURATION);
+ return true;
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ if (mFirstPosition > 0) {
+ final int viewportHeight = getHeight() - mListPadding.top - mListPadding.bottom;
+ smoothScrollBy(-viewportHeight, PositionScroller.SCROLL_DURATION);
+ return true;
+ }
+ } return false;
+ }
+ return super.performAccessibilityAction(action, arguments);
}
/**
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 1986450..ffabd1d 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.os.Bundle;
import android.util.AttributeSet;
import android.view.FocusFinder;
import android.view.InputDevice;
@@ -737,10 +738,42 @@ public class HorizontalScrollView extends FrameLayout {
}
@Override
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ final int viewportWidth = getWidth() - mPaddingLeft - mPaddingRight;
+ final int targetScrollX = Math.min(mScrollX + viewportWidth, getScrollRange());
+ if (targetScrollX != mScrollX) {
+ smoothScrollTo(targetScrollX, 0);
+ return true;
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ final int viewportWidth = getWidth() - mPaddingLeft - mPaddingRight;
+ final int targetScrollX = Math.max(0, mScrollX - viewportWidth);
+ if (targetScrollX != mScrollX) {
+ smoothScrollTo(targetScrollX, 0);
+ return true;
+ }
+ } return false;
+ }
+ return super.performAccessibilityAction(action, arguments);
+ }
+
+ @Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(HorizontalScrollView.class.getName());
- info.setScrollable(getScrollRange() > 0);
+ final int scrollRange = getScrollRange();
+ if (scrollRange > 0) {
+ info.setScrollable(true);
+ if (mScrollX > 0) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ }
+ if (mScrollX < scrollRange) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ }
+ }
}
@Override
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 11d1ed0..6ff924b 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -133,16 +133,6 @@ public class NumberPicker extends LinearLayout {
private static final int UNSCALED_DEFAULT_SELECTION_DIVIDERS_DISTANCE = 48;
/**
- * The default unscaled minimal distance for a swipe to be considered a fling.
- */
- private static final int UNSCALED_DEFAULT_MIN_FLING_DISTANCE = 150;
-
- /**
- * Coefficient for adjusting touch scroll distance.
- */
- private static final float TOUCH_SCROLL_DECELERATION_COEFFICIENT = 2.0f;
-
- /**
* The resource id for the default layout.
*/
private static final int DEFAULT_LAYOUT_RESOURCE_ID = R.layout.number_picker;
@@ -233,11 +223,6 @@ public class NumberPicker extends LinearLayout {
private final int mTextSize;
/**
- * The minimal distance for a swipe to be considered a fling.
- */
- private final int mMinFlingDistance;
-
- /**
* The height of the gap between text elements if the selector wheel.
*/
private int mSelectorTextGapHeight;
@@ -298,6 +283,11 @@ public class NumberPicker extends LinearLayout {
private final Paint mSelectorWheelPaint;
/**
+ * The {@link Drawable} for pressed virtual (increment/decrement) buttons.
+ */
+ private final Drawable mVirtualButtonPressedDrawable;
+
+ /**
* The height of a selector element (text + gap).
*/
private int mSelectorElementHeight;
@@ -435,11 +425,26 @@ public class NumberPicker extends LinearLayout {
private int mLastHoveredChildVirtualViewId;
/**
+ * Whether the increment virtual button is pressed.
+ */
+ private boolean mIncrementVirtualButtonPressed;
+
+ /**
+ * Whether the decrement virtual button is pressed.
+ */
+ private boolean mDecrementVirtualButtonPressed;
+
+ /**
* Provider to report to clients the semantic structure of this widget.
*/
private AccessibilityNodeProviderImpl mAccessibilityNodeProvider;
/**
+ * Helper class for managing pressed state of the virtual buttons.
+ */
+ private final PressedStateHelper mPressedStateHelper;
+
+ /**
* Interface to listen for changes of the current value.
*/
public interface OnValueChangeListener {
@@ -553,12 +558,6 @@ public class NumberPicker extends LinearLayout {
mSelectionDividersDistance = attributesArray.getDimensionPixelSize(
R.styleable.NumberPicker_selectionDividersDistance, defSelectionDividerDistance);
- final int defMinFlingDistance = (int) TypedValue.applyDimension(
- TypedValue.COMPLEX_UNIT_DIP, UNSCALED_DEFAULT_MIN_FLING_DISTANCE,
- getResources().getDisplayMetrics());
- mMinFlingDistance = attributesArray.getDimensionPixelSize(
- R.styleable.NumberPicker_minFlingDistance, defMinFlingDistance);
-
mMinHeight = attributesArray.getDimensionPixelSize(
R.styleable.NumberPicker_internalMinHeight, SIZE_UNSPECIFIED);
@@ -581,8 +580,13 @@ public class NumberPicker extends LinearLayout {
mComputeMaxWidth = (mMaxWidth == SIZE_UNSPECIFIED);
+ mVirtualButtonPressedDrawable = attributesArray.getDrawable(
+ R.styleable.NumberPicker_virtualButtonPressedDrawable);
+
attributesArray.recycle();
+ mPressedStateHelper = new PressedStateHelper();
+
// By default Linearlayout that we extend is not drawn. This is
// its draw() method is not called but dispatchDraw() is called
// directly (see ViewGroup.drawChild()). However, this class uses
@@ -776,7 +780,19 @@ public class NumberPicker extends LinearLayout {
mLastDownEventTime = event.getEventTime();
mIngonreMoveEvents = false;
mShowSoftInputOnTap = false;
- // Make sure we wupport flinging inside scrollables.
+ // Handle pressed state before any state change.
+ if (mLastDownEventY < mTopSelectionDividerTop) {
+ if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
+ mPressedStateHelper.buttonPressDelayed(
+ PressedStateHelper.BUTTON_DECREMENT);
+ }
+ } else if (mLastDownEventY > mBottomSelectionDividerBottom) {
+ if (mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
+ mPressedStateHelper.buttonPressDelayed(
+ PressedStateHelper.BUTTON_INCREMENT);
+ }
+ }
+ // Make sure we support flinging inside scrollables.
getParent().requestDisallowInterceptTouchEvent(true);
if (!mFlingScroller.isFinished()) {
mFlingScroller.forceFinished(true);
@@ -826,8 +842,7 @@ public class NumberPicker extends LinearLayout {
onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
}
} else {
- int deltaMoveY = (int) ((currentMoveY - mLastDownOrMoveEventY)
- / TOUCH_SCROLL_DECELERATION_COEFFICIENT);
+ int deltaMoveY = (int) ((currentMoveY - mLastDownOrMoveEventY));
scrollBy(0, deltaMoveY);
invalidate();
}
@@ -836,23 +851,12 @@ public class NumberPicker extends LinearLayout {
case MotionEvent.ACTION_UP: {
removeBeginSoftInputCommand();
removeChangeCurrentByOneFromLongPress();
+ mPressedStateHelper.cancel();
VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumFlingVelocity);
int initialVelocity = (int) velocityTracker.getYVelocity();
if (Math.abs(initialVelocity) > mMinimumFlingVelocity) {
- int deltaMove = (int) (event.getY() - mLastDownEventY);
- int absDeltaMoveY = Math.abs(deltaMove);
- if (absDeltaMoveY > mMinFlingDistance) {
- fling(initialVelocity);
- } else {
- final int normalizedDeltaMove =
- (int) (absDeltaMoveY / TOUCH_SCROLL_DECELERATION_COEFFICIENT);
- if (normalizedDeltaMove < mSelectorElementHeight) {
- snapToNextValue(deltaMove < 0);
- } else {
- snapToClosestValue();
- }
- }
+ fling(initialVelocity);
onScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
} else {
int eventY = (int) event.getY();
@@ -867,8 +871,12 @@ public class NumberPicker extends LinearLayout {
- SELECTOR_MIDDLE_ITEM_INDEX;
if (selectorIndexOffset > 0) {
changeValueByOne(true);
+ mPressedStateHelper.buttonTapped(
+ PressedStateHelper.BUTTON_INCREMENT);
} else if (selectorIndexOffset < 0) {
changeValueByOne(false);
+ mPressedStateHelper.buttonTapped(
+ PressedStateHelper.BUTTON_DECREMENT);
}
}
} else {
@@ -1356,6 +1364,22 @@ public class NumberPicker extends LinearLayout {
float x = (mRight - mLeft) / 2;
float y = mCurrentScrollOffset;
+ // draw the virtual buttons pressed state if needed
+ if (mVirtualButtonPressedDrawable != null
+ && mScrollState == OnScrollListener.SCROLL_STATE_IDLE) {
+ if (mDecrementVirtualButtonPressed) {
+ mVirtualButtonPressedDrawable.setState(PRESSED_STATE_SET);
+ mVirtualButtonPressedDrawable.setBounds(0, 0, mRight, mTopSelectionDividerTop);
+ mVirtualButtonPressedDrawable.draw(canvas);
+ }
+ if (mIncrementVirtualButtonPressed) {
+ mVirtualButtonPressedDrawable.setState(PRESSED_STATE_SET);
+ mVirtualButtonPressedDrawable.setBounds(0, mBottomSelectionDividerBottom, mRight,
+ mBottom);
+ mVirtualButtonPressedDrawable.draw(canvas);
+ }
+ }
+
// draw the selector wheel
int[] selectorIndices = mSelectorIndices;
for (int i = 0; i < selectorIndices.length; i++) {
@@ -1465,15 +1489,15 @@ public class NumberPicker extends LinearLayout {
*/
private void initializeSelectorWheelIndices() {
mSelectorIndexToStringCache.clear();
- int[] selectorIdices = mSelectorIndices;
+ int[] selectorIndices = mSelectorIndices;
int current = getValue();
for (int i = 0; i < mSelectorIndices.length; i++) {
int selectorIndex = current + (i - SELECTOR_MIDDLE_ITEM_INDEX);
if (mWrapSelectorWheel) {
selectorIndex = getWrappedSelectorIndex(selectorIndex);
}
- mSelectorIndices[i] = selectorIndex;
- ensureCachedScrollSelectorValue(mSelectorIndices[i]);
+ selectorIndices[i] = selectorIndex;
+ ensureCachedScrollSelectorValue(selectorIndices[i]);
}
}
@@ -1775,6 +1799,7 @@ public class NumberPicker extends LinearLayout {
if (mBeginSoftInputOnLongPressCommand != null) {
removeCallbacks(mBeginSoftInputOnLongPressCommand);
}
+ mPressedStateHelper.cancel();
}
/**
@@ -1910,39 +1935,80 @@ public class NumberPicker extends LinearLayout {
return false;
}
- private void snapToNextValue(boolean increment) {
- int deltaY = mCurrentScrollOffset - mInitialScrollOffset;
- int amountToScroll = 0;
- if (deltaY != 0) {
- mPreviousScrollerY = 0;
- if (deltaY > 0) {
- if (increment) {
- amountToScroll = - deltaY;
- } else {
- amountToScroll = mSelectorElementHeight - deltaY;
- }
- } else {
- if (increment) {
- amountToScroll = - mSelectorElementHeight - deltaY;
- } else {
- amountToScroll = - deltaY;
- }
+ class PressedStateHelper implements Runnable {
+ public static final int BUTTON_INCREMENT = 1;
+ public static final int BUTTON_DECREMENT = 2;
+
+ private final int MODE_PRESS = 1;
+ private final int MODE_TAPPED = 2;
+
+ private int mManagedButton;
+ private int mMode;
+
+ public void cancel() {
+ mMode = 0;
+ mManagedButton = 0;
+ NumberPicker.this.removeCallbacks(this);
+ if (mIncrementVirtualButtonPressed) {
+ mIncrementVirtualButtonPressed = false;
+ invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom);
+ }
+ mDecrementVirtualButtonPressed = false;
+ if (mDecrementVirtualButtonPressed) {
+ invalidate(0, 0, mRight, mTopSelectionDividerTop);
}
- mFlingScroller.startScroll(0, 0, 0, amountToScroll, SNAP_SCROLL_DURATION);
- invalidate();
}
- }
- private void snapToClosestValue() {
- // adjust to the closest value
- int deltaY = mInitialScrollOffset - mCurrentScrollOffset;
- if (deltaY != 0) {
- mPreviousScrollerY = 0;
- if (Math.abs(deltaY) > mSelectorElementHeight / 2) {
- deltaY += (deltaY > 0) ? -mSelectorElementHeight : mSelectorElementHeight;
+ public void buttonPressDelayed(int button) {
+ cancel();
+ mMode = MODE_PRESS;
+ mManagedButton = button;
+ NumberPicker.this.postDelayed(this, ViewConfiguration.getTapTimeout());
+ }
+
+ public void buttonTapped(int button) {
+ cancel();
+ mMode = MODE_TAPPED;
+ mManagedButton = button;
+ NumberPicker.this.post(this);
+ }
+
+ @Override
+ public void run() {
+ switch (mMode) {
+ case MODE_PRESS: {
+ switch (mManagedButton) {
+ case BUTTON_INCREMENT: {
+ mIncrementVirtualButtonPressed = true;
+ invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom);
+ } break;
+ case BUTTON_DECREMENT: {
+ mDecrementVirtualButtonPressed = true;
+ invalidate(0, 0, mRight, mTopSelectionDividerTop);
+ }
+ }
+ } break;
+ case MODE_TAPPED: {
+ switch (mManagedButton) {
+ case BUTTON_INCREMENT: {
+ if (!mIncrementVirtualButtonPressed) {
+ NumberPicker.this.postDelayed(this,
+ ViewConfiguration.getPressedStateDuration());
+ }
+ mIncrementVirtualButtonPressed ^= true;
+ invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom);
+ } break;
+ case BUTTON_DECREMENT: {
+ if (!mDecrementVirtualButtonPressed) {
+ NumberPicker.this.postDelayed(this,
+ ViewConfiguration.getPressedStateDuration());
+ }
+ mDecrementVirtualButtonPressed ^= true;
+ invalidate(0, 0, mRight, mTopSelectionDividerTop);
+ }
+ }
+ } break;
}
- mFlingScroller.startScroll(0, 0, 0, deltaY, SNAP_SCROLL_DURATION);
- invalidate();
}
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index f912c66..b398ce4 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.os.Bundle;
import android.os.StrictMode;
import android.util.AttributeSet;
import android.view.FocusFinder;
@@ -740,10 +741,42 @@ public class ScrollView extends FrameLayout {
}
@Override
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+ final int viewportHeight = getHeight() - mPaddingBottom - mPaddingTop;
+ final int targetScrollY = Math.min(mScrollY + viewportHeight, getScrollRange());
+ if (targetScrollY != mScrollY) {
+ smoothScrollTo(0, targetScrollY);
+ return true;
+ }
+ } return false;
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+ final int viewportHeight = getHeight() - mPaddingBottom - mPaddingTop;
+ final int targetScrollY = Math.max(mScrollY - viewportHeight, 0);
+ if (targetScrollY != mScrollY) {
+ smoothScrollTo(0, targetScrollY);
+ return true;
+ }
+ } return false;
+ }
+ return super.performAccessibilityAction(action, arguments);
+ }
+
+ @Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(ScrollView.class.getName());
- info.setScrollable(getScrollRange() > 0);
+ final int scrollRange = getScrollRange();
+ if (scrollRange > 0) {
+ info.setScrollable(true);
+ if (mScrollY > 0) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
+ }
+ if (mScrollY < scrollRange) {
+ info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ }
+ }
}
@Override
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index ebf8a4a..7ca02e1 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -343,6 +343,36 @@ public class SpellChecker implements SpellCheckerSessionListener {
if (!isInDictionary && looksLikeTypo) {
createMisspelledSuggestionSpan(
editable, suggestionsInfo, spellCheckSpan, offset, length);
+ } else {
+ // Valid word -- isInDictionary || !looksLikeTypo
+ if (mIsSentenceSpellCheckSupported) {
+ // Allow the spell checker to remove existing misspelled span by
+ // overwriting the span over the same place
+ final int spellCheckSpanStart = editable.getSpanStart(spellCheckSpan);
+ final int spellCheckSpanEnd = editable.getSpanEnd(spellCheckSpan);
+ final int start;
+ final int end;
+ if (offset != USE_SPAN_RANGE && length != USE_SPAN_RANGE) {
+ start = spellCheckSpanStart + offset;
+ end = start + length;
+ } else {
+ start = spellCheckSpanStart;
+ end = spellCheckSpanEnd;
+ }
+ if (spellCheckSpanStart >= 0 && spellCheckSpanEnd > spellCheckSpanStart
+ && end > start) {
+ final Long key = Long.valueOf(TextUtils.packRangeInLong(start, end));
+ final SuggestionSpan tempSuggestionSpan = mSuggestionSpanCache.get(key);
+ if (tempSuggestionSpan != null) {
+ if (DBG) {
+ Log.i(TAG, "Remove existing misspelled span. "
+ + editable.subSequence(start, end));
+ }
+ editable.removeSpan(tempSuggestionSpan);
+ mSuggestionSpanCache.remove(key);
+ }
+ }
+ }
}
return spellCheckSpan;
}
@@ -473,8 +503,16 @@ public class SpellChecker implements SpellCheckerSessionListener {
private Object mRange = new Object();
public void parse(int start, int end) {
- if (end > start) {
- setRangeSpan((Editable) mTextView.getText(), start, end);
+ final int max = mTextView.length();
+ final int parseEnd;
+ if (end > max) {
+ Log.w(TAG, "Parse invalid region, from " + start + " to " + end);
+ parseEnd = max;
+ } else {
+ parseEnd = end;
+ }
+ if (parseEnd > start) {
+ setRangeSpan((Editable) mTextView.getText(), start, parseEnd);
parse();
}
}
@@ -612,6 +650,8 @@ public class SpellChecker implements SpellCheckerSessionListener {
break;
}
if (spellCheckEnd <= spellCheckStart) {
+ Log.w(TAG, "Trying to spellcheck invalid region, from "
+ + start + " to " + end);
break;
}
if (createSpellCheckSpan) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 555c974..098a034 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -154,6 +154,7 @@ import java.util.Locale;
* @attr ref android.R.styleable#TextView_textColorLink
* @attr ref android.R.styleable#TextView_textSize
* @attr ref android.R.styleable#TextView_textScaleX
+ * @attr ref android.R.styleable#TextView_fontFamily
* @attr ref android.R.styleable#TextView_typeface
* @attr ref android.R.styleable#TextView_textStyle
* @attr ref android.R.styleable#TextView_cursorVisible
@@ -464,6 +465,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
ColorStateList textColorHint = null;
ColorStateList textColorLink = null;
int textSize = 15;
+ String fontFamily = null;
int typefaceIndex = -1;
int styleIndex = -1;
boolean allCaps = false;
@@ -516,6 +518,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
typefaceIndex = appearance.getInt(attr, -1);
break;
+ case com.android.internal.R.styleable.TextAppearance_fontFamily:
+ fontFamily = appearance.getString(attr);
+ break;
+
case com.android.internal.R.styleable.TextAppearance_textStyle:
styleIndex = appearance.getInt(attr, -1);
break;
@@ -781,6 +787,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
styleIndex = a.getInt(attr, styleIndex);
break;
+ case com.android.internal.R.styleable.TextView_fontFamily:
+ fontFamily = a.getString(attr);
+ break;
+
case com.android.internal.R.styleable.TextView_password:
password = a.getBoolean(attr, password);
break;
@@ -1051,7 +1061,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
typefaceIndex = MONOSPACE;
}
- setTypefaceByIndex(typefaceIndex, styleIndex);
+ setTypefaceFromAttrs(fontFamily, typefaceIndex, styleIndex);
if (shadowcolor != 0) {
setShadowLayer(r, dx, dy, shadowcolor);
@@ -1111,8 +1121,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
- private void setTypefaceByIndex(int typefaceIndex, int styleIndex) {
+ private void setTypefaceFromAttrs(String familyName, int typefaceIndex, int styleIndex) {
Typeface tf = null;
+ if (familyName != null) {
+ tf = Typeface.create(familyName, styleIndex);
+ if (tf != null) {
+ setTypeface(tf);
+ return;
+ }
+ }
switch (typefaceIndex) {
case SANS:
tf = Typeface.SANS_SERIF;
@@ -2160,14 +2177,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
setLinkTextColor(colors);
}
+ String familyName;
int typefaceIndex, styleIndex;
+ familyName = appearance.getString(com.android.internal.R.styleable.
+ TextAppearance_fontFamily);
typefaceIndex = appearance.getInt(com.android.internal.R.styleable.
TextAppearance_typeface, -1);
styleIndex = appearance.getInt(com.android.internal.R.styleable.
TextAppearance_textStyle, -1);
- setTypefaceByIndex(typefaceIndex, styleIndex);
+ setTypefaceFromAttrs(familyName, typefaceIndex, styleIndex);
if (appearance.getBoolean(com.android.internal.R.styleable.TextAppearance_textAllCaps,
false)) {
@@ -2269,6 +2289,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*
* @see #getTypeface()
*
+ * @attr ref android.R.styleable#TextView_fontFamily
* @attr ref android.R.styleable#TextView_typeface
* @attr ref android.R.styleable#TextView_textStyle
*/
@@ -2290,6 +2311,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*
* @see #setTypeface(Typeface)
*
+ * @attr ref android.R.styleable#TextView_fontFamily
* @attr ref android.R.styleable#TextView_typeface
* @attr ref android.R.styleable#TextView_textStyle
*/
@@ -3690,15 +3712,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
boolean forceUpdate = false;
if (isPassword) {
setTransformationMethod(PasswordTransformationMethod.getInstance());
- setTypefaceByIndex(MONOSPACE, 0);
+ setTypefaceFromAttrs(null /* fontFamily */, MONOSPACE, 0);
} else if (isVisiblePassword) {
if (mTransformation == PasswordTransformationMethod.getInstance()) {
forceUpdate = true;
}
- setTypefaceByIndex(MONOSPACE, 0);
+ setTypefaceFromAttrs(null /* fontFamily */, MONOSPACE, 0);
} else if (wasPassword || wasVisiblePassword) {
// not in password mode, clean up typeface and transformation
- setTypefaceByIndex(-1, -1);
+ setTypefaceFromAttrs(null /* fontFamily */, -1, -1);
if (mTransformation == PasswordTransformationMethod.getInstance()) {
forceUpdate = true;
}