Merge "Moving ssl_certificate layout, resources, and helper code to SslCertificate Add IKeyChainService.deleteCaCertificate"
diff --git a/api/current.txt b/api/current.txt
index 0cb32f0..1395ef1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -15279,11 +15279,11 @@
public final class ContactsContract {
ctor public ContactsContract();
+ field public static final java.lang.String ALLOW_PROFILE = "allow_profile";
field public static final java.lang.String AUTHORITY = "com.android.contacts";
field public static final android.net.Uri AUTHORITY_URI;
field public static final java.lang.String CALLER_IS_SYNCADAPTER = "caller_is_syncadapter";
field public static final java.lang.String DIRECTORY_PARAM_KEY = "directory";
- field public static final java.lang.String INCLUDE_PROFILE = "include_profile";
field public static final java.lang.String LIMIT_PARAM_KEY = "limit";
field public static final java.lang.String PRIMARY_ACCOUNT_NAME = "name_for_primary_account";
field public static final java.lang.String PRIMARY_ACCOUNT_TYPE = "type_for_primary_account";
@@ -22847,8 +22847,10 @@
field public static final int TYPE_VIEW_HOVER_ENTER = 128; // 0x80
field public static final int TYPE_VIEW_HOVER_EXIT = 256; // 0x100
field public static final int TYPE_VIEW_LONG_CLICKED = 2; // 0x2
+ field public static final int TYPE_VIEW_SCROLLED = 4096; // 0x1000
field public static final int TYPE_VIEW_SELECTED = 4; // 0x4
field public static final int TYPE_VIEW_TEXT_CHANGED = 16; // 0x10
+ field public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192; // 0x2000
field public static final int TYPE_WINDOW_CONTENT_CHANGED = 2048; // 0x800
field public static final int TYPE_WINDOW_STATE_CHANGED = 32; // 0x20
}
@@ -22897,6 +22899,7 @@
method public boolean isFocused();
method public boolean isLongClickable();
method public boolean isPassword();
+ method public boolean isScrollable();
method public boolean isSelected();
method public static android.view.accessibility.AccessibilityNodeInfo obtain(android.view.View);
method public static android.view.accessibility.AccessibilityNodeInfo obtain();
@@ -22916,6 +22919,7 @@
method public void setPackageName(java.lang.CharSequence);
method public void setParent(android.view.View);
method public void setPassword(boolean);
+ method public void setScrollable(boolean);
method public void setSelected(boolean);
method public void setSource(android.view.View);
method public void setText(java.lang.CharSequence);
@@ -22937,13 +22941,17 @@
method public int getItemCount();
method public android.os.Parcelable getParcelableData();
method public int getRemovedCount();
+ method public int getScrollX();
+ method public int getScrollY();
method public android.view.accessibility.AccessibilityNodeInfo getSource();
method public java.util.List<java.lang.CharSequence> getText();
+ method public int getToIndex();
method public int getWindowId();
method public boolean isChecked();
method public boolean isEnabled();
method public boolean isFullScreen();
method public boolean isPassword();
+ method public boolean isScrollable();
method public static android.view.accessibility.AccessibilityRecord obtain(android.view.accessibility.AccessibilityRecord);
method public static android.view.accessibility.AccessibilityRecord obtain();
method public void recycle();
@@ -22960,7 +22968,11 @@
method public void setParcelableData(android.os.Parcelable);
method public void setPassword(boolean);
method public void setRemovedCount(int);
+ method public void setScrollX(int);
+ method public void setScrollY(int);
+ method public void setScrollable(boolean);
method public void setSource(android.view.View);
+ method public void setToIndex(int);
}
}
diff --git a/cmds/keystore/test-keystore b/cmds/keystore/test-keystore
index 82b276f..3be51b3 100755
--- a/cmds/keystore/test-keystore
+++ b/cmds/keystore/test-keystore
@@ -116,11 +116,12 @@
expect "1 No error"
expect "baz"
- log "system does not have access to read any keys"
+ log "get baz"
keystore system g baz
- expect "6 Permission denied"
-
- log "however, root can read system user keys (as can wifi or vpn users)"
+ expect "1 No error"
+ expect "quux"
+
+ log "root can read system user keys (as can wifi or vpn users)"
keystore root g baz
expect "1 No error"
expect "quux"
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index e927f6c..208869b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1573,7 +1573,7 @@
boolean hardwareAccelerated = sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_hardwareAccelerated,
- false);
+ owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_hasCode,
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 6f92247..a866436 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -53,6 +53,7 @@
private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0);
private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false);
+ private static boolean mLinkUp;
private LinkProperties mLinkProperties;
private LinkCapabilities mLinkCapabilities;
private NetworkInfo mNetworkInfo;
@@ -74,8 +75,25 @@
mTracker = tracker;
}
- public void interfaceLinkStatusChanged(String iface, boolean up) {
- Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
+ public void interfaceStatusChanged(String iface, boolean up) {
+ Log.d(TAG, "Interface status changed: " + iface + (up ? "up" : "down"));
+ }
+
+ public void interfaceLinkStateChanged(String iface, boolean up) {
+ if (mIface.equals(iface) && mLinkUp != up) {
+ Log.d(TAG, "Interface " + iface + " link " + (up ? "up" : "down"));
+ mLinkUp = up;
+
+ // use DHCP
+ if (up) {
+ mTracker.reconnect();
+ } else {
+ NetworkUtils.stopDhcp(mIface);
+ mTracker.mNetworkInfo.setIsAvailable(false);
+ mTracker.mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED,
+ null, null);
+ }
+ }
}
public void interfaceAdded(String iface) {
@@ -91,6 +109,7 @@
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_ETHERNET, 0, NETWORKTYPE, "");
mLinkProperties = new LinkProperties();
mLinkCapabilities = new LinkCapabilities();
+ mLinkUp = false;
mNetworkInfo.setIsAvailable(false);
setTeardownRequested(false);
@@ -182,14 +201,11 @@
// register for notifications from NetworkManagement Service
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
- mInterfaceObserver = new InterfaceObserver(this);
- try {
- service.registerObserver(mInterfaceObserver);
- } catch (RemoteException e) {
- Log.e(TAG, "Could not register InterfaceObserver " + e);
- }
- // connect to an ethernet interface that already exists
+ mInterfaceObserver = new InterfaceObserver(this);
+
+ // enable and try to connect to an ethernet interface that
+ // already exists
sIfaceMatch = context.getResources().getString(
com.android.internal.R.string.config_ethernet_iface_regex);
try {
@@ -197,6 +213,8 @@
for (String iface : ifaces) {
if (iface.matches(sIfaceMatch)) {
mIface = iface;
+ InterfaceConfiguration config = service.getInterfaceConfig(iface);
+ mLinkUp = config.isActive();
reconnect();
break;
}
@@ -204,6 +222,12 @@
} catch (RemoteException e) {
Log.e(TAG, "Could not get list of interfaces " + e);
}
+
+ try {
+ service.registerObserver(mInterfaceObserver);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not register InterfaceObserver " + e);
+ }
}
/**
diff --git a/core/java/android/net/INetworkManagementEventObserver.aidl b/core/java/android/net/INetworkManagementEventObserver.aidl
index d30b63d..4436e6e 100644
--- a/core/java/android/net/INetworkManagementEventObserver.aidl
+++ b/core/java/android/net/INetworkManagementEventObserver.aidl
@@ -23,12 +23,21 @@
*/
interface INetworkManagementEventObserver {
/**
- * Interface link status has changed.
+ * Interface configuration status has changed.
*
* @param iface The interface.
- * @param link True if link is up.
+ * @param up True if the interface has been enabled.
*/
- void interfaceLinkStatusChanged(String iface, boolean link);
+ void interfaceStatusChanged(String iface, boolean up);
+
+ /**
+ * Interface physical-layer link state has changed. For Ethernet,
+ * this method is invoked when the cable is plugged in or unplugged.
+ *
+ * @param iface The interface.
+ * @param up True if the physical link-layer connection signal is valid.
+ */
+ void interfaceLinkStateChanged(String iface, boolean up);
/**
* An interface has been added to the system
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 1b28aa2..6c7c58d 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -278,6 +278,16 @@
/**
* Current version under development.
+ *
+ * <p>Applications targeting this or a later release will get these
+ * new changes in behavior:</p>
+ * <ul>
+ * <li> 2d drawing hardware acceleration is now turned on by default.
+ * You can use
+ * {@link android.R.attr#hardwareAccelerated android:hardwareAccelerated}
+ * to turn it off if needed, although this is strongly discouraged since
+ * it will result in poor performance on larger screen devices.
+ * </ul>
*/
public static final int ICE_CREAM_SANDWICH = CUR_DEVELOPMENT;
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a17983a..21373ec 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -313,8 +313,8 @@
*/
public void release(int flags) {
synchronized (mToken) {
- mHandler.removeCallbacks(mReleaser);
if (!mRefCounted || --mCount == 0) {
+ mHandler.removeCallbacks(mReleaser);
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
diff --git a/core/java/android/pim/EventRecurrence.java b/core/java/android/pim/EventRecurrence.java
index cde7dac..830f63f 100644
--- a/core/java/android/pim/EventRecurrence.java
+++ b/core/java/android/pim/EventRecurrence.java
@@ -456,6 +456,19 @@
return true;
}
+ /**
+ * Determines whether this rule specifies a simple monthly rule by weekday, such as
+ * "FREQ=MONTHLY;BYDAY=3TU" (the 3rd Tuesday of every month).
+ * <p>
+ * Negative days, e.g. "FREQ=MONTHLY;BYDAY=-1TU" (the last Tuesday of every month),
+ * will cause "false" to be returned.
+ * <p>
+ * Rules that fire every week, such as "FREQ=MONTHLY;BYDAY=TU" (every Tuesday of every
+ * month) will cause "false" to be returned. (Note these are usually expressed as
+ * WEEKLY rules, and hence are uncommon.)
+ *
+ * @return true if this rule is of the appropriate form
+ */
public boolean repeatsMonthlyOnDayCount() {
if (this.freq != MONTHLY) {
return false;
@@ -465,6 +478,10 @@
return false;
}
+ if (bydayNum[0] <= 0) {
+ return false;
+ }
+
return true;
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b5a11ab..cb96bfd2 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -123,14 +123,16 @@
/**
* An optional URI parameter for selection queries that instructs the
- * provider to include the user's personal profile contact entry (if any)
- * in the contact results. If present, the user's profile will always be
- * the first entry returned. The default value is false.
+ * provider to allow the user's personal profile contact entry (if any)
+ * to appear in a list of contact results. It is only useful when issuing
+ * a query that may retrieve more than one contact. If present, the user's
+ * profile will always be the first entry returned. The default value is
+ * false.
*
* Specifying this parameter will result in a security error if the calling
* application does not have android.permission.READ_PROFILE permission.
*/
- public static final String INCLUDE_PROFILE = "include_profile";
+ public static final String ALLOW_PROFILE = "allow_profile";
/**
* A query parameter key used to specify the package that is requesting a query.
diff --git a/core/java/android/provider/SyncConstValue.java b/core/java/android/provider/SyncConstValue.java
index 2fcf315..027aed1 100644
--- a/core/java/android/provider/SyncConstValue.java
+++ b/core/java/android/provider/SyncConstValue.java
@@ -18,7 +18,7 @@
/**
* Columns for tables that are synced to a server.
- * @deprecated
+ * @deprecated Do not use.
* @hide
*/
public interface SyncConstValue
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 5dbda90..6c3d387 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -2361,11 +2361,11 @@
* Gets the {@link KeyCharacterMap} associated with the keyboard device.
*
* @return The associated key character map.
- * @throws {@link UnavailableException} if the key character map
+ * @throws {@link KeyCharacterMap.UnavailableException} if the key character map
* could not be loaded because it was malformed or the default key character map
* is missing from the system.
*
- * @see {@link KeyCharacterMap#load}
+ * @see KeyCharacterMap#load
*/
public final KeyCharacterMap getKeyCharacterMap() {
return KeyCharacterMap.load(mDeviceId);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 7e75c4e..5743134 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2326,6 +2326,7 @@
private CheckForLongPress mPendingCheckForLongPress;
private CheckForTap mPendingCheckForTap = null;
private PerformClick mPerformClick;
+ private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
private UnsetPressedState mUnsetPressedState;
@@ -3699,7 +3700,6 @@
* @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
*/
public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
-
}
/**
@@ -3728,12 +3728,23 @@
event.setEnabled(isEnabled());
event.setContentDescription(mContentDescription);
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
- ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
- getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
- event.setItemCount(focusablesTempList.size());
- event.setCurrentItemIndex(focusablesTempList.indexOf(this));
- focusablesTempList.clear();
+ final int eventType = event.getEventType();
+ switch (eventType) {
+ case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
+ if (mAttachInfo != null) {
+ ArrayList<View> focusablesTempList = mAttachInfo.mFocusablesTempList;
+ getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
+ FOCUSABLES_ALL);
+ event.setItemCount(focusablesTempList.size());
+ event.setCurrentItemIndex(focusablesTempList.indexOf(this));
+ focusablesTempList.clear();
+ }
+ } break;
+ case AccessibilityEvent.TYPE_VIEW_SCROLLED: {
+ event.setScrollX(mScrollX);
+ event.setScrollY(mScrollY);
+ event.setItemCount(getHeight());
+ } break;
}
}
@@ -6165,6 +6176,16 @@
}
/**
+ * Remove the pending callback for sending a
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
+ */
+ private void removeSendViewScrolledAccessibilityEventCallback() {
+ if (mSendViewScrolledAccessibilityEvent != null) {
+ removeCallbacks(mSendViewScrolledAccessibilityEvent);
+ }
+ }
+
+ /**
* Sets the TouchDelegate for this View.
*/
public void setTouchDelegate(TouchDelegate delegate) {
@@ -6337,6 +6358,10 @@
* @param oldt Previous vertical scroll origin.
*/
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ postSendViewScrolledAccessibilityEventCallback();
+ }
+
mBackgroundSizeChanged = true;
final AttachInfo ai = mAttachInfo;
@@ -8263,6 +8288,22 @@
}
/**
+ * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
+ * This event is sent at most once every
+ * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
+ */
+ private void postSendViewScrolledAccessibilityEventCallback() {
+ if (mSendViewScrolledAccessibilityEvent == null) {
+ mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
+ }
+ if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
+ mSendViewScrolledAccessibilityEvent.mIsPending = true;
+ postDelayed(mSendViewScrolledAccessibilityEvent,
+ ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
+ }
+ }
+
+ /**
* Called by a parent to request that a child update its values for mScrollX
* and mScrollY if necessary. This will typically be done if the child is
* animating a scroll using a {@link android.widget.Scroller Scroller}
@@ -9019,6 +9060,7 @@
removeUnsetPressCallback();
removeLongPressCallback();
removePerformClickCallback();
+ removeSendViewScrolledAccessibilityEventCallback();
destroyDrawingCache();
@@ -13820,6 +13862,18 @@
host.invalidate(true);
}
}
+ }
+ /**
+ * Resuable callback for sending
+ * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
+ */
+ private class SendViewScrolledAccessibilityEvent implements Runnable {
+ public volatile boolean mIsPending;
+
+ public void run() {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
+ mIsPending = false;
+ }
}
}
diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewAncestor.java
index e5d6d9f..2b692f3 100644
--- a/core/java/android/view/ViewAncestor.java
+++ b/core/java/android/view/ViewAncestor.java
@@ -136,13 +136,6 @@
static final ArrayList<ComponentCallbacks> sConfigCallbacks
= new ArrayList<ComponentCallbacks>();
- /**
- * Delay before dispatching an accessibility event that the window
- * content has changed. The window content is considered changed
- * after a layout pass.
- */
- private static final long SEND_WINDOW_CONTENT_CHANGED_DELAY_MILLIS = 500;
-
long mLastTrackballTime = 0;
final TrackballAxis mTrackballAxisX = new TrackballAxis();
final TrackballAxis mTrackballAxisY = new TrackballAxis();
@@ -284,7 +277,7 @@
AccessibilityInteractionConnectionManager mAccessibilityInteractionConnectionManager;
- SendWindowContentChanged mSendWindowContentChanged;
+ SendWindowContentChangedAccessibilityEvent mSendWindowContentChangedAccessibilityEvent;
private final int mDensity;
@@ -3692,14 +3685,19 @@
/**
* Post a callback to send a
* {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
+ * This event is send at most once every
+ * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
*/
private void postSendWindowContentChangedCallback() {
- if (mSendWindowContentChanged == null) {
- mSendWindowContentChanged = new SendWindowContentChanged();
- } else {
- removeCallbacks(mSendWindowContentChanged);
+ if (mSendWindowContentChangedAccessibilityEvent == null) {
+ mSendWindowContentChangedAccessibilityEvent =
+ new SendWindowContentChangedAccessibilityEvent();
}
- postDelayed(mSendWindowContentChanged, SEND_WINDOW_CONTENT_CHANGED_DELAY_MILLIS);
+ if (!mSendWindowContentChangedAccessibilityEvent.mIsPending) {
+ mSendWindowContentChangedAccessibilityEvent.mIsPending = true;
+ postDelayed(mSendWindowContentChangedAccessibilityEvent,
+ ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
+ }
}
/**
@@ -3707,8 +3705,8 @@
* {@link AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED} event.
*/
private void removeSendWindowContentChangedCallback() {
- if (mSendWindowContentChanged != null) {
- removeCallbacks(mSendWindowContentChanged);
+ if (mSendWindowContentChangedAccessibilityEvent != null) {
+ removeCallbacks(mSendWindowContentChangedAccessibilityEvent);
}
}
@@ -4634,10 +4632,19 @@
}
}
- private class SendWindowContentChanged implements Runnable {
+ private class SendWindowContentChangedAccessibilityEvent implements Runnable {
+ public volatile boolean mIsPending;
+
public void run() {
if (mView != null) {
- mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ // Send the event directly since we do not want to append the
+ // source text because this is the text for the entire window
+ // and we just want to notify that the content has changed.
+ AccessibilityEvent event = AccessibilityEvent.obtain(
+ AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ mView.onInitializeAccessibilityEvent(event);
+ AccessibilityManager.getInstance(mView.mContext).sendAccessibilityEvent(event);
+ mIsPending = false;
}
}
}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 5919150..f3a5050 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -176,6 +176,14 @@
private static final int TOUCH_EXPLORATION_TAP_SLOP = 80;
/**
+ * Delay before dispatching a recurring accessibility event in milliseconds.
+ * This delay guarantees that a recurring event will be send at most once
+ * during the {@link #SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS} time
+ * frame.
+ */
+ private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 400;
+
+ /**
* The maximum size of View's drawing cache, expressed in bytes. This size
* should be at least equal to the size of the screen in ARGB888 format.
*/
@@ -498,6 +506,19 @@
}
/**
+ * Interval for dispatching a recurring accessibility event in milliseconds.
+ * This interval guarantees that a recurring event will be send at most once
+ * during the {@link #getSendRecurringAccessibilityEventsInterval()} time frame.
+ *
+ * @return The delay in milliseconds.
+ *
+ * @hide
+ */
+ public static long getSendRecurringAccessibilityEventsInterval() {
+ return SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS;
+ }
+
+ /**
* @return Distance a touch must be outside the bounds of a window for it
* to be counted as outside the window for purposes of dismissing that
* window.
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 30d6489..25f01a7 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -56,76 +56,132 @@
* <b>View clicked</b> - represents the event of clicking on a {@link android.view.View}
* like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br>
* Type:{@link #TYPE_VIEW_CLICKED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * Properties:</br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * </ul>
* <p>
* <b>View long clicked</b> - represents the event of long clicking on a {@link android.view.View}
* like {@link android.widget.Button}, {@link android.widget.CompoundButton}, etc. <br>
* Type:{@link #TYPE_VIEW_LONG_CLICKED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * Properties:</br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * </ul>
* <p>
* <b>View selected</b> - represents the event of selecting an item usually in
* the context of an {@link android.widget.AdapterView}. <br>
* Type: {@link #TYPE_VIEW_SELECTED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * Properties:</br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * <li>{@link #getItemCount()} -The number of selectable items of the source.</li>
+ * <li>{@link #getCurrentItemIndex()} - The currently selected item index.</li>
+ * </ul>
+ * <p>
* <p>
* <b>View focused</b> - represents the event of focusing a
* {@link android.view.View}. <br>
* Type: {@link #TYPE_VIEW_FOCUSED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()}
+ * Properties:</br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * <li>{@link #getItemCount()} -The number of focusable items on the screen.</li>
+ * <li>{@link #getCurrentItemIndex()} - The currently focused item index.</li>
+ * </ul>
* <p>
* <b>View text changed</b> - represents the event of changing the text of an
* {@link android.widget.EditText}. <br>
* Type: {@link #TYPE_VIEW_TEXT_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()},
- * {@link #isChecked()},
- * {@link #isEnabled()},
- * {@link #isPassword()},
- * {@link #getItemCount()},
- * {@link #getCurrentItemIndex()},
- * {@link #getFromIndex()},
- * {@link #getAddedCount()},
- * {@link #getRemovedCount()},
- * {@link #getBeforeText()}
+ * Properties:</br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #isChecked()} - Whether the source is checked.</li>
+ * <li>{@link #getFromIndex()} - The text change start index.</li>
+ * <li>{@link #getAddedCount()} - The number of added characters.</li>
+ * <li>{@link #getRemovedCount()} - The number of removed characters.</li>
+ * <li>{@link #getBeforeText()} - The text of the source before the change.</li>
+ * </ul>
+ * <p>
+ * <b>View text selection changed</b> - represents the event of changing the text
+ * selection of an {@link android.widget.EditText}.<br>
+ * Type: {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} <br>
+ * Properties:</br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #isPassword()} - Whether the source is password.</li>
+ * <li>{@link #getFromIndex()} - The selection start index.</li>
+ * <li>{@link #getToIndex()} - The selection end index.</li>
+ * <li>{@link #getItemCount()} - The length of the source text.</li>
+ * <ul>
+ * <p>
+ * <b>View scrolled</b> - represents the event of scrolling a view. If
+ * the source is a descendant of {@link android.widget.AdapterView} the
+ * scroll is reported in terms of visible items - the first visible item,
+ * the last visible item, and the total items - because the the source
+ * is unaware if its pixel size since its adapter is responsible for
+ * creating views. In all other cases the scroll is reported as the current
+ * scroll on the X and Y axis respectively plus the height of the source in
+ * pixels.<br>
+ * Type: {@link #TYPE_VIEW_SCROLLED} <br>
+ * Properties:</br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #getScrollX()} - The horizontal offset of the source
+ * (without descendants of AdapterView)).</li>
+ * <li>{@link #getScrollY()} - The vertical offset of the source
+ * (without descendants of AdapterView)).</li>
+ * <li>{@link #getFromIndex()} - The index of the first visible item of the source
+ * (for descendants of AdapterView).</li>
+ * <li>{@link #getToIndex()} - The index of the last visible item of the source
+ * (for descendants of AdapterView).</li>
+ * <li>{@link #getItemCount()} - The total items of the source (for descendants of AdapterView)
+ * or the height of the source in pixels (all other cases).</li>
+ * <ul>
* <p>
* <b>TRANSITION TYPES</b> <br>
* <p>
@@ -133,33 +189,40 @@
* {@link android.widget.PopupWindow}, {@link android.view.Menu},
* {@link android.app.Dialog}, etc. <br>
* Type: {@link #TYPE_WINDOW_STATE_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
+ * Properties:</br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * </ul>
* <p>
* <b>Window content changed</b> - represents the event of change in the
* content of a window. This change can be adding/removing view, changing
* a view size, etc.<br>
* Type: {@link #TYPE_WINDOW_CONTENT_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
+ * Properties:</br>
+ * <ul>
+ * <li>{@link #getSource()} - The source info (for registered clients).</li> *
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <ul>
* <p>
* <b>NOTIFICATION TYPES</b> <br>
* <p>
* <b>Notification state changed</b> - represents the event showing/hiding
* {@link android.app.Notification}.
* Type: {@link #TYPE_NOTIFICATION_STATE_CHANGED} <br>
- * Properties:
- * {@link #getClassName()},
- * {@link #getPackageName()},
- * {@link #getEventTime()},
- * {@link #getText()}
- * {@link #getParcelableData()}
+ * Properties:</br>
+ * <ul>
+ * <li>{@link #getClassName()} - The class name of the source.</li>
+ * <li>{@link #getPackageName()} - The package name of the source.</li>
+ * <li>{@link #getEventTime()} - The event time.</li>
+ * <li>{@link #getText()} - The text of the source.</li>
+ * <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li>
+ * </ul>
* <p>
* <b>Security note</b>
* <p>
@@ -258,6 +321,16 @@
public static final int TYPE_WINDOW_CONTENT_CHANGED = 0x00000800;
/**
+ * Represents the event of scrolling a view.
+ */
+ public static final int TYPE_VIEW_SCROLLED = 0x00001000;
+
+ /**
+ * Represents the event of changing the selection in an {@link android.widget.EditText}.
+ */
+ public static final int TYPE_VIEW_TEXT_SELECTION_CHANGED = 0x00002000;
+
+ /**
* Mask for {@link AccessibilityEvent} all types.
*
* @see #TYPE_VIEW_CLICKED
@@ -564,6 +637,9 @@
record.mCurrentItemIndex = parcel.readInt();
record.mItemCount = parcel.readInt();
record.mFromIndex = parcel.readInt();
+ record.mToIndex = parcel.readInt();
+ record.mScrollX = parcel.readInt();
+ record.mScrollY = parcel.readInt();
record.mAddedCount = parcel.readInt();
record.mRemovedCount = parcel.readInt();
record.mClassName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
@@ -613,6 +689,9 @@
parcel.writeInt(record.mCurrentItemIndex);
parcel.writeInt(record.mItemCount);
parcel.writeInt(record.mFromIndex);
+ parcel.writeInt(record.mToIndex);
+ parcel.writeInt(record.mScrollX);
+ parcel.writeInt(record.mScrollY);
parcel.writeInt(record.mAddedCount);
parcel.writeInt(record.mRemovedCount);
TextUtils.writeToParcel(record.mClassName, parcel, flags);
@@ -657,8 +736,12 @@
builder.append("; IsPassword: " + record.isPassword());
builder.append("; IsChecked: " + record.isChecked());
builder.append("; IsFullScreen: " + record.isFullScreen());
+ builder.append("; Scrollable: " + record.isScrollable());
builder.append("; BeforeText: " + record.mBeforeText);
builder.append("; FromIndex: " + record.mFromIndex);
+ builder.append("; ToIndex: " + record.mToIndex);
+ builder.append("; ScrollX: " + record.mScrollX);
+ builder.append("; ScrollY: " + record.mScrollY);
builder.append("; AddedCount: " + record.mAddedCount);
builder.append("; RemovedCount: " + record.mRemovedCount);
builder.append("; ParcelableData: " + record.mParcelableData);
@@ -704,6 +787,10 @@
return "TYPE_TOUCH_EXPLORATION_GESTURE_END";
case TYPE_WINDOW_CONTENT_CHANGED:
return "TYPE_WINDOW_CONTENT_CHANGED";
+ case TYPE_VIEW_TEXT_SELECTION_CHANGED:
+ return "TYPE_VIEW_TEXT_SELECTION_CHANGED";
+ case TYPE_VIEW_SCROLLED:
+ return "TYPE_VIEW_SCROLLED";
default:
return null;
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 555667b..dbbe7be 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -83,6 +83,8 @@
private static final int PROPERTY_PASSWORD = 0x00000100;
+ private static final int PROPERTY_SCROLLABLE = 0x00000200;
+
// Readable representations - lazily initialized.
private static SparseArray<String> sActionSymbolicNames;
@@ -570,6 +572,27 @@
}
/**
+ * Gets if the node is scrollable.
+ *
+ * @return True if the node is scrollable, false otherwise.
+ */
+ public boolean isScrollable() {
+ return getBooleanProperty(PROPERTY_SCROLLABLE);
+ }
+
+ /**
+ * Sets if the node is scrollable.
+ *
+ * @param scrollable True if the node is scrollable, false otherwise.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setScrollable(boolean scrollable) {
+ enforceNotSealed();
+ setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
+ }
+
+ /**
* Gets the package this node comes from.
*
* @return The package name.
@@ -1017,6 +1040,7 @@
builder.append("; longClickable: ").append(isLongClickable());
builder.append("; enabled: ").append(isEnabled());
builder.append("; password: ").append(isPassword());
+ builder.append("; scrollable: " + isScrollable());
builder.append("; [");
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index 9c495e21..b9815c5 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -40,6 +40,7 @@
private static final int PROPERTY_ENABLED = 0x00000002;
private static final int PROPERTY_PASSWORD = 0x00000004;
private static final int PROPERTY_FULL_SCREEN = 0x00000080;
+ private static final int PROPERTY_SCROLLABLE = 0x00000100;
// Housekeeping
private static final int MAX_POOL_SIZE = 10;
@@ -54,6 +55,10 @@
int mCurrentItemIndex;
int mItemCount;
int mFromIndex;
+ int mToIndex;
+ int mScrollX;
+ int mScrollY;
+
int mAddedCount;
int mRemovedCount;
int mSourceViewId = View.NO_ID;
@@ -71,7 +76,6 @@
* Hide constructor.
*/
AccessibilityRecord() {
-
}
/**
@@ -85,6 +89,9 @@
mCurrentItemIndex = record.mCurrentItemIndex;
mItemCount = record.mItemCount;
mFromIndex = record.mFromIndex;
+ mToIndex = record.mToIndex;
+ mScrollX = record.mScrollX;
+ mScrollY = record.mScrollY;
mAddedCount = record.mAddedCount;
mRemovedCount = record.mRemovedCount;
mClassName = record.mClassName;
@@ -246,6 +253,27 @@
}
/**
+ * Gets if the source is scrollable.
+ *
+ * @return True if the source is scrollable, false otherwise.
+ */
+ public boolean isScrollable() {
+ return getBooleanProperty(PROPERTY_SCROLLABLE);
+ }
+
+ /**
+ * Sets if the source is scrollable.
+ *
+ * @param scrollable True if the source is scrollable, false otherwise.
+ *
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setScrollable(boolean scrollable) {
+ enforceNotSealed();
+ setBooleanProperty(PROPERTY_SCROLLABLE, scrollable);
+ }
+
+ /**
* Gets the number of items that can be visited.
*
* @return The number of items.
@@ -288,18 +316,24 @@
}
/**
- * Gets the index of the first character of the changed sequence.
+ * Gets the index of the first character of the changed sequence,
+ * or the beginning of a text selection or the index of the first
+ * visible item when scrolling.
*
- * @return The index of the first character.
+ * @return The index of the first character or selection
+ * start or the first visible item.
*/
public int getFromIndex() {
return mFromIndex;
}
/**
- * Sets the index of the first character of the changed sequence.
+ * Sets the index of the first character of the changed sequence
+ * or the beginning of a text selection or the index of the first
+ * visible item when scrolling.
*
- * @param fromIndex The index of the first character.
+ * @param fromIndex The index of the first character or selection
+ * start or the first visible item.
*
* @throws IllegalStateException If called from an AccessibilityService.
*/
@@ -309,6 +343,65 @@
}
/**
+ * Gets the index of text selection end or the index of the last
+ * visible item when scrolling.
+ *
+ * @return The index of selection end or last item index.
+ */
+ public int getToIndex() {
+ return mToIndex;
+ }
+
+ /**
+ * Sets the index of text selection end or the index of the last
+ * visible item when scrolling.
+ *
+ * @param toIndex The index of selection end or last item index.
+ */
+ public void setToIndex(int toIndex) {
+ enforceNotSealed();
+ mToIndex = toIndex;
+ }
+
+ /**
+ * Gets the scroll position of the source along the X axis.
+ *
+ * @return The scroll along the X axis.
+ */
+ public int getScrollX() {
+ return mScrollX;
+ }
+
+ /**
+ * Sets the scroll position of the source along the X axis.
+ *
+ * @param scrollX The scroll along the X axis.
+ */
+ public void setScrollX(int scrollX) {
+ enforceNotSealed();
+ mScrollX = scrollX;
+ }
+
+ /**
+ * Gets the scroll position of the source along the Y axis.
+ *
+ * @return The scroll along the Y axis.
+ */
+ public int getScrollY() {
+ return mScrollY;
+ }
+
+ /**
+ * Sets the scroll position of the source along the Y axis.
+ *
+ * @param scrollY The scroll along the Y axis.
+ */
+ public void setScrollY(int scrollY) {
+ enforceNotSealed();
+ mScrollY = scrollY;
+ }
+
+ /**
* Gets the number of added characters.
*
* @return The number of added characters.
@@ -576,6 +669,9 @@
mCurrentItemIndex = INVALID_POSITION;
mItemCount = 0;
mFromIndex = 0;
+ mToIndex = 0;
+ mScrollX = 0;
+ mScrollY = 0;
mAddedCount = 0;
mRemovedCount = 0;
mClassName = null;
@@ -599,8 +695,12 @@
builder.append("; IsPassword: " + getBooleanProperty(PROPERTY_PASSWORD));
builder.append("; IsChecked: " + getBooleanProperty(PROPERTY_CHECKED));
builder.append("; IsFullScreen: " + getBooleanProperty(PROPERTY_FULL_SCREEN));
+ builder.append("; Scrollable: " + getBooleanProperty(PROPERTY_SCROLLABLE));
builder.append("; BeforeText: " + mBeforeText);
builder.append("; FromIndex: " + mFromIndex);
+ builder.append("; ToIndex: " + mToIndex);
+ builder.append("; ScrollX: " + mScrollX);
+ builder.append("; ScrollY: " + mScrollY);
builder.append("; AddedCount: " + mAddedCount);
builder.append("; RemovedCount: " + mRemovedCount);
builder.append("; ParcelableData: " + mParcelableData);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3fe8149..1449b18 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -55,6 +55,8 @@
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
@@ -1257,6 +1259,33 @@
onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
}
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setScrollable(true);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setScrollable(true);
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ event.setFromIndex(mFirstPosition);
+ event.setToIndex(mFirstPosition + getChildCount());
+ event.setItemCount(mItemCount);
+ }
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ // Do not append text content to scroll events they are fired frequently
+ // and the client has already received another event type with the text.
+ if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ super.dispatchPopulateAccessibilityEvent(event);
+ }
+ return false;
+ }
+
/**
* Indicates whether the children's drawing cache is used during a scroll.
* By default, the drawing cache is enabled but this will consume more memory.
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index ce76bee..0ffd087 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -34,6 +34,8 @@
import android.view.ViewGroup;
import android.view.SoundEffectConstants;
import android.view.ContextMenu.ContextMenuInfo;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.Transformation;
/**
@@ -344,7 +346,34 @@
int getChildHeight(View child) {
return child.getMeasuredHeight();
}
-
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setScrollable(true);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setScrollable(true);
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ event.setFromIndex(mFirstPosition);
+ event.setToIndex(mFirstPosition + getChildCount());
+ event.setItemCount(mItemCount);
+ }
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ // Do not append text content to scroll events they are fired frequently
+ // and the client has already received another event type with the text.
+ if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ super.dispatchPopulateAccessibilityEvent(event);
+ }
+ return false;
+ }
+
/**
* Tracks a motion scroll. In reality, this is used to do just about any
* movement to items (touch scroll, arrow-key scroll, set an item as selected).
@@ -382,7 +411,9 @@
mRecycler.clear();
setSelectionToCenterChild();
-
+
+ onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
+
invalidate();
}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 17b3bda..7c9be1e 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -35,6 +35,8 @@
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import java.util.List;
@@ -692,6 +694,28 @@
awakenScrollBars();
}
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setScrollable(true);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setScrollable(true);
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ // Do not append text content to scroll events they are fired frequently
+ // and the client has already received another event type with the text.
+ if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ super.dispatchPopulateAccessibilityEvent(event);
+ }
+ return false;
+ }
+
private int getScrollRange() {
int scrollRange = 0;
if (getChildCount() > 0) {
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 27edb88..12775a4 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -36,6 +36,8 @@
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewParent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import java.util.List;
@@ -690,6 +692,28 @@
awakenScrollBars();
}
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.setScrollable(true);
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ event.setScrollable(true);
+ }
+
+ @Override
+ public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
+ // Do not append text content to scroll events they are fired frequently
+ // and the client has already received another event type with the text.
+ if (event.getEventType() != AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ super.dispatchPopulateAccessibilityEvent(event);
+ }
+ return false;
+ }
+
private int getScrollRange() {
int scrollRange = 0;
if (getChildCount() > 0) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 17aea8b..85e7eec 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6834,9 +6834,9 @@
* @param selEnd The new selection end location.
*/
protected void onSelectionChanged(int selStart, int selEnd) {
- // intentionally empty
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
}
-
+
/**
* Adds a TextWatcher to the list of those whose methods are called
* whenever this TextView's text changes.
@@ -7922,6 +7922,12 @@
final boolean isPassword = hasPasswordTransformationMethod();
event.setPassword(isPassword);
+
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED) {
+ event.setFromIndex(Selection.getSelectionStart(mText));
+ event.setToIndex(Selection.getSelectionEnd(mText));
+ event.setItemCount(mText.length());
+ }
}
@Override
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 1b22e2d..18bd754 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -273,7 +273,8 @@
// These must match the int values in Bitmap.java
enum JavaEncodeFormat {
kJPEG_JavaEncodeFormat = 0,
- kPNG_JavaEncodeFormat = 1
+ kPNG_JavaEncodeFormat = 1,
+ kWEBP_JavaEncodeFormat = 2
};
static bool Bitmap_compress(JNIEnv* env, jobject clazz, SkBitmap* bitmap,
@@ -288,6 +289,9 @@
case kPNG_JavaEncodeFormat:
fm = SkImageEncoder::kPNG_Type;
break;
+ case kWEBP_JavaEncodeFormat:
+ fm = SkImageEncoder::kWEBP_Type;
+ break;
default:
return false;
}
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f7974e9..03b332e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -235,12 +235,13 @@
<attr name="vmSafeMode" format="boolean" />
<!-- <p>Flag indicating whether the application's rendering should be hardware
- accelerated if possible. This flag is turned off by default, both for
- applications and activities.</p>
+ accelerated if possible. This flag is turned on by default for applications
+ that are targeting {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH}
+ or later.</p>
<p>This flag can be set on the application and any activity declared
in the manifest. When enabled for the application, each activity is
automatically assumed to be hardware accelerated. This flag can be
- overriden in the activity tags, either turning it off (if on for the
+ overridden in the activity tags, either turning it off (if on for the
application) or on (if off for the application.)</p>
<p>When this flag is turned on for an activity (either directly or via
the application tag), every window created from the activity, including
@@ -1020,7 +1021,7 @@
{@link #AndroidManifest manifest} tag. -->
<declare-styleable name="AndroidManifestSupportsScreens" parent="AndroidManifest">
<!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
- this is the new way to specify the screens an application is
+ this is the new way to specify the minimum screen size an application is
compatible with. This attribute provides the required minimum
"smallest screen width" (as per the -swNNNdp resource configuration)
that the application can run on. For example, a typical phone
@@ -1031,17 +1032,15 @@
or xlargeScreens attributes will be used instead. -->
<attr name="requiresSmallestWidthDp" format="integer" />
<!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
- this is the new way to specify the screens an application is
+ this is the new way to specify the largest screens an application is
compatible with. This attribute provides the maximum
"smallest screen width" (as per the -swNNNdp resource configuration)
that the application is designed for. If this value is smaller than
the "smallest screen width" of the device it is running on, the user
- will of offered to run it in a compatibility mode that emulates a
- smaller screen. Currently the compatibility mode only emulates
- phone screens, so it will not be used it the application provides
- a requiresSmallestWidthDp that is larger than 320. Typical values
- used with this attribute are 320 for a phone screen, 600 for a
- 7" tablet, and 720 for a 10" tablet. -->
+ is offered to run it in a compatibility mode that emulates a
+ smaller screen and zooms it to fit the screen. Currently the compatibility mode only
+ emulates phone screens with a 320dp width, so compatibility mode is not applied if the
+ value for compatibleWidthLimitDp is larger than 320. -->
<attr name="compatibleWidthLimitDp" format="integer" />
<!-- Starting with {@link android.os.Build.VERSION_CODES#HONEYCOMB_MR2},
this is the new way to specify the screens an application is
@@ -1050,9 +1049,9 @@
that the application can work well on. If this value is smaller than
the "smallest screen width" of the device it is running on, the
application will be forced in to screen compatibility mode with
- no way for the user to turn it off. Currently the compatibility mode
- only emulates phone screens, so even if this value is larger than 320
- the width the app runs in will be a 320 phone dimension. -->
+ no way for the user to turn it off. Currently the compatibility mode only
+ emulates phone screens with a 320dp width, so compatibility mode is not applied if the
+ value for largestWidthLimitDp is larger than 320. -->
<attr name="largestWidthLimitDp" format="integer" />
<!-- Indicates whether the application supports smaller screen form-factors.
A small screen is defined as one with a smaller aspect ratio than
diff --git a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
index aedfbad..2ed7c52 100644
--- a/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
+++ b/core/tests/coretests/src/android/webkit/AccessibilityInjectorTest.java
@@ -95,7 +95,7 @@
private WebView mWebView;
/** Used for caching the default bindings so they can be restored. */
- private String mDefaultKeyBindings;
+ private static String sDefaultKeyBindings;
/** The received selection string for assertion checking. */
private static String sReceivedSelectionString = SELECTION_STRING_UNKNOWN;
@@ -1696,7 +1696,7 @@
*/
private void injectTestWebContentKeyBindings() {
ContentResolver contentResolver = getActivity().getContentResolver();
- mDefaultKeyBindings = Settings.Secure.getString(contentResolver,
+ sDefaultKeyBindings = Settings.Secure.getString(contentResolver,
Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS);
Settings.Secure.putString(contentResolver,
Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS, TEST_KEY_DINDINGS);
@@ -1708,7 +1708,7 @@
private void restoreDefaultWebContentKeyBindings() {
Settings.Secure.putString(getActivity().getContentResolver(),
Settings.Secure.ACCESSIBILITY_WEB_CONTENT_KEY_BINDINGS,
- mDefaultKeyBindings);
+ sDefaultKeyBindings);
}
/**
diff --git a/data/fonts/DroidSansEthiopic-Bold.ttf b/data/fonts/DroidSansEthiopic-Bold.ttf
index 0d4500c..e06cac2 100644
--- a/data/fonts/DroidSansEthiopic-Bold.ttf
+++ b/data/fonts/DroidSansEthiopic-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidSansEthiopic-Regular.ttf b/data/fonts/DroidSansEthiopic-Regular.ttf
index dd88aa1..0adcbbe 100644
--- a/data/fonts/DroidSansEthiopic-Regular.ttf
+++ b/data/fonts/DroidSansEthiopic-Regular.ttf
Binary files differ
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index abea85b..3ec174e 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -222,7 +222,8 @@
<li><a href="<?cs var:toroot ?>guide/topics/manifest/receiver-element.html"><receiver></a></li>
<li><a href="<?cs var:toroot ?>guide/topics/manifest/service-element.html"><service></a></li>
<li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-gl-texture-element.html"><supports-gl-texture></a></li>
- <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html"><supports-screens></a></li> <!-- ##api level 4## -->
+ <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html"><supports-screens></a>
+ <span class="new">updated</span></li> <!-- ##api level 4## -->
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-configuration-element.html"><uses-configuration></a></li>
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-feature-element.html"><uses-feature></a></li> <!-- ##api level 4## -->
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-library-element.html"><uses-library></a></li>
@@ -256,7 +257,7 @@
<div><a href="<?cs var:toroot ?>guide/topics/renderscript/index.html">
<span class="en">RenderScript</span>
</a>
- <span class="new-child">new!</span></div>
+ <span class="new">new!</span></div>
<ul>
<li><a href="<?cs var:toroot ?>guide/topics/renderscript/graphics.html">
<span class="en">3D Graphics</span>
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
index ee99a37..605a2bb 100644
--- a/docs/html/guide/topics/manifest/supports-screens-element.jd
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -8,12 +8,15 @@
<dt>syntax:</dt>
<dd>
<pre class="stx">
-<supports-screens android:<a href="#resizeable">resizeable</a>=["true" | "false"]
- android:<a href="#small">smallScreens</a>=["true" | "false"]
- android:<a href="#normal">normalScreens</a>=["true" | "false"]
- android:<a href="#large">largeScreens</a>=["true" | "false"]
+<supports-screens android:<a href="#requiresSmallest">requiresSmallestWidthDp</a>="<em>integer</em>"
+ android:<a href="#compatibleWidth">compatibleWidthLimitDp</a>="<em>integer</em>"
+ android:<a href="#largestWidth">largestWidthLimitDp</a>="<em>integer</em>"
+ android:<a href="#resizeable">resizeable</a>=["true"| "false"]
+ android:<a href="#small">smallScreens</a>=["true" | "false"]
+ android:<a href="#normal">normalScreens</a>=["true" | "false"]
+ android:<a href="#large">largeScreens</a>=["true" | "false"]
android:<a href="#xlarge">xlargeScreens</a>=["true" | "false"]
- android:<a href="#any">anyDensity</a>=["true" | "false"] />
+ android:<a href="#any">anyDensity</a>=["true" | "false"] />
</pre>
</dd>
@@ -21,36 +24,37 @@
<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code></dd>
<dt>description:</dt>
-<dd>Lets you specify the screen dimensions the
-application supports. By default, a modern application (using API Level 4 or higher) supports all
-screen sizes; older applications are assumed to support only the "normal" screen size. Screen
-size is determined as the available pixels to an application after density scaling has been
-applied. (Note that screen size is a separate axis from screen density.)
+<dd>Lets you specify the screen sizes your application supports and enable screen
+compatibility mode for screens larger than what your application supports. By default, a modern
+application (using API Level 4 or higher) supports all screen sizes; older applications are assumed
+to support only the "normal" screen size. Screen size is determined by the number of pixels on the
+screen after the system accounts for screen density scaling.
-<p>An application "supports" a given screen size if it fills the entire screen and works as
-expected. By default, the system will resize your application to fill the screen, if you have set
+<p>An application "supports" a given screen size if it resizes properly to fill the entire screen.
+By default, the system resizes your application UI to fill the screen if you have set
either <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
minSdkVersion}</a> or <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-targetSdkVersion}</a> to {@code "4"} or higher. Resizing works well for most applications and
-you don't have to do any extra work to make your application work on larger screens.</p>
+targetSdkVersion}</a> to {@code "4"} or higher. Normal resizing works well for most applications and
+you don't have to do any extra work to make your application work on screens larger than a
+handset device.</p>
-<p>In addition to allowing the system to resize your application, you can add additional support
-for different screen sizes by providing <a
+<p>In addition to allowing the system to resize your application to fit the current screen, you can
+optimize your UI for different screen sizes by providing <a
href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">alternative
layout resources</a> for different sizes. For instance, you might want to modify the layout
of an activity when it is on a tablet or similar device that has an <em>xlarge</em> screen.</p>
-<p>If your application does not support <em>large</em> or <em>xlarge</em> screens, then you should
-declare that it is not resizeable by setting <a href="#resizeable">{@code android:resizeable}</a> to
-{@code "false"}, so that the system will not resize your application on larger screens.</p>
+<p>However, if your application does not work well when resized to fit different screen sizes,
+you can use the attributes of the {@code <supports-screens>} element to control whether
+your application should be distributed to smaller screens or have its UI scaled up to fit larger
+screens using the system's screen compatibility mode. When you have not designed for larger screen
+sizes and the normal resizing does not achieve the appropriate results, <em>screen compatibility
+mode</em> will scale your UI by emulating a <em>normal</em> size screen and then zooming in on it so
+that it fills the entire screen—thus achieving the same layout as a normal handset device on
+the large screen (but this usually causes pixelation and blurring of your UI).</p>
-<p>If your application does not support <em>small</em> screens, then
-there isn't much the system can do to make the application work well on a smaller screen, so
-external services (such as Android Market) should not allow users to install the application on such
-screens.</p>
-
-
-<p>For more information, see
+<p>For more information about how to properly support different screen sizes so that you can avoid
+using screen compatibility mode, read
<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.</p>
@@ -59,6 +63,74 @@
<dd>
<dl class="attr">
+ <dt id="requiresSmallest">{@code android:requiresSmallestWidthDp}</dt>
+ <dd>This attribute specifies the minimum "smallest screen width" with which your
+application is compatible. In order for a device to be considered compatible with your
+application, the shortest side of the available screen space must be equal to or greater than this
+value.
+<p>The width against which your value is compared takes into account screen decorations and system
+UI. For example, if the device has some persistent UI elements on the left or right edge of the
+display, the system declares the device's available width as one that is smaller than the actual
+screen size, accounting for these UI elements because those are screen pixels not available for your
+UI. Thus, the value you use should be the actual smallest width required by your layout.</p>
+<p>If your application properly resizes for smaller screen sizes (down to the
+<em>small</em> size or a minimum width of 320dp), you do
+not need to use this attribute. Otherwise, you should use a value for this attribute that
+matches the smallest value used by your application for the <a
+href="{@docRoot}guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">
+smallest screen width qualifier</a> ({@code sw<N>dp}).</p>
+
+<p>For example, a typical handset screen has a minimum width of 320dp, a 7" tablet has a minimum
+width of 600dp, and a 10" tablet has a minimum width of 720dp. If the smallest available screen
+width on a device is less than the value you supply here, then the application is considered
+incompatible with that
+device. External services such as Android Market use this to determine whether a device
+is compatible with your application and prevent incompatible devices from installing it.</p>
+<p>Beginning with Android 3.2 (API level 13), using this attribute is the preferred way to
+specify the minimum screen size your application requires, instead of using the other attributes
+for small, normal, large, and xlarge screens. The advantage of using this attribute is that you
+have more control over exactly how much screen space your application needs at a minimum in order
+to properly display its UI, rather than relying on the generalized size groups.</p>
+<p>This attribute has no default value. If this attribute is not specified, then any of the old
+<code><a href="#small">smallScreens</a></code>, <code><a href="#normal">normalScreens</a></code>,
+<code><a href="#large">largeScreens</a></code>, or <code><a href="#xlarge">xlargeScreens</a></code>
+attributes are used instead to determine the smallest screen required.</p>
+ <p>This attribute was introduced in API level 13.</p>
+ </dd>
+
+ <dt id="compatibleWidth">{@code android:compatibleWidthLimitDp}</dt>
+ <dd>This attribute allows you to enable screen compatibility mode as a user-optional feature by
+specifying the maximum "smallest screen width" for which your application is designed. If the value
+you supply here is less than the shortest side of the available screen space, users can still
+install your application, but are offered to run it in screen compatibility mode. By default, screen
+compatibility mode is disabled and your layout is resized to fit the screen as usual, but a
+button is available in the system bar that allows the user to toggle screen compatibility mode on
+and off.
+ <p>If your application is compatible with all screen sizes and its layout properly resizes, you do
+not need to use this attribute.</p>
+ <p class="note"><strong>Note:</strong> Currently, screen compatibility mode only emulates handset
+screens with a 320dp width, so screen compatibility mode is not applied if your value for {@code
+android:compatibleWidthLimitDp} is larger than 320.</p>
+ <p>This attribute was introduced in API level 13.</p>
+ </dd>
+
+ <dt id="largestWidth">{@code android:largestWidthLimitDp}</dt>
+ <dd>This attribute allows you to force enable screen compatibility mode by specifying the maximum
+"smallest screen width" for which your application is designed. If the value you supply here is less
+than the shortest side of the available screen space, the application runs in screen
+compatibility mode with no way for the user to disable it.
+ <p>If your application is compatible with all screen sizes and its layout properly resizes, you do
+not need to use this attribute. Otherwise, you should first consider using the <a
+href="#compatibleWidth">{@code android:compatibleWidthLimitDp}</a> attribute. You should use the
+{@code android:largestWidthLimitDp} attribute only when your application is functionally broken when
+resized for larger screens and screen compatibility mode is the only way that users should use
+your application.</p>
+ <p class="note"><strong>Note:</strong> Currently, screen compatibility mode only emulates handset
+screens with a 320dp width, so screen compatibility mode is not applied if your value for {@code
+android:largestWidthLimitDp} is larger than 320.</p>
+ <p>This attribute was introduced in API level 13.</p>
+ </dd>
+
<dt><a name="resizeable"></a>{@code android:resizeable}</dt>
<dd>Indicates whether the application is resizeable for different screen sizes. This attribute is
true, by default, if you have set either <a
@@ -75,6 +147,7 @@
application does not work well on larger screens, follow the guide to <a
href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a> to enable
additional screen support.</p>
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
@@ -91,6 +164,7 @@
{@code "4"} or higher,
the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
{@code "false"}.
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
<dt><a name="normal"></a>{@code android:normalScreens}</dt>
@@ -99,12 +173,13 @@
screen, but WQVGA low density and WVGA high density are also
considered to be normal. This attribute is "true" by default,
and applications currently should leave it that way.
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
<dt><a name="large"></a>{@code android:largeScreens}</dt>
<dd>Indicates whether the application supports larger screen form-factors.
A large screen is defined as a screen that is significantly larger
- than a "normal" phone screen, and thus might require some special care
+ than a "normal" handset screen, and thus might require some special care
on the application's part to make good use of it, though it may rely on resizing by the
system to fill the screen. If the application has set either <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code minSdkVersion}</a> or <a
@@ -112,6 +187,7 @@
{@code "4"} or higher,
the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
{@code "false"}.
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
<dt><a name="xlarge"></a>{@code android:xlargeScreens}</dt>
@@ -125,7 +201,8 @@
{@code "4"} or higher,
the default value for this is {@code "true"}, any value less than {@code "4"} results in this set to
{@code "false"}.
- <p>This attribute was introduced in API Level 9.</p>
+ <p>This attribute was introduced in API level 9.</p>
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
<dt><a name="any"></a>{@code android:anyDensity}</dt>
@@ -142,6 +219,7 @@
down application assets by a factor of 0.75 (low dpi screens) or scale them up by a factor of 1.5
(high dpi screens), when you don't provide alternative resources for a specifc screen density. The
screen density is expressed as dots-per-inch (dpi).</p>
+ <p><strong>This attribute is deprecated</strong> as of API level 13.</p>
</dd>
diff --git a/docs/html/guide/topics/resources/providing-resources.jd b/docs/html/guide/topics/resources/providing-resources.jd
index a996ccc..ea778c1 100644
--- a/docs/html/guide/topics/resources/providing-resources.jd
+++ b/docs/html/guide/topics/resources/providing-resources.jd
@@ -335,80 +335,101 @@
</tr>
<tr id="SmallestScreenWidthQualifier">
<td>Smallest screen width</td>
- <td>Examples:<br/>
+ <td><code>sw<N>dp</code><br/><br/>
+ Examples:<br/>
<code>sw320dp</code><br/>
<code>sw600dp</code><br/>
<code>sw720dp</code><br/>
etc.
</td>
<td>
- <p>Specifies a minimum "smallest screen width," in "dp" units, at which the resource
- should be used. This configuration value represents the base screen size
- of the device, regardless of the orientation of the display. It is based
- on the smallest width the application will have in which to perform its
- UI layout (in dp units) regardless of the orientation of the screen. The
- value here takes into account screen decorations so if the device has some
- persistent UI elements on the left or right edge of the display it must
- present a value here that is smaller than the real screen size, accounting
- for these UI elements reducing the application's available space.</p>
- <p>Some values you may use here for common screen sizes:</p>
+ <p>Specifies the "smallest width" in {@code dp} units that must be available to your
+ application in order for the resources to be used, regardless of the screen's current
+ orientation. For example, if your layout requires that its shortest side be at least 600
+ dp in length at all times, then you can use this to create the layout resources, {@code
+ res/layout-sw600dp/}, and the system will use them only when the shortest side of
+ available screen space it at least 600dp.</p>
+ <p>The width against which the system compares your value takes into account screen
+ decorations and system UI. For example, if the device has some persistent UI elements on the
+ left or right edge of the display, the system declares its own available width as one that
+ is smaller than the actual screen size, accounting for these UI elements because those are
+ screen pixels not available for your UI. Thus, the value you use should be the actual
+ smallest width required by your layout.</p>
+ <p>Some values you might use here for common screen sizes:</p>
<ul>
- <li>240x320 ldpi (QVGA phone): 320
- <li>320x480 mdpi (phone): 320
- <li>480x800 hdpi (high density phone): 320
- <li>480x800 mdpi (tablet/phone): 480
- <li>600x1024 mdpi (7" tablet): 600
- <li>720x1280 mdpi (10" tablet): 720
+ <li>320, for devices with screen configurations such as:
+ <ul>
+ <li>240x320 ldpi (QVGA handset)</li>
+ <li>320x480 mdpi (handset)</li>
+ <li>480x800 hdpi (high density handset)</li>
+ </ul>
+ </li>
+ <li>480, for screens such as 480x800 mdpi (tablet/handset).</li>
+ <li>600, for screens such as 600x1024 mdpi (7" tablet).</li>
+ <li>720, for screens such as 720x1280 mdpi (10" tablet).</li>
</ul>
- <p><em>Added in API Level 13.</em></p>
- <p>Also see the {@link android.content.res.Configuration#smallestScreenWidthDp}
- configuration field, which holds the current smallest screen width.</p>
+ <p>When your application provides multiple resource directories with different values for
+ this qualifier, the system uses the one closest to (without exceeding) the smallest width
+ for the available space. </p>
+ <p><em>Added in API level 13.</em></p>
+ <p>Also see the <a
+ href="{@docRoot}guide/topics/manifest/supports-screens-element.html#requiresSmallest">{@code
+ android:requiresSmallestWidthDp}</a> attribute, which declares the smallest available width
+ with which your application is compatible, and the {@link
+ android.content.res.Configuration#smallestScreenWidthDp} configuration field, which holds
+ the current smallest screen width for the device.</p>
</td>
</tr>
<tr id="ScreenWidthQualifier">
<td>Screen width</td>
- <td>Examples:<br/>
+ <td><code>w<N>dp</code><br/><br/>
+ Examples:<br/>
<code>w720dp</code><br/>
<code>w1024dp</code><br/>
etc.
</td>
<td>
- <p>Specifies a minimum screen width, in "dp" units, at which the resource
- should be used. This configuration value will change when the orientation
- changes between landscape and portrait to match the current actual width.
- When multiple screen width configurations are available, the closest to
- the current screen width will be used. The
- value here takes into account screen decorations so if the device has some
- persistent UI elements on the left or right edge of the display it must
- present a value here that is smaller than the real screen size, accounting
- for these UI elements reducing the application's available space.</p>
- <p><em>Added in API Level 13.</em></p>
+ <p>Specifies a minimum screen width, in {@code dp} units at which the resource
+ should be used—defined by the <code><N></code> value. This
+ configuration value will change when the orientation
+ changes between landscape and portrait to match the current actual width.</p>
+ <p>When your application provides multiple resource directories with different values
+ for this configuration, the system uses the one closest to (without exceeding)
+ the device's current screen width. The
+ value here takes into account screen decorations, so if the device has some
+ persistent UI elements on the left or right edge of the display, it
+ uses a value for the width that is smaller than the real screen size, accounting
+ for these UI elements and reducing the application's available space.</p>
+ <p><em>Added in API level 13.</em></p>
<p>Also see the {@link android.content.res.Configuration#screenWidthDp}
configuration field, which holds the current screen width.</p>
</td>
</tr>
<tr id="ScreenHeightQualifier">
<td>Screen height</td>
- <td>Examples:<br/>
+ <td><code>h<N>dp</code><br/><br/>
+ Examples:<br/>
<code>h720dp</code><br/>
<code>h1024dp</code><br/>
etc.
</td>
<td>
- <p>Specifies a minimum screen height, in "dp" units, at which the resource
- should be used. This configuration value will change when the orientation
- changes between landscape and portrait to match the current actual height.
- When multiple screen height configurations are available, the closest to
- the current screen height will be used. The
- value here takes into account screen decorations so if the device has some
- persistent UI elements on the left or right edge of the display it must
- present a value here that is smaller than the real screen size, accounting
- for these UI elements reducing the application's available space. Screen
+ <p>Specifies a minimum screen height, in "dp" units at which the resource
+ should be used—defined by the <code><N></code> value. This
+ configuration value will change when the orientation
+ changes between landscape and portrait to match the current actual height.</p>
+ <p>When your application provides multiple resource directories with different values
+ for this configuration, the system uses the one closest to (without exceeding)
+ the device's current screen height. The
+ value here takes into account screen decorations, so if the device has some
+ persistent UI elements on the top or bottom edge of the display, it uses
+ a value for the height that is smaller than the real screen size, accounting
+ for these UI elements and reducing the application's available space. Screen
decorations that are not fixed (such as a phone status bar that can be
hidden when full screen) are <em>not</em> accounted for here, nor are
- window decorations like title bar, so applications must be prepared to
+ window decorations like the title bar or action bar, so applications must be prepared to
deal with a somewhat smaller space than they specify.
- <p><em>Added in API Level 13.</em></p>
+ <p><em>Added in API level 13.</em></p>
<p>Also see the {@link android.content.res.Configuration#screenHeightDp}
configuration field, which holds the current screen width.</p>
</td>
@@ -444,9 +465,9 @@
medium-density HVGA screen. The minimum layout size for this screen configuration
is approximately 720x960 dp units. In most cases, devices with extra large
screens would be too large to carry in a pocket and would most likely
- be tablet-style devices. <em>Added in API Level 9.</em></li>
+ be tablet-style devices. <em>Added in API level 9.</em></li>
</ul>
- <p><em>Added in API Level 4.</em></p>
+ <p><em>Added in API level 4.</em></p>
<p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple
Screens</a> for more information.</p>
<p>Also see the {@link android.content.res.Configuration#screenLayout} configuration field,
@@ -465,7 +486,7 @@
<li>{@code long}: Long screens, such as WQVGA, WVGA, FWVGA</li>
<li>{@code notlong}: Not long screens, such as QVGA, HVGA, and VGA</li>
</ul>
- <p><em>Added in API Level 4.</em></p>
+ <p><em>Added in API level 4.</em></p>
<p>This is based purely on the aspect ratio of the screen (a "long" screen is wider). This
is not related to the screen orientation.</p>
<p>Also see the {@link android.content.res.Configuration#screenLayout} configuration field,
@@ -503,7 +524,7 @@
<li>{@code car}: Device is in a car dock</li>
<li>{@code desk}: Device is in a desk dock</li>
</ul>
- <p><em>Added in API Level 8.</em></p>
+ <p><em>Added in API level 8.</em></p>
<p>This can change during the life of your application if the user places the device in a
dock. You can enable or disable this mode using {@link
android.app.UiModeManager}. See <a href="runtime-changes.html">Handling Runtime Changes</a> for
@@ -521,7 +542,7 @@
<li>{@code night}: Night time</li>
<li>{@code notnight}: Day time</li>
</ul>
- <p><em>Added in API Level 8.</em></p>
+ <p><em>Added in API level 8.</em></p>
<p>This can change during the life of your application if night mode is left in
auto mode (default), in which case the mode changes based on the time of day. You can enable
or disable this mode using {@link android.app.UiModeManager}. See <a
@@ -549,7 +570,7 @@
<li>{@code nodpi}: This can be used for bitmap resources that you do not want to be scaled
to match the device density.</li>
</ul>
- <p><em>Added in API Level 4.</em></p>
+ <p><em>Added in API level 4.</em></p>
<p>There is thus a 3:4:6:8 scaling ratio between the four densities, so a 9x9 bitmap
in ldpi is 12x12 in mdpi, 18x18 in hdpi and 24x24 in xhdpi.</p>
<p>When Android selects which resource files to use,
@@ -689,17 +710,17 @@
</tr>
-->
<tr id="VersionQualifier">
- <td>Platform Version (API Level)</td>
+ <td>Platform Version (API level)</td>
<td>Examples:<br/>
<code>v3</code><br/>
<code>v4</code><br/>
<code>v7</code><br/>
etc.</td>
<td>
- <p>The API Level supported by the device. For example, <code>v1</code> for API Level
-1 (devices with Android 1.0 or higher) and <code>v4</code> for API Level 4 (devices with Android
+ <p>The API level supported by the device. For example, <code>v1</code> for API level
+1 (devices with Android 1.0 or higher) and <code>v4</code> for API level 4 (devices with Android
1.6 or higher). See the <a
-href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a> document for more information
+href="{@docRoot}guide/appendix/api-levels.html">Android API levels</a> document for more information
about these values.</p>
<p class="caution"><strong>Caution:</strong> Android 1.5 and 1.6 only match resources
with this qualifier when it exactly matches the platform version. See the section below about <a
@@ -863,7 +884,7 @@
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
minSdkVersion}</a> is set to 4, and you qualify all of your drawable resources using <a
href="#NightQualifier">night mode</a> ({@code night} or {@code notnight}, which were added in API
-Level 8), then an API Level 4 device cannot access your drawable resources and will crash. In this
+Level 8), then an API level 4 device cannot access your drawable resources and will crash. In this
case, you probably want {@code notnight} to be your default resources, so you should exclude that
qualifier so your drawable resources are in either {@code drawable/} or {@code drawable-night/}.</p>
@@ -896,7 +917,7 @@
<dd>{@code long} and {@code notlong}</dd>
</dl>
-<p>These configuration qualifiers were introduced in Android 1.6, so Android 1.5 (API Level 3) and
+<p>These configuration qualifiers were introduced in Android 1.6, so Android 1.5 (API level 3) and
lower does not support them. If you use these configuration qualifiers and do not provide
corresponding default resources, then an Android 1.5 device might use any one of the resource
directories named with the above screen configuration qualifiers, because it ignores these
@@ -926,9 +947,9 @@
<p>You need SDK Tools, Revision 6 (or greater), because it includes a new packaging tool that
automatically applies an appropriate <a href="#VersionQualifier">version qualifier</a> to any
resource directory named with a qualifier that does not exist in Android 1.0. For example, because
-the density qualifier was introduced in Android 1.6 (API Level 4), when the packaging tool
+the density qualifier was introduced in Android 1.6 (API level 4), when the packaging tool
encounters a resource directory using the density qualifier, it adds {@code v4} to the directory
-name to ensure that older versions do not use those resources (only API Level 4 and higher support
+name to ensure that older versions do not use those resources (only API level 4 and higher support
that qualifier). Thus, by putting your medium-density resources in a directory <em>without</em> the
{@code mdpi} qualifier, they are still accessible by Android 1.5, and any device that supports the
density qualifer and has a medium-density screen also uses the default resources (which are mdpi)
@@ -937,7 +958,7 @@
</li>
</ol>
-<p class="note"><strong>Note:</strong> Later versions of Android, such as API Level 8,
+<p class="note"><strong>Note:</strong> Later versions of Android, such as API level 8,
introduce other configuration qualifiers that older version do not support. To provide the best
compatibility, you should always include a set of default resources for each type of resource
that your application uses, as discussed above to provide the best device compatibility.</p>
@@ -1068,7 +1089,7 @@
<p>The correct behavior is for the system to match resources marked with a <a
href="#VersionQualifier">version qualifier</a> equal
-to or less than the platform version on the device, but on Android 1.5 and 1.6, (API Level 3 and 4),
+to or less than the platform version on the device, but on Android 1.5 and 1.6, (API level 3 and 4),
there is a bug that causes the system to match resources marked with the version qualifier
only when it exactly matches the version on the device.</p>
diff --git a/docs/html/guide/topics/search/index.jd b/docs/html/guide/topics/search/index.jd
index 7ac5ff1..218511b 100644
--- a/docs/html/guide/topics/search/index.jd
+++ b/docs/html/guide/topics/search/index.jd
@@ -52,7 +52,13 @@
<p class="note"><strong>Note</strong>: The search framework does <em>not</em> provide APIs to
search your data. To perform a search, you need to use APIs appropriate for your data. For example,
if your data is stored in an SQLite database, you should use the {@link android.database.sqlite}
-APIs to perform searches.</p>
+APIs to perform searches.
+<br/><br/>
+Also, there is no guarantee that every device provides a dedicated SEARCH button to invoke the
+search interface in your application. When using the search dialog or a custom interface, you
+must always provide a search button in your UI that activates the search interface. For more
+information, see <a href="search-dialog.html#InvokingTheSearchDialog">Invoking the search
+dialog</a>.</p>
<p>The following documents show you how to use Android's framework to implement search:</p>
diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd
index af6c8f2..d869a44 100644
--- a/docs/html/guide/topics/search/search-dialog.jd
+++ b/docs/html/guide/topics/search/search-dialog.jd
@@ -17,29 +17,30 @@
<h2>In this document</h2>
<ol>
-<li><a href="#TheBasics">The Basics</a></li>
-<li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
-<li><a href="#SearchableActivity">Creating a Searchable Activity</a>
- <ol>
- <li><a href="#DeclaringSearchableActivity">Declaring a searchable activity</a></li>
- <li><a href="#EnableSearch">Enabling the search dialog and search widget</a></li>
- <li><a href="#PerformingSearch">Performing a search</a></li>
- </ol>
-</li>
-<li><a href="#UsingTheSearchDialog">Using the Search Dialog</a>
- <ol>
- <li><a href="#LifeCycle">The impact of the search dialog on your activity lifecycle</a></li>
- <li><a href="#SearchContextData">Passing search context data</a></li>
- </ol>
-</li>
-<li><a href="#UsingSearchWidget">Using the Search Widget</a>
- <ol>
- <li><a href="#ConfiguringWidget">Configuring the search widget</a></li>
- <li><a href="#WidgetFeatures">Other search widget features</a></li>
- </ol>
-</li>
-<li><a href="#VoiceSearch">Adding Voice Search</a></li>
-<li><a href="#SearchSuggestions">Adding Search Suggestions</a></li>
+ <li><a href="#TheBasics">The Basics</a></li>
+ <li><a href="#SearchableConfiguration">Creating a Searchable Configuration</a></li>
+ <li><a href="#SearchableActivity">Creating a Searchable Activity</a>
+ <ol>
+ <li><a href="#DeclaringSearchableActivity">Declaring a searchable activity</a></li>
+ <li><a href="#PerformingSearch">Performing a search</a></li>
+ </ol>
+ </li>
+ <li><a href="#SearchDialog">Using the Search Dialog</a>
+ <ol>
+ <li><a href="#InvokingTheSearchDialog">Invoking the search dialog</a></li>
+ <li><a href="#LifeCycle">The impact of the search dialog on your activity lifecycle</a></li>
+ <li><a href="#SearchContextData">Passing search context data</a></li>
+ </ol>
+ </li>
+ <li><a href="#UsingSearchWidget">Using the Search Widget</a>
+ <ol>
+ <li><a href="#ConfiguringWidget">Configuring the search widget</a></li>
+ <li><a href="#WidgetFeatures">Other search widget features</a></li>
+ <li><a href="#UsingBoth">Using both the widget and the dialog</a></li>
+ </ol>
+ </li>
+ <li><a href="#VoiceSearch">Adding Voice Search</a></li>
+ <li><a href="#SearchSuggestions">Adding Search Suggestions</a></li>
</ol>
<h2>Key classes</h2>
@@ -494,13 +495,13 @@
<h3 id="InvokingTheSearchDialog">Invoking the search dialog</h3>
-<p>As mentioned above, the device SEARCH button and {@link android.app.Activity#onSearchRequested
-onSearchRequested()} method will open the search dialog, as long as the current activity
-has declared the searchable activity to use, as shown in the previous section.</p>
+<p>As mentioned above, the device SEARCH button will open the search dialog as long as the current
+activity has declared in the manifest the searchable activity to use.</p>
-<p>However, you should not assume that a SEARCH button is available on the user's device. You
-should always provide another search button in your UI that activates the search dialog by calling
-{@link android.app.Activity#onSearchRequested()}.</p>
+<p>However, some devices do not include a dedicated SEARCH button, so you should not assume that
+it's always available. When using the search dialog, you must <strong>always provide another search
+button in your UI</strong> that activates the search dialog by calling {@link
+android.app.Activity#onSearchRequested()}.</p>
<p>For instance, you should either provide a menu item in your <a
href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or a button in your
@@ -510,12 +511,6 @@
medium and high density screens, which you can use for your search menu item or button (low-density
screens scale-down the hdpi image by one half). </p>
-<!-- ... maybe this should go into the Creating Menus document ....
-<p>If you chose to provide a shortcut key for the menu item, using {@link
-android.view.MenuItem#setAlphabeticShortcut(char)}, then SearchManager.MENU_KEY is the recommended
-key character, representing the default search key.</p>
--->
-
<p>You can also enable "type-to-search" functionality, which activates the search dialog when the
user starts typing on the keyboard—the keystrokes are inserted into the search dialog. You can
enable type-to-search in your activity by calling
diff --git a/docs/html/resources/tutorials/views/hello-spinner.jd b/docs/html/resources/tutorials/views/hello-spinner.jd
index 7a3a9c3..e9dc20f 100644
--- a/docs/html/resources/tutorials/views/hello-spinner.jd
+++ b/docs/html/resources/tutorials/views/hello-spinner.jd
@@ -105,7 +105,7 @@
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
- Toast.makeText(parent.getContext()), "The planet is " +
+ Toast.makeText(parent.getContext(), "The planet is " +
parent.getItemAtPosition(pos).toString(), Toast.LENGTH_LONG).show();
}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 12dc93c..40d54bb 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -681,7 +681,8 @@
*/
public enum CompressFormat {
JPEG (0),
- PNG (1);
+ PNG (1),
+ WEBP (2);
CompressFormat(int nativeInt) {
this.nativeInt = nativeInt;
diff --git a/include/binder/IMemory.h b/include/binder/IMemory.h
index 74d2cc7..2d0db00 100644
--- a/include/binder/IMemory.h
+++ b/include/binder/IMemory.h
@@ -43,6 +43,7 @@
virtual void* getBase() const = 0;
virtual size_t getSize() const = 0;
virtual uint32_t getFlags() const = 0;
+ virtual uint32_t getOffset() const = 0;
// these are there just for backward source compatibility
int32_t heapID() const { return getHeapID(); }
diff --git a/include/binder/MemoryHeapBase.h b/include/binder/MemoryHeapBase.h
index 2f2e31b..bbbda9c 100644
--- a/include/binder/MemoryHeapBase.h
+++ b/include/binder/MemoryHeapBase.h
@@ -27,7 +27,7 @@
// ---------------------------------------------------------------------------
-class MemoryHeapBase : public virtual BnMemoryHeap
+class MemoryHeapBase : public virtual BnMemoryHeap
{
public:
enum {
@@ -38,12 +38,12 @@
NO_CACHING = 0x00000200
};
- /*
+ /*
* maps the memory referenced by fd. but DOESN'T take ownership
* of the filedescriptor (it makes a copy with dup()
*/
MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
-
+
/*
* maps memory from the given device
*/
@@ -61,9 +61,10 @@
virtual void* getBase() const;
virtual size_t getSize() const;
virtual uint32_t getFlags() const;
+ virtual uint32_t getOffset() const;
const char* getDevice() const;
-
+
/* this closes this heap -- use carefully */
void dispose();
@@ -74,12 +75,12 @@
mDevice = device;
return mDevice ? NO_ERROR : ALREADY_EXISTS;
}
-
+
protected:
MemoryHeapBase();
// init() takes ownership of fd
status_t init(int fd, void *base, int size,
- int flags = 0, const char* device = NULL);
+ int flags = 0, const char* device = NULL);
private:
status_t mapfd(int fd, size_t size, uint32_t offset = 0);
@@ -90,6 +91,7 @@
uint32_t mFlags;
const char* mDevice;
bool mNeedUnmap;
+ uint32_t mOffset;
};
// ---------------------------------------------------------------------------
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index bc8c412..1ace8f8 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -42,11 +42,11 @@
public:
HeapCache();
virtual ~HeapCache();
-
+
virtual void binderDied(const wp<IBinder>& who);
- sp<IMemoryHeap> find_heap(const sp<IBinder>& binder);
- void free_heap(const sp<IBinder>& binder);
+ sp<IMemoryHeap> find_heap(const sp<IBinder>& binder);
+ void free_heap(const sp<IBinder>& binder);
sp<IMemoryHeap> get_heap(const sp<IBinder>& binder);
void dump_heaps();
@@ -57,7 +57,7 @@
int32_t count;
};
- void free_heap(const wp<IBinder>& binder);
+ void free_heap(const wp<IBinder>& binder);
Mutex mHeapCacheLock;
KeyedVector< wp<IBinder>, heap_info_t > mHeapCache;
@@ -81,11 +81,12 @@
virtual void* getBase() const;
virtual size_t getSize() const;
virtual uint32_t getFlags() const;
+ virtual uint32_t getOffset() const;
private:
friend class IMemory;
friend class HeapCache;
-
+
// for debugging in this module
static inline sp<IMemoryHeap> find_heap(const sp<IBinder>& binder) {
return gHeapCache->find_heap(binder);
@@ -97,7 +98,7 @@
return gHeapCache->get_heap(binder);
}
static inline void dump_heaps() {
- gHeapCache->dump_heaps();
+ gHeapCache->dump_heaps();
}
void assertMapped() const;
@@ -107,6 +108,7 @@
mutable void* mBase;
mutable size_t mSize;
mutable uint32_t mFlags;
+ mutable uint32_t mOffset;
mutable bool mRealHeap;
mutable Mutex mLock;
};
@@ -123,7 +125,7 @@
BpMemory(const sp<IBinder>& impl);
virtual ~BpMemory();
virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const;
-
+
private:
mutable sp<IMemoryHeap> mHeap;
mutable ssize_t mOffset;
@@ -203,7 +205,7 @@
BnMemory::BnMemory() {
}
-BnMemory::~BnMemory() {
+BnMemory::~BnMemory() {
}
status_t BnMemory::onTransact(
@@ -229,7 +231,7 @@
BpMemoryHeap::BpMemoryHeap(const sp<IBinder>& impl)
: BpInterface<IMemoryHeap>(impl),
- mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mRealHeap(false)
+ mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mOffset(0), mRealHeap(false)
{
}
@@ -242,7 +244,7 @@
sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder();
if (VERBOSE) {
- LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d",
+ LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d",
binder.get(), this, mSize, mHeapId);
CallStack stack;
stack.update();
@@ -270,6 +272,7 @@
if (mHeapId == -1) {
mBase = heap->mBase;
mSize = heap->mSize;
+ mOffset = heap->mOffset;
android_atomic_write( dup( heap->mHeapId ), &mHeapId );
}
} else {
@@ -286,13 +289,14 @@
// remote call without mLock held, worse case scenario, we end up
// calling transact() from multiple threads, but that's not a problem,
// only mmap below must be in the critical section.
-
+
Parcel data, reply;
data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor());
status_t err = remote()->transact(HEAP_ID, data, &reply);
int parcel_fd = reply.readFileDescriptor();
ssize_t size = reply.readInt32();
uint32_t flags = reply.readInt32();
+ uint32_t offset = reply.readInt32();
LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)",
asBinder().get(), parcel_fd, size, err, strerror(-err));
@@ -309,7 +313,7 @@
Mutex::Autolock _l(mLock);
if (mHeapId == -1) {
mRealHeap = true;
- mBase = mmap(0, size, access, MAP_SHARED, fd, 0);
+ mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
if (mBase == MAP_FAILED) {
LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)",
asBinder().get(), size, fd, strerror(errno));
@@ -317,6 +321,7 @@
} else {
mSize = size;
mFlags = flags;
+ mOffset = offset;
android_atomic_write(fd, &mHeapId);
}
}
@@ -343,14 +348,19 @@
return mFlags;
}
+uint32_t BpMemoryHeap::getOffset() const {
+ assertMapped();
+ return mOffset;
+}
+
// ---------------------------------------------------------------------------
IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap");
-BnMemoryHeap::BnMemoryHeap() {
+BnMemoryHeap::BnMemoryHeap() {
}
-BnMemoryHeap::~BnMemoryHeap() {
+BnMemoryHeap::~BnMemoryHeap() {
}
status_t BnMemoryHeap::onTransact(
@@ -362,6 +372,7 @@
reply->writeFileDescriptor(getHeapID());
reply->writeInt32(getSize());
reply->writeInt32(getFlags());
+ reply->writeInt32(getOffset());
return NO_ERROR;
} break;
default:
@@ -383,17 +394,17 @@
void HeapCache::binderDied(const wp<IBinder>& binder)
{
//LOGD("binderDied binder=%p", binder.unsafe_get());
- free_heap(binder);
+ free_heap(binder);
}
-sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder)
+sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder)
{
Mutex::Autolock _l(mHeapCacheLock);
ssize_t i = mHeapCache.indexOfKey(binder);
if (i>=0) {
heap_info_t& info = mHeapCache.editValueAt(i);
LOGD_IF(VERBOSE,
- "found binder=%p, heap=%p, size=%d, fd=%d, count=%d",
+ "found binder=%p, heap=%p, size=%d, fd=%d, count=%d",
binder.get(), info.heap.get(),
static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
@@ -415,7 +426,7 @@
free_heap( wp<IBinder>(binder) );
}
-void HeapCache::free_heap(const wp<IBinder>& binder)
+void HeapCache::free_heap(const wp<IBinder>& binder)
{
sp<IMemoryHeap> rel;
{
@@ -426,7 +437,7 @@
int32_t c = android_atomic_dec(&info.count);
if (c == 1) {
LOGD_IF(VERBOSE,
- "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d",
+ "removing binder=%p, heap=%p, size=%d, fd=%d, count=%d",
binder.unsafe_get(), info.heap.get(),
static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
@@ -450,7 +461,7 @@
return realHeap;
}
-void HeapCache::dump_heaps()
+void HeapCache::dump_heaps()
{
Mutex::Autolock _l(mHeapCacheLock);
int c = mHeapCache.size();
@@ -459,7 +470,7 @@
BpMemoryHeap const* h(static_cast<BpMemoryHeap const *>(info.heap.get()));
LOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%d)",
mHeapCache.keyAt(i).unsafe_get(),
- info.heap.get(), info.count,
+ info.heap.get(), info.count,
h->mHeapId, h->mBase, h->mSize);
}
}
diff --git a/libs/binder/MemoryHeapBase.cpp b/libs/binder/MemoryHeapBase.cpp
index 9f501e2..bf4a73f 100644
--- a/libs/binder/MemoryHeapBase.cpp
+++ b/libs/binder/MemoryHeapBase.cpp
@@ -40,15 +40,15 @@
// ---------------------------------------------------------------------------
-MemoryHeapBase::MemoryHeapBase()
+MemoryHeapBase::MemoryHeapBase()
: mFD(-1), mSize(0), mBase(MAP_FAILED),
- mDevice(NULL), mNeedUnmap(false)
+ mDevice(NULL), mNeedUnmap(false), mOffset(0)
{
}
MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
- mDevice(0), mNeedUnmap(false)
+ mDevice(0), mNeedUnmap(false), mOffset(0)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
@@ -65,7 +65,7 @@
MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
- mDevice(0), mNeedUnmap(false)
+ mDevice(0), mNeedUnmap(false), mOffset(0)
{
int open_flags = O_RDWR;
if (flags & NO_CACHING)
@@ -84,7 +84,7 @@
MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
- mDevice(0), mNeedUnmap(false)
+ mDevice(0), mNeedUnmap(false), mOffset(0)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
@@ -141,6 +141,7 @@
}
mFD = fd;
mSize = size;
+ mOffset = offset;
return NO_ERROR;
}
@@ -183,5 +184,9 @@
return mDevice;
}
+uint32_t MemoryHeapBase::getOffset() const {
+ return mOffset;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 314425f..cd97302 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -4216,6 +4216,10 @@
mNode, OMX_IndexConfigCommonOutputCrop,
&rect, sizeof(rect));
+ CODEC_LOGI(
+ "video dimensions are %ld x %ld",
+ video_def->nFrameWidth, video_def->nFrameHeight);
+
if (err == OK) {
CHECK_GE(rect.nLeft, 0);
CHECK_GE(rect.nTop, 0);
@@ -4230,6 +4234,10 @@
rect.nTop,
rect.nLeft + rect.nWidth - 1,
rect.nTop + rect.nHeight - 1);
+
+ CODEC_LOGI(
+ "Crop rect is %ld x %ld @ (%ld, %ld)",
+ rect.nWidth, rect.nHeight, rect.nLeft, rect.nTop);
} else {
mOutputFormat->setRect(
kKeyCropRect,
@@ -4238,7 +4246,6 @@
video_def->nFrameHeight - 1);
}
}
-
break;
}
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
index 830d2e0..ec7bd1c 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.cpp
@@ -139,7 +139,8 @@
}
status_t SoftAVC::initDecoder() {
- if (H264SwDecInit(&mHandle, 1) == H264SWDEC_OK) {
+ // Force decoder to output buffers in display order.
+ if (H264SwDecInit(&mHandle, 0) == H264SWDEC_OK) {
return OK;
}
return UNKNOWN_ERROR;
diff --git a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
index 3439efd..1cc85e8 100644
--- a/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
+++ b/media/libstagefright/codecs/on2/h264dec/SoftAVC.h
@@ -52,7 +52,7 @@
kInputPortIndex = 0,
kOutputPortIndex = 1,
kNumInputBuffers = 8,
- kNumOutputBuffers = 16,
+ kNumOutputBuffers = 2,
};
enum EOSStatus {
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index fd933cc..5cc3f78 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ColorConverter"
+#include <utils/Log.h>
+
#include <media/stagefright/ColorConverter.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaErrors.h>
@@ -424,61 +428,30 @@
status_t ColorConverter::convertTIYUV420PackedSemiPlanar(
const BitmapParams &src, const BitmapParams &dst) {
-
-/*
-The TIYUV420PackedSemiPlanar format is same as YUV420PackedSemiPlanar but with
-additional padding as shown in the diagram below. The padded width and padded
-height is different for different compression formats and it is read from the
-codec. In this color conversion routine, the padded resolution is obtained from
-src bitmap.
-
- ------------------------------------
-| |
-| |
-| ------------------------- |
-| | | |
-| | | |
-| | Y DATA | |
-| | | |
-| | | |
-| | | |
-| ------------------------- |
-| |
-| ------------ |
-| | | |
-| | | |
-| | UV DATA | |
-| | | |
-| | | |
-| | | |
-| ------------ |
-| |
-| |
- ------------------------------------
-*/
-
- LOGV("src.mCropLeft = %d src.mCropTop =%d src.mWidth = %d src.mHeight = %d"
- " dst.mWidth = %d dst.mHeight = %d", src.mCropLeft , src.mCropTop,
- src.mWidth, src.mHeight, dst.mWidth, dst.mHeight);
-
- size_t offset = (src.mWidth * src.mCropTop) + src.mCropLeft;
-
uint8_t *kAdjustedClip = initClip();
- uint32_t *dst_ptr = (uint32_t *)dst.mBits;
+ if (!((dst.mWidth & 3) == 0
+ && (src.mCropLeft & 1) == 0
+ && src.cropWidth() == dst.cropWidth()
+ && src.cropHeight() == dst.cropHeight())) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ uint32_t *dst_ptr = (uint32_t *)dst.mBits
+ + (dst.mCropTop * dst.mWidth + dst.mCropLeft) / 2;
+
const uint8_t *src_y = (const uint8_t *)src.mBits;
- const uint8_t *src_u = (const uint8_t *)(src_y-offset) + (src.mWidth * src.mHeight);
- src_u += ( ( src.mWidth * (src.mCropTop/2) ) + src.mCropLeft );
- const uint8_t *src_v = src_u + 1;
- for (size_t y = 0; y < dst.mHeight; ++y) {
- for (size_t x = 0; x < dst.mWidth; x += 2) {
+ const uint8_t *src_u =
+ (const uint8_t *)src_y + src.mWidth * (src.mHeight - src.mCropTop / 2);
- signed y1 = (signed)src_y[x] - 16; //Y pixel
- signed y2 = (signed)src_y[x + 1] - 16; //2nd Y pixel
+ for (size_t y = 0; y < src.cropHeight(); ++y) {
+ for (size_t x = 0; x < src.cropWidth(); x += 2) {
+ signed y1 = (signed)src_y[x] - 16;
+ signed y2 = (signed)src_y[x + 1] - 16;
- signed u = (signed)src_u[x & ~1] - 128; //U component
- signed v = (signed)src_u[(x & ~1) + 1] - 128; //V component
+ signed u = (signed)src_u[x & ~1] - 128;
+ signed v = (signed)src_u[(x & ~1) + 1] - 128;
signed u_b = u * 517;
signed u_g = -u * 100;
@@ -502,19 +475,21 @@
uint32_t rgb2 =
((kAdjustedClip[r2] >> 3) << 11)
- | ((kAdjustedClip[g1] >> 2) << 5)
- | (kAdjustedClip[b1] >> 3);
+ | ((kAdjustedClip[g2] >> 2) << 5)
+ | (kAdjustedClip[b2] >> 3);
dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
}
- src_y += src.mWidth; //increment Y-pixel line
- if (y&1) {
- src_u += src.mWidth; //increment U-V line
+ src_y += src.mWidth;
+
+ if (y & 1) {
+ src_u += src.mWidth;
}
dst_ptr += dst.mWidth / 2;
}
+
return OK;
}
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index a4e8ee4..a4ca32d 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -50,6 +50,9 @@
mCropBottom = mHeight - 1;
}
+ mCropWidth = mCropRight - mCropLeft + 1;
+ mCropHeight = mCropBottom - mCropTop + 1;
+
int32_t rotationDegrees;
if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
rotationDegrees = 0;
@@ -60,17 +63,18 @@
switch (mColorFormat) {
case OMX_COLOR_FormatYUV420Planar:
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
{
halFormat = HAL_PIXEL_FORMAT_YV12;
- bufWidth = (mWidth + 1) & ~1;
- bufHeight = (mHeight + 1) & ~1;
+ bufWidth = (mCropWidth + 1) & ~1;
+ bufHeight = (mCropHeight + 1) & ~1;
break;
}
default:
halFormat = HAL_PIXEL_FORMAT_RGB_565;
- bufWidth = mWidth;
- bufHeight = mHeight;
+ bufWidth = mCropWidth;
+ bufHeight = mCropHeight;
mConverter = new ColorConverter(
mColorFormat, OMX_COLOR_Format16bitRGB565);
@@ -79,8 +83,8 @@
}
CHECK(mNativeWindow != NULL);
- CHECK(mWidth > 0);
- CHECK(mHeight > 0);
+ CHECK(mCropWidth > 0);
+ CHECK(mCropHeight > 0);
CHECK(mConverter == NULL || mConverter->isValid());
CHECK_EQ(0,
@@ -109,14 +113,6 @@
CHECK_EQ(0, native_window_set_buffers_transform(
mNativeWindow.get(), transform));
}
-
- android_native_rect_t crop;
- crop.left = mCropLeft;
- crop.top = mCropTop;
- crop.right = mCropRight + 1;
- crop.bottom = mCropBottom + 1;
-
- CHECK_EQ(0, native_window_set_crop(mNativeWindow.get(), &crop));
}
SoftwareRenderer::~SoftwareRenderer() {
@@ -142,7 +138,7 @@
GraphicBufferMapper &mapper = GraphicBufferMapper::get();
- Rect bounds(mWidth, mHeight);
+ Rect bounds(mCropWidth, mCropHeight);
void *dst;
CHECK_EQ(0, mapper.lock(
@@ -152,13 +148,11 @@
mConverter->convert(
data,
mWidth, mHeight,
- 0, 0, mWidth - 1, mHeight - 1,
+ mCropLeft, mCropTop, mCropRight, mCropBottom,
dst,
buf->stride, buf->height,
- 0, 0, mWidth - 1, mHeight - 1);
- } else {
- CHECK_EQ(mColorFormat, OMX_COLOR_FormatYUV420Planar);
-
+ 0, 0, mCropWidth - 1, mCropHeight - 1);
+ } else if (mColorFormat == OMX_COLOR_FormatYUV420Planar) {
const uint8_t *src_y = (const uint8_t *)data;
const uint8_t *src_u = (const uint8_t *)data + mWidth * mHeight;
const uint8_t *src_v = src_u + (mWidth / 2 * mHeight / 2);
@@ -170,22 +164,57 @@
uint8_t *dst_v = dst_y + dst_y_size;
uint8_t *dst_u = dst_v + dst_c_size;
- for (int y = 0; y < mHeight; ++y) {
- memcpy(dst_y, src_y, mWidth);
+ for (int y = 0; y < mCropHeight; ++y) {
+ memcpy(dst_y, src_y, mCropWidth);
src_y += mWidth;
dst_y += buf->stride;
}
- for (int y = 0; y < (mHeight + 1) / 2; ++y) {
- memcpy(dst_u, src_u, (mWidth + 1) / 2);
- memcpy(dst_v, src_v, (mWidth + 1) / 2);
+ for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+ memcpy(dst_u, src_u, (mCropWidth + 1) / 2);
+ memcpy(dst_v, src_v, (mCropWidth + 1) / 2);
src_u += mWidth / 2;
src_v += mWidth / 2;
dst_u += dst_c_stride;
dst_v += dst_c_stride;
}
+ } else {
+ CHECK_EQ(mColorFormat, OMX_TI_COLOR_FormatYUV420PackedSemiPlanar);
+
+ const uint8_t *src_y =
+ (const uint8_t *)data;
+
+ const uint8_t *src_uv =
+ (const uint8_t *)data + mWidth * (mHeight - mCropTop / 2);
+
+ uint8_t *dst_y = (uint8_t *)dst;
+
+ size_t dst_y_size = buf->stride * buf->height;
+ size_t dst_c_stride = ALIGN(buf->stride / 2, 16);
+ size_t dst_c_size = dst_c_stride * buf->height / 2;
+ uint8_t *dst_v = dst_y + dst_y_size;
+ uint8_t *dst_u = dst_v + dst_c_size;
+
+ for (int y = 0; y < mCropHeight; ++y) {
+ memcpy(dst_y, src_y, mCropWidth);
+
+ src_y += mWidth;
+ dst_y += buf->stride;
+ }
+
+ for (int y = 0; y < (mCropHeight + 1) / 2; ++y) {
+ size_t tmp = (mCropWidth + 1) / 2;
+ for (size_t x = 0; x < tmp; ++x) {
+ dst_u[x] = src_uv[2 * x];
+ dst_v[x] = src_uv[2 * x + 1];
+ }
+
+ src_uv += mWidth;
+ dst_u += dst_c_stride;
+ dst_v += dst_c_stride;
+ }
}
CHECK_EQ(0, mapper.unlock(buf->handle));
diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h
index 78037b97..8f2ea95 100644
--- a/media/libstagefright/include/SoftwareRenderer.h
+++ b/media/libstagefright/include/SoftwareRenderer.h
@@ -47,6 +47,7 @@
sp<ANativeWindow> mNativeWindow;
int32_t mWidth, mHeight;
int32_t mCropLeft, mCropTop, mCropRight, mCropBottom;
+ int32_t mCropWidth, mCropHeight;
SoftwareRenderer(const SoftwareRenderer &);
SoftwareRenderer &operator=(const SoftwareRenderer &);
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index a404f1f..d4354db 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -485,24 +485,20 @@
};
static const MimeToURL kMimeToURL[] = {
{ "video/avc",
- "file:///sdcard/media_api/video/H264_AAC.3gp" },
- { "video/mp4v-es", "file:///sdcard/media_api/video/gingerkids.MP4" },
+ "file:///sdcard/media_api/video/H264_500_AAC_128.3gp" },
+ { "video/mp4v-es", "file:///sdcard/media_api/video/MPEG4_320_AAC_64.mp4" },
{ "video/3gpp",
"file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
{ "audio/3gpp",
"file:///sdcard/media_api/video/H263_500_AMRNB_12.3gp" },
- { "audio/amr-wb",
- "file:///sdcard/media_api/music/"
- "AI_AMR-WB_12.65kbps(13kbps)_16khz_mono_NMC.awb" },
+ { "audio/amr-wb", NULL },
{ "audio/mp4a-latm",
- "file:///sdcard/media_api/video/H264_AAC.3gp" },
+ "file:///sdcard/media_api/video/H263_56_AAC_24.3gp" },
{ "audio/mpeg",
- "file:///sdcard/media_api/music/MP3CBR.mp3" },
- { "audio/vorbis",
- "file:///sdcard/media_api/metaDataTestMedias/OGG/"
- "When You Say Nothing At All.ogg" },
+ "file:///sdcard/media_api/music/MP3_48KHz_128kbps_s_1_17_CBR.mp3" },
+ { "audio/vorbis", NULL },
{ "video/x-vnd.on2.vp8",
- "file:///sdcard/media_api/webm/big-buck-bunny_trailer.webm" },
+ "file:///sdcard/media_api/video/big-buck-bunny_trailer.webm" },
{ MEDIA_MIMETYPE_AUDIO_G711_ALAW, "file:///sdcard/M1F1-Alaw-AFsp.wav" },
{ MEDIA_MIMETYPE_AUDIO_G711_MLAW,
"file:///sdcard/M1F1-mulaw-AFsp.wav" },
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
index a3749cf..a583aad 100644
--- a/services/camera/libcameraservice/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -559,13 +559,8 @@
ANativeWindowBuffer* anb;
rc = a->dequeueBuffer(a, &anb);
if (!rc) {
- rc = a->lockBuffer(a, anb);
- if (!rc) {
- *buffer = &anb->handle;
- *stride = anb->stride;
- }
- else
- a->cancelBuffer(a, anb);
+ *buffer = &anb->handle;
+ *stride = anb->stride;
}
return rc;
}
@@ -576,6 +571,14 @@
(type *) ((char *) __mptr - (char *)(&((type *)0)->member)); })
#endif
+ static int __lock_buffer(struct preview_stream_ops* w,
+ buffer_handle_t* buffer)
+ {
+ ANativeWindow *a = anw(w);
+ return a->lockBuffer(a,
+ container_of(buffer, ANativeWindowBuffer, handle));
+ }
+
static int __enqueue_buffer(struct preview_stream_ops* w,
buffer_handle_t* buffer)
{
@@ -641,6 +644,7 @@
void initHalPreviewWindow()
{
mHalPreviewWindow.nw.cancel_buffer = __cancel_buffer;
+ mHalPreviewWindow.nw.lock_buffer = __lock_buffer;
mHalPreviewWindow.nw.dequeue_buffer = __dequeue_buffer;
mHalPreviewWindow.nw.enqueue_buffer = __enqueue_buffer;
mHalPreviewWindow.nw.set_buffer_count = __set_buffer_count;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 8ac8f2b..8fb6274 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -1610,6 +1610,16 @@
}
}
}
+
+ // TODO: Temporary notifying upstread change to Tethering.
+ // @see bug/4455071
+ /** Notify TetheringService if interface name has been changed. */
+ if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
+ Phone.REASON_LINK_PROPERTIES_CHANGED)) {
+ if (isTetheringSupported()) {
+ mTethering.handleTetherIfaceChange();
+ }
+ }
}
private void addPrivateDnsRoutes(NetworkStateTracker nt) {
@@ -2035,7 +2045,10 @@
break;
case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
info = (NetworkInfo) msg.obj;
- handleConnectivityChange(info.getType(), true);
+ // TODO: Temporary allowing network configuration
+ // change not resetting sockets.
+ // @see bug/4455071
+ handleConnectivityChange(info.getType(), false);
break;
case EVENT_CLEAR_NET_TRANSITION_WAKELOCK:
String causedBy = null;
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 2b01c5e..e730d0d 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -141,12 +141,26 @@
}
/**
- * Notify our observers of an interface link status change
+ * Notify our observers of an interface status change
*/
- private void notifyInterfaceLinkStatusChanged(String iface, boolean link) {
+ private void notifyInterfaceStatusChanged(String iface, boolean up) {
for (INetworkManagementEventObserver obs : mObservers) {
try {
- obs.interfaceLinkStatusChanged(iface, link);
+ obs.interfaceStatusChanged(iface, up);
+ } catch (Exception ex) {
+ Slog.w(TAG, "Observer notifier failed", ex);
+ }
+ }
+ }
+
+ /**
+ * Notify our observers of an interface link state change
+ * (typically, an Ethernet cable has been plugged-in or unplugged).
+ */
+ private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
+ for (INetworkManagementEventObserver obs : mObservers) {
+ try {
+ obs.interfaceLinkStateChanged(iface, up);
} catch (Exception ex) {
Slog.w(TAG, "Observer notifier failed", ex);
}
@@ -207,6 +221,7 @@
* Format: "NNN Iface added <name>"
* "NNN Iface removed <name>"
* "NNN Iface changed <name> <up/down>"
+ * "NNN Iface linkstatus <name> <up/down>"
*/
if (cooked.length < 4 || !cooked[1].equals("Iface")) {
throw new IllegalStateException(
@@ -219,7 +234,10 @@
notifyInterfaceRemoved(cooked[3]);
return true;
} else if (cooked[2].equals("changed") && cooked.length == 5) {
- notifyInterfaceLinkStatusChanged(cooked[3], cooked[4].equals("up"));
+ notifyInterfaceStatusChanged(cooked[3], cooked[4].equals("up"));
+ return true;
+ } else if (cooked[2].equals("linkstate") && cooked.length == 5) {
+ notifyInterfaceLinkStateChanged(cooked[3], cooked[4].equals("up"));
return true;
}
throw new IllegalStateException(
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 7266d7d..d81dfdb 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -179,14 +179,17 @@
mIface = iface;
}
- public void interfaceLinkStatusChanged(String iface, boolean link) {
- if (link) {
+ public void interfaceStatusChanged(String iface, boolean up) {
+ if (up) {
if (TextUtils.equals(iface, mIface)) {
mHandler.obtainMessage(mMsg).sendToTarget();
}
}
}
+ public void interfaceLinkStateChanged(String iface, boolean up) {
+ }
+
public void interfaceAdded(String iface) {
// TODO - an interface added in the UP state should also trigger a StatusChanged
// notification..
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index f6dd43a..a2019fc 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1131,7 +1131,9 @@
| AccessibilityEvent.TYPE_VIEW_HOVER_ENTER | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
| AccessibilityEvent.TYPE_VIEW_LONG_CLICKED | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
| AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_SELECTED
- | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+ | AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
+ | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
+ | AccessibilityEvent.TYPE_VIEW_SCROLLED;
private int mRetrievalAlowingWindowId;
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index aab189a6..1af7015 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -26,7 +26,6 @@
import android.os.Handler;
import android.os.SystemClock;
import android.util.Slog;
-import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.WindowManagerPolicy;
@@ -73,15 +72,6 @@
private static final int STATE_DRAGGING = 0x00000002;
private static final int STATE_DELEGATING = 0x00000004;
- // Human readable symbolic names for the states of the explorer.
- private static final SparseArray<String> sStateSymbolicNames = new SparseArray<String>();
- static {
- SparseArray<String> symbolicNames = sStateSymbolicNames;
- symbolicNames.append(STATE_TOUCH_EXPLORING, "STATE_TOUCH_EXPLORING");
- symbolicNames.append(STATE_DRAGGING, "STATE_DRAGING");
- symbolicNames.append(STATE_DELEGATING, "STATE_DELEGATING");
- }
-
// Invalid pointer ID.
private static final int INVALID_POINTER_ID = -1;
@@ -189,7 +179,7 @@
if (DEBUG) {
Slog.d(LOG_TAG_RECEIVED, "Received event: " + event + ", policyFlags=0x"
+ Integer.toHexString(policyFlags));
- Slog.d(LOG_TAG_STATE, sStateSymbolicNames.get(mCurrentState));
+ Slog.d(LOG_TAG_STATE, getStateSymbolicName(mCurrentState));
}
// Keep track of the pointers's state.
@@ -708,8 +698,7 @@
private void sendActionDownAndUp(MotionEvent prototype, int policyFlags) {
final PointerProperties[] pointerProperties = mTempPointerProperties;
final PointerCoords[] pointerCoords = mTempPointerCoords;
- final int pointerId = mPointerTracker.getLastReceivedUpPointerId();
- final int pointerIndex = prototype.findPointerIndex(pointerId);
+ final int pointerIndex = prototype.getActionIndex();
// Send down.
prototype.getPointerProperties(pointerIndex, pointerProperties[0]);
@@ -884,6 +873,25 @@
}
/**
+ * Gets the symbolic name of a state.
+ *
+ * @param state A state.
+ * @return The state symbolic name.
+ */
+ private static String getStateSymbolicName(int state) {
+ switch (state) {
+ case STATE_TOUCH_EXPLORING:
+ return "STATE_TOUCH_EXPLORING";
+ case STATE_DRAGGING:
+ return "STATE_DRAGGING";
+ case STATE_DELEGATING:
+ return "STATE_DELEGATING";
+ default:
+ throw new IllegalArgumentException("Unknown state: " + state);
+ }
+ }
+
+ /**
* Helper class for tracking pointers and more specifically which of
* them are currently down, which are active, and which are delivered
* to the view hierarchy. The enclosing {@link TouchExplorer} uses the
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 911cac2..6bb7949 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -189,8 +189,8 @@
mDnsServers[1] = DNS_DEFAULT_SERVER2;
}
- public void interfaceLinkStatusChanged(String iface, boolean link) {
- if (DEBUG) Log.d(TAG, "interfaceLinkStatusChanged " + iface + ", " + link);
+ public void interfaceStatusChanged(String iface, boolean up) {
+ if (DEBUG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
boolean found = false;
boolean usb = false;
if (isWifi(iface)) {
@@ -205,7 +205,7 @@
synchronized (mIfaces) {
TetherInterfaceSM sm = mIfaces.get(iface);
- if (link) {
+ if (up) {
if (sm == null) {
sm = new TetherInterfaceSM(iface, mLooper, usb);
mIfaces.put(iface, sm);
@@ -220,6 +220,11 @@
}
}
+ public void interfaceLinkStateChanged(String iface, boolean up) {
+ if (DEBUG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
+ interfaceStatusChanged(iface, up);
+ }
+
private boolean isUsb(String iface) {
for (String regex : mTetherableUsbRegexs) {
if (iface.matches(regex)) return true;
@@ -689,6 +694,14 @@
return retVal;
}
+ //TODO: Temporary handling upstream change triggered without
+ // CONNECTIVITY_ACTION. Only to accomodate interface
+ // switch during HO.
+ // @see bug/4455071
+ public void handleTetherIfaceChange() {
+ mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
+ }
+
class TetherInterfaceSM extends StateMachine {
// notification from the master SM that it's not in tether mode
static final int CMD_TETHER_MODE_DEAD = 1;
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index 47813f8..db3b61e 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -173,7 +173,11 @@
}
// INetworkManagementEventObserver.Stub
- public void interfaceLinkStatusChanged(String name, boolean up) {
+ public void interfaceStatusChanged(String name, boolean up) {
+ }
+
+ // INetworkManagementEventObserver.Stub
+ public void interfaceLinkStateChanged(String name, boolean up) {
}
// INetworkManagementEventObserver.Stub