summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityManagerNative.java16
-rw-r--r--core/java/android/app/IActivityManager.java3
-rw-r--r--core/java/android/app/MediaRouteButton.java13
-rw-r--r--core/java/android/app/StatusBarManager.java33
-rw-r--r--core/java/android/content/Intent.java8
-rw-r--r--core/java/android/content/pm/ActivityInfo.java8
-rw-r--r--core/java/android/content/pm/PackageParser.java7
-rw-r--r--core/java/android/content/pm/PackageUserState.java8
-rw-r--r--core/java/android/content/pm/UserInfo.java6
-rw-r--r--core/java/android/content/pm/VerificationParams.java71
-rwxr-xr-xcore/java/android/provider/ContactsContract.java86
-rw-r--r--core/java/android/provider/Settings.java13
-rw-r--r--core/java/android/view/ScaleGestureDetector.java22
-rw-r--r--core/java/android/view/SimulatedTrackball.java106
-rw-r--r--core/java/android/view/View.java140
-rw-r--r--core/java/android/view/ViewGroup.java64
-rw-r--r--core/java/android/view/ViewRootImpl.java17
-rw-r--r--core/java/android/widget/CheckedTextView.java17
-rw-r--r--core/java/android/widget/Gallery.java18
-rw-r--r--core/java/android/widget/ImageView.java13
-rw-r--r--core/java/android/widget/NumberPicker.java8
21 files changed, 497 insertions, 180 deletions
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 9874b0b..83acb4d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1783,6 +1783,12 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case REQUEST_BUG_REPORT_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ requestBugReport();
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -4066,5 +4072,15 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
+ public void requestBugReport() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(REQUEST_BUG_REPORT_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 9454636..3124671 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -361,6 +361,8 @@ public interface IActivityManager extends IInterface {
public void registerUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
public void unregisterUserSwitchObserver(IUserSwitchObserver observer) throws RemoteException;
+ public void requestBugReport() throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -613,4 +615,5 @@ public interface IActivityManager extends IInterface {
int REGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+154;
int UNREGISTER_USER_SWITCH_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+155;
int GET_RUNNING_USER_IDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+156;
+ int REQUEST_BUG_REPORT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+157;
}
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index cfc8bbd..a9ccef0 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -221,21 +221,28 @@ public class MediaRouteButton extends View {
void updateRouteCount() {
final int N = mRouter.getRouteCount();
int count = 0;
+ boolean hasVideoRoutes = false;
for (int i = 0; i < N; i++) {
final RouteInfo route = mRouter.getRouteAt(i);
- if ((route.getSupportedTypes() & mRouteTypes) != 0) {
+ final int routeTypes = route.getSupportedTypes();
+ if ((routeTypes & mRouteTypes) != 0) {
if (route instanceof RouteGroup) {
count += ((RouteGroup) route).getRouteCount();
} else {
count++;
}
+ if ((routeTypes & MediaRouter.ROUTE_TYPE_LIVE_VIDEO) != 0) {
+ hasVideoRoutes = true;
+ }
}
}
setEnabled(count != 0);
- // Only allow toggling if we have more than just user routes
- mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0;
+ // Only allow toggling if we have more than just user routes.
+ // Don't toggle if we support video routes, we may have to let the dialog scan.
+ mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0 &&
+ !hasVideoRoutes;
}
@Override
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 1e61e10..3d656c7 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -97,13 +97,13 @@ public class StatusBarManager {
}
/**
- * Expand the notifications.
+ * Expand the notifications panel.
*/
- public void expandNotifications() {
+ public void expandNotificationsPanel() {
try {
final IStatusBarService svc = getService();
if (svc != null) {
- svc.expandNotifications();
+ svc.expandNotificationsPanel();
}
} catch (RemoteException ex) {
// system process is dead anyway.
@@ -112,13 +112,13 @@ public class StatusBarManager {
}
/**
- * Collapse the notifications.
+ * Collapse the notifications and settings panels.
*/
- public void collapseNotifications() {
+ public void collapsePanels() {
try {
final IStatusBarService svc = getService();
if (svc != null) {
- svc.collapseNotifications();
+ svc.collapsePanels();
}
} catch (RemoteException ex) {
// system process is dead anyway.
@@ -127,28 +127,13 @@ public class StatusBarManager {
}
/**
- * Expand the quick settings.
+ * Expand the settings panel.
*/
- public void expandQuickSettings() {
+ public void expandSettingsPanel() {
try {
final IStatusBarService svc = getService();
if (svc != null) {
- svc.expandQuickSettings();
- }
- } catch (RemoteException ex) {
- // system process is dead anyway.
- throw new RuntimeException(ex);
- }
- }
-
- /**
- * Collapse the quick settings.
- */
- public void collapseQuickSettings() {
- try {
- final IStatusBarService svc = getService();
- if (svc != null) {
- svc.collapseQuickSettings();
+ svc.expandSettingsPanel();
}
} catch (RemoteException ex) {
// system process is dead anyway.
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b9518b8..c301c5c 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1305,6 +1305,14 @@ public class Intent implements Parcelable, Cloneable {
= "android.intent.extra.REFERRER";
/**
+ * Used as an int extra field with {@link #ACTION_INSTALL_PACKAGE} and
+ * {@link} #ACTION_VIEW} to indicate the uid of the package that initiated the install
+ * @hide
+ */
+ public static final String EXTRA_ORIGINATING_UID
+ = "android.intent.extra.ORIGINATING_UID";
+
+ /**
* Used as a boolean extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
* package. Tells the installer UI to skip the confirmation with the user
* if the .apk is replacing an existing one.
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 0b320f0..b884b98 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -172,10 +172,16 @@ public class ActivityInfo extends ComponentInfo
*/
public static final int FLAG_IMMERSIVE = 0x0400;
/**
+ * @hide Bit in {@link #flags}: If set, this component will only be seen
+ * by the primary user. Only works with broadcast receivers. Set from the
+ * {@link android.R.attr#primaryUserOnly} attribute.
+ */
+ public static final int FLAG_PRIMARY_USER_ONLY = 0x20000000;
+ /**
* Bit in {@link #flags}: If set, a single instance of the receiver will
* run for all users on the device. Set from the
* {@link android.R.attr#singleUser} attribute. Note that this flag is
- * only relevent for ActivityInfo structures that are describiner receiver
+ * only relevant for ActivityInfo structures that are describing receiver
* components; it is not applied to activities.
*/
public static final int FLAG_SINGLE_USER = 0x40000000;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 0a22fca..c2b75f4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2193,7 +2193,7 @@ public class PackageParser {
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestActivity_singleUser,
false)) {
- a.info.flags |= ServiceInfo.FLAG_SINGLE_USER;
+ a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
if (a.info.exported) {
Slog.w(TAG, "Activity exported request ignored due to singleUser: "
+ a.className + " at " + mArchiveSourcePath + " "
@@ -2202,6 +2202,11 @@ public class PackageParser {
}
setExported = true;
}
+ if (sa.getBoolean(
+ com.android.internal.R.styleable.AndroidManifestActivity_primaryUserOnly,
+ false)) {
+ a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
+ }
}
sa.recycle();
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index 3579977..7b3d8cd 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -34,6 +34,14 @@ public class PackageUserState {
public HashSet<String> enabledComponents;
public PackageUserState() {
+ this(true);
+ }
+
+ /** @hide */
+ public PackageUserState(boolean isSystem) {
+ if (!isSystem) {
+ stopped = notLaunched = true;
+ }
installed = true;
enabled = COMPONENT_ENABLED_STATE_DEFAULT;
}
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index ab32523..593f826 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -71,6 +71,9 @@ public class UserInfo implements Parcelable {
public long creationTime;
public long lastLoggedInTime;
+ /** User is only partially created. */
+ public boolean partial;
+
public UserInfo(int id, String name, int flags) {
this(id, name, null, flags);
}
@@ -105,6 +108,7 @@ public class UserInfo implements Parcelable {
serialNumber = orig.serialNumber;
creationTime = orig.creationTime;
lastLoggedInTime = orig.lastLoggedInTime;
+ partial = orig.partial;
}
public UserHandle getUserHandle() {
@@ -128,6 +132,7 @@ public class UserInfo implements Parcelable {
dest.writeInt(serialNumber);
dest.writeLong(creationTime);
dest.writeLong(lastLoggedInTime);
+ dest.writeInt(partial ? 1 : 0);
}
public static final Parcelable.Creator<UserInfo> CREATOR
@@ -148,5 +153,6 @@ public class UserInfo implements Parcelable {
serialNumber = source.readInt();
creationTime = source.readLong();
lastLoggedInTime = source.readLong();
+ partial = source.readInt() != 0;
}
}
diff --git a/core/java/android/content/pm/VerificationParams.java b/core/java/android/content/pm/VerificationParams.java
index 6454de0..22e1a85 100644
--- a/core/java/android/content/pm/VerificationParams.java
+++ b/core/java/android/content/pm/VerificationParams.java
@@ -27,6 +27,9 @@ import android.os.Parcelable;
* @hide
*/
public class VerificationParams implements Parcelable {
+ /** A constant used to indicate that a uid value is not present. */
+ public static final int NO_UID = -1;
+
/** What we print out first when toString() is called. */
private static final String TO_STRING_PREFIX = "VerificationParams{";
@@ -39,6 +42,9 @@ public class VerificationParams implements Parcelable {
/** HTTP referrer URI associated with the originatingURI. */
private final Uri mReferrer;
+ /** UID of the application that the install request originated from. */
+ private final int mOriginatingUid;
+
/** UID of application requesting the install */
private int mInstallerUid;
@@ -57,16 +63,19 @@ public class VerificationParams implements Parcelable {
* from. May be {@code null}.
* @param referrer HTTP referrer URI associated with the originatingURI.
* May be {@code null}.
+ * @param originatingUid UID of the application that the install request originated
+ * from, or NO_UID if not present
* @param manifestDigest an object that holds the digest of the package
* which can be used to verify ownership. May be {@code null}.
*/
public VerificationParams(Uri verificationURI, Uri originatingURI, Uri referrer,
- ManifestDigest manifestDigest) {
+ int originatingUid, ManifestDigest manifestDigest) {
mVerificationURI = verificationURI;
mOriginatingURI = originatingURI;
mReferrer = referrer;
+ mOriginatingUid = originatingUid;
mManifestDigest = manifestDigest;
- mInstallerUid = -1;
+ mInstallerUid = NO_UID;
}
public Uri getVerificationURI() {
@@ -81,11 +90,16 @@ public class VerificationParams implements Parcelable {
return mReferrer;
}
+ /** return NO_UID if not available */
+ public int getOriginatingUid() {
+ return mOriginatingUid;
+ }
+
public ManifestDigest getManifestDigest() {
return mManifestDigest;
}
- /** @return -1 when not set */
+ /** @return NO_UID when not set */
public int getInstallerUid() {
return mInstallerUid;
}
@@ -111,31 +125,39 @@ public class VerificationParams implements Parcelable {
final VerificationParams other = (VerificationParams) o;
- if (mVerificationURI == null && other.mVerificationURI != null) {
- return false;
- }
- if (!mVerificationURI.equals(other.mVerificationURI)) {
+ if (mVerificationURI == null) {
+ if (other.mVerificationURI != null) {
+ return false;
+ }
+ } else if (!mVerificationURI.equals(other.mVerificationURI)) {
return false;
}
- if (mOriginatingURI == null && other.mOriginatingURI != null) {
- return false;
- }
- if (!mOriginatingURI.equals(other.mOriginatingURI)) {
+ if (mOriginatingURI == null) {
+ if (other.mOriginatingURI != null) {
+ return false;
+ }
+ } else if (!mOriginatingURI.equals(other.mOriginatingURI)) {
return false;
}
- if (mReferrer == null && other.mReferrer != null) {
- return false;
- }
- if (!mReferrer.equals(other.mReferrer)) {
+ if (mReferrer == null) {
+ if (other.mReferrer != null) {
+ return false;
+ }
+ } else if (!mReferrer.equals(other.mReferrer)) {
return false;
}
- if (mManifestDigest == null && other.mManifestDigest != null) {
+ if (mOriginatingUid != other.mOriginatingUid) {
return false;
}
- if (mManifestDigest != null && !mManifestDigest.equals(other.mManifestDigest)) {
+
+ if (mManifestDigest == null) {
+ if (other.mManifestDigest != null) {
+ return false;
+ }
+ } else if (!mManifestDigest.equals(other.mManifestDigest)) {
return false;
}
@@ -150,11 +172,12 @@ public class VerificationParams implements Parcelable {
public int hashCode() {
int hash = 3;
- hash += 5 * (mVerificationURI==null?1:mVerificationURI.hashCode());
- hash += 7 * (mOriginatingURI==null?1:mOriginatingURI.hashCode());
- hash += 11 * (mReferrer==null?1:mReferrer.hashCode());
- hash += 13 * (mManifestDigest==null?1:mManifestDigest.hashCode());
- hash += 17 * mInstallerUid;
+ hash += 5 * (mVerificationURI == null ? 1 : mVerificationURI.hashCode());
+ hash += 7 * (mOriginatingURI == null ? 1 : mOriginatingURI.hashCode());
+ hash += 11 * (mReferrer == null ? 1 : mReferrer.hashCode());
+ hash += 13 * mOriginatingUid;
+ hash += 17 * (mManifestDigest == null ? 1 : mManifestDigest.hashCode());
+ hash += 19 * mInstallerUid;
return hash;
}
@@ -169,6 +192,8 @@ public class VerificationParams implements Parcelable {
sb.append(mOriginatingURI.toString());
sb.append(",mReferrer=");
sb.append(mReferrer.toString());
+ sb.append(",mOriginatingUid=");
+ sb.append(mOriginatingUid);
sb.append(",mManifestDigest=");
sb.append(mManifestDigest.toString());
sb.append(",mInstallerUid=");
@@ -183,6 +208,7 @@ public class VerificationParams implements Parcelable {
dest.writeParcelable(mVerificationURI, 0);
dest.writeParcelable(mOriginatingURI, 0);
dest.writeParcelable(mReferrer, 0);
+ dest.writeInt(mOriginatingUid);
dest.writeParcelable(mManifestDigest, 0);
dest.writeInt(mInstallerUid);
}
@@ -192,6 +218,7 @@ public class VerificationParams implements Parcelable {
mVerificationURI = source.readParcelable(Uri.class.getClassLoader());
mOriginatingURI = source.readParcelable(Uri.class.getClassLoader());
mReferrer = source.readParcelable(Uri.class.getClassLoader());
+ mOriginatingUid = source.readInt();
mManifestDigest = source.readParcelable(ManifestDigest.class.getClassLoader());
mInstallerUid = source.readInt();
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b3ab385..5b49ba3 100755
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -7659,6 +7659,54 @@ public final class ContactsContract {
public static final int MODE_LARGE = 3;
/**
+ * Constructs the QuickContacts intent with a view's rect.
+ * @hide
+ */
+ public static Intent composeQuickContactsIntent(Context context, View target, Uri lookupUri,
+ int mode, String[] excludeMimes) {
+ // Find location and bounds of target view, adjusting based on the
+ // assumed local density.
+ final float appScale = context.getResources().getCompatibilityInfo().applicationScale;
+ final int[] pos = new int[2];
+ target.getLocationOnScreen(pos);
+
+ final Rect rect = new Rect();
+ rect.left = (int) (pos[0] * appScale + 0.5f);
+ rect.top = (int) (pos[1] * appScale + 0.5f);
+ rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f);
+ rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f);
+
+ return composeQuickContactsIntent(context, rect, lookupUri, mode, excludeMimes);
+ }
+
+ /**
+ * Constructs the QuickContacts intent.
+ * @hide
+ */
+ public static Intent composeQuickContactsIntent(Context context, Rect target,
+ Uri lookupUri, int mode, String[] excludeMimes) {
+ // When launching from an Activiy, we don't want to start a new task, but otherwise
+ // we *must* start a new task. (Otherwise startActivity() would crash.)
+ Context actualContext = context;
+ while ((actualContext instanceof ContextWrapper)
+ && !(actualContext instanceof Activity)) {
+ actualContext = ((ContextWrapper) actualContext).getBaseContext();
+ }
+ final int intentFlags = (actualContext instanceof Activity)
+ ? Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
+ : Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK;
+
+ // Launch pivot dialog through intent for now
+ final Intent intent = new Intent(ACTION_QUICK_CONTACT).addFlags(intentFlags);
+
+ intent.setData(lookupUri);
+ intent.setSourceBounds(target);
+ intent.putExtra(EXTRA_MODE, mode);
+ intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
+ return intent;
+ }
+
+ /**
* Trigger a dialog that lists the various methods of interacting with
* the requested {@link Contacts} entry. This may be based on available
* {@link ContactsContract.Data} rows under that contact, and may also
@@ -7683,20 +7731,10 @@ public final class ContactsContract {
*/
public static void showQuickContact(Context context, View target, Uri lookupUri, int mode,
String[] excludeMimes) {
- // Find location and bounds of target view, adjusting based on the
- // assumed local density.
- final float appScale = context.getResources().getCompatibilityInfo().applicationScale;
- final int[] pos = new int[2];
- target.getLocationOnScreen(pos);
-
- final Rect rect = new Rect();
- rect.left = (int) (pos[0] * appScale + 0.5f);
- rect.top = (int) (pos[1] * appScale + 0.5f);
- rect.right = (int) ((pos[0] + target.getWidth()) * appScale + 0.5f);
- rect.bottom = (int) ((pos[1] + target.getHeight()) * appScale + 0.5f);
-
// Trigger with obtained rectangle
- showQuickContact(context, rect, lookupUri, mode, excludeMimes);
+ Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
+ excludeMimes);
+ context.startActivity(intent);
}
/**
@@ -7727,25 +7765,9 @@ public final class ContactsContract {
*/
public static void showQuickContact(Context context, Rect target, Uri lookupUri, int mode,
String[] excludeMimes) {
- // When launching from an Activiy, we don't want to start a new task, but otherwise
- // we *must* start a new task. (Otherwise startActivity() would crash.)
- Context actualContext = context;
- while ((actualContext instanceof ContextWrapper)
- && !(actualContext instanceof Activity)) {
- actualContext = ((ContextWrapper) actualContext).getBaseContext();
- }
- final int intentFlags = (actualContext instanceof Activity)
- ? Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
- : Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK;
-
- // Launch pivot dialog through intent for now
- final Intent intent = new Intent(ACTION_QUICK_CONTACT).addFlags(intentFlags);
-
- intent.setData(lookupUri);
- intent.setSourceBounds(target);
- intent.putExtra(EXTRA_MODE, mode);
- intent.putExtra(EXTRA_EXCLUDE_MIMES, excludeMimes);
- context.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
+ excludeMimes);
+ context.startActivity(intent);
}
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 550713d..8825f58 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3141,6 +3141,12 @@ public final class Settings {
public static final String DEVICE_PROVISIONED = Global.DEVICE_PROVISIONED;
/**
+ * Whether the current user has been set up via setup wizard (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String USER_SETUP_COMPLETE = "user_setup_complete";
+
+ /**
* List of input methods that are currently enabled. This is a string
* containing the IDs of all enabled input methods, each ID separated
* by ':'.
@@ -4619,13 +4625,6 @@ public final class Settings {
public static final String SMS_SHORT_CODE_RULE = "sms_short_code_rule";
/**
- * Prefix for SMS short code regex patterns (country code is appended).
- * @see com.android.internal.telephony.SmsUsageMonitor
- * @hide
- */
- public static final String SMS_SHORT_CODES_PREFIX = "sms_short_codes_";
-
- /**
* Used to disable Tethering on a device - defaults to true
* @hide
*/
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index b0a2711..4873860 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -19,6 +19,7 @@ package android.view;
import android.content.Context;
import android.os.SystemClock;
import android.util.FloatMath;
+import android.util.Log;
import java.util.Arrays;
@@ -223,10 +224,14 @@ public class ScaleGestureDetector {
* @param id pointer id to clear
* @see #addTouchHistory(MotionEvent)
*/
- private void removeTouchHistoryForId(int id) {
+ private boolean removeTouchHistoryForId(int id) {
+ if (id >= mTouchHistoryLastAccepted.length) {
+ return false;
+ }
mTouchHistoryLastAccepted[id] = Float.NaN;
mTouchHistoryDirection[id] = 0;
mTouchHistoryLastAcceptedTime[id] = 0;
+ return true;
}
/**
@@ -236,6 +241,11 @@ public class ScaleGestureDetector {
* @see #addTouchHistory(MotionEvent)
*/
private float getAdjustedTouchHistory(int id) {
+ if (id >= mTouchHistoryLastAccepted.length) {
+ Log.e(TAG, "Error retrieving adjusted touch history for id=" + id +
+ " - incomplete event stream?");
+ return 0;
+ }
return mTouchHistoryLastAccepted[id];
}
@@ -244,6 +254,10 @@ public class ScaleGestureDetector {
* @see #addTouchHistory(MotionEvent)
*/
private void clearTouchHistory() {
+ if (mTouchHistoryLastAccepted == null) {
+ // All three arrays will be null if this is the case; nothing to do.
+ return;
+ }
Arrays.fill(mTouchHistoryLastAccepted, Float.NaN);
Arrays.fill(mTouchHistoryDirection, 0);
Arrays.fill(mTouchHistoryLastAcceptedTime, 0);
@@ -333,7 +347,11 @@ public class ScaleGestureDetector {
final float focusY = sumY / div;
if (pointerUp) {
- removeTouchHistoryForId(event.getPointerId(event.getActionIndex()));
+ final int id = event.getPointerId(event.getActionIndex());
+ if (!removeTouchHistoryForId(id)) {
+ Log.e(TAG, "Got ACTION_POINTER_UP for previously unknown id=" + id +
+ " - incomplete event stream?");
+ }
} else {
addTouchHistory(event);
}
diff --git a/core/java/android/view/SimulatedTrackball.java b/core/java/android/view/SimulatedTrackball.java
new file mode 100644
index 0000000..1e152d8
--- /dev/null
+++ b/core/java/android/view/SimulatedTrackball.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+/**
+ * This class creates trackball events from touchpad events.
+ * @see ViewRootImpl
+ */
+class SimulatedTrackball {
+
+ //The position of the previous touchpad event
+ private float mLastTouchpadXPosition;
+ private float mLastTouchpadYPosition;
+ //Where the touchpad was initially pressed
+ private float mTouchpadEnterXPosition;
+ private float mTouchpadEnterYPosition;
+ //When the last touchpad event occurred
+ private long mLastTouchPadStartTimeMs = 0;
+
+ //Change in position allowed during tap events
+ private float mTouchSlop;
+ private float mTouchSlopSquared;
+ //Has the TouchSlop constraint been invalidated
+ private boolean mAlwaysInTapRegion = true;
+
+ //Maximum difference in milliseconds between the down and up of a touch event
+ //for it to be considered a tap
+ //TODO:Read this value from a config file
+ private static final int MAX_TAP_TIME = 250;
+
+ public SimulatedTrackball(){
+ mTouchSlop = ViewConfiguration.getTouchSlop();
+ mTouchSlopSquared = mTouchSlop * mTouchSlop;
+ }
+
+ public void updateTrackballDirection(ViewRootImpl viewroot, MotionEvent event){
+ //Store what time the touchpad event occurred
+ final long time = event.getEventTime();
+ MotionEvent trackballEvent;
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ mLastTouchPadStartTimeMs = time;
+ mAlwaysInTapRegion = true;
+ mTouchpadEnterXPosition = event.getX();
+ mTouchpadEnterYPosition = event.getY();
+ break;
+ case MotionEvent.ACTION_HOVER_MOVE:
+ //Find the difference in position between the two most recent touchpad events
+ float deltaX = event.getX() - mLastTouchpadXPosition;
+ float deltaY = event.getY() - mLastTouchpadYPosition;
+
+ //TODO: Get simulated trackball configuration parameters
+ //Create a trackball event from recorded touchpad event data
+ trackballEvent = MotionEvent.obtain(mLastTouchPadStartTimeMs, time,
+ MotionEvent.ACTION_MOVE, deltaX / 50,
+ deltaY / 50, 0, 0, event.getMetaState(),
+ 10f, 10f, event.getDeviceId(), 0);
+ trackballEvent.setSource(InputDevice.SOURCE_CLASS_TRACKBALL);
+ //Add the new event to event queue
+ viewroot.enqueueInputEvent(trackballEvent);
+
+ deltaX = event.getX() - mTouchpadEnterXPosition;
+ deltaY = event.getY() - mTouchpadEnterYPosition;
+ if (mTouchSlopSquared < deltaX * deltaX + deltaY * deltaY){
+ mAlwaysInTapRegion = false;
+ }
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ if (time-mLastTouchPadStartTimeMs<MAX_TAP_TIME && mAlwaysInTapRegion){
+ //Trackball Down
+ trackballEvent = MotionEvent.obtain(mLastTouchPadStartTimeMs, time,
+ MotionEvent.ACTION_DOWN, 0, 0, 0, 0, event.getMetaState(),
+ 10f, 10f, event.getDeviceId(), 0);
+ trackballEvent.setSource(InputDevice.SOURCE_CLASS_TRACKBALL);
+ //Add the new event to event queue
+ viewroot.enqueueInputEvent(trackballEvent);
+
+ //Trackball Release
+ trackballEvent = MotionEvent.obtain(mLastTouchPadStartTimeMs, time,
+ MotionEvent.ACTION_UP, 0, 0, 0, 0, event.getMetaState(),
+ 10f, 10f, event.getDeviceId(), 0);
+ trackballEvent.setSource(InputDevice.SOURCE_CLASS_TRACKBALL);
+ //Add the new event to event queue
+ viewroot.enqueueInputEvent(trackballEvent);
+ }
+ break;
+ }
+ //Store touch event position
+ mLastTouchpadXPosition = event.getX();
+ mLastTouchpadYPosition = event.getY();
+ }
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b5bb98a..6a35d51 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5887,6 +5887,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* layout attribute and/or the inherited value from the parent
*
* @return true if the layout is right-to-left.
+ *
+ * @hide
*/
@ViewDebug.ExportedProperty(category = "layout")
public boolean isLayoutRtl() {
@@ -11628,9 +11630,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
* that the parent directionality can and will be resolved before its children.
*
+ * @return true if resolution has been done, false otherwise.
+ *
* @hide
*/
- public void resolveLayoutDirection() {
+ public boolean resolveLayoutDirection() {
// Clear any previous layout direction resolution
mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
@@ -11641,15 +11645,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
case LAYOUT_DIRECTION_INHERIT:
// We cannot resolve yet. LTR is by default and let the resolution happen again
// later to get the correct resolved value
- if (!canResolveLayoutDirection()) return;
-
- ViewGroup viewGroup = ((ViewGroup) mParent);
+ if (!canResolveLayoutDirection()) return false;
- // We cannot resolve yet on the parent too. LTR is by default and let the
- // resolution happen again later
- if (!viewGroup.canResolveLayoutDirection()) return;
+ View parent = ((View) mParent);
+ // Parent has not yet resolved, LTR is still the default
+ if (!parent.isLayoutDirectionResolved()) return false;
- if (viewGroup.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
+ if (parent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
}
break;
@@ -11669,6 +11671,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Set to resolved
mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
+ return true;
}
/**
@@ -11679,10 +11682,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
public boolean canResolveLayoutDirection() {
- switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
- PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
+ switch (getRawLayoutDirection()) {
case LAYOUT_DIRECTION_INHERIT:
- return (mParent != null) && (mParent instanceof ViewGroup);
+ return (mParent != null) && (mParent instanceof ViewGroup) &&
+ ((ViewGroup) mParent).canResolveLayoutDirection();
default:
return true;
}
@@ -16697,9 +16700,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Resolve the text direction.
*
+ * @return true if resolution has been done, false otherwise.
+ *
* @hide
*/
- public void resolveTextDirection() {
+ public boolean resolveTextDirection() {
// Reset any previous text direction resolution
mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
@@ -16708,29 +16713,35 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final int textDirection = getRawTextDirection();
switch(textDirection) {
case TEXT_DIRECTION_INHERIT:
- if (canResolveTextDirection()) {
- ViewGroup viewGroup = ((ViewGroup) mParent);
-
- // Set current resolved direction to the same value as the parent's one
- final int parentResolvedDirection = viewGroup.getTextDirection();
- switch (parentResolvedDirection) {
- case TEXT_DIRECTION_FIRST_STRONG:
- case TEXT_DIRECTION_ANY_RTL:
- case TEXT_DIRECTION_LTR:
- case TEXT_DIRECTION_RTL:
- case TEXT_DIRECTION_LOCALE:
- mPrivateFlags2 |=
- (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
- break;
- default:
- // Default resolved direction is "first strong" heuristic
- mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
- }
- } else {
+ if (!canResolveTextDirection()) {
// We cannot do the resolution if there is no parent, so use the default one
mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
// Resolution will need to happen again later
- return;
+ return false;
+ }
+
+ View parent = ((View) mParent);
+ // Parent has not yet resolved, so we still return the default
+ if (!parent.isTextDirectionResolved()) {
+ mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
+ // Resolution will need to happen again later
+ return false;
+ }
+
+ // Set current resolved direction to the same value as the parent's one
+ final int parentResolvedDirection = parent.getTextDirection();
+ switch (parentResolvedDirection) {
+ case TEXT_DIRECTION_FIRST_STRONG:
+ case TEXT_DIRECTION_ANY_RTL:
+ case TEXT_DIRECTION_LTR:
+ case TEXT_DIRECTION_RTL:
+ case TEXT_DIRECTION_LOCALE:
+ mPrivateFlags2 |=
+ (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
+ break;
+ default:
+ // Default resolved direction is "first strong" heuristic
+ mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
}
break;
case TEXT_DIRECTION_FIRST_STRONG:
@@ -16752,6 +16763,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Set to resolved
mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
+ return true;
}
/**
@@ -16762,7 +16774,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private boolean canResolveTextDirection() {
switch (getRawTextDirection()) {
case TEXT_DIRECTION_INHERIT:
- return (mParent != null) && (mParent instanceof ViewGroup);
+ return (mParent != null) && (mParent instanceof View) &&
+ ((View) mParent).canResolveTextDirection();
default:
return true;
}
@@ -16892,9 +16905,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* Resolve the text alignment.
*
+ * @return true if resolution has been done, false otherwise.
+ *
* @hide
*/
- public void resolveTextAlignment() {
+ public boolean resolveTextAlignment() {
// Reset any previous text alignment resolution
mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
@@ -16904,32 +16919,37 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
switch (textAlignment) {
case TEXT_ALIGNMENT_INHERIT:
// Check if we can resolve the text alignment
- if (canResolveTextAlignment() && mParent instanceof View) {
- View view = (View) mParent;
-
- final int parentResolvedTextAlignment = view.getTextAlignment();
- switch (parentResolvedTextAlignment) {
- case TEXT_ALIGNMENT_GRAVITY:
- case TEXT_ALIGNMENT_TEXT_START:
- case TEXT_ALIGNMENT_TEXT_END:
- case TEXT_ALIGNMENT_CENTER:
- case TEXT_ALIGNMENT_VIEW_START:
- case TEXT_ALIGNMENT_VIEW_END:
- // Resolved text alignment is the same as the parent resolved
- // text alignment
- mPrivateFlags2 |=
- (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
- break;
- default:
- // Use default resolved text alignment
- mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
- }
- }
- else {
+ if (!canResolveTextAlignment()) {
// We cannot do the resolution if there is no parent so use the default
mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
// Resolution will need to happen again later
- return;
+ return false;
+ }
+ View parent = (View) mParent;
+
+ // Parent has not yet resolved, so we still return the default
+ if (!parent.isTextAlignmentResolved()) {
+ mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
+ // Resolution will need to happen again later
+ return false;
+ }
+
+ final int parentResolvedTextAlignment = parent.getTextAlignment();
+ switch (parentResolvedTextAlignment) {
+ case TEXT_ALIGNMENT_GRAVITY:
+ case TEXT_ALIGNMENT_TEXT_START:
+ case TEXT_ALIGNMENT_TEXT_END:
+ case TEXT_ALIGNMENT_CENTER:
+ case TEXT_ALIGNMENT_VIEW_START:
+ case TEXT_ALIGNMENT_VIEW_END:
+ // Resolved text alignment is the same as the parent resolved
+ // text alignment
+ mPrivateFlags2 |=
+ (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
+ break;
+ default:
+ // Use default resolved text alignment
+ mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
}
break;
case TEXT_ALIGNMENT_GRAVITY:
@@ -16952,6 +16972,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Set the resolved
mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
+ return true;
}
/**
@@ -16962,7 +16983,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private boolean canResolveTextAlignment() {
switch (getRawTextAlignment()) {
case TEXT_DIRECTION_INHERIT:
- return (mParent != null);
+ return (mParent != null) && (mParent instanceof View) &&
+ ((View) mParent).canResolveTextAlignment();
default:
return true;
}
@@ -17243,7 +17265,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @return the measure specification based on size and mode
*/
public static int makeMeasureSpec(int size, int mode) {
- return size + mode;
+ return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
/**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 343db86..9af8f2c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3476,6 +3476,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
ai.mKeepScreenOn = lastKeepOn;
}
+ if (child.isLayoutDirectionInherited()) {
+ child.resetResolvedLayoutDirection();
+ child.resolveRtlPropertiesIfNeeded();
+ }
+
onViewAdded(child);
if ((child.mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE) {
@@ -5347,48 +5352,54 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @hide
*/
@Override
- public void resolveLayoutDirection() {
- super.resolveLayoutDirection();
-
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.isLayoutDirectionInherited()) {
- child.resolveLayoutDirection();
+ public boolean resolveLayoutDirection() {
+ final boolean result = super.resolveLayoutDirection();
+ if (result) {
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.isLayoutDirectionInherited()) {
+ child.resolveLayoutDirection();
+ }
}
}
+ return result;
}
/**
* @hide
*/
@Override
- public void resolveTextDirection() {
- super.resolveTextDirection();
-
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.isTextDirectionInherited()) {
- child.resolveTextDirection();
+ public boolean resolveTextDirection() {
+ final boolean result = super.resolveTextDirection();
+ if (result) {
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.isTextDirectionInherited()) {
+ child.resolveTextDirection();
+ }
}
}
+ return result;
}
/**
* @hide
*/
@Override
- public void resolveTextAlignment() {
- super.resolveTextAlignment();
-
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.isTextAlignmentInherited()) {
- child.resolveTextAlignment();
+ public boolean resolveTextAlignment() {
+ final boolean result = super.resolveTextAlignment();
+ if (result) {
+ int count = getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.isTextAlignmentInherited()) {
+ child.resolveTextAlignment();
+ }
}
}
+ return result;
}
/**
@@ -5984,7 +5995,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
- protected boolean isLayoutRtl() {
+ /**
+ * @hide
+ */
+ public boolean isLayoutRtl() {
return (layoutDirection == View.LAYOUT_DIRECTION_RTL);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c2e884d..73019b2 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -145,6 +145,8 @@ public final class ViewRootImpl implements ViewParent,
final TrackballAxis mTrackballAxisX = new TrackballAxis();
final TrackballAxis mTrackballAxisY = new TrackballAxis();
+ final SimulatedTrackball mSimulatedTrackball = new SimulatedTrackball();
+
int mLastJoystickXDirection;
int mLastJoystickYDirection;
int mLastJoystickXKeyCode;
@@ -3438,7 +3440,6 @@ public final class ViewRootImpl implements ViewParent,
if (mInputEventConsistencyVerifier != null) {
mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
}
-
if (mView != null && mAdded && (q.mFlags & QueuedInputEvent.FLAG_DELIVER_POST_IME) == 0) {
if (LOCAL_LOGV)
Log.v(TAG, "Dispatching generic motion " + event + " to " + mView);
@@ -3465,12 +3466,17 @@ public final class ViewRootImpl implements ViewParent,
private void deliverGenericMotionEventPostIme(QueuedInputEvent q) {
final MotionEvent event = (MotionEvent) q.mEvent;
- final boolean isJoystick = (event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
+ final int source = event.getSource();
+ final boolean isJoystick = (source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
+ final boolean isTouchPad = (source & InputDevice.SOURCE_CLASS_POSITION) != 0;
// If there is no view, then the event will not be handled.
if (mView == null || !mAdded) {
if (isJoystick) {
updateJoystickDirection(event, false);
+ } else if (isTouchPad) {
+ //Convert TouchPad motion into a TrackBall event
+ mSimulatedTrackball.updateTrackballDirection(this, event);
}
finishInputEvent(q, false);
return;
@@ -3480,6 +3486,9 @@ public final class ViewRootImpl implements ViewParent,
if (mView.dispatchGenericMotionEvent(event)) {
if (isJoystick) {
updateJoystickDirection(event, false);
+ } else if (isTouchPad) {
+ //Convert TouchPad motion into a TrackBall event
+ mSimulatedTrackball.updateTrackballDirection(this, event);
}
finishInputEvent(q, true);
return;
@@ -3490,6 +3499,10 @@ public final class ViewRootImpl implements ViewParent,
// those.
updateJoystickDirection(event, true);
finishInputEvent(q, true);
+ } else if (isTouchPad) {
+ //Convert TouchPad motion into a TrackBall event
+ mSimulatedTrackball.updateTrackballDirection(this, event);
+ finishInputEvent(q, true);
} else {
finishInputEvent(q, false);
}
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index bc78adc..cea1fd5 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -46,6 +46,9 @@ public class CheckedTextView extends TextView implements Checkable {
private int mCheckMarkWidth;
private boolean mNeedRequestlayout;
+ private int initialPaddingLeft = -1;
+ private int initialPaddingRight = -1;
+
private static final int[] CHECKED_STATE_SET = {
R.attr.state_checked
};
@@ -176,10 +179,22 @@ public class CheckedTextView extends TextView implements Checkable {
protected void internalSetPadding(int left, int top, int right, int bottom) {
super.internalSetPadding(left, top, right, bottom);
setBasePadding(isLayoutRtl());
+ initialPaddingLeft = mPaddingLeft;
+ initialPaddingRight = mPaddingRight;
}
@Override
public void onPaddingChanged(int layoutDirection) {
+ updatePadding();
+ }
+
+ @Override
+ public void onRtlPropertiesChanged() {
+ super.onRtlPropertiesChanged();
+ updatePadding();
+ }
+
+ private void updatePadding() {
int newPadding = (mCheckMarkDrawable != null) ?
mCheckMarkWidth + mBasePadding : mBasePadding;
mNeedRequestlayout |= (mPaddingRight != newPadding);
@@ -193,7 +208,7 @@ public class CheckedTextView extends TextView implements Checkable {
mNeedRequestlayout = false;
}
}
-
+
@Override
public void setPadding(int left, int top, int right, int bottom) {
super.setPadding(left, top, right, bottom);
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index b72b8cb..e0c5bbd 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -182,6 +182,12 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
*/
private boolean mIsRtl = true;
+ /**
+ * Offset between the center of the selected child view and the center of the Gallery.
+ * Used to reset position correctly during layout.
+ */
+ private int mSelectedCenterOffset;
+
public Gallery(Context context) {
this(context, null);
}
@@ -395,6 +401,14 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
setSelectionToCenterChild();
+ final View selChild = mSelectedChild;
+ if (selChild != null) {
+ final int childLeft = selChild.getLeft();
+ final int childCenter = selChild.getWidth() / 2;
+ final int galleryCenter = getWidth() / 2;
+ mSelectedCenterOffset = childLeft + childCenter - galleryCenter;
+ }
+
onScrollChanged(0, 0, 0, 0); // dummy values, View's implementation does not use these.
invalidate();
@@ -537,6 +551,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
// We haven't been callbacking during the fling, so do it now
super.selectionChanged();
}
+ mSelectedCenterOffset = 0;
invalidate();
}
@@ -650,7 +665,8 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList
View sel = makeAndAddView(mSelectedPosition, 0, 0, true);
// Put the selected child in the center
- int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2);
+ int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2) +
+ mSelectedCenterOffset;
sel.offsetLeftAndRight(selectedOffset);
fillToGalleryRight();
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 87396fb..1d465ce 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -789,6 +789,12 @@ public class ImageView extends View {
if (resizeWidth) {
int newWidth = (int)(desiredAspect * (heightSize - ptop - pbottom)) +
pleft + pright;
+
+ // Allow the width to outgrow its original estimate if height is fixed.
+ if (!resizeHeight) {
+ widthSize = resolveAdjustedSize(newWidth, mMaxWidth, widthMeasureSpec);
+ }
+
if (newWidth <= widthSize) {
widthSize = newWidth;
done = true;
@@ -799,6 +805,13 @@ public class ImageView extends View {
if (!done && resizeHeight) {
int newHeight = (int)((widthSize - pleft - pright) / desiredAspect) +
ptop + pbottom;
+
+ // Allow the height to outgrow its original estimate if width is fixed.
+ if (!resizeWidth) {
+ heightSize = resolveAdjustedSize(newHeight, mMaxHeight,
+ heightMeasureSpec);
+ }
+
if (newHeight <= heightSize) {
heightSize = newHeight;
}
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 704f6b6..4918e48 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1361,6 +1361,14 @@ public class NumberPicker extends LinearLayout {
// Allow text entry rather than strictly numeric entry.
mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+ // Make sure the min, max, respect the size of the displayed
+ // values. This will take care of the current value as well.
+ if (getMinValue() >= displayedValues.length) {
+ setMinValue(0);
+ }
+ if (getMaxValue() >= displayedValues.length) {
+ setMaxValue(displayedValues.length - 1);
+ }
} else {
mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
}