Merge "Add a cached formatted phone number to call log."
diff --git a/CleanSpec.mk b/CleanSpec.mk
index eb8471a..1c85279 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -114,6 +114,7 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/fonts/Lohit_Hindi.ttf)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/fonts/DroidSans*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 034e3c7..4a144a2 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3246,6 +3246,7 @@
try {
String resolvedType = null;
if (fillInIntent != null) {
+ fillInIntent.setAllowFds(false);
resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
}
int result = ActivityManagerNative.getDefault()
@@ -3370,6 +3371,7 @@
if (mParent == null) {
int result = IActivityManager.START_RETURN_INTENT_TO_CALLER;
try {
+ intent.setAllowFds(false);
result = ActivityManagerNative.getDefault()
.startActivity(mMainThread.getApplicationThread(),
intent, intent.resolveTypeIfNeeded(
@@ -3419,6 +3421,7 @@
public boolean startNextMatchingActivity(Intent intent) {
if (mParent == null) {
try {
+ intent.setAllowFds(false);
return ActivityManagerNative.getDefault()
.startNextMatchingActivity(mToken, intent);
} catch (RemoteException e) {
@@ -3692,6 +3695,9 @@
}
if (false) Log.v(TAG, "Finishing self: token=" + mToken);
try {
+ if (resultData != null) {
+ resultData.setAllowFds(false);
+ }
if (ActivityManagerNative.getDefault()
.finishActivity(mToken, resultCode, resultData)) {
mFinished = true;
@@ -3812,6 +3818,7 @@
int flags) {
String packageName = getPackageName();
try {
+ data.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_ACTIVITY_RESULT, packageName,
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 0776e10..99aae37 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2674,6 +2674,7 @@
// Next have the activity save its current state and managed dialogs...
if (!r.activity.mFinished && saveState) {
state = new Bundle();
+ state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
r.state = state;
}
@@ -2775,6 +2776,7 @@
if (!r.activity.mFinished && saveState) {
if (r.state == null) {
state = new Bundle();
+ state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, state);
r.state = state;
} else {
@@ -3306,6 +3308,7 @@
}
if (r.state == null && !r.stopped && !r.isPreHoneycomb()) {
r.state = new Bundle();
+ r.state.setAllowFds(false);
mInstrumentation.callActivityOnSaveInstanceState(r.activity, r.state);
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 2139704..2bf1fb7 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -874,6 +874,7 @@
try {
String resolvedType = null;
if (fillInIntent != null) {
+ fillInIntent.setAllowFds(false);
resolvedType = fillInIntent.resolveTypeIfNeeded(getContentResolver());
}
int result = ActivityManagerNative.getDefault()
@@ -892,6 +893,7 @@
public void sendBroadcast(Intent intent) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, false, false);
@@ -903,6 +905,7 @@
public void sendBroadcast(Intent intent, String receiverPermission) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, receiverPermission, false, false);
@@ -915,6 +918,7 @@
String receiverPermission) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, receiverPermission, true, false);
@@ -946,6 +950,7 @@
}
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, receiverPermission,
@@ -958,6 +963,7 @@
public void sendStickyBroadcast(Intent intent) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, null,
Activity.RESULT_OK, null, null, null, false, true);
@@ -989,6 +995,7 @@
}
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().broadcastIntent(
mMainThread.getApplicationThread(), intent, resolvedType, rd,
initialCode, initialData, initialExtras, null,
@@ -1005,6 +1012,7 @@
intent.setDataAndType(intent.getData(), resolvedType);
}
try {
+ intent.setAllowFds(false);
ActivityManagerNative.getDefault().unbroadcastIntent(
mMainThread.getApplicationThread(), intent);
} catch (RemoteException e) {
@@ -1069,6 +1077,7 @@
@Override
public ComponentName startService(Intent service) {
try {
+ service.setAllowFds(false);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()));
@@ -1086,6 +1095,7 @@
@Override
public boolean stopService(Intent service) {
try {
+ service.setAllowFds(false);
int res = ActivityManagerNative.getDefault().stopService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()));
@@ -1116,6 +1126,7 @@
< android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
flags |= BIND_WAIVE_PRIORITY;
}
+ service.setAllowFds(false);
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
@@ -1148,6 +1159,9 @@
public boolean startInstrumentation(ComponentName className,
String profileFile, Bundle arguments) {
try {
+ if (arguments != null) {
+ arguments.setAllowFds(false);
+ }
return ActivityManagerNative.getDefault().startInstrumentation(
className, profileFile, 0, arguments, null);
} catch (RemoteException e) {
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index f3bc495..d7f5c55 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1375,6 +1375,7 @@
}
}
try {
+ intent.setAllowFds(false);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
@@ -1415,6 +1416,7 @@
try {
String[] resolvedTypes = new String[intents.length];
for (int i=0; i<intents.length; i++) {
+ intents[i].setAllowFds(false);
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
}
int result = ActivityManagerNative.getDefault()
@@ -1471,6 +1473,7 @@
}
}
try {
+ intent.setAllowFds(false);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 2549c84..522f477 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -661,6 +661,9 @@
"Finishing broadcast to unregistered receiver");
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
+ if (extras != null) {
+ extras.setAllowFds(false);
+ }
mgr.finishReceiver(this, resultCode, data, extras, false);
} catch (RemoteException e) {
Slog.w(ActivityThread.TAG, "Couldn't finish broadcast to unregistered receiver");
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index b4827cb..b0637a7 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -192,6 +192,7 @@
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
+ intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_ACTIVITY, packageName,
@@ -249,6 +250,7 @@
String packageName = context.getPackageName();
String[] resolvedTypes = new String[intents.length];
for (int i=0; i<intents.length; i++) {
+ intents[i].setAllowFds(false);
resolvedTypes[i] = intents[i].resolveTypeIfNeeded(context.getContentResolver());
}
try {
@@ -287,6 +289,7 @@
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
+ intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_BROADCAST, packageName,
@@ -324,6 +327,7 @@
String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
context.getContentResolver()) : null;
try {
+ intent.setAllowFds(false);
IIntentSender target =
ActivityManagerNative.getDefault().getIntentSender(
IActivityManager.INTENT_SENDER_SERVICE, packageName,
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index 028149b..3cbaf92 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -366,6 +366,9 @@
mFinished = true;
try {
+ if (mResultExtras != null) {
+ mResultExtras.setAllowFds(false);
+ }
if (mOrderedHint) {
am.finishReceiver(mToken, mResultCode, mResultData, mResultExtras,
mAbortBroadcast);
@@ -462,6 +465,7 @@
IActivityManager am = ActivityManagerNative.getDefault();
IBinder binder = null;
try {
+ service.setAllowFds(false);
binder = am.peekService(service, service.resolveTypeIfNeeded(
myContext.getContentResolver()));
} catch (RemoteException e) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index f44d038..08fe0aa 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3568,6 +3568,13 @@
return mExtras != null && mExtras.hasFileDescriptors();
}
+ /** @hide */
+ public void setAllowFds(boolean allowFds) {
+ if (mExtras != null) {
+ mExtras.setAllowFds(allowFds);
+ }
+ }
+
/**
* Retrieve extended data from the intent.
*
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index c288f8a..28206b7 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -54,6 +54,7 @@
private boolean mHasFds = false;
private boolean mFdsKnown = true;
+ private boolean mAllowFds = true;
/**
* The ClassLoader used when unparcelling data from mParcelledData.
@@ -186,7 +187,14 @@
public ClassLoader getClassLoader() {
return mClassLoader;
}
-
+
+ /** @hide */
+ public boolean setAllowFds(boolean allowFds) {
+ boolean orig = mAllowFds;
+ mAllowFds = allowFds;
+ return orig;
+ }
+
/**
* Clones the current Bundle. The internal map is cloned, but the keys and
* values to which it refers are copied by reference.
@@ -1589,24 +1597,29 @@
* @param parcel The parcel to copy this bundle to.
*/
public void writeToParcel(Parcel parcel, int flags) {
- if (mParcelledData != null) {
- int length = mParcelledData.dataSize();
- parcel.writeInt(length);
- parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
- parcel.appendFrom(mParcelledData, 0, length);
- } else {
- parcel.writeInt(-1); // dummy, will hold length
- parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
-
- int oldPos = parcel.dataPosition();
- parcel.writeMapInternal(mMap);
- int newPos = parcel.dataPosition();
-
- // Backpatch length
- parcel.setDataPosition(oldPos - 8);
- int length = newPos - oldPos;
- parcel.writeInt(length);
- parcel.setDataPosition(newPos);
+ final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
+ try {
+ if (mParcelledData != null) {
+ int length = mParcelledData.dataSize();
+ parcel.writeInt(length);
+ parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
+ parcel.appendFrom(mParcelledData, 0, length);
+ } else {
+ parcel.writeInt(-1); // dummy, will hold length
+ parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
+
+ int oldPos = parcel.dataPosition();
+ parcel.writeMapInternal(mMap);
+ int newPos = parcel.dataPosition();
+
+ // Backpatch length
+ parcel.setDataPosition(oldPos - 8);
+ int length = newPos - oldPos;
+ parcel.writeInt(length);
+ parcel.setDataPosition(newPos);
+ }
+ } finally {
+ parcel.restoreAllowFds(oldAllowFds);
}
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index e9ed676..15e3af4 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -323,6 +323,12 @@
*/
public final native void setDataCapacity(int size);
+ /** @hide */
+ public final native boolean pushAllowFds(boolean allowFds);
+
+ /** @hide */
+ public final native void restoreAllowFds(boolean lastValue);
+
/**
* Returns the raw bytes of the parcel.
*
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index e954983..34e7d4d 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -153,6 +153,18 @@
public abstract MenuInflater getMenuInflater();
/**
+ * Returns whether the UI presenting this action mode can take focus or not.
+ * This is used by internal components within the framework that would otherwise
+ * present an action mode UI that requires focus, such as an EditText as a custom view.
+ *
+ * @return true if the UI used to show this action mode can take focus
+ * @hide Internal use only
+ */
+ public boolean isUiFocusable() {
+ return true;
+ }
+
+ /**
* Callback interface for action modes. Supplied to
* {@link View#startActionMode(Callback)}, a Callback
* configures and handles events raised by a user's interaction with an action mode.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d193d6e..9628afb 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1487,6 +1487,18 @@
}
/**
+ * Accessibility event types that are dispatched for text population.
+ */
+ private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
+ AccessibilityEvent.TYPE_VIEW_CLICKED
+ | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
+ | AccessibilityEvent.TYPE_VIEW_SELECTED
+ | AccessibilityEvent.TYPE_VIEW_FOCUSED
+ | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
+ | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
+ | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT;
+
+ /**
* Temporary Rect currently for use in setBackground(). This will probably
* be extended in the future to hold our own class with more than just
* a Rect. :)
@@ -3855,7 +3867,10 @@
return;
}
onInitializeAccessibilityEvent(event);
- dispatchPopulateAccessibilityEvent(event);
+ // Only a subset of accessibility events populates text content.
+ if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
+ dispatchPopulateAccessibilityEvent(event);
+ }
// In the beginning we called #isShown(), so we know that getParent() is not null.
getParent().requestSendAccessibilityEvent(this, event);
}
@@ -3876,6 +3891,10 @@
* {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
* is responsible for handling this call.
* </p>
+ * <p>
+ * <em>Note:</em> Accessibility events of certain types are not dispatched for
+ * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
+ * </p>
*
* @param event The event.
*
@@ -3895,12 +3914,6 @@
* Note: Called from the default {@link AccessibilityDelegate}.
*/
boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
- // Do not populate text to scroll events. They describe position change
- // and usually come from container with a lot of text which is not very
- // informative for accessibility purposes. Also they are fired frequently.
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
- return true;
- }
onPopulateAccessibilityEvent(event);
return false;
}
@@ -12093,6 +12106,39 @@
}
/**
+ * Finds a view by its unuque and stable accessibility id.
+ *
+ * @param accessibilityId The searched accessibility id.
+ * @return The found view.
+ */
+ final View findViewByAccessibilityId(int accessibilityId) {
+ if (accessibilityId < 0) {
+ return null;
+ }
+ return findViewByAccessibilityIdTraversal(accessibilityId);
+ }
+
+ /**
+ * Performs the traversal to find a view by its unuque and stable accessibility id.
+ *
+ * <strong>Note:</strong>This method does not stop at the root namespace
+ * boundary since the user can touch the screen at an arbitrary location
+ * potentially crossing the root namespace bounday which will send an
+ * accessibility event to accessibility services and they should be able
+ * to obtain the event source. Also accessibility ids are guaranteed to be
+ * unique in the window.
+ *
+ * @param accessibilityId The accessibility id.
+ * @return The found view.
+ */
+ View findViewByAccessibilityIdTraversal(int accessibilityId) {
+ if (getAccessibilityViewId() == accessibilityId) {
+ return this;
+ }
+ return null;
+ }
+
+ /**
* Look for a child view with the given tag. If this view has the given
* tag, return this view.
*
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index fb0d80a..5b4a6f8 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -821,6 +821,24 @@
}
}
+ @Override
+ View findViewByAccessibilityIdTraversal(int accessibilityId) {
+ View foundView = super.findViewByAccessibilityIdTraversal(accessibilityId);
+ if (foundView != null) {
+ return foundView;
+ }
+ final int childrenCount = mChildrenCount;
+ final View[] children = mChildren;
+ for (int i = 0; i < childrenCount; i++) {
+ View child = children[i];
+ foundView = child.findViewByAccessibilityIdTraversal(accessibilityId);
+ if (foundView != null) {
+ return foundView;
+ }
+ }
+ return null;
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 9cb4e5e..e7c91f9 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -74,7 +74,6 @@
import android.widget.Scroller;
import com.android.internal.policy.PolicyManager;
-import com.android.internal.util.Predicate;
import com.android.internal.view.BaseSurfaceHolder;
import com.android.internal.view.IInputMethodCallback;
import com.android.internal.view.IInputMethodSession;
@@ -4462,9 +4461,6 @@
final class AccessibilityInteractionController {
private static final int POOL_SIZE = 5;
- private FindByAccessibilitytIdPredicate mFindByAccessibilityIdPredicate =
- new FindByAccessibilitytIdPredicate();
-
private ArrayList<AccessibilityNodeInfo> mTempAccessibilityNodeInfoList =
new ArrayList<AccessibilityNodeInfo>();
@@ -4551,11 +4547,8 @@
AccessibilityNodeInfo info = null;
try {
- FindByAccessibilitytIdPredicate predicate = mFindByAccessibilityIdPredicate;
- predicate.init(accessibilityId);
- View root = ViewRootImpl.this.mView;
- View target = root.findViewByPredicate(predicate);
- if (target != null && target.getVisibility() == View.VISIBLE) {
+ View target = findViewByAccessibilityId(accessibilityId);
+ if (target != null) {
info = target.createAccessibilityNodeInfo();
}
} finally {
@@ -4794,25 +4787,12 @@
if (root == null) {
return null;
}
- mFindByAccessibilityIdPredicate.init(accessibilityId);
- View foundView = root.findViewByPredicate(mFindByAccessibilityIdPredicate);
- if (foundView == null || foundView.getVisibility() != View.VISIBLE) {
+ View foundView = root.findViewByAccessibilityId(accessibilityId);
+ if (foundView != null && foundView.getVisibility() != View.VISIBLE) {
return null;
}
return foundView;
}
-
- private final class FindByAccessibilitytIdPredicate implements Predicate<View> {
- public int mSearchedId;
-
- public void init(int searchedId) {
- mSearchedId = searchedId;
- }
-
- public boolean apply(View view) {
- return (view.getAccessibilityViewId() == mSearchedId);
- }
- }
}
private class SendWindowContentChangedAccessibilityEvent implements Runnable {
@@ -4820,18 +4800,7 @@
public void run() {
if (mView != null) {
- // Check again for accessibility state since this is executed delayed.
- AccessibilityManager accessibilityManager =
- AccessibilityManager.getInstance(mView.mContext);
- if (accessibilityManager.isEnabled()) {
- // 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.sendAccessibilityEvent(event);
- }
+ mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
mIsPending = false;
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index c93b564..91fbb0e 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -69,14 +69,16 @@
* <em>Type:</em>{@link #TYPE_VIEW_CLICKED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <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 #getText()} - The text of the source's sub-tree.</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 #getContentDescription()} - The content description of the source.</li>
* </ul>
* </p>
* <p>
@@ -85,14 +87,16 @@
* <em>Type:</em>{@link #TYPE_VIEW_LONG_CLICKED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <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 #getText()} - The text of the source's sub-tree.</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 #getContentDescription()} - The content description of the source.</li>
* </ul>
* </p>
* <p>
@@ -101,16 +105,18 @@
* <em>Type:</em> {@link #TYPE_VIEW_SELECTED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <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 #getText()} - The text of the source's sub-tree.</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>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
* </p>
* <p>
@@ -119,16 +125,18 @@
* <em>Type:</em> {@link #TYPE_VIEW_FOCUSED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <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 #getText()} - The text of the source's sub-tree.</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>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
* </p>
* <p>
@@ -137,6 +145,7 @@
* <em>Type:</em> {@link #TYPE_VIEW_TEXT_CHANGED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <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>
@@ -149,7 +158,17 @@
* <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>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
* </p>
* <p>
* <b>View text selection changed</b> - represents the event of changing the text
@@ -157,35 +176,47 @@
* <em>Type:</em> {@link #TYPE_VIEW_TEXT_SELECTION_CHANGED} </br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <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>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
* </p>
* <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
+ * is unaware of 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>
* <em>Type:</em> {@link #TYPE_VIEW_SCROLLED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <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 #getText()} - The text of the source's sub-tree.</li>
* <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* <li>{@link #getScrollX()} - The horizontal offset of the source
* (without descendants of AdapterView)).</li>
@@ -197,56 +228,165 @@
* (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>
+ * <li>{@link #getText()} - Text for providing more context.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
* </p>
* <p>
* <b>TRANSITION TYPES</b></br>
* </p>
+ * <p>
* <b>Window state changed</b> - represents the event of opening a
* {@link android.widget.PopupWindow}, {@link android.view.Menu},
* {@link android.app.Dialog}, etc.</br>
* <em>Type:</em> {@link #TYPE_WINDOW_STATE_CHANGED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <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 #getText()} - The text of the source's sub-tree.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* </ul>
* </p>
* <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>
+ * </p>
* <p>
* <strong>Note:</strong> This event is fired only for the window source of the
- * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED})
+ * last accessibility event different from {@link #TYPE_NOTIFICATION_STATE_CHANGED}
* and its purpose is to notify clients that the content of the user interaction
- * window has changed.
- * </p>
+ * window has changed.</br>
* <em>Type:</em> {@link #TYPE_WINDOW_CONTENT_CHANGED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
* <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>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
+ * </p>
* <p>
* <b>NOTIFICATION TYPES</b></br>
+ * </p>
* <p>
* <b>Notification state changed</b> - represents the event showing
- * {@link android.app.Notification}.
+ * {@link android.app.Notification}.</br>
* <em>Type:</em> {@link #TYPE_NOTIFICATION_STATE_CHANGED}</br>
* <em>Properties:</em></br>
* <ul>
+ * <li>{@link #getEventType()} - The type of the event.</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 #getText()} - The text of the source's sub-tree.</li>
* <li>{@link #getParcelableData()} - The posted {@link android.app.Notification}.</li>
+ * <li>{@link #getText()} - Text for providing more context.</li>
* </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
+ * </p>
+ * <p>
+ * <b>EXPLORATION TYPES</b></br>
+ * </p>
+ * <p>
+ * <b>View hover enter</b> - represents the event of beginning to hover
+ * over a {@link android.view.View}. The hover may be generated via
+ * exploring the screen by touch or via a pointing device.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_HOVER_ENTER}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
+ * <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's sub-tree.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
+ * </ul>
+ * </p>
+ * <b>View hover exit</b> - represents the event of stopping to hover
+ * over a {@link android.view.View}. The hover may be generated via
+ * exploring the screen by touch or via a pointing device.</br>
+ * <em>Type:</em> {@link #TYPE_VIEW_HOVER_EXIT}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
+ * <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's sub-tree.</li>
+ * <li>{@link #isEnabled()} - Whether the source is enabled.</li>
+ * <li>{@link #getContentDescription()} - The content description of the source.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * <b>Touch exploration gesture start</b> - represents the event of starting a touch
+ * exploring gesture.</br>
+ * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_START}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
+ * </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
+ * </p>
+ * <p>
+ * <b>Touch exploration gesture end</b> - represents the event of ending a touch
+ * exploring gesture.</br>
+ * <em>Type:</em> {@link #TYPE_TOUCH_EXPLORATION_GESTURE_END}</br>
+ * <em>Properties:</em></br>
+ * <ul>
+ * <li>{@link #getEventType()} - The type of the event.</li>
+ * </ul>
+ * <em>Note:</em> This event type is not dispatched to descendants though
+ * {@link android.view.View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.dispatchPopulateAccessibilityEvent(AccessibilityEvent)}, hence the event
+ * source {@link android.view.View} and the sub-tree rooted at it will not receive
+ * calls to {@link android.view.View#onPopulateAccessibilityEvent(AccessibilityEvent)
+ * View.onPopulateAccessibilityEvent(AccessibilityEvent)}. The preferred way to add
+ * text content to such events is by setting the
+ * {@link android.R.styleable#View_contentDescription contentDescription} of the source
+ * view.</br>
* </p>
* <p>
* <b>Security note</b>
@@ -254,6 +394,7 @@
* Since an event contains the text of its source privacy can be compromised by leaking
* sensitive information such as passwords. To address this issue any event fired in response
* to manipulation of a PASSWORD field does NOT CONTAIN the text of the password.
+ * </p>
*
* @see android.view.accessibility.AccessibilityManager
* @see android.accessibilityservice.AccessibilityService
diff --git a/core/java/android/webkit/FindActionModeCallback.java b/core/java/android/webkit/FindActionModeCallback.java
index a322fa3d..7398262 100644
--- a/core/java/android/webkit/FindActionModeCallback.java
+++ b/core/java/android/webkit/FindActionModeCallback.java
@@ -180,6 +180,14 @@
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ if (!mode.isUiFocusable()) {
+ // If the action mode we're running in is not focusable the user
+ // will not be able to type into the find on page field. This
+ // should only come up when we're running in a dialog which is
+ // already less than ideal; disable the option for now.
+ return false;
+ }
+
mode.setCustomView(mCustomView);
mode.getMenuInflater().inflate(com.android.internal.R.menu.webview_find,
menu);
diff --git a/core/java/android/webkit/SelectActionModeCallback.java b/core/java/android/webkit/SelectActionModeCallback.java
index 104deb1..8c174aa 100644
--- a/core/java/android/webkit/SelectActionModeCallback.java
+++ b/core/java/android/webkit/SelectActionModeCallback.java
@@ -17,13 +17,12 @@
package android.webkit;
import android.app.SearchManager;
+import android.content.Context;
import android.content.Intent;
import android.provider.Browser;
-import android.webkit.WebView;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
-import android.view.View;
class SelectActionModeCallback implements ActionMode.Callback {
private WebView mWebView;
@@ -45,9 +44,25 @@
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- mode.getMenuInflater().inflate(com.android.internal.R.menu.webview_copy,
- menu);
- mode.setTitle(com.android.internal.R.string.textSelectionCABTitle);
+ mode.getMenuInflater().inflate(com.android.internal.R.menu.webview_copy, menu);
+
+ final Context context = mWebView.getContext();
+ boolean allowText = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon);
+ mode.setTitle(allowText ?
+ context.getString(com.android.internal.R.string.textSelectionCABTitle) : null);
+
+ if (!mode.isUiFocusable()) {
+ // If the action mode UI we're running in isn't capable of taking window focus
+ // the user won't be able to type into the find on page UI. Disable this functionality.
+ // (Note that this should only happen in floating dialog windows.)
+ // This can be removed once we can handle multiple focusable windows at a time
+ // in a better way.
+ final MenuItem findOnPageItem = menu.findItem(com.android.internal.R.id.find);
+ if (findOnPageItem != null) {
+ findOnPageItem.setVisible(false);
+ }
+ }
mActionMode = mode;
return true;
}
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 217ad7c..092e2b5 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -1092,4 +1092,11 @@
return url != null ? url.getProtocol() + "://" + url.getHost() + url.getPath() : null;
}
+
+ public void setGravityForRtl(boolean rtl) {
+ int gravity = rtl ? Gravity.RIGHT : Gravity.LEFT;
+ gravity |= mSingle ? Gravity.CENTER_VERTICAL : Gravity.TOP;
+ setGravity(gravity);
+ }
+
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 370cce4..eaed9fe 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -4078,8 +4078,8 @@
boolean pressed = (mTouchMode == TOUCH_SHORTPRESS_START_MODE
|| mTouchMode == TOUCH_INIT_MODE
|| mTouchMode == TOUCH_SHORTPRESS_MODE);
- nativeRecordButtons(hasFocus() && hasWindowFocus(),
- (pressed && !USE_WEBKIT_RINGS)
+ recordButtons(canvas,
+ hasFocus() && hasWindowFocus(), (pressed && !USE_WEBKIT_RINGS)
|| mTrackballDown || mGotCenterDown, false);
drawCoreAndCursorRing(canvas, mBackgroundColor,
mDrawCursorRing && drawRings);
@@ -4760,12 +4760,12 @@
}
String text = nativeFocusCandidateText();
int nodePointer = nativeFocusCandidatePointer();
- mWebTextView.setGravity(nativeFocusCandidateIsRtlText() ?
- Gravity.RIGHT : Gravity.NO_GRAVITY);
// This needs to be called before setType, which may call
// requestFormData, and it needs to have the correct nodePointer.
mWebTextView.setNodePointer(nodePointer);
mWebTextView.setType(nativeFocusCandidateType());
+ // Gravity needs to be set after setType
+ mWebTextView.setGravityForRtl(nativeFocusCandidateIsRtlText());
updateWebTextViewPadding();
if (null == text) {
if (DebugFlags.WEB_VIEW) {
@@ -5133,7 +5133,7 @@
.obtainMessage(LONG_PRESS_CENTER), LONG_PRESS_TIMEOUT);
// Already checked mNativeClass, so we do not need to check it
// again.
- nativeRecordButtons(hasFocus() && hasWindowFocus(), true, true);
+ recordButtons(null, hasFocus() && hasWindowFocus(), true, true);
if (!wantsKeyEvents) return true;
}
// Bubble up the key event as WebView doesn't handle it
@@ -5561,7 +5561,7 @@
mDrawCursorRing = true;
setFocusControllerActive(true);
if (mNativeClass != 0) {
- nativeRecordButtons(true, false, true);
+ recordButtons(null, true, false, true);
}
} else {
if (!inEditingMode()) {
@@ -5570,7 +5570,7 @@
mDrawCursorRing = false;
setFocusControllerActive(false);
}
- // We do not call nativeRecordButtons here because we assume
+ // We do not call recordButtons here because we assume
// that when we lost focus, or window focus, it got called with
// false for the first parameter
}
@@ -5589,7 +5589,7 @@
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
mTouchMode = TOUCH_DONE_MODE;
if (mNativeClass != 0) {
- nativeRecordButtons(false, false, true);
+ recordButtons(null, false, false, true);
}
setFocusControllerActive(false);
}
@@ -5647,13 +5647,13 @@
if (hasWindowFocus()) {
mDrawCursorRing = true;
if (mNativeClass != 0) {
- nativeRecordButtons(true, false, true);
+ recordButtons(null, true, false, true);
}
setFocusControllerActive(true);
//} else {
// The WebView has gained focus while we do not have
// windowfocus. When our window lost focus, we should have
- // called nativeRecordButtons(false...)
+ // called recordButtons(false...)
}
} else {
// When we lost focus, unless focus went to the TextView (which is
@@ -5661,7 +5661,7 @@
if (!inEditingMode()) {
mDrawCursorRing = false;
if (mNativeClass != 0) {
- nativeRecordButtons(false, false, true);
+ recordButtons(null, false, false, true);
}
setFocusControllerActive(false);
}
@@ -6762,7 +6762,7 @@
if (mNativeClass == 0) {
return false;
}
- nativeRecordButtons(hasFocus() && hasWindowFocus(), true, true);
+ recordButtons(null, hasFocus() && hasWindowFocus(), true, true);
if (time - mLastCursorTime <= TRACKBALL_TIMEOUT
&& !mLastCursorBounds.equals(nativeGetCursorRingBounds())) {
nativeSelectBestAt(mLastCursorBounds);
@@ -9349,6 +9349,24 @@
return nativeTileProfilingGetFloat(frame, tile, key);
}
+ /**
+ * Helper method to deal with differences between hardware and software rendering
+ */
+ private void recordButtons(Canvas canvas, boolean focus, boolean pressed,
+ boolean inval) {
+ boolean isHardwareAccel = canvas != null
+ ? canvas.isHardwareAccelerated()
+ : isHardwareAccelerated();
+ if (isHardwareAccel) {
+ // We never want to change button state if we are hardware accelerated,
+ // but we DO want to invalidate as necessary so that the GL ring
+ // can be drawn
+ nativeRecordButtons(false, false, inval);
+ } else {
+ nativeRecordButtons(focus, pressed, inval);
+ }
+ }
+
private native int nativeCacheHitFramePointer();
private native boolean nativeCacheHitIsPlugin();
private native Rect nativeCacheHitNodeBounds();
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index c37cc52..60b24bc 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -33,6 +33,8 @@
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
import android.widget.ActivityChooserModel.ActivityChooserModelClient;
/**
@@ -169,6 +171,11 @@
private boolean mIsAttachedToWindow;
/**
+ * String resource for formatting content description of the default target.
+ */
+ private int mDefaultActionButtonContentDescription;
+
+ /**
* Create a new instance.
*
* @param context The application environment.
@@ -259,7 +266,7 @@
*
* <strong>Note:</strong> Clients would like to set this drawable
* as a clue about the action the chosen activity will perform. For
- * example, if share activity is to be chosen the drawable should
+ * example, if a share activity is to be chosen the drawable should
* give a clue that sharing is to be performed.
*
* @param drawable The drawable.
@@ -269,6 +276,21 @@
}
/**
+ * Sets the content description for the button that expands the activity
+ * overflow list.
+ *
+ * description as a clue about the action performed by the button.
+ * For example, if a share activity is to be chosen the content
+ * description should be something like "Share with".
+ *
+ * @param resourceId The content description resource id.
+ */
+ public void setExpandActivityOverflowButtonContentDescription(int resourceId) {
+ CharSequence contentDescription = mContext.getString(resourceId);
+ mExpandActivityOverflowButtonImage.setContentDescription(contentDescription);
+ }
+
+ /**
* Set the provider hosting this view, if applicable.
* @hide Internal use only
*/
@@ -329,6 +351,8 @@
if (mProvider != null) {
mProvider.subUiVisibilityChanged(true);
}
+ popupWindow.getListView().setContentDescription(mContext.getString(
+ R.string.activitychooserview_choose_application));
}
}
@@ -431,6 +455,20 @@
}
/**
+ * Sets a content description of the default action button. This
+ * resource should be a string taking one formatting argument and
+ * will be used for formatting the content description of the button
+ * dynamically as the default target changes. For example, a resource
+ * pointing to the string "share with %1$s" will result in a content
+ * description "share with Bluetooth" for the Bluetooth activity.
+ *
+ * @param resourceId The resource id.
+ */
+ public void setDefaultActionButtonContentDescription(int resourceId) {
+ mDefaultActionButtonContentDescription = resourceId;
+ }
+
+ /**
* Gets the list popup window which is lazily initialized.
*
* @return The popup.
@@ -465,6 +503,12 @@
ResolveInfo activity = mAdapter.getDefaultActivity();
PackageManager packageManager = mContext.getPackageManager();
mDefaultActivityButtonImage.setImageDrawable(activity.loadIcon(packageManager));
+ if (mDefaultActionButtonContentDescription != 0) {
+ CharSequence label = activity.loadLabel(packageManager);
+ String contentDescription = mContext.getString(
+ mDefaultActionButtonContentDescription, label);
+ mDefaultActivityButton.setContentDescription(contentDescription);
+ }
} else {
mDefaultActivityButton.setVisibility(View.GONE);
}
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index a4b4e78..61c5dd4 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -881,20 +881,14 @@
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
- final int eventType = event.getEventType();
- switch (eventType) {
- case AccessibilityEvent.TYPE_VIEW_SCROLLED:
- // Do not populate the text of scroll events.
- return true;
- case AccessibilityEvent.TYPE_VIEW_FOCUSED:
- // This is an exceptional case which occurs when a window gets the
- // focus and sends a focus event via its focused child to announce
- // current focus/selection. AdapterView fires selection but not focus
- // events so we change the event type here.
- if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
- event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
- }
- break;
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
+ // This is an exceptional case which occurs when a window gets the
+ // focus and sends a focus event via its focused child to announce
+ // current focus/selection. AdapterView fires selection but not focus
+ // events so we change the event type here.
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
+ event.setEventType(AccessibilityEvent.TYPE_VIEW_SELECTED);
+ }
}
View selectedView = getSelectedView();
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 84ebec3..63a0870 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -25,6 +25,7 @@
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
+import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.AttributeSet;
import android.view.View;
@@ -228,6 +229,8 @@
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
mChanged = true;
+
+ updateContentDescription(mCalendar);
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -243,4 +246,11 @@
invalidate();
}
};
+
+ private void updateContentDescription(Time time) {
+ final int flags = DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_24HOUR;
+ String contentDescription = DateUtils.formatDateTime(mContext,
+ time.toMillis(false), flags);
+ setContentDescription(contentDescription);
+ }
}
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index 3f5b571c..a0eba9a 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -371,16 +371,6 @@
}
}
- @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).
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index 1bbc501..324dfd7 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -725,16 +725,6 @@
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 61ea5c9..3ac4e80 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -730,16 +730,6 @@
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/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 3627890..bb27b73 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -171,6 +171,12 @@
activityChooserView.setExpandActivityOverflowButtonDrawable(drawable);
activityChooserView.setProvider(this);
+ // Set content description.
+ activityChooserView.setDefaultActionButtonContentDescription(
+ R.string.shareactionprovider_share_with_application);
+ activityChooserView.setExpandActivityOverflowButtonContentDescription(
+ R.string.shareactionprovider_share_with);
+
return activityChooserView;
}
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index ac9535a..772c129 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -30,8 +30,6 @@
import com.android.internal.util.ArrayUtils;
-import java.util.Locale;
-
/**
* Helper class for TextView. Bridge between the TextView and the Dictionnary service.
@@ -167,15 +165,12 @@
@Override
public void onGetSuggestions(SuggestionsInfo[] results) {
- final Editable editable = (Editable) mTextView.getText();
for (int i = 0; i < results.length; i++) {
SuggestionsInfo suggestionsInfo = results[i];
if (suggestionsInfo.getCookie() != mCookie) continue;
final int sequenceNumber = suggestionsInfo.getSequence();
for (int j = 0; j < mLength; j++) {
- final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[j];
-
if (sequenceNumber == mIds[j]) {
final int attributes = suggestionsInfo.getSuggestionsAttributes();
boolean isInDictionary =
@@ -184,31 +179,78 @@
((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_TYPO) > 0);
if (!isInDictionary && looksLikeTypo) {
- String[] suggestions = getSuggestions(suggestionsInfo);
- SuggestionSpan suggestionSpan = new SuggestionSpan(
- mTextView.getContext(), suggestions,
- SuggestionSpan.FLAG_EASY_CORRECT |
- SuggestionSpan.FLAG_MISSPELLED);
- final int start = editable.getSpanStart(spellCheckSpan);
- final int end = editable.getSpanEnd(spellCheckSpan);
- editable.setSpan(suggestionSpan, start, end,
- Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- // TODO limit to the word rectangle region
- mTextView.invalidate();
+ createMisspelledSuggestionSpan(suggestionsInfo, mSpellCheckSpans[j]);
}
- editable.removeSpan(spellCheckSpan);
+ break;
}
}
}
}
- private static String[] getSuggestions(SuggestionsInfo suggestionsInfo) {
- // A negative suggestion count is possible
- final int len = Math.max(0, suggestionsInfo.getSuggestionsCount());
- String[] suggestions = new String[len];
- for (int j = 0; j < len; j++) {
- suggestions[j] = suggestionsInfo.getSuggestionAt(j);
+ private void createMisspelledSuggestionSpan(SuggestionsInfo suggestionsInfo,
+ SpellCheckSpan spellCheckSpan) {
+ final Editable editable = (Editable) mTextView.getText();
+ final int start = editable.getSpanStart(spellCheckSpan);
+ final int end = editable.getSpanEnd(spellCheckSpan);
+
+ // Other suggestion spans may exist on that region, with identical suggestions, filter
+ // them out to avoid duplicates. First, filter suggestion spans on that exact region.
+ SuggestionSpan[] suggestionSpans = editable.getSpans(start, end, SuggestionSpan.class);
+ final int length = suggestionSpans.length;
+ for (int i = 0; i < length; i++) {
+ final int spanStart = editable.getSpanStart(suggestionSpans[i]);
+ final int spanEnd = editable.getSpanEnd(suggestionSpans[i]);
+ if (spanStart != start || spanEnd != end) {
+ suggestionSpans[i] = null;
+ break;
+ }
}
- return suggestions;
+
+ final int suggestionsCount = suggestionsInfo.getSuggestionsCount();
+ String[] suggestions;
+ if (suggestionsCount <= 0) {
+ // A negative suggestion count is possible
+ suggestions = ArrayUtils.emptyArray(String.class);
+ } else {
+ int numberOfSuggestions = 0;
+ suggestions = new String[suggestionsCount];
+
+ for (int i = 0; i < suggestionsCount; i++) {
+ final String spellSuggestion = suggestionsInfo.getSuggestionAt(i);
+ if (spellSuggestion == null) break;
+ boolean suggestionFound = false;
+
+ for (int j = 0; j < length && !suggestionFound; j++) {
+ if (suggestionSpans[j] == null) break;
+
+ String[] suggests = suggestionSpans[j].getSuggestions();
+ for (int k = 0; k < suggests.length; k++) {
+ if (spellSuggestion.equals(suggests[k])) {
+ // The suggestion is already provided by an other SuggestionSpan
+ suggestionFound = true;
+ break;
+ }
+ }
+ }
+
+ if (!suggestionFound) {
+ suggestions[numberOfSuggestions++] = spellSuggestion;
+ }
+ }
+
+ if (numberOfSuggestions != suggestionsCount) {
+ String[] newSuggestions = new String[numberOfSuggestions];
+ System.arraycopy(suggestions, 0, newSuggestions, 0, numberOfSuggestions);
+ suggestions = newSuggestions;
+ }
+ }
+
+ SuggestionSpan suggestionSpan = new SuggestionSpan(mTextView.getContext(), suggestions,
+ SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED);
+ editable.setSpan(suggestionSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+ // TODO limit to the word rectangle region
+ mTextView.invalidate();
+ editable.removeSpan(spellCheckSpan);
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5cd7902..f833bb5 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -353,6 +353,8 @@
// Set when this TextView gained focus with some text selected. Will start selection mode.
private boolean mCreatedWithASelection = false;
+ // Size of the window for the word iterator, should be greater than the longest word's length
+ private static final int WORD_ITERATOR_WINDOW_WIDTH = 50;
private WordIterator mWordIterator;
private SpellChecker mSpellChecker;
@@ -2937,11 +2939,19 @@
Spannable sp = new SpannableString(mText);
- for (ChangeWatcher cw :
- sp.getSpans(0, sp.length(), ChangeWatcher.class)) {
+ for (ChangeWatcher cw : sp.getSpans(0, sp.length(), ChangeWatcher.class)) {
sp.removeSpan(cw);
}
+ SuggestionSpan[] suggestionSpans = sp.getSpans(0, sp.length(), SuggestionSpan.class);
+ for (int i = 0; i < suggestionSpans.length; i++) {
+ int flags = suggestionSpans[i].getFlags();
+ if ((flags & SuggestionSpan.FLAG_EASY_CORRECT) != 0
+ && (flags & SuggestionSpan.FLAG_MISSPELLED) != 0) {
+ sp.removeSpan(suggestionSpans[i]);
+ }
+ }
+
sp.removeSpan(mSuggestionRangeSpan);
ss.text = sp;
@@ -4449,7 +4459,6 @@
if (mSpellChecker != null) {
mSpellChecker.closeSession();
- removeMisspelledSpans();
// Forces the creation of a new SpellChecker next time this window is created.
// Will handle the cases where the settings has been changed in the meantime.
mSpellChecker = null;
@@ -8461,24 +8470,6 @@
}
}
- /**
- * Removes the suggestion spans for misspelled words.
- */
- private void removeMisspelledSpans() {
- if (mText instanceof Spannable) {
- Spannable spannable = (Spannable) mText;
- SuggestionSpan[] suggestionSpans = spannable.getSpans(0,
- spannable.length(), SuggestionSpan.class);
- for (int i = 0; i < suggestionSpans.length; i++) {
- int flags = suggestionSpans[i].getFlags();
- if ((flags & SuggestionSpan.FLAG_EASY_CORRECT) != 0
- && (flags & SuggestionSpan.FLAG_MISSPELLED) != 0) {
- spannable.removeSpan(suggestionSpans[i]);
- }
- }
- }
- }
-
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (mMovement != null && mText instanceof Spannable && mLayout != null) {
@@ -8959,9 +8950,8 @@
mWordIterator = new WordIterator();
}
- final int TEXT_WINDOW_WIDTH = 50; // Should be larger than the longest word's length
- final int windowStart = Math.max(0, start - TEXT_WINDOW_WIDTH);
- final int windowEnd = Math.min(mText.length(), end + TEXT_WINDOW_WIDTH);
+ final int windowStart = Math.max(0, start - WORD_ITERATOR_WINDOW_WIDTH);
+ final int windowEnd = Math.min(mText.length(), end + WORD_ITERATOR_WINDOW_WIDTH);
mWordIterator.setCharSequence(mText.subSequence(windowStart, windowEnd));
return windowStart;
@@ -9930,7 +9920,7 @@
// Fallback on the default highlight color when the first span does not provide one
mSuggestionRangeSpan.setBackgroundColor(mHighlightColor);
} else {
- final float BACKGROUND_TRANSPARENCY = 0.3f;
+ final float BACKGROUND_TRANSPARENCY = 0.4f;
final int newAlpha = (int) (Color.alpha(underlineColor) * BACKGROUND_TRANSPARENCY);
mSuggestionRangeSpan.setBackgroundColor(
(underlineColor & 0x00FFFFFF) + (newAlpha << 24));
@@ -9996,7 +9986,9 @@
intent.putExtra("word", originalText);
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
- suggestionInfo.removeMisspelledFlag();
+ // There is no way to know if the word was indeed added. Re-check.
+ editable.removeSpan(suggestionInfo.suggestionSpan);
+ updateSpellCheckSpans(spanStart, spanEnd);
} else {
// SuggestionSpans are removed by replace: save them before
SuggestionSpan[] suggestionSpans = editable.getSpans(spanStart, spanEnd,
@@ -10256,7 +10248,8 @@
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- TypedArray styledAttributes = mContext.obtainStyledAttributes(R.styleable.Theme);
+ TypedArray styledAttributes = mContext.obtainStyledAttributes(
+ com.android.internal.R.styleable.SelectionModeDrawables);
boolean allowText = getContext().getResources().getBoolean(
com.android.internal.R.bool.config_allowActionMenuItemTextWithIcon);
@@ -10269,7 +10262,7 @@
if (!allowText) {
// Provide an icon, text will not be displayed on smaller screens.
selectAllIconId = styledAttributes.getResourceId(
- R.styleable.Theme_actionModeSelectAllDrawable, 0);
+ R.styleable.SelectionModeDrawables_actionModeSelectAllDrawable, 0);
}
menu.add(0, ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
@@ -10281,7 +10274,7 @@
if (canCut()) {
menu.add(0, ID_CUT, 0, com.android.internal.R.string.cut).
setIcon(styledAttributes.getResourceId(
- R.styleable.Theme_actionModeCutDrawable, 0)).
+ R.styleable.SelectionModeDrawables_actionModeCutDrawable, 0)).
setAlphabeticShortcut('x').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
@@ -10290,7 +10283,7 @@
if (canCopy()) {
menu.add(0, ID_COPY, 0, com.android.internal.R.string.copy).
setIcon(styledAttributes.getResourceId(
- R.styleable.Theme_actionModeCopyDrawable, 0)).
+ R.styleable.SelectionModeDrawables_actionModeCopyDrawable, 0)).
setAlphabeticShortcut('c').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
@@ -10299,7 +10292,7 @@
if (canPaste()) {
menu.add(0, ID_PASTE, 0, com.android.internal.R.string.paste).
setIcon(styledAttributes.getResourceId(
- R.styleable.Theme_actionModePasteDrawable, 0)).
+ R.styleable.SelectionModeDrawables_actionModePasteDrawable, 0)).
setAlphabeticShortcut('v').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 7444d46..f52e773 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -237,9 +237,7 @@
}
// set the content descriptions
- if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- setContentDescriptions();
- }
+ setContentDescriptions();
}
@Override
diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java
index ecda47e..edf4443 100644
--- a/core/java/com/android/internal/view/StandaloneActionMode.java
+++ b/core/java/com/android/internal/view/StandaloneActionMode.java
@@ -36,17 +36,19 @@
private ActionMode.Callback mCallback;
private WeakReference<View> mCustomView;
private boolean mFinished;
+ private boolean mFocusable;
private MenuBuilder mMenu;
public StandaloneActionMode(Context context, ActionBarContextView view,
- ActionMode.Callback callback) {
+ ActionMode.Callback callback, boolean isFocusable) {
mContext = context;
mContextView = view;
mCallback = callback;
mMenu = new MenuBuilder(context).setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
mMenu.setCallback(this);
+ mFocusable = isFocusable;
}
@Override
@@ -139,4 +141,8 @@
invalidate();
mContextView.showOverflowMenu();
}
+
+ public boolean isUiFocusable() {
+ return mFocusable;
+ }
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 4a38775..4d1276c 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -24,11 +24,15 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
import android.os.FileObserver;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.os.storage.IMountService;
import android.provider.Settings;
import android.security.KeyStore;
@@ -55,6 +59,8 @@
*/
public class LockPatternUtils {
+ private static final String OPTION_ENABLE_FACELOCK = "enable_facelock";
+
private static final String TAG = "LockPatternUtils";
private static final String SYSTEM_DIRECTORY = "/system/";
@@ -110,6 +116,7 @@
public static final String PASSWORD_TYPE_ALTERNATE_KEY = "lockscreen.password_type_alternate";
private final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
private final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
+ private final static String LOCKSCREEN_OPTIONS = "lockscreen.options";
public final static String LOCKSCREEN_BIOMETRIC_WEAK_FALLBACK
= "lockscreen.biometric_weak_fallback";
@@ -434,7 +441,7 @@
* Calls back SetupFaceLock to delete the gallery file when the lock type is changed
*/
void deleteGallery() {
- if(isBiometricEnabled()) {
+ if(usingBiometricWeak()) {
Intent intent = new Intent().setClassName("com.android.facelock",
"com.android.facelock.SetupFaceLock");
intent.putExtra("deleteGallery", true);
@@ -677,6 +684,9 @@
return quality;
}
+ /**
+ * @return true if the lockscreen method is set to biometric weak
+ */
public boolean usingBiometricWeak() {
int quality =
(int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
@@ -810,7 +820,7 @@
|| backupMode == DevicePolicyManager.PASSWORD_QUALITY_COMPLEX;
return savedPasswordExists() && (passwordEnabled ||
- (isBiometricEnabled() && backupEnabled));
+ (usingBiometricWeak() && backupEnabled));
}
/**
@@ -824,16 +834,36 @@
return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED)
&& (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
== DevicePolicyManager.PASSWORD_QUALITY_SOMETHING ||
- (isBiometricEnabled() && backupEnabled));
+ (usingBiometricWeak() && backupEnabled));
}
/**
- * @return Whether biometric weak lock is enabled.
+ * @return Whether biometric weak lock is installed and that the front facing camera exists
*/
- public boolean isBiometricEnabled() {
- // TODO: check if it's installed
- return getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
- == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
+ public boolean isBiometricWeakInstalled() {
+ // Check that the system flag was set
+ if (!OPTION_ENABLE_FACELOCK.equals(getString(LOCKSCREEN_OPTIONS))) {
+ return false;
+ }
+
+ // Check that it's installed
+ PackageManager pm = mContext.getPackageManager();
+ try {
+ pm.getPackageInfo("com.android.facelock", PackageManager.GET_ACTIVITIES);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+
+ // Check that the camera is enabled
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)) {
+ return false;
+ }
+ if (getDevicePolicyManager().getCameraDisabled(null)) {
+ return false;
+ }
+
+
+ return true;
}
/**
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 18bd754..da055fc 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -392,10 +392,20 @@
SkSafeUnref(ctable);
size_t size = bitmap->getSize();
+
+ android::Parcel::ReadableBlob blob;
+ android::status_t status = p->readBlob(size, &blob);
+ if (status) {
+ doThrowRE(env, "Could not read bitmap from parcel blob.");
+ delete bitmap;
+ return NULL;
+ }
+
bitmap->lockPixels();
- memcpy(bitmap->getPixels(), p->readInplace(size), size);
+ memcpy(bitmap->getPixels(), blob.data(), size);
bitmap->unlockPixels();
+ blob.release();
return GraphicsJNI::createBitmap(env, bitmap, buffer, isMutable, NULL, density);
}
@@ -431,17 +441,24 @@
}
size_t size = bitmap->getSize();
+
+ android::Parcel::WritableBlob blob;
+ android::status_t status = p->writeBlob(size, &blob);
+ if (status) {
+ doThrowRE(env, "Could not write bitmap to parcel blob.");
+ return false;
+ }
+
bitmap->lockPixels();
- void* pDst = p->writeInplace(size);
-
const void* pSrc = bitmap->getPixels();
-
if (pSrc == NULL) {
- memset(pDst, 0, size);
+ memset(blob.data(), 0, size);
} else {
- memcpy(pDst, pSrc, size);
+ memcpy(blob.data(), pSrc, size);
}
bitmap->unlockPixels();
+
+ blob.release();
return true;
}
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 86ae7d2..9ba95bd 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -251,26 +251,32 @@
}
}
-bool TextLayoutCacheKey::operator<(const TextLayoutCacheKey& rhs) const {
- LTE_INT(count) {
- LTE_INT(typeface) {
- LTE_FLOAT(textSize) {
- LTE_FLOAT(textSkewX) {
- LTE_FLOAT(textScaleX) {
- LTE_INT(flags) {
- LTE_INT(hinting) {
- LTE_INT(dirFlags) {
- return memcmp(getText(), rhs.getText(),
- count * sizeof(UChar)) < 0;
- }
- }
- }
- }
- }
- }
- }
- }
- return false;
+int TextLayoutCacheKey::compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
+ int deltaInt = lhs.count - rhs.count;
+ if (deltaInt != 0) return (deltaInt);
+
+ if (lhs.typeface < rhs.typeface) return -1;
+ if (lhs.typeface > rhs.typeface) return +1;
+
+ if (lhs.textSize < rhs.textSize) return -1;
+ if (lhs.textSize > rhs.textSize) return +1;
+
+ if (lhs.textSkewX < rhs.textSkewX) return -1;
+ if (lhs.textSkewX > rhs.textSkewX) return +1;
+
+ if (lhs.textScaleX < rhs.textScaleX) return -1;
+ if (lhs.textScaleX > rhs.textScaleX) return +1;
+
+ deltaInt = lhs.flags - rhs.flags;
+ if (deltaInt != 0) return (deltaInt);
+
+ deltaInt = lhs.hinting - rhs.hinting;
+ if (deltaInt != 0) return (deltaInt);
+
+ deltaInt = lhs.dirFlags - rhs.dirFlags;
+ if (deltaInt) return (deltaInt);
+
+ return memcmp(lhs.getText(), rhs.getText(), lhs.count * sizeof(UChar));
}
void TextLayoutCacheKey::internalTextCopy() {
@@ -620,7 +626,9 @@
return;
}
*outStartIndex = mLogClusters[start];
- *outGlyphsCount = mLogClusters[start + count - 1] - mLogClusters[start] + 1;
+ size_t endIndex = (start + count >= mAdvances.size()) ?
+ mGlyphs.size() : mLogClusters[start + count];
+ *outGlyphsCount = endIndex - *outStartIndex;
#if DEBUG_GLYPHS
LOGD("getGlyphsIndexes - start=%d count=%d - startIndex=%d count=%d", start, count,
*outStartIndex, *outGlyphsCount);
diff --git a/core/jni/android/graphics/TextLayoutCache.h b/core/jni/android/graphics/TextLayoutCache.h
index 35dd6fd..6dda1e5 100644
--- a/core/jni/android/graphics/TextLayoutCache.h
+++ b/core/jni/android/graphics/TextLayoutCache.h
@@ -72,8 +72,6 @@
TextLayoutCacheKey(const TextLayoutCacheKey& other);
- bool operator<(const TextLayoutCacheKey& rhs) const;
-
/**
* We need to copy the text when we insert the key into the cache itself.
* We don't need to copy the text when we are only comparing keys.
@@ -85,6 +83,8 @@
*/
size_t getSize();
+ static int compare(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs);
+
private:
const UChar* text; // if text is NULL, use textCopy
String16 textCopy;
@@ -97,11 +97,18 @@
uint32_t flags;
SkPaint::Hinting hinting;
- inline const UChar* getText() const {
- return text ? text : textCopy.string();
- }
+ inline const UChar* getText() const { return text ? text : textCopy.string(); }
+
}; // TextLayoutCacheKey
+inline int strictly_order_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
+ return TextLayoutCacheKey::compare(lhs, rhs) < 0;
+}
+
+inline int compare_type(const TextLayoutCacheKey& lhs, const TextLayoutCacheKey& rhs) {
+ return TextLayoutCacheKey::compare(lhs, rhs);
+}
+
/*
* TextLayoutCacheValue is the Cache value
*/
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 494a2b3..1718e74 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -697,6 +697,10 @@
LOGE("!!! FAILED BINDER TRANSACTION !!!");
//jniThrowException(env, "java/lang/OutOfMemoryError", "Binder transaction too large");
break;
+ case FDS_NOT_ALLOWED:
+ jniThrowException(env, "java/lang/RuntimeException",
+ "Not allowed to write file descriptors here");
+ break;
default:
LOGE("Unknown binder error code. 0x%x", err);
}
@@ -1275,7 +1279,7 @@
if (parcel != NULL) {
const status_t err = parcel->setDataSize(size);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1294,11 +1298,29 @@
if (parcel != NULL) {
const status_t err = parcel->setDataCapacity(size);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
+static jboolean android_os_Parcel_pushAllowFds(JNIEnv* env, jobject clazz, jboolean allowFds)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ jboolean ret = JNI_TRUE;
+ if (parcel != NULL) {
+ ret = (jboolean)parcel->pushAllowFds(allowFds);
+ }
+ return ret;
+}
+
+static void android_os_Parcel_restoreAllowFds(JNIEnv* env, jobject clazz, jboolean lastValue)
+{
+ Parcel* parcel = parcelForJavaObject(env, clazz);
+ if (parcel != NULL) {
+ parcel->restoreAllowFds((bool)lastValue);
+ }
+}
+
static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz,
jobject data, jint offset,
jint length)
@@ -1310,12 +1332,13 @@
const status_t err = parcel->writeInt32(length);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
+ return;
}
void* dest = parcel->writeInplace(length);
if (dest == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, NO_MEMORY);
return;
}
@@ -1333,7 +1356,7 @@
if (parcel != NULL) {
const status_t err = parcel->writeInt32(val);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1344,7 +1367,7 @@
if (parcel != NULL) {
const status_t err = parcel->writeInt64(val);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1355,7 +1378,7 @@
if (parcel != NULL) {
const status_t err = parcel->writeFloat(val);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1366,7 +1389,7 @@
if (parcel != NULL) {
const status_t err = parcel->writeDouble(val);
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1386,7 +1409,7 @@
err = parcel->writeString16(NULL, 0);
}
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1397,7 +1420,7 @@
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1409,7 +1432,7 @@
const status_t err =
parcel->writeDupFileDescriptor(jniGetFDFromFileDescriptor(env, object));
if (err != NO_ERROR) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ signalExceptionForError(env, clazz, err);
}
}
}
@@ -1717,7 +1740,10 @@
return;
}
- (void) thisParcel->appendFrom(otherParcel, offset, length);
+ status_t err = thisParcel->appendFrom(otherParcel, offset, length);
+ if (err != NO_ERROR) {
+ signalExceptionForError(env, clazz, err);
+ }
}
static jboolean android_os_Parcel_hasFileDescriptors(JNIEnv* env, jobject clazz)
@@ -1792,6 +1818,8 @@
{"setDataSize", "(I)V", (void*)android_os_Parcel_setDataSize},
{"setDataPosition", "(I)V", (void*)android_os_Parcel_setDataPosition},
{"setDataCapacity", "(I)V", (void*)android_os_Parcel_setDataCapacity},
+ {"pushAllowFds", "(Z)Z", (void*)android_os_Parcel_pushAllowFds},
+ {"restoreAllowFds", "(Z)V", (void*)android_os_Parcel_restoreAllowFds},
{"writeNative", "([BII)V", (void*)android_os_Parcel_writeNative},
{"writeInt", "(I)V", (void*)android_os_Parcel_writeInt},
{"writeLong", "(J)V", (void*)android_os_Parcel_writeLong},
diff --git a/core/res/res/drawable-hdpi/stat_sys_adb.png b/core/res/res/drawable-hdpi/stat_sys_adb.png
index 8e15aba2..e7e1d8d 100644
--- a/core/res/res/drawable-hdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-hdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_adb.png b/core/res/res/drawable-mdpi/stat_sys_adb.png
index ebedfa3..86d113f 100644
--- a/core/res/res/drawable-mdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-mdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_adb.png b/core/res/res/drawable-xhdpi/stat_sys_adb.png
index 92f8dd4..684d57a 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_adb.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_adb.png
Binary files differ
diff --git a/core/res/res/layout/screen_simple_overlay_action_mode.xml b/core/res/res/layout/screen_simple_overlay_action_mode.xml
new file mode 100644
index 0000000..eb093e7
--- /dev/null
+++ b/core/res/res/layout/screen_simple_overlay_action_mode.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+This is an optimized layout for a screen, with the minimum set of features
+enabled.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:fitsSystemWindows="true">
+ <FrameLayout
+ android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:foregroundInsidePadding="false"
+ android:foregroundGravity="fill_horizontal|top"
+ android:foreground="?android:attr/windowContentOverlay" />
+ <ViewStub android:id="@+id/action_mode_bar_stub"
+ android:inflatedId="@+id/action_mode_bar"
+ android:layout="@layout/action_mode_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+</FrameLayout>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index c990125..a27abb3 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3181,6 +3181,12 @@
<!-- Base text color, typeface, size, and style. -->
<attr name="textAppearance" />
</declare-styleable>
+ <declare-styleable name="SelectionModeDrawables">
+ <attr name="actionModeSelectAllDrawable" />
+ <attr name="actionModeCutDrawable" />
+ <attr name="actionModeCopyDrawable" />
+ <attr name="actionModePasteDrawable" />
+ </declare-styleable>
<declare-styleable name="SuggestionSpan">
<attr name="textUnderlineColor" />
<attr name="textUnderlineThickness" />
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 727c6ea..dbd49fb 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1566,7 +1566,7 @@
<!-- The attribute that holds a Base64-encoded public key. -->
<attr name="publicKey" format="string" />
- <!-- Attributes relating to a package verifier -->
+ <!-- Attributes relating to a package verifier. -->
<declare-styleable name="AndroidManifestPackageVerifier" parent="AndroidManifest">
<!-- Specifies the Java-style package name that defines this
package verifier. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 2d5d4cc..1e0151a 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3182,6 +3182,16 @@
<!-- Description of the Enter button in a KeyboardView. [CHAR LIMIT=NONE] -->
<string name="keyboardview_keycode_enter">Enter</string>
+ <!-- ActivityChooserView - accessibility support -->
+ <!-- Description of the shwoing of a popup window with activities to choose from. [CHAR LIMIT=NONE] -->
+ <string name="activitychooserview_choose_application">Choose an application</string>
+
+ <!-- ShareActionProvider - accessibility support -->
+ <!-- Description of the choose target button in a ShareActionProvider (share UI). [CHAR LIMIT=NONE] -->
+ <string name="shareactionprovider_share_with">Share with</string>
+ <!-- Description of a share target (both in the list of such or the default share button) in a ShareActionProvider (share UI). [CHAR LIMIT=NONE] -->
+ <string name="shareactionprovider_share_with_application">Share with <xliff:g id="application_name" example="Bluetooth">%s</xliff:g></string>
+
<!-- Slide lock screen -->
<!-- Description of the sliding handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index b6e213c..13de1c9 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -250,7 +250,7 @@
</style>
<style name="TextAppearance.EasyCorrectSuggestion" parent="TextAppearance.Suggestion">
- <item name="android:textUnderlineColor">#ff888888</item>
+ <item name="android:textUnderlineColor">#ffC8C8C8</item>
</style>
<style name="TextAppearance.MisspelledSuggestion" parent="TextAppearance.Suggestion">
diff --git a/data/sounds/AudioPackage7.mk b/data/sounds/AudioPackage7.mk
index 16171dc..9983f38 100755
--- a/data/sounds/AudioPackage7.mk
+++ b/data/sounds/AudioPackage7.mk
@@ -27,17 +27,24 @@
$(LOCAL_PATH)/effects/ogg/Lock.ogg:system/media/audio/ui/Lock.ogg \
$(LOCAL_PATH)/effects/ogg/Unlock.ogg:system/media/audio/ui/Unlock.ogg \
$(LOCAL_PATH)/notifications/ogg/Altair.ogg:system/media/audio/notifications/Altair.ogg \
- $(LOCAL_PATH)/notifications/ogg/Antares.ogg:system/media/audio/notifications/Antares.ogg \
- $(LOCAL_PATH)/notifications/ogg/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \
- $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
- $(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
- $(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Arcturus.ogg:system/media/audio/notifications/Arcturus.ogg \
$(LOCAL_PATH)/notifications/ogg/Betelgeuse.ogg:system/media/audio/notifications/Betelgeuse.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Capella.ogg:system/media/audio/notifications/Capella.ogg \
+ $(LOCAL_PATH)/notifications/ogg/CetiAlpha.ogg:system/media/audio/notifications/CetiAlpha.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Deneb.ogg:system/media/audio/notifications/Deneb.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Hojus.ogg:system/media/audio/notifications/Hojus.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Lalande.ogg:system/media/audio/notifications/Lalande.ogg \
$(LOCAL_PATH)/notifications/ogg/Mira.ogg:system/media/audio/notifications/Mira.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Polaris.ogg:system/media/audio/notifications/Polaris.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Procyon.ogg:system/media/audio/notifications/Procyon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Proxima.ogg:system/media/audio/notifications/Proxima.ogg \
$(LOCAL_PATH)/notifications/ogg/Upsilon.ogg:system/media/audio/notifications/Upsilon.ogg \
+ $(LOCAL_PATH)/notifications/ogg/Vega.ogg:system/media/audio/notifications/Vega.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Acheron.ogg:system/media/audio/ringtones/Acheron.ogg \
$(LOCAL_PATH)/ringtones/ogg/Andromeda.ogg:system/media/audio/ringtones/Andromeda.ogg \
$(LOCAL_PATH)/ringtones/ogg/Aquila.ogg:system/media/audio/ringtones/Aquila.ogg \
$(LOCAL_PATH)/ringtones/ogg/ArgoNavis.ogg:system/media/audio/ringtones/ArgoNavis.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/CanisMajor.ogg:system/media/audio/ringtones/CanisMajor.ogg \
$(LOCAL_PATH)/ringtones/ogg/Carina.ogg:system/media/audio/ringtones/Carina.ogg \
$(LOCAL_PATH)/ringtones/ogg/Cassiopeia.ogg:system/media/audio/ringtones/Cassiopeia.ogg \
$(LOCAL_PATH)/ringtones/ogg/Centaurus.ogg:system/media/audio/ringtones/Centaurus.ogg \
@@ -45,8 +52,10 @@
$(LOCAL_PATH)/ringtones/ogg/Draco.ogg:system/media/audio/ringtones/Draco.ogg \
$(LOCAL_PATH)/ringtones/ogg/Hydra.ogg:system/media/audio/ringtones/Hydra.ogg \
$(LOCAL_PATH)/ringtones/ogg/Machina.ogg:system/media/audio/ringtones/Machina.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Nasqueron.ogg:system/media/audio/ringtones/Nasqueron.ogg \
$(LOCAL_PATH)/ringtones/ogg/Orion.ogg:system/media/audio/ringtones/Orion.ogg \
$(LOCAL_PATH)/ringtones/ogg/Pegasus.ogg:system/media/audio/ringtones/Pegasus.ogg \
+ $(LOCAL_PATH)/ringtones/ogg/Perseus.ogg:system/media/audio/ringtones/Perseus.ogg \
$(LOCAL_PATH)/ringtones/ogg/Pyxis.ogg:system/media/audio/ringtones/Pyxis.ogg \
$(LOCAL_PATH)/ringtones/ogg/Rigel.ogg:system/media/audio/ringtones/Rigel.ogg \
$(LOCAL_PATH)/ringtones/ogg/Scarabaeus.ogg:system/media/audio/ringtones/Scarabaeus.ogg \
diff --git a/data/sounds/notifications/ogg/Arcturus.ogg b/data/sounds/notifications/ogg/Arcturus.ogg
new file mode 100644
index 0000000..8b83285
--- /dev/null
+++ b/data/sounds/notifications/ogg/Arcturus.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Capella.ogg b/data/sounds/notifications/ogg/Capella.ogg
new file mode 100755
index 0000000..88a955d
--- /dev/null
+++ b/data/sounds/notifications/ogg/Capella.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/CetiAlpha.ogg b/data/sounds/notifications/ogg/CetiAlpha.ogg
new file mode 100644
index 0000000..cd09526
--- /dev/null
+++ b/data/sounds/notifications/ogg/CetiAlpha.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Polaris.ogg b/data/sounds/notifications/ogg/Polaris.ogg
new file mode 100755
index 0000000..0f63a65
--- /dev/null
+++ b/data/sounds/notifications/ogg/Polaris.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Procyon.ogg b/data/sounds/notifications/ogg/Procyon.ogg
new file mode 100755
index 0000000..e5ffcdb
--- /dev/null
+++ b/data/sounds/notifications/ogg/Procyon.ogg
Binary files differ
diff --git a/data/sounds/notifications/ogg/Vega.ogg b/data/sounds/notifications/ogg/Vega.ogg
new file mode 100644
index 0000000..7cdbf21
--- /dev/null
+++ b/data/sounds/notifications/ogg/Vega.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Acheron.ogg b/data/sounds/ringtones/ogg/Acheron.ogg
new file mode 100644
index 0000000..67d7388
--- /dev/null
+++ b/data/sounds/ringtones/ogg/Acheron.ogg
Binary files differ
diff --git a/data/sounds/ringtones/ogg/Nasqueron.ogg b/data/sounds/ringtones/ogg/Nasqueron.ogg
new file mode 100644
index 0000000..ae1a725
--- /dev/null
+++ b/data/sounds/ringtones/ogg/Nasqueron.ogg
Binary files differ
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 464430b..1e3e275 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -101,41 +101,41 @@
</a></div>
<ul>
<li><a href="<?cs var:toroot ?>guide/topics/ui/declaring-layout.html">
- <span class="en">Declaring Layout</span>
- </a></li>
- <li><a href="<?cs var:toroot ?>guide/topics/ui/menus.html">
- <span class="en">Creating Menus</span>
- </a></li>
- <li><a href="<?cs var:toroot ?>guide/topics/ui/actionbar.html">
- <span class="en">Using the Action Bar</span>
- </a></li>
- <li><a href="<?cs var:toroot ?>guide/topics/ui/dialogs.html">
- <span class="en">Creating Dialogs</span>
+ <span class="en">XML Layouts</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/ui-events.html">
- <span class="en">Handling UI Events</span>
+ <span class="en">Input Events</span>
+ </a></li>
+ <li><a href="<?cs var:toroot ?>guide/topics/ui/menus.html">
+ <span class="en">Menus</span>
+ </a></li>
+ <li><a href="<?cs var:toroot ?>guide/topics/ui/actionbar.html">
+ <span class="en">Action Bar</span>
+ </a></li>
+ <li><a href="<?cs var:toroot ?>guide/topics/ui/dialogs.html">
+ <span class="en">Dialogs</span>
</a></li>
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/topics/ui/notifiers/index.html">
- <span class="en">Notifying the User</span>
+ <span class="en">Notifications</span>
</a></div>
<ul>
<li><a href="<?cs var:toroot ?>guide/topics/ui/notifiers/toasts.html">
- <span class="en">Creating Toast Notifications</span>
+ <span class="en">Toast Notifications</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/notifiers/notifications.html">
- <span class="en">Creating Status Bar Notifications</span>
+ <span class="en">Status Bar Notifications</span>
</a></li>
</ul>
</li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/drag-drop.html">
- <span class="en">Dragging and Dropping</span>
+ <span class="en">Drag and Drop</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/themes.html">
- <span class="en">Applying Styles and Themes</span>
+ <span class="en">Styles and Themes</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/custom-components.html">
- <span class="en">Building Custom Components</span>
+ <span class="en">Custom Components</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/topics/ui/binding.html">
<span class="en">Binding to Data with AdapterView</span>
diff --git a/docs/html/guide/practices/design/seamlessness.jd b/docs/html/guide/practices/design/seamlessness.jd
index dedc16f..6c73426 100644
--- a/docs/html/guide/practices/design/seamlessness.jd
+++ b/docs/html/guide/practices/design/seamlessness.jd
@@ -171,7 +171,7 @@
avoid rolling your own as much as possible. Instead, use a Theme. You
can override or extend those parts of the theme that you need to, but at least
you're starting from the same UI base as all the other applications. For all
-the details, read <a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>.</p>
+the details, read <a href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a>.</p>
<h2 id="flexui">Design Your UI to Work with Multiple Screen Resolutions</h2>
diff --git a/docs/html/guide/practices/ui_guidelines/menu_design.jd b/docs/html/guide/practices/ui_guidelines/menu_design.jd
index 7751a7b..3edf33f 100644
--- a/docs/html/guide/practices/ui_guidelines/menu_design.jd
+++ b/docs/html/guide/practices/ui_guidelines/menu_design.jd
@@ -260,8 +260,8 @@
<img src={@docRoot}images/menu_design/TaskFlowDiagram.png>
<p>
- For more technical information on menus, see
- <a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>.
+ For more technical information on menus, see the
+ <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a> developer guide.
</p>
<h3 id="commands_fixed">Commands Fixed in an Activity Screen</h4>
diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd
index 22283cd..20ce701 100644
--- a/docs/html/guide/topics/appwidgets/index.jd
+++ b/docs/html/guide/topics/appwidgets/index.jd
@@ -297,8 +297,7 @@
<p>Creating the App Widget layout is simple if you're
familiar with <a
-href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout in
-XML</a>.
+href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a>.
However, you must be aware that App Widget layouts are based on {@link
android.widget.RemoteViews},
which do not support every kind of layout or view widget.</p>
diff --git a/docs/html/guide/topics/fundamentals/fragments.jd b/docs/html/guide/topics/fundamentals/fragments.jd
index 3908a7c..8f61945 100644
--- a/docs/html/guide/topics/fundamentals/fragments.jd
+++ b/docs/html/guide/topics/fundamentals/fragments.jd
@@ -631,8 +631,9 @@
handle the selected item, then the event is passed to the fragment's callback. This is true for
the Options Menu and context menus.</p>
-<p>For more information about menus, see <a href="{@docRoot}guide/topics/ui/menus.html">Creating
-Menus</a> and <a href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action Bar</a>.</p>
+<p>For more information about menus, see the <a
+href="{@docRoot}guide/topics/ui/menus.html">Menus</a> and <a
+href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> developer guides.</p>
diff --git a/docs/html/guide/topics/graphics/index.jd b/docs/html/guide/topics/graphics/index.jd
index 2490e39..f0a923a 100644
--- a/docs/html/guide/topics/graphics/index.jd
+++ b/docs/html/guide/topics/graphics/index.jd
@@ -150,7 +150,7 @@
<p class="note"><strong>Note: </strong> In order to request an invalidate from a thread other than your main
Activity's thread, you must call <code>{@link android.view.View#postInvalidate()}</code>.</p>
-<p>Also read <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>
+<p>Also read <a href="{@docRoot}guide/topics/ui/custom-components.html">Custom Components</a>
for a guide to extending a View class, and <a href="2d-graphics.html">2D Graphics: Drawables</a> for
information on using Drawable objects like images from your resources and other primitive shapes.</p>
diff --git a/docs/html/guide/topics/resources/layout-resource.jd b/docs/html/guide/topics/resources/layout-resource.jd
index b069521..286e3d1 100644
--- a/docs/html/guide/topics/resources/layout-resource.jd
+++ b/docs/html/guide/topics/resources/layout-resource.jd
@@ -7,7 +7,7 @@
<div id="qv">
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a></li>
+ <li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a></li>
</ol>
</div>
</div>
@@ -127,8 +127,9 @@
</dl>
<p>More attributes are supported by the {@link android.view.View}
base class, and many more are supported by each implementation of
- {@link android.view.View}. Read <a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring
- Layout</a> for more information. For a reference of all available attributes,
+ {@link android.view.View}. Read <a
+href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a> for more information. For
+a reference of all available attributes,
see the corresponding reference documentation (for example, the <a
href="{@docRoot}reference/android/widget/TextView.html#lattrs">TextView XML attributes</a>).</p>
</dd>
@@ -235,7 +236,8 @@
<p>You can create your own custom {@link android.view.View} and {@link android.view.ViewGroup}
elements and apply them to your layout the same as a standard layout
element. You can also specify the attributes supported in the XML element. To learn more,
-read <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>.
+see the <a href="{@docRoot}guide/topics/ui/custom-components.html">Custom Components</a> developer
+guide.
</p>
</dd> <!-- end elements and attributes -->
@@ -273,7 +275,7 @@
<dt>see also:</dt>
<dd>
<ul>
- <li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a></li>
+ <li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a></li>
<li>{@link android.view.View}</li>
<li>{@link android.view.ViewGroup}</li>
</ul>
diff --git a/docs/html/guide/topics/resources/localization.jd b/docs/html/guide/topics/resources/localization.jd
index 36e12f6..9affb15 100755
--- a/docs/html/guide/topics/resources/localization.jd
+++ b/docs/html/guide/topics/resources/localization.jd
@@ -52,7 +52,7 @@
<li><a
href="{@docRoot}resources/tutorials/localization/index.html">Hello, L10N Tutorial</a></li>
<li><a href="{@docRoot}guide/topics/resources/providing-resources.html">Providing Resources</a></li>
- <li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a></li>
+ <li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a></li>
<li><a href="{@docRoot}reference/android/app/Activity.html#ActivityLifecycle">Activity Lifecycle</a></li>
</ol>
</div>
diff --git a/docs/html/guide/topics/resources/menu-resource.jd b/docs/html/guide/topics/resources/menu-resource.jd
index 5b90ce2..64cdf21 100644
--- a/docs/html/guide/topics/resources/menu-resource.jd
+++ b/docs/html/guide/topics/resources/menu-resource.jd
@@ -7,7 +7,7 @@
<div id="qv">
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a></li>
+ <li><a href="{@docRoot}guide/topics/ui/menus.html">Menus</a></li>
</ol>
</div>
</div>
@@ -15,8 +15,8 @@
<p>A menu resource defines an application menu (Options Menu, Context Menu, or submenu) that
can be inflated with {@link android.view.MenuInflater}.</p>
-<p>For a guide to using menus, see the <a href="{@docRoot}guide/topics/ui/menus.html">Creating
-Menus</a> document.</p>
+<p>For a guide to using menus, see the <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a>
+developer guide.</p>
<dl class="xml">
@@ -132,22 +132,22 @@
bar. Setting multiple items to always appear as action items can result in them overlapping
with other UI in the action bar.</td></tr>
</table>
- <p>See <a href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action Bar</a> for
-more information.</p>
+ <p>See the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> developer
+guide for more information.</p>
<p>Introduced in API Level 11.</p>
</dd>
<dt><code>android:actionViewLayout</code></dt>
<dd><em>Layout resource</em>. A layout to use as the action view.
- <p>See <a href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action Bar</a> for
-more information.</p>
+ <p>See the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> developer
+guide for more information.</p>
<p>Introduced in API Level 11.</p></dd>
<dt><code>android:actionViewClassName</code></dt>
<dd><em>Class name</em>. A fully-qualified class name for the {@link android.view.View}
to use as the action view.
- <p>See <a href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action Bar</a> for
-more information.</p>
+ <p>See the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> developer
+guide for more information.</p>
<p class="warning"><strong>Warning:</strong> If you obfuscate your code using <a
href="{@docRoot}guide/developing/tools/proguard.html">ProGuard</a> (or a similar tool),
be sure to exclude the class you specify in this attribute from renaming, because it can break the
diff --git a/docs/html/guide/topics/resources/style-resource.jd b/docs/html/guide/topics/resources/style-resource.jd
index def727c..f6252dba 100644
--- a/docs/html/guide/topics/resources/style-resource.jd
+++ b/docs/html/guide/topics/resources/style-resource.jd
@@ -7,7 +7,7 @@
<div id="qv">
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a></li>
+ <li><a href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a></li>
</ol>
</div>
</div>
@@ -18,7 +18,7 @@
an entire {@link android.app.Activity} or application (from within the manifest file).</p>
<p>For more information about creating and applying styles, please read
-<a href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>.</p>
+<a href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a>.</p>
<p class="note"><strong>Note:</strong> A style is a simple resource that is referenced
using the value provided in the {@code name} attribute (not the name of the XML file). As
diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd
index d869a44..27409d5 100644
--- a/docs/html/guide/topics/search/search-dialog.jd
+++ b/docs/html/guide/topics/search/search-dialog.jd
@@ -748,8 +748,8 @@
documentation for {@link android.widget.SearchView} and its nested interfaces for the
appropriate event listeners.</p>
-<p>For more information about action views in the Action Bar, read <a
-href="{@docRoot}guide/topics/ui/actionbar.html#ActionView">Using the Action Bar</a> (which
+<p>For more information about action views in the Action Bar, read the <a
+href="{@docRoot}guide/topics/ui/actionbar.html#ActionView">Action Bar</a> developer guide (which
includes sample code for adding a search widget as an action view).</p>
@@ -803,8 +803,8 @@
android.app.Activity#onSearchRequested onSearchRequested()}.</p>
<p>For more information about how items in the Action Bar work and how to handle this situation, see
-the documentation for <a href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action
-Bar</a>.</p>
+the <a href="{@docRoot}guide/topics/ui/actionbar.html">Action
+Bar</a> developer guide.</p>
<p>Also see the <a
href="{@docRoot}resources/samples/SearchableDictionary/src/com/example/android/searchabledict/
diff --git a/docs/html/guide/topics/ui/actionbar.jd b/docs/html/guide/topics/ui/actionbar.jd
index 6f12b95..4742923 100644
--- a/docs/html/guide/topics/ui/actionbar.jd
+++ b/docs/html/guide/topics/ui/actionbar.jd
@@ -1,4 +1,4 @@
-page.title=Using the Action Bar
+page.title=Action Bar
parent.title=User Interface
parent.link=index.html
@jd:body
@@ -49,7 +49,7 @@
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a></li>
+ <li><a href="{@docRoot}guide/topics/ui/menus.html">Menus</a></li>
</ol>
</div>
</div>
@@ -157,7 +157,7 @@
<p>When the activity first starts, the system populates the Action Bar and overflow menu by calling
{@link android.app.Activity#onCreateOptionsMenu onCreateOptionsMenu()} for your activity. As
-discussed in the guide to <a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>, it's in
+discussed in the <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a> developer guid, it's in
this callback method that you define the Options Menu for the activity.</p>
<p>You can specify a menu item to appear as an action item—if there is room
@@ -211,7 +211,7 @@
collide with other elements in the Action Bar.</p>
<p>For more information about menus, see the <a
-href="{@docRoot}guide/topics/ui/menus.html#options-menu">Creating Menus</a> developer guide.</p>
+href="{@docRoot}guide/topics/ui/menus.html#options-menu">Menus</a> developer guide.</p>
<h3 id="Home">Using the app icon as an action item</h3>
@@ -845,7 +845,7 @@
</dl>
<p>For more information about using themes in your application, read <a
-href="{@docRoot}guide/topics/ui/themes.html">Applying Styles and Themes</a>.</p>
+href="{@docRoot}guide/topics/ui/themes.html">Styles and Themes</a>.</p>
diff --git a/docs/html/guide/topics/ui/custom-components.jd b/docs/html/guide/topics/ui/custom-components.jd
index 900e08b..be82dbc 100644
--- a/docs/html/guide/topics/ui/custom-components.jd
+++ b/docs/html/guide/topics/ui/custom-components.jd
@@ -1,4 +1,4 @@
-page.title=Building Custom Components
+page.title=Custom Components
parent.title=User Interface
parent.link=index.html
@jd:body
diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index 4a574be..4dc915f 100644
--- a/docs/html/guide/topics/ui/declaring-layout.jd
+++ b/docs/html/guide/topics/ui/declaring-layout.jd
@@ -1,4 +1,4 @@
-page.title=Declaring Layout
+page.title=XML Layouts
parent.title=User Interface
parent.link=index.html
@jd:body
diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd
index c1272b6..16f14cb 100644
--- a/docs/html/guide/topics/ui/dialogs.jd
+++ b/docs/html/guide/topics/ui/dialogs.jd
@@ -1,4 +1,4 @@
-page.title=Creating Dialogs
+page.title=Dialogs
parent.title=User Interface
parent.link=index.html
@jd:body
diff --git a/docs/html/guide/topics/ui/drag-drop.jd b/docs/html/guide/topics/ui/drag-drop.jd
index 0329c192..93753cc 100644
--- a/docs/html/guide/topics/ui/drag-drop.jd
+++ b/docs/html/guide/topics/ui/drag-drop.jd
@@ -1,4 +1,4 @@
-page.title=Dragging and Dropping
+page.title=Drag and Drop
parent.title=User Interface
parent.link=index.html
@jd:body
@@ -107,7 +107,7 @@
<a href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a>
</li>
<li>
- <a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a>
+ <a href="{@docRoot}guide/topics/ui/ui-events.html">Input Events</a>
</li>
</ol>
</div>
diff --git a/docs/html/guide/topics/ui/index.jd b/docs/html/guide/topics/ui/index.jd
index 375c9fe..d3060c5 100644
--- a/docs/html/guide/topics/ui/index.jd
+++ b/docs/html/guide/topics/ui/index.jd
@@ -9,7 +9,7 @@
<li><a href="#ViewHierarchy">View Hierarchy</a></li>
<li><a href="#Layout">Layout</a></li>
<li><a href="#Widgets">Widgets</a></li>
- <li><a href="#Events">UI Events</a></li>
+ <li><a href="#Events">Input Events</a></li>
<li><a href="#Menus">Menus</a></li>
<li><a href="#Advanced">Advanced Topics</a>
<ol>
@@ -104,7 +104,7 @@
another LinearLayout (or other type of view group) inside here, to lengthen the view hierarchy and create a more
complex layout.</p>
-<p>For more on building a UI layout, read <a href="declaring-layout.html">Declaring Layout</a>.
+<p>For more on building a UI layout, read <a href="declaring-layout.html">XML Layouts</a>.
<div class="sidebox-wrapper">
<div class="sidebox">
@@ -132,16 +132,16 @@
But you're not limited to the kinds of widgets provided by the Android platform. If you'd
like to do something more customized and create your own actionable elements, you can, by defining your own
View object or by extending and combining existing widgets.</p>
-<p>Read more in <a href="custom-components.html">Building Custom Components</a>.</p>
+<p>Read more in the <a href="custom-components.html">Custom Components</a> developer guide.</p>
<p>For a list of the widgets provided by Android, see the {@link android.widget} package.</p>
-<h2 id="Events">UI Events</h2>
+<h2 id="Events">Input Events</h2>
<p>Once you've added some Views/widgets to the UI, you probably want to know about the
-user's interaction with them, so you can perform actions. To be informed of UI events, you need to
-do one of two things:</p>
+user's interaction with them, so you can perform actions. To be informed of user input events, you
+need to do one of two things:</p>
<ul>
<li><strong>Define an event listener and register it with the View.</strong> More often than not,
this is how you'll listen for events. The View class contains a collection of nested interfaces named
@@ -166,8 +166,8 @@
</li>
</ul>
-<p>Continue reading about handling user interaction with Views in the <a href="ui-events.html">Handling UI Events</a>
-document.</p>
+<p>Continue reading about handling user interaction with Views in the <a
+href="ui-events.html">Input Events</a> document.</p>
<h2 id="Menus">Menus</h2>
@@ -192,7 +192,7 @@
<p>And just like your application layout, you have the option to declare the items for you menu in an XML file.</p>
-<p>Read <a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a> to learn more.</p>
+<p>Read <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a> to learn more.</p>
<h2 id="Advanced">Advanced Topics</h2>
@@ -232,4 +232,4 @@
<p>Styles and themes are resources. Android provides some default style and theme resources that you can use,
or you can declare your own custom style and theme resources.</p>
<p>Learn more about using styles and themes in the
-<a href="themes.html">Applying Styles and Themes</a> document.</p>
+<a href="themes.html">Styles and Themes</a> document.</p>
diff --git a/docs/html/guide/topics/ui/menus.jd b/docs/html/guide/topics/ui/menus.jd
index 984bf8f..2948244 100644
--- a/docs/html/guide/topics/ui/menus.jd
+++ b/docs/html/guide/topics/ui/menus.jd
@@ -1,4 +1,4 @@
-page.title=Creating Menus
+page.title=Menus
parent.title=User Interface
parent.link=index.html
@jd:body
@@ -36,7 +36,7 @@
<h2>See also</h2>
<ol>
- <li><a href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action Bar</a></li>
+ <li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a></li>
<li><a href="{@docRoot}guide/topics/resources/menu-resource.html">Menu Resource</a></li>
</ol>
</div>
@@ -301,8 +301,8 @@
items in the Options Menu. If you want to provide menu items that are context-sensitive to a {@link
android.view.View}, use a <a href="#context-menu">Context Menu</a>.</p>
-<p>If you're developing for Android 3.0 or higher, be sure to also read <a
-href="{@docRoot}guide/topics/ui/actionbar.html">Using the Action Bar</a>.</p>
+<p>If you're developing for Android 3.0 or higher, be sure to also read the <a
+href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a> developer guide.</p>
diff --git a/docs/html/guide/topics/ui/notifiers/index.jd b/docs/html/guide/topics/ui/notifiers/index.jd
index 8fc57fc..c61d4f0 100644
--- a/docs/html/guide/topics/ui/notifiers/index.jd
+++ b/docs/html/guide/topics/ui/notifiers/index.jd
@@ -1,19 +1,8 @@
-page.title=Notifying the User
+page.title=Notifications
parent.title=User Interface
parent.link=../index.html
@jd:body
-<div id="qv-wrapper">
- <div id="qv">
- <h2>Topics</h2>
- <ol>
- <li><a href="toasts.html">Creating Toast Notifications</a></li>
- <li><a href="notifications.html">Creating Status Bar Notifications</a></li>
- <li><a href="{@docRoot}guide/topics/ui/dialogs.html">Creating Dialogs</a></li>
- </ol>
- </div>
-</div>
-
<p>Several types of situations may arise that require you to notify the user
about an event that occurs in your application. Some events require the user to respond
and others do not. For example:</p>
@@ -57,7 +46,7 @@
the user to respond and take action, consider using a
<a href="#StatusBar">Status Bar Notification</a> instead.</p>
-<p>For more information, refer to <a href="toasts.html">Creating Toast Notifications</a>.</p>
+<p>For more information, refer to <a href="toasts.html">Toast Notifications</a>.</p>
<h2 id="StatusBar">Status Bar Notification</h2>
@@ -79,7 +68,7 @@
<a href="#Dialog">Dialog Notification</a> instead.</p>
<p>For more information, refer to
-<a href="notifications.html">Creating Status Bar Notifications</a>.</p>
+<a href="notifications.html">Status Bar Notifications</a>.</p>
<h2 id="Dialog">Dialog Notification</h2>
@@ -97,7 +86,7 @@
in your application's UI and for other purposes besides notifications.
For a complete discussion on all the available types of dialogs,
including its uses for notifications, refer to
-<a href="{@docRoot}guide/topics/ui/dialogs.html">Creating Dialogs</a>.</p>
+<a href="{@docRoot}guide/topics/ui/dialogs.html">Dialogs</a>.</p>
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index f12c5ee..7bc1cde 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -1,5 +1,5 @@
-page.title=Creating Status Bar Notifications
-parent.title=Notifying the User
+page.title=Status Bar Notifications
+parent.title=Notifications
parent.link=index.html
@jd:body
diff --git a/docs/html/guide/topics/ui/notifiers/toasts.jd b/docs/html/guide/topics/ui/notifiers/toasts.jd
index 0d3e10c..1a1fb1f 100644
--- a/docs/html/guide/topics/ui/notifiers/toasts.jd
+++ b/docs/html/guide/topics/ui/notifiers/toasts.jd
@@ -1,5 +1,5 @@
-page.title=Creating Toast Notifications
-parent.title=Notifying the User
+page.title=Toast Notifications
+parent.title=Notifications
parent.link=index.html
@jd:body
diff --git a/docs/html/guide/topics/ui/themes.jd b/docs/html/guide/topics/ui/themes.jd
index a213bea..d787492 100644
--- a/docs/html/guide/topics/ui/themes.jd
+++ b/docs/html/guide/topics/ui/themes.jd
@@ -1,4 +1,4 @@
-page.title=Applying Styles and Themes
+page.title=Styles and Themes
parent.title=User Interface
parent.link=index.html
@jd:body
diff --git a/docs/html/guide/topics/ui/ui-events.jd b/docs/html/guide/topics/ui/ui-events.jd
index 7d7bfaf..93bad43 100644
--- a/docs/html/guide/topics/ui/ui-events.jd
+++ b/docs/html/guide/topics/ui/ui-events.jd
@@ -1,4 +1,4 @@
-page.title=Handling UI Events
+page.title=Input Events
parent.title=User Interface
parent.link=index.html
@jd:body
@@ -72,7 +72,8 @@
<dt><code>onCreateContextMenu()</code></dt>
<dd>From {@link android.view.View.OnCreateContextMenuListener}.
This is called when a Context Menu is being built (as the result of a sustained "long click"). See the discussion
- on context menus in <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Creating Menus</a> for more information.</dd>
+ on context menus in the <a href="{@docRoot}guide/topics/ui/menus.html#context-menu">Menus</a>
+ developer guide.</dd>
</dl>
<p>These methods are the sole inhabitants of their respective interface. To define one of these methods
@@ -159,8 +160,9 @@
<p>If you're building a custom component from View, then you'll be able to define several callback methods
used as default event handlers.
-In the document on <a href="{@docRoot}guide/topics/ui/custom-components.html">Building Custom Components</a>,
-you'll learn see some of the common callbacks used for event handling, including:</p>
+In the document about <a href="{@docRoot}guide/topics/ui/custom-components.html">Custom
+Components</a>, you'll learn see some of the common callbacks used for event handling,
+including:</p>
<ul>
<li><code>{@link android.view.View#onKeyDown}</code> - Called when a new key event occurs.</li>
<li><code>{@link android.view.View#onKeyUp}</code> - Called when a key up event occurs.</li>
diff --git a/docs/html/guide/tutorials/notepad/notepad-ex2.jd b/docs/html/guide/tutorials/notepad/notepad-ex2.jd
index 854731f..fed40ab 100644
--- a/docs/html/guide/tutorials/notepad/notepad-ex2.jd
+++ b/docs/html/guide/tutorials/notepad/notepad-ex2.jd
@@ -299,7 +299,8 @@
in real Android applications.</p>
<p>Creating a
good UI is part art and part science, and the rest is work. Mastery of <a
- href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a> is an essential part of creating
+ href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a> is an essential part of
+creating
a good looking Android application.</p>
<p>Take a look at the
<a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a>
diff --git a/docs/html/resources/faq/commontasks.jd b/docs/html/resources/faq/commontasks.jd
index b211db0..c72343a0 100644
--- a/docs/html/resources/faq/commontasks.jd
+++ b/docs/html/resources/faq/commontasks.jd
@@ -268,7 +268,8 @@
{@link android.app.Activity#finishActivity(int) Activity.finishActivity()}
on any screens that it opens to close them. </p>
<a name="listening" id="listening"></a><h2>Listening for Button Clicks</h2>
-<p>Button click and other UI event capturing are covered in <a href="{@docRoot}guide/topics/ui/ui-events.html">Handling UI Events</a> on the UI Design page.</p>
+<p>Button click and other UI event capturing are covered in <a
+href="{@docRoot}guide/topics/ui/ui-events.html">Input Events</a>.</p>
<a name="configurewindowproperties" id="configurewindowproperties"></a><h2>Configuring General Window Properties</h2>
<p>You can set a number of general window properties, such as whether to display
a title, whether the window is floating, and whether it displays an icon, by
@@ -543,7 +544,7 @@
which enables a dialog box with an embedded progress bar to send a "I'm working
on it" notification to the user. </p>
<a name="addmenuitems" id="addmenuitems"></a><h2>Adding Items to the Screen Menu</h2>
-<p>See <a href="{@docRoot}guide/topics/ui/menus.html">Creating Menus</a>.</p>
+<p>See <a href="{@docRoot}guide/topics/ui/menus.html">Menus</a>.</p>
<a name="webpage" id="webpage"></a><h2>Display a Web Page</h2>
<p>Use the {@link android.webkit.WebView webkit.WebView} object. </p>
diff --git a/docs/html/resources/tutorials/notepad/notepad-ex2.jd b/docs/html/resources/tutorials/notepad/notepad-ex2.jd
index 499b796..7e3288f1 100644
--- a/docs/html/resources/tutorials/notepad/notepad-ex2.jd
+++ b/docs/html/resources/tutorials/notepad/notepad-ex2.jd
@@ -299,7 +299,8 @@
in real Android applications.</p>
<p>Creating a
good UI is part art and part science, and the rest is work. Mastery of <a
- href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a> is an essential part of creating
+ href="{@docRoot}guide/topics/ui/declaring-layout.html">XML Layouts</a> is an essential part of
+creating
a good looking Android application.</p>
<p>Take a look at the
<a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a>
diff --git a/docs/html/search.jd b/docs/html/search.jd
index 339ce2d..407bc86 100644
--- a/docs/html/search.jd
+++ b/docs/html/search.jd
@@ -64,11 +64,14 @@
// upon ajax search, refresh the url and search title
searchControl.setSearchStartingCallback(this, function(control, searcher, query) {
+ $("#searchTitle").html("search results for <em>" + escapeHTML(query) + "</em>");
+
// save the tab index from the hash
tabIndex = location.hash.split("&t=")[1];
-
- $("#searchTitle").html("search results for <em>" + escapeHTML(query) + "</em>");
$.history.add('q=' + query + '&t=' + tabIndex);
+ });
+
+ searchControl.setSearchCompleteCallback(this, function(control, searcher) {
openTab();
});
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index bfe13f0..3fa2acb 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -38,6 +38,9 @@
class Parcel
{
public:
+ class ReadableBlob;
+ class WritableBlob;
+
Parcel();
~Parcel();
@@ -46,7 +49,7 @@
size_t dataAvail() const;
size_t dataPosition() const;
size_t dataCapacity() const;
-
+
status_t setDataSize(size_t size);
void setDataPosition(size_t pos) const;
status_t setDataCapacity(size_t size);
@@ -56,6 +59,9 @@
status_t appendFrom(const Parcel *parcel,
size_t start, size_t len);
+ bool pushAllowFds(bool allowFds);
+ void restoreAllowFds(bool lastValue);
+
bool hasFileDescriptors() const;
// Writes the RPC header.
@@ -109,7 +115,13 @@
// Place a file descriptor into the parcel. A dup of the fd is made, which
// will be closed once the parcel is destroyed.
status_t writeDupFileDescriptor(int fd);
-
+
+ // Writes a blob to the parcel.
+ // If the blob is small, then it is stored in-place, otherwise it is
+ // transferred by way of an anonymous shared memory region.
+ // The caller should call release() on the blob after writing its contents.
+ status_t writeBlob(size_t len, WritableBlob* outBlob);
+
status_t writeObject(const flat_binder_object& val, bool nullMetaData);
// Like Parcel.java's writeNoException(). Just writes a zero int32.
@@ -157,7 +169,11 @@
// Retrieve a file descriptor from the parcel. This returns the raw fd
// in the parcel, which you do not own -- use dup() to get your own copy.
int readFileDescriptor() const;
-
+
+ // Reads a blob from the parcel.
+ // The caller should call release() on the blob after reading its contents.
+ status_t readBlob(size_t len, ReadableBlob* outBlob) const;
+
const flat_binder_object* readObject(bool nullMetaData) const;
// Explicitly close all file descriptors in the parcel.
@@ -177,7 +193,7 @@
release_func relFunc, void* relCookie);
void print(TextOutput& to, uint32_t flags = 0) const;
-
+
private:
Parcel(const Parcel& o);
Parcel& operator=(const Parcel& o);
@@ -212,9 +228,40 @@
mutable bool mFdsKnown;
mutable bool mHasFds;
+ bool mAllowFds;
release_func mOwner;
void* mOwnerCookie;
+
+ class Blob {
+ public:
+ Blob();
+ ~Blob();
+
+ void release();
+ inline size_t size() const { return mSize; }
+
+ protected:
+ void init(bool mapped, void* data, size_t size);
+ void clear();
+
+ bool mMapped;
+ void* mData;
+ size_t mSize;
+ };
+
+public:
+ class ReadableBlob : public Blob {
+ friend class Parcel;
+ public:
+ inline const void* data() const { return mData; }
+ };
+
+ class WritableBlob : public Blob {
+ friend class Parcel;
+ public:
+ inline void* data() { return mData; }
+ };
};
// ---------------------------------------------------------------------------
diff --git a/include/utils/Errors.h b/include/utils/Errors.h
index 81f818b..0b75b19 100644
--- a/include/utils/Errors.h
+++ b/include/utils/Errors.h
@@ -72,6 +72,7 @@
TIMED_OUT = 0x80000005,
UNKNOWN_TRANSACTION = 0x80000006,
#endif
+ FDS_NOT_ALLOWED = 0x80000007,
};
// Restore define; enumeration is in "android" namespace, so the value defined
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index a0fc4d0..608877e 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -30,12 +30,14 @@
#include <utils/TextOutput.h>
#include <utils/misc.h>
#include <utils/Flattenable.h>
+#include <cutils/ashmem.h>
#include <private/binder/binder_module.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <sys/mman.h>
#ifndef INT32_MAX
#define INT32_MAX ((int32_t)(2147483647))
@@ -54,6 +56,9 @@
// Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
#define EX_HAS_REPLY_HEADER -128
+// Maximum size of a blob to transfer in-place.
+static const size_t IN_PLACE_BLOB_LIMIT = 40 * 1024;
+
// XXX This can be made public if we want to provide
// support for typed data.
struct small_flat_data
@@ -399,6 +404,8 @@
mDataPos += len;
mDataSize += len;
+ err = NO_ERROR;
+
if (numObjects > 0) {
// grow objects
if (mObjectsCapacity < mObjectsSize + numObjects) {
@@ -430,11 +437,28 @@
flat->handle = dup(flat->handle);
flat->cookie = (void*)1;
mHasFds = mFdsKnown = true;
+ if (!mAllowFds) {
+ err = FDS_NOT_ALLOWED;
+ }
}
}
}
- return NO_ERROR;
+ return err;
+}
+
+bool Parcel::pushAllowFds(bool allowFds)
+{
+ const bool origValue = mAllowFds;
+ if (!allowFds) {
+ mAllowFds = false;
+ }
+ return origValue;
+}
+
+void Parcel::restoreAllowFds(bool lastValue)
+{
+ mAllowFds = lastValue;
}
bool Parcel::hasFileDescriptors() const
@@ -706,6 +730,54 @@
return writeObject(obj, true);
}
+status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob)
+{
+ status_t status;
+
+ if (!mAllowFds || len <= IN_PLACE_BLOB_LIMIT) {
+ LOGV("writeBlob: write in place");
+ status = writeInt32(0);
+ if (status) return status;
+
+ void* ptr = writeInplace(len);
+ if (!ptr) return NO_MEMORY;
+
+ outBlob->init(false /*mapped*/, ptr, len);
+ return NO_ERROR;
+ }
+
+ LOGV("writeBlob: write to ashmem");
+ int fd = ashmem_create_region("Parcel Blob", len);
+ if (fd < 0) return NO_MEMORY;
+
+ int result = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
+ if (result < 0) {
+ status = -result;
+ } else {
+ void* ptr = ::mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (ptr == MAP_FAILED) {
+ status = -errno;
+ } else {
+ result = ashmem_set_prot_region(fd, PROT_READ);
+ if (result < 0) {
+ status = -result;
+ } else {
+ status = writeInt32(1);
+ if (!status) {
+ status = writeFileDescriptor(fd);
+ if (!status) {
+ outBlob->init(true /*mapped*/, ptr, len);
+ return NO_ERROR;
+ }
+ }
+ }
+ }
+ ::munmap(ptr, len);
+ }
+ ::close(fd);
+ return status;
+}
+
status_t Parcel::write(const Flattenable& val)
{
status_t err;
@@ -759,6 +831,9 @@
// remember if it's a file descriptor
if (val.type == BINDER_TYPE_FD) {
+ if (!mAllowFds) {
+ return FDS_NOT_ALLOWED;
+ }
mHasFds = mFdsKnown = true;
}
@@ -1025,6 +1100,32 @@
return BAD_TYPE;
}
+status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
+{
+ int32_t useAshmem;
+ status_t status = readInt32(&useAshmem);
+ if (status) return status;
+
+ if (!useAshmem) {
+ LOGV("readBlob: read in place");
+ const void* ptr = readInplace(len);
+ if (!ptr) return BAD_VALUE;
+
+ outBlob->init(false /*mapped*/, const_cast<void*>(ptr), len);
+ return NO_ERROR;
+ }
+
+ LOGV("readBlob: read from ashmem");
+ int fd = readFileDescriptor();
+ if (fd == int(BAD_TYPE)) return BAD_VALUE;
+
+ void* ptr = ::mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+ if (!ptr) return NO_MEMORY;
+
+ outBlob->init(true /*mapped*/, ptr, len);
+ return NO_ERROR;
+}
+
status_t Parcel::read(Flattenable& val) const
{
// size
@@ -1283,6 +1384,7 @@
mNextObjectHint = 0;
mHasFds = false;
mFdsKnown = true;
+ mAllowFds = true;
return NO_ERROR;
}
@@ -1434,6 +1536,7 @@
mNextObjectHint = 0;
mHasFds = false;
mFdsKnown = true;
+ mAllowFds = true;
mOwner = NULL;
}
@@ -1452,4 +1555,33 @@
mFdsKnown = true;
}
+// --- Parcel::Blob ---
+
+Parcel::Blob::Blob() :
+ mMapped(false), mData(NULL), mSize(0) {
+}
+
+Parcel::Blob::~Blob() {
+ release();
+}
+
+void Parcel::Blob::release() {
+ if (mMapped && mData) {
+ ::munmap(mData, mSize);
+ }
+ clear();
+}
+
+void Parcel::Blob::init(bool mapped, void* data, size_t size) {
+ mMapped = mapped;
+ mData = data;
+ mSize = size;
+}
+
+void Parcel::Blob::clear() {
+ mMapped = false;
+ mData = NULL;
+ mSize = 0;
+}
+
}; // namespace android
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel.xml
index 1641c70..2947bfb 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_notification_panel.xml
@@ -34,6 +34,7 @@
android:paddingRight="15dp"
android:src="@drawable/ic_notify_clear"
android:visibility="invisible"
+ android:contentDescription="@string/accessibility_clear_all"
/>
<RelativeLayout
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 38ac8a7..3e2def5 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -65,6 +65,7 @@
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:src="@drawable/ic_notify_quicksettings"
+ android:contentDescription="@string/accessibility_settings_button"
/>
<ImageView android:id="@+id/clear_all_button"
@@ -74,6 +75,7 @@
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:src="@drawable/ic_notify_clear"
+ android:contentDescription="@string/accessibility_clear_all"
/>
</RelativeLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 26200ec..e971896 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -282,13 +282,13 @@
<string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>
<!-- Content description of the button for showing a settings panel in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_settings_button">Settings button.</string>
+ <string name="accessibility_settings_button">System settings.</string>
<!-- Content description of the button for showing a notifications panel in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_notifications_button">Notifications button.</string>
+ <string name="accessibility_notifications_button">Notifications.</string>
<!-- Content description of the button for removing a notification in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
- <string name="accessibility_remove_notification">Remove notification.</string>
+ <string name="accessibility_remove_notification">Clear notification.</string>
<!-- Content description of the enabled GPS icon in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_gps_enabled">GPS enabled.</string>
@@ -336,4 +336,6 @@
<!-- Notification text: when GPS has found a fix [CHAR LIMIT=50] -->
<string name="gps_notification_found_text">Location set by GPS</string>
+ <!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_clear_all">Clear all notifications.</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 59b09d49..744a46b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -44,6 +44,7 @@
private boolean mMobileVisible = false;
private int mMobileStrengthId = 0, mMobileActivityId = 0, mMobileTypeId = 0;
private boolean mIsAirplaneMode = false;
+ private String mWifiDescription, mMobileDescription, mMobileTypeDescription;
ViewGroup mWifiGroup, mMobileGroup;
ImageView mWifi, mMobile, mWifiActivity, mMobileActivity, mMobileType;
@@ -95,20 +96,24 @@
super.onDetachedFromWindow();
}
- public void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon) {
+ public void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon,
+ String contentDescription) {
mWifiVisible = visible;
mWifiStrengthId = strengthIcon;
mWifiActivityId = activityIcon;
+ mWifiDescription = contentDescription;
apply();
}
public void setMobileDataIndicators(boolean visible, int strengthIcon, int activityIcon,
- int typeIcon) {
+ int typeIcon, String contentDescription, String typeContentDescription) {
mMobileVisible = visible;
mMobileStrengthId = strengthIcon;
mMobileActivityId = activityIcon;
mMobileTypeId = typeIcon;
+ mMobileDescription = contentDescription;
+ mMobileTypeDescription = typeContentDescription;
apply();
}
@@ -125,6 +130,7 @@
mWifiGroup.setVisibility(View.VISIBLE);
mWifi.setImageResource(mWifiStrengthId);
mWifiActivity.setImageResource(mWifiActivityId);
+ mWifiGroup.setContentDescription(mWifiDescription);
} else {
mWifiGroup.setVisibility(View.GONE);
}
@@ -139,6 +145,7 @@
mMobile.setImageResource(mMobileStrengthId);
mMobileActivity.setImageResource(mMobileActivityId);
mMobileType.setImageResource(mMobileTypeId);
+ mMobileGroup.setContentDescription(mMobileTypeDescription + " " + mMobileDescription);
} else {
mMobileGroup.setVisibility(View.GONE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index a98d519..8d964e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -139,9 +139,10 @@
IBatteryStats mBatteryStats;
public interface SignalCluster {
- void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon);
+ void setWifiIndicators(boolean visible, int strengthIcon, int activityIcon,
+ String contentDescription);
void setMobileDataIndicators(boolean visible, int strengthIcon, int activityIcon,
- int typeIcon);
+ int typeIcon, String contentDescription, String typeContentDescription);
void setIsAirplaneMode(boolean is);
}
@@ -235,12 +236,16 @@
cluster.setWifiIndicators(
mWifiConnected, // only show wifi in the cluster if connected
mWifiIconId,
- mWifiActivityIconId);
+ mWifiActivityIconId,
+ mContentDescriptionWifi);
cluster.setMobileDataIndicators(
mHasMobileDataFeature,
mPhoneSignalIconId,
mMobileActivityIconId,
- mDataTypeIconId);
+ mDataTypeIconId,
+ mContentDescriptionPhoneSignal,
+ mContentDescriptionDataType);
+
}
public void setStackedMode(boolean stacked) {
@@ -807,8 +812,8 @@
(mServiceState == null || (!hasService() && !mServiceState.isEmergencyOnly()))) {
// Only display the flight-mode icon if not in "emergency calls only" mode.
label = context.getString(R.string.status_bar_settings_signal_meter_disconnected);
- mContentDescriptionCombinedSignal = mContext.getString(
- R.string.accessibility_airplane_mode);
+ mContentDescriptionCombinedSignal = mContentDescriptionPhoneSignal
+ = mContext.getString(R.string.accessibility_airplane_mode);
// look again; your radios are now airplanes
mPhoneSignalIconId = mDataSignalIconId = R.drawable.stat_sys_signal_flightmode;
@@ -863,12 +868,15 @@
cluster.setWifiIndicators(
mWifiConnected, // only show wifi in the cluster if connected
mWifiIconId,
- mWifiActivityIconId);
+ mWifiActivityIconId,
+ mContentDescriptionWifi);
cluster.setMobileDataIndicators(
mHasMobileDataFeature,
mPhoneSignalIconId,
mMobileActivityIconId,
- mDataTypeIconId);
+ mDataTypeIconId,
+ mContentDescriptionPhoneSignal,
+ mContentDescriptionDataType);
cluster.setIsAirplaneMode(mAirplaneMode);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index f970ff3..ca5d274 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -531,7 +531,8 @@
((KeyguardScreen) mUnlockScreen).onResume();
}
- if (mLockPatternUtils.usingBiometricWeak()) {
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW);
} else {
mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
@@ -1014,7 +1015,8 @@
// Binds to FaceLock service, but does not tell it to start
public void bindToFaceLock() {
- if (mLockPatternUtils.usingBiometricWeak()) {
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
if (!mBoundToFaceLockService) {
if (DEBUG) Log.d(TAG, "before bind to FaceLock service");
mContext.bindService(new Intent(IFaceLockInterface.class.getName()),
@@ -1030,7 +1032,8 @@
// Tells FaceLock to stop and then unbinds from the FaceLock service
public void stopAndUnbindFromFaceLock() {
- if (mLockPatternUtils.usingBiometricWeak()) {
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
stopFaceLock();
if (mBoundToFaceLockService) {
@@ -1079,7 +1082,8 @@
// Tells the FaceLock service to start displaying its UI and perform recognition
public void startFaceLock(IBinder windowToken, int x, int y, int h, int w)
{
- if (mLockPatternUtils.usingBiometricWeak()) {
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
synchronized (mFaceLockServiceRunningLock) {
if (!mFaceLockServiceRunning) {
if (DEBUG) Log.d(TAG, "Starting FaceLock");
@@ -1099,7 +1103,8 @@
// Tells the FaceLock service to stop displaying its UI and stop recognition
public void stopFaceLock()
{
- if (mLockPatternUtils.usingBiometricWeak()) {
+ if (mLockPatternUtils.usingBiometricWeak() &&
+ mLockPatternUtils.isBiometricWeakInstalled()) {
// Note that attempting to stop FaceLock when it's not running is not an issue.
// FaceLock can return, which stops it and then we try to stop it when the
// screen is turned off. That's why we check.
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 9205b9a..2cd6eab 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2147,15 +2147,12 @@
mActionMode = mode;
} else {
if (mActionModeView == null) {
- if (hasFeature(FEATURE_ACTION_MODE_OVERLAY)) {
+ if (isFloating()) {
mActionModeView = new ActionBarContextView(mContext);
mActionModePopup = new PopupWindow(mContext, null,
com.android.internal.R.attr.actionModePopupWindowStyle);
mActionModePopup.setLayoutInScreenEnabled(true);
mActionModePopup.setLayoutInsetDecor(true);
- mActionModePopup.setFocusable(true);
- mActionModePopup.setOutsideTouchable(false);
- mActionModePopup.setTouchModal(false);
mActionModePopup.setWindowLayoutType(
WindowManager.LayoutParams.TYPE_APPLICATION);
mActionModePopup.setContentView(mActionModeView);
@@ -2186,7 +2183,8 @@
if (mActionModeView != null) {
mActionModeView.killMode();
- mode = new StandaloneActionMode(getContext(), mActionModeView, wrappedCallback);
+ mode = new StandaloneActionMode(getContext(), mActionModeView, wrappedCallback,
+ mActionModePopup == null);
if (callback.onCreateActionMode(mode, mode.getMenu())) {
mode.invalidate();
mActionModeView.initForMode(mode);
@@ -2664,6 +2662,8 @@
layoutResource = com.android.internal.R.layout.screen_title;
}
// System.out.println("Title!");
+ } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
+ layoutResource = com.android.internal.R.layout.screen_simple_overlay_action_mode;
} else {
// Embedded, so no decoration is needed.
layoutResource = com.android.internal.R.layout.screen_simple;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 968180c..ed67707 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -276,6 +276,7 @@
int mLidOpenRotation;
int mCarDockRotation;
int mDeskDockRotation;
+ int mHdmiRotation;
int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
int mUserRotation = Surface.ROTATION_0;
@@ -777,6 +778,12 @@
? mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_width)
: 0;
+
+ if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
+ mHdmiRotation = mPortraitRotation;
+ } else {
+ mHdmiRotation = mLandscapeRotation;
+ }
}
public void updateSettings() {
@@ -2922,7 +2929,7 @@
int preferredRotation = -1;
if (mHdmiPlugged) {
// Ignore sensor when plugged into HDMI.
- preferredRotation = mLandscapeRotation;
+ preferredRotation = mHdmiRotation;
} else if (mLidOpen == LID_OPEN && mLidOpenRotation >= 0) {
// Ignore sensor when lid switch is open and rotation is forced.
preferredRotation = mLidOpenRotation;
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index bc145b1..3e1fb9f 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -2426,7 +2426,7 @@
final List<InputMethodSubtype> subtypes = getSubtypes(imi);
final String systemLocale = res.getConfiguration().locale.toString();
if (TextUtils.isEmpty(systemLocale)) return new ArrayList<InputMethodSubtype>();
- HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap =
+ final HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap =
new HashMap<String, InputMethodSubtype>();
final int N = subtypes.size();
boolean containsKeyboardSubtype = false;
@@ -2444,7 +2444,7 @@
return new ArrayList<InputMethodSubtype>(applicableModeAndSubtypesMap.values());
}
for (int i = 0; i < N; ++i) {
- InputMethodSubtype subtype = subtypes.get(i);
+ final InputMethodSubtype subtype = subtypes.get(i);
final String locale = subtype.getLocale();
final String mode = subtype.getMode();
// When system locale starts with subtype's locale, that subtype will be applicable
@@ -2456,10 +2456,12 @@
// need to find applicable subtypes aggressively unlike
// findLastResortApplicableSubtypeLocked.
if (systemLocale.startsWith(locale)) {
- InputMethodSubtype applicableSubtype = applicableModeAndSubtypesMap.get(mode);
+ final InputMethodSubtype applicableSubtype = applicableModeAndSubtypesMap.get(mode);
// If more applicable subtypes are contained, skip.
- if (applicableSubtype != null
- && systemLocale.equals(applicableSubtype.getLocale())) continue;
+ if (applicableSubtype != null) {
+ if (systemLocale.equals(applicableSubtype.getLocale())) continue;
+ if (!systemLocale.equals(locale)) continue;
+ }
applicableModeAndSubtypesMap.put(mode, subtype);
if (!containsKeyboardSubtype
&& SUBTYPE_MODE_KEYBOARD.equalsIgnoreCase(subtype.getMode())) {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 883fc71..660681b 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -149,6 +149,8 @@
private static final int WIFI_ENABLED = 1;
/* Wifi enabled while in airplane mode */
private static final int WIFI_ENABLED_AIRPLANE_OVERRIDE = 2;
+ /* Wifi disabled due to airplane mode on */
+ private static final int WIFI_DISABLED_AIRPLANE_ON = 3;
private AtomicInteger mWifiState = new AtomicInteger(WIFI_DISABLED);
private AtomicBoolean mAirplaneModeOn = new AtomicBoolean(false);
@@ -478,14 +480,19 @@
private void persistWifiEnabled(boolean enabled) {
final ContentResolver cr = mContext.getContentResolver();
+ boolean airplane = mAirplaneModeOn.get() && isAirplaneToggleable();
if (enabled) {
- if (isAirplaneModeOn() && isAirplaneToggleable()) {
+ if (airplane) {
mWifiState.set(WIFI_ENABLED_AIRPLANE_OVERRIDE);
} else {
mWifiState.set(WIFI_ENABLED);
}
} else {
- mWifiState.set(WIFI_DISABLED);
+ if (airplane) {
+ mWifiState.set(WIFI_DISABLED_AIRPLANE_ON);
+ } else {
+ mWifiState.set(WIFI_DISABLED);
+ }
}
Settings.Secure.putInt(cr, Settings.Secure.WIFI_ON, mWifiState.get());
}
diff --git a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
index 413894b..c9d615c 100644
--- a/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/content/res/Resources_Theme_Delegate.java
@@ -25,7 +25,7 @@
import android.util.TypedValue;
/**
- * Delegate used to provide new implementation of a select few methods of {@link Theme}
+ * Delegate used to provide new implementation of a select few methods of {@link Resources$Theme}
*
* Through the layoutlib_create tool, the original methods of Theme have been replaced
* by calls to methods of the same name in this delegate class.
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java
index 2745770..adad2ac 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java
@@ -16,6 +16,9 @@
package android.graphics;
+/**
+ * Class allowing access to package-protected methods/fields.
+ */
public class Typeface_Accessor {
public static void resetDefaults() {
diff --git a/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java b/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java
index ad95fcc..2961f97 100644
--- a/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/os/Looper_Accessor.java
@@ -15,6 +15,9 @@
*/
package android.os;
+/**
+ * Class allowing access to package-protected methods/fields.
+ */
public class Looper_Accessor {
public static void cleanupThread() {
diff --git a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
index e3778b1..96de51c 100644
--- a/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/AttachInfo_Accessor.java
@@ -22,6 +22,9 @@
import android.os.Handler;
import android.view.View.AttachInfo;
+/**
+ * Class allowing access to package-protected methods/fields.
+ */
public class AttachInfo_Accessor {
public static void setAttachInfo(View view) {
diff --git a/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java b/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java
index 01db34e..c3533e0 100644
--- a/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/ViewConfiguration_Accessor.java
@@ -16,6 +16,9 @@
package android.view;
+/**
+ * Class allowing access to package-protected methods/fields.
+ */
public class ViewConfiguration_Accessor {
public static void clearConfigurations() {
diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java
index 875336a..7a6e52e 100644
--- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java
+++ b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Accessor.java
@@ -16,6 +16,9 @@
package android.view.inputmethod;
+/**
+ * Class allowing access to package-protected methods/fields.
+ */
public class InputMethodManager_Accessor {
public static void resetInstance() {
diff --git a/tools/layoutlib/bridge/src/com/android/internal/textservice/ITextServicesManager_Stub_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/textservice/ITextServicesManager_Stub_Delegate.java
new file mode 100644
index 0000000..9efdcaf
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/textservice/ITextServicesManager_Stub_Delegate.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.textservice;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.view.textservice.SpellCheckerInfo;
+import android.view.textservice.SpellCheckerSubtype;
+
+
+/**
+ * Delegate used to provide new implementation of a select few methods of
+ * {@link ITextServicesManager$Stub}
+ *
+ * Through the layoutlib_create tool, the original methods of Stub have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class ITextServicesManager_Stub_Delegate {
+
+ @LayoutlibDelegate
+ public static ITextServicesManager asInterface(IBinder obj) {
+ // ignore the obj and return a fake interface implementation
+ return new FakeTextServicesManager();
+ }
+
+ private static class FakeTextServicesManager implements ITextServicesManager {
+
+ public void finishSpellCheckerService(ISpellCheckerSessionListener arg0)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public SpellCheckerInfo getCurrentSpellChecker(String arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public SpellCheckerSubtype getCurrentSpellCheckerSubtype(String arg0, boolean arg1)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public SpellCheckerInfo[] getEnabledSpellCheckers() throws RemoteException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void getSpellCheckerService(String arg0, String arg1,
+ ITextServicesSessionListener arg2, ISpellCheckerSessionListener arg3, Bundle arg4)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean isSpellCheckerEnabled() throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void setCurrentSpellChecker(String arg0, String arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setCurrentSpellCheckerSubtype(String arg0, int arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setSpellCheckerEnabled(boolean arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ public IBinder asBinder() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ }
+ }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 0453a5e..fbbcbc1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -67,6 +67,7 @@
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
+import android.view.textservice.TextServicesManager;
import java.io.File;
import java.io.FileInputStream;
@@ -414,6 +415,11 @@
return mBridgeInflater;
}
+ if (TEXT_SERVICES_MANAGER_SERVICE.equals(service)) {
+ // we need to return a valid service to avoid NPE
+ return TextServicesManager.getInstance();
+ }
+
// AutoCompleteTextView and MultiAutoCompleteTextView want a window
// service. We don't have any but it's not worth an exception.
if (WINDOW_SERVICE.equals(service)) {
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index 0a15627..70c8a00 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -111,7 +111,7 @@
"android.view.inputmethod.InputMethodManager#getInstance",
"android.util.Log#println_native",
"com.android.internal.util.XmlUtils#convertValueToInt",
- // TODO: comment out once DelegateClass is working
+ "com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
};
/**
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java
index ac4ae6d..89b53ab 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/DelegateMethodAdapter2.java
@@ -188,20 +188,24 @@
boolean pushedArg0 = false;
int maxStack = 0;
+ // Check if the last segment of the class name has inner an class.
+ // Right now we only support one level of inner classes.
+ Type outerType = null;
+ int slash = mClassName.lastIndexOf('/');
+ int dol = mClassName.lastIndexOf('$');
+ if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
+ String outerClass = mClassName.substring(0, dol);
+ outerType = Type.getObjectType(outerClass);
+
+ // Change a delegate class name to "com/foo/Outer_Inner_Delegate"
+ delegateClassName = delegateClassName.replace('$', '_');
+ }
+
// For an instance method (e.g. non-static), push the 'this' preceded
// by the 'this' of any outer class, if any.
if (!mIsStatic) {
- // Check if the last segment of the class name has inner an class.
- // Right now we only support one level of inner classes.
- int slash = mClassName.lastIndexOf('/');
- int dol = mClassName.lastIndexOf('$');
- if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
- String outerClass = mClassName.substring(0, dol);
- Type outerType = Type.getObjectType(outerClass);
- // Change a delegate class name to "com/foo/Outer_Inner_Delegate"
- delegateClassName = delegateClassName.replace('$', '_');
-
+ if (outerType != null) {
// The first-level inner class has a package-protected member called 'this$0'
// that points to the outer class.
@@ -213,6 +217,7 @@
outerType.getDescriptor()); // type of the field
maxStack++;
paramTypes.add(outerType);
+
}
// Push "this" for the instance method, which is always ALOAD 0