summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/content/Intent.java16
-rw-r--r--core/java/android/content/res/Configuration.java65
-rw-r--r--core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java1
-rw-r--r--core/java/android/os/BatteryStats.java37
-rw-r--r--core/java/android/os/storage/IMountService.java53
-rw-r--r--core/java/android/os/storage/StorageManager.java12
-rw-r--r--core/java/android/service/carrier/CarrierConfigService.java4
-rw-r--r--core/java/android/service/carrier/CarrierMessagingService.java4
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java29
-rw-r--r--core/java/android/text/BidiFormatter.java6
-rw-r--r--core/java/android/view/Display.java11
-rw-r--r--core/java/android/view/DisplayInfo.java3
-rw-r--r--core/java/android/view/HardwareRenderer.java21
-rw-r--r--core/java/android/view/ThreadedRenderer.java32
-rw-r--r--core/java/android/view/ViewRootImpl.java40
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java9
-rw-r--r--core/java/android/webkit/WebView.java2
-rw-r--r--core/java/android/webkit/WebViewFactory.java72
-rw-r--r--core/java/android/widget/DayPickerPagerAdapter.java9
-rw-r--r--core/java/android/widget/DayPickerView.java4
-rw-r--r--core/java/android/widget/Editor.java76
21 files changed, 406 insertions, 100 deletions
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 7d76760..2db623b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1535,6 +1535,22 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.MANAGE_APP_PERMISSIONS";
/**
+ * Activity action: Launch UI to manage permissions.
+ * <p>
+ * Input: Nothing.
+ * </p>
+ * <p>
+ * Output: Nothing.
+ * </p>
+ *
+ * @hide
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_MANAGE_PERMISSIONS =
+ "android.intent.action.MANAGE_PERMISSIONS";
+
+ /**
* Intent extra: An app package name.
* <p>
* Type: String
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index bc6d4ce..fd60476 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -156,9 +156,34 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* value indicating that a layout dir has been set to RTL. */
public static final int SCREENLAYOUT_LAYOUTDIR_RTL = 0x02 << SCREENLAYOUT_LAYOUTDIR_SHIFT;
+ /** Constant for {@link #screenLayout}: bits that encode roundness of the screen. */
+ public static final int SCREENLAYOUT_ROUND_MASK = 0x300;
+ /** @hide Constant for {@link #screenLayout}: bit shift to get to screen roundness bits */
+ public static final int SCREENLAYOUT_ROUND_SHIFT = 8;
+ /**
+ * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
+ * that it is unknown whether or not the screen has a round shape.
+ */
+ public static final int SCREENLAYOUT_ROUND_UNDEFINED = 0x00;
+ /**
+ * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
+ * that the screen does not have a rounded shape.
+ */
+ public static final int SCREENLAYOUT_ROUND_NO = 0x1 << SCREENLAYOUT_ROUND_SHIFT;
+ /**
+ * Constant for {@link #screenLayout}: a {@link #SCREENLAYOUT_ROUND_MASK} value indicating
+ * that the screen has a rounded shape. Corners may not be visible to the user;
+ * developers should pay special attention to the {@link android.view.WindowInsets} delivered
+ * to views for more information about ensuring content is not obscured.
+ *
+ * <p>Corresponds to the <code>-round</code> resource qualifier.</p>
+ */
+ public static final int SCREENLAYOUT_ROUND_YES = 0x2 << SCREENLAYOUT_ROUND_SHIFT;
+
/** Constant for {@link #screenLayout}: a value indicating that screenLayout is undefined */
public static final int SCREENLAYOUT_UNDEFINED = SCREENLAYOUT_SIZE_UNDEFINED |
- SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED;
+ SCREENLAYOUT_LONG_UNDEFINED | SCREENLAYOUT_LAYOUTDIR_UNDEFINED |
+ SCREENLAYOUT_ROUND_UNDEFINED;
/**
* Special flag we generate to indicate that the screen layout requires
@@ -174,18 +199,22 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* <p>The {@link #SCREENLAYOUT_SIZE_MASK} bits define the overall size
* of the screen. They may be one of
* {@link #SCREENLAYOUT_SIZE_SMALL}, {@link #SCREENLAYOUT_SIZE_NORMAL},
- * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.
+ * {@link #SCREENLAYOUT_SIZE_LARGE}, or {@link #SCREENLAYOUT_SIZE_XLARGE}.</p>
*
* <p>The {@link #SCREENLAYOUT_LONG_MASK} defines whether the screen
* is wider/taller than normal. They may be one of
- * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.
+ * {@link #SCREENLAYOUT_LONG_NO} or {@link #SCREENLAYOUT_LONG_YES}.</p>
*
* <p>The {@link #SCREENLAYOUT_LAYOUTDIR_MASK} defines whether the screen layout
* is either LTR or RTL. They may be one of
- * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.
+ * {@link #SCREENLAYOUT_LAYOUTDIR_LTR} or {@link #SCREENLAYOUT_LAYOUTDIR_RTL}.</p>
+ *
+ * <p>The {@link #SCREENLAYOUT_ROUND_MASK} defines whether the screen has a rounded
+ * shape. They may be one of {@link #SCREENLAYOUT_ROUND_NO} or {@link #SCREENLAYOUT_ROUND_YES}.
+ * </p>
*
* <p>See <a href="{@docRoot}guide/practices/screens_support.html">Supporting
- * Multiple Screens</a> for more information.
+ * Multiple Screens</a> for more information.</p>
*/
public int screenLayout;
@@ -1328,6 +1357,16 @@ public final class Configuration implements Parcelable, Comparable<Configuration
}
/**
+ * Return whether the screen has a round shape. Apps may choose to change styling based
+ * on this property, such as the alignment or layout of text or informational icons.
+ *
+ * @return true if the screen is rounded, false otherwise
+ */
+ public boolean isScreenRound() {
+ return (screenLayout & SCREENLAYOUT_ROUND_MASK) == SCREENLAYOUT_ROUND_YES;
+ }
+
+ /**
*
* @hide
*/
@@ -1425,6 +1464,17 @@ public final class Configuration implements Parcelable, Comparable<Configuration
break;
}
+ switch (config.screenLayout & Configuration.SCREENLAYOUT_ROUND_MASK) {
+ case Configuration.SCREENLAYOUT_ROUND_YES:
+ parts.add("round");
+ break;
+ case Configuration.SCREENLAYOUT_ROUND_NO:
+ parts.add("notround");
+ break;
+ default:
+ break;
+ }
+
switch (config.orientation) {
case Configuration.ORIENTATION_LANDSCAPE:
parts.add("land");
@@ -1640,6 +1690,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
delta.screenLayout |= change.screenLayout & SCREENLAYOUT_LONG_MASK;
}
+ if ((base.screenLayout & SCREENLAYOUT_ROUND_MASK) !=
+ (change.screenLayout & SCREENLAYOUT_ROUND_MASK)) {
+ delta.screenLayout |= change.screenLayout & SCREENLAYOUT_ROUND_MASK;
+ }
+
if ((base.uiMode & UI_MODE_TYPE_MASK) != (change.uiMode & UI_MODE_TYPE_MASK)) {
delta.uiMode |= change.uiMode & UI_MODE_TYPE_MASK;
}
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index d08c52b..9046e81 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -371,7 +371,6 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
mDeviceImpl.stopRepeating();
} catch (IllegalStateException e) {
// OK: Camera device may already be closed, nothing else to do
- Log.w(TAG, mIdString + "The camera device was already closed: ", e);
// TODO: Fire onClosed anytime we get the device onClosed or the ISE?
// or just suppress the ISE only and rely onClosed.
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 4dfe0de..5f515eb 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -425,6 +425,24 @@ public abstract class BatteryStats implements Parcelable {
public abstract long getMobileRadioActiveTime(int which);
public abstract int getMobileRadioActiveCount(int which);
+ /**
+ * Get the total cpu time (in microseconds) this UID had processes executing in userspace.
+ */
+ public abstract long getUserCpuTimeUs(int which);
+
+ /**
+ * Get the total cpu time (in microseconds) this UID had processes executing kernel syscalls.
+ */
+ public abstract long getSystemCpuTimeUs(int which);
+
+ /**
+ * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed.
+ * @param speedStep the index of the CPU speed. This is not the actual speed of the CPU.
+ * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
+ * @see BatteryStats#getCpuSpeedSteps()
+ */
+ public abstract long getTimeAtCpuSpeed(int step, int which);
+
public static abstract class Sensor {
/*
* FIXME: it's not correct to use this magic value because it
@@ -506,15 +524,6 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract long getForegroundTime(int which);
- /**
- * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed.
- * @param speedStep the index of the CPU speed. This is not the actual speed of the
- * CPU.
- * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
- * @see BatteryStats#getCpuSpeedSteps()
- */
- public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
-
public abstract int countExcessivePowers();
public abstract ExcessivePower getExcessivePower(int i);
@@ -3873,6 +3882,16 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ final long userCpuTimeUs = u.getUserCpuTimeUs(which);
+ final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
+ if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Total cpu time: ");
+ formatTimeMs(sb, (userCpuTimeUs + systemCpuTimeUs) / 1000);
+ pw.println(sb.toString());
+ }
+
final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
= u.getProcessStats();
for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 2b058a8..e55ae99 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -1005,6 +1005,22 @@ public interface IMountService extends IInterface {
}
@Override
+ public long benchmark(String volId) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeString(volId);
+ mRemote.transact(Stub.TRANSACTION_benchmark, _data, _reply, 0);
+ _reply.readException();
+ return _reply.readLong();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ @Override
public void partitionPublic(String diskId) throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
@@ -1113,6 +1129,22 @@ public interface IMountService extends IInterface {
}
@Override
+ public void setDebugFlags(int _flags, int _mask) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(_flags);
+ _data.writeInt(_mask);
+ mRemote.transact(Stub.TRANSACTION_setDebugFlags, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ @Override
public String getPrimaryStorageUuid() throws RemoteException {
Parcel _data = Parcel.obtain();
Parcel _reply = Parcel.obtain();
@@ -1257,6 +1289,9 @@ public interface IMountService extends IInterface {
static final int TRANSACTION_getPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 57;
static final int TRANSACTION_setPrimaryStorageUuid = IBinder.FIRST_CALL_TRANSACTION + 58;
+ static final int TRANSACTION_benchmark = IBinder.FIRST_CALL_TRANSACTION + 59;
+ static final int TRANSACTION_setDebugFlags = IBinder.FIRST_CALL_TRANSACTION + 60;
+
/**
* Cast an IBinder object into an IMountService interface, generating a
* proxy if needed.
@@ -1726,6 +1761,14 @@ public interface IMountService extends IInterface {
reply.writeNoException();
return true;
}
+ case TRANSACTION_benchmark: {
+ data.enforceInterface(DESCRIPTOR);
+ String volId = data.readString();
+ long res = benchmark(volId);
+ reply.writeNoException();
+ reply.writeLong(res);
+ return true;
+ }
case TRANSACTION_partitionPublic: {
data.enforceInterface(DESCRIPTOR);
String diskId = data.readString();
@@ -1778,6 +1821,14 @@ public interface IMountService extends IInterface {
reply.writeNoException();
return true;
}
+ case TRANSACTION_setDebugFlags: {
+ data.enforceInterface(DESCRIPTOR);
+ int _flags = data.readInt();
+ int _mask = data.readInt();
+ setDebugFlags(_flags, _mask);
+ reply.writeNoException();
+ return true;
+ }
case TRANSACTION_getPrimaryStorageUuid: {
data.enforceInterface(DESCRIPTOR);
String volumeUuid = getPrimaryStorageUuid();
@@ -2088,6 +2139,7 @@ public interface IMountService extends IInterface {
public void mount(String volId) throws RemoteException;
public void unmount(String volId) throws RemoteException;
public void format(String volId) throws RemoteException;
+ public long benchmark(String volId) throws RemoteException;
public void partitionPublic(String diskId) throws RemoteException;
public void partitionPrivate(String diskId) throws RemoteException;
@@ -2097,6 +2149,7 @@ public interface IMountService extends IInterface {
public void setVolumeUserFlags(String fsUuid, int flags, int mask) throws RemoteException;
public void forgetVolume(String fsUuid) throws RemoteException;
public void forgetAllVolumes() throws RemoteException;
+ public void setDebugFlags(int flags, int mask) throws RemoteException;
public String getPrimaryStorageUuid() throws RemoteException;
public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback)
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 8c0bbbf..8ff56f8 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -82,6 +82,9 @@ public class StorageManager {
/** {@hide} */
public static final String UUID_PRIMARY_PHYSICAL = "primary_physical";
+ /** {@hide} */
+ public static final int DEBUG_FORCE_ADOPTABLE = 1 << 0;
+
private final Context mContext;
private final ContentResolver mResolver;
@@ -641,6 +644,15 @@ public class StorageManager {
}
/** {@hide} */
+ public long benchmark(String volId) {
+ try {
+ return mMountService.benchmark(volId);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /** {@hide} */
public void partitionPublic(String diskId) {
try {
mMountService.partitionPublic(diskId);
diff --git a/core/java/android/service/carrier/CarrierConfigService.java b/core/java/android/service/carrier/CarrierConfigService.java
index bc42b6b..bf33ad5 100644
--- a/core/java/android/service/carrier/CarrierConfigService.java
+++ b/core/java/android/service/carrier/CarrierConfigService.java
@@ -23,14 +23,14 @@ import android.os.PersistableBundle;
* A service that sets carrier configuration for telephony services.
* <p>
* To extend this class, you must declare the service in your manifest file to require the
- * {@link android.Manifest.permission#BIND_CARRIER_CONFIG_SERVICE} permission and include an intent
+ * {@link android.Manifest.permission#BIND_CARRIER_SERVICES} permission and include an intent
* filter with the {@link #SERVICE_INTERFACE} action. For example:
* </p>
*
* <pre>{@code
* <service android:name=".MyCarrierConfigService"
* android:label="@string/service_name"
- * android:permission="android.permission.BIND_CARRIER_CONFIG_SERVICE">
+ * android:permission="android.permission.BIND_CARRIER_SERVICES">
* <intent-filter>
* <action android:name="android.service.carrier.CarrierConfigService" />
* </intent-filter>
diff --git a/core/java/android/service/carrier/CarrierMessagingService.java b/core/java/android/service/carrier/CarrierMessagingService.java
index d7bf10c..f5396a3 100644
--- a/core/java/android/service/carrier/CarrierMessagingService.java
+++ b/core/java/android/service/carrier/CarrierMessagingService.java
@@ -31,12 +31,12 @@ import java.util.List;
* A service that receives calls from the system when new SMS and MMS are
* sent or received.
* <p>To extend this class, you must declare the service in your manifest file with
- * the {@link android.Manifest.permission#BIND_CARRIER_MESSAGING_SERVICE} permission
+ * the {@link android.Manifest.permission#BIND_CARRIER_SERVICES} permission
* and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
* <pre>
* &lt;service android:name=".MyMessagingService"
* android:label="&#64;string/service_name"
- * android:permission="android.permission.BIND_CARRIER_MESSAGING_SERVICE">
+ * android:permission="android.permission.BIND_CARRIER_SERVICES">
* &lt;intent-filter>
* &lt;action android:name="android.service.carrier.CarrierMessagingService" />
* &lt;/intent-filter>
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 7956a3f..b8493d4 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -27,6 +27,10 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
@@ -322,7 +326,7 @@ public abstract class NotificationListenerService extends Service {
if (!isBound()) return;
try {
getNotificationInterface().cancelNotificationsFromListener(mWrapper,
- new String[] {key});
+ new String[] { key });
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
@@ -464,6 +468,8 @@ public abstract class NotificationListenerService extends Service {
for (int i = 0; i < N; i++) {
Notification notification = list.get(i).getNotification();
Builder.rebuild(getContext(), notification);
+ // convert icon metadata to legacy format for older clients
+ createLegacyIconExtras(notification);
}
return list.toArray(new StatusBarNotification[N]);
} catch (android.os.RemoteException ex) {
@@ -636,6 +642,24 @@ public abstract class NotificationListenerService extends Service {
}
}
+ /** Convert new-style Icons to legacy representations for pre-M clients. */
+ private void createLegacyIconExtras(Notification n) {
+ Icon smallIcon = n.getSmallIcon();
+ Icon largeIcon = n.getLargeIcon();
+ if (smallIcon.getType() == Icon.TYPE_RESOURCE) {
+ n.extras.putInt(Notification.EXTRA_SMALL_ICON, smallIcon.getResId());
+ n.icon = smallIcon.getResId();
+ }
+ if (largeIcon != null) {
+ Drawable d = largeIcon.loadDrawable(getContext());
+ if (d != null && d instanceof BitmapDrawable) {
+ final Bitmap largeIconBits = ((BitmapDrawable) d).getBitmap();
+ n.extras.putParcelable(Notification.EXTRA_LARGE_ICON, largeIconBits);
+ n.largeIcon = largeIconBits;
+ }
+ }
+ }
+
private class INotificationListenerWrapper extends INotificationListener.Stub {
@Override
public void onNotificationPosted(IStatusBarNotificationHolder sbnHolder,
@@ -649,6 +673,9 @@ public abstract class NotificationListenerService extends Service {
}
Notification.Builder.rebuild(getContext(), sbn.getNotification());
+ // convert icon metadata to legacy format for older clients
+ createLegacyIconExtras(sbn.getNotification());
+
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
synchronized (mWrapper) {
applyUpdate(update);
diff --git a/core/java/android/text/BidiFormatter.java b/core/java/android/text/BidiFormatter.java
index 2a2589a..7ea9da1 100644
--- a/core/java/android/text/BidiFormatter.java
+++ b/core/java/android/text/BidiFormatter.java
@@ -25,7 +25,7 @@ import java.util.Locale;
/**
* Utility class for formatting text for display in a potentially opposite-directionality context
* without garbling. The directionality of the context is set at formatter creation and the
- * directionality of the text can be either estimated or passed in when known.
+ * directionality of the text can be either estimated or passed in when known.
*
* <p>To support versions lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR2},
* you can use the support library's {@link android.support.v4.text.BidiFormatter} class.
@@ -377,9 +377,11 @@ public final class BidiFormatter {
* See {@link TextDirectionHeuristics} for pre-defined heuristics.
* @param isolate Whether to directionally isolate the string to prevent it from garbling the
* content around it
- * @return Input string after applying the above processing.
+ * @return Input string after applying the above processing. {@code null} if {@code str} is
+ * {@code null}.
*/
public String unicodeWrap(String str, TextDirectionHeuristic heuristic, boolean isolate) {
+ if (str == null) return null;
final boolean isRtl = heuristic.isRtl(str, 0, str.length());
StringBuilder result = new StringBuilder();
if (getStereoReset() && isolate) {
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index d4b971a..5a587fe 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -172,6 +172,17 @@ public final class Display {
public static final int FLAG_PRESENTATION = 1 << 3;
/**
+ * Display flag: Indicates that the display has a round shape.
+ * <p>
+ * This flag identifies displays that are circular, elliptical or otherwise
+ * do not permit the user to see all the way to the logical corners of the display.
+ * </p>
+ *
+ * @see #getFlags
+ */
+ public static final int FLAG_ROUND = 1 << 4;
+
+ /**
* Display flag: Indicates that the contents of the display should not be scaled
* to fit the physical screen dimensions. Used for development only to emulate
* devices with smaller physicals screens while preserving density.
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index b9fde8a..cf17990 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -609,6 +609,9 @@ public final class DisplayInfo implements Parcelable {
if ((flags & Display.FLAG_SCALING_DISABLED) != 0) {
result.append(", FLAG_SCALING_DISABLED");
}
+ if ((flags & Display.FLAG_ROUND) != 0) {
+ result.append(", FLAG_ROUND");
+ }
return result.toString();
}
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 6632f39..5e58250 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -260,7 +260,7 @@ public abstract class HardwareRenderer {
/**
* Gets the current width of the surface. This is the width that the surface
- * was last set to in a call to {@link #setup(int, int, Rect)}.
+ * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
*
* @return the current width of the surface
*/
@@ -268,7 +268,7 @@ public abstract class HardwareRenderer {
/**
* Gets the current height of the surface. This is the height that the surface
- * was last set to in a call to {@link #setup(int, int, Rect)}.
+ * was last set to in a call to {@link #setup(int, int, View.AttachInfo, Rect)}.
*
* @return the current width of the surface
*/
@@ -373,19 +373,20 @@ public abstract class HardwareRenderer {
*
* @param width The width of the drawing surface.
* @param height The height of the drawing surface.
+ * @param attachInfo Information about the window.
* @param surface The surface to hardware accelerate
* @param surfaceInsets The drawing surface insets to apply
*
* @return true if the surface was initialized, false otherwise. Returning
* false might mean that the surface was already initialized.
*/
- boolean initializeIfNeeded(int width, int height, Surface surface, Rect surfaceInsets)
- throws OutOfResourcesException {
+ boolean initializeIfNeeded(int width, int height, View.AttachInfo attachInfo,
+ Surface surface, Rect surfaceInsets) throws OutOfResourcesException {
if (isRequested()) {
// We lost the gl context, so recreate it.
if (!isEnabled()) {
if (initialize(surface)) {
- setup(width, height, surfaceInsets);
+ setup(width, height, attachInfo, surfaceInsets);
return true;
}
}
@@ -398,9 +399,17 @@ public abstract class HardwareRenderer {
*
* @param width The width of the drawing surface.
* @param height The height of the drawing surface.
+ * @param attachInfo Information about the window.
* @param surfaceInsets The drawing surface insets to apply
*/
- abstract void setup(int width, int height, Rect surfaceInsets);
+ abstract void setup(int width, int height, View.AttachInfo attachInfo, Rect surfaceInsets);
+
+ /**
+ * Updates the light position based on the position of the window.
+ *
+ * @param attachInfo Information about the window.
+ */
+ abstract void setLightCenter(View.AttachInfo attachInfo);
/**
* Optional, sets the name of the renderer. Useful for debugging purposes.
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 1fd7109..7f243d3 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -19,11 +19,10 @@ package android.view;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.content.Context;
-import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
+import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -31,7 +30,6 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Trace;
import android.util.Log;
-import android.util.LongSparseArray;
import android.view.Surface.OutOfResourcesException;
import android.view.View.AttachInfo;
@@ -41,8 +39,6 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.HashSet;
/**
* Hardware renderer that proxies the rendering to a render thread. Most calls
@@ -197,10 +193,10 @@ public class ThreadedRenderer extends HardwareRenderer {
}
@Override
- void setup(int width, int height, Rect surfaceInsets) {
- final float lightX = width / 2.0f;
+ void setup(int width, int height, AttachInfo attachInfo, Rect surfaceInsets) {
mWidth = width;
mHeight = height;
+
if (surfaceInsets != null && (surfaceInsets.left != 0 || surfaceInsets.right != 0
|| surfaceInsets.top != 0 || surfaceInsets.bottom != 0)) {
mHasInsets = true;
@@ -218,10 +214,23 @@ public class ThreadedRenderer extends HardwareRenderer {
mSurfaceWidth = width;
mSurfaceHeight = height;
}
+
mRootNode.setLeftTopRightBottom(-mInsetLeft, -mInsetTop, mSurfaceWidth, mSurfaceHeight);
- nSetup(mNativeProxy, mSurfaceWidth, mSurfaceHeight,
- lightX, mLightY, mLightZ, mLightRadius,
+ nSetup(mNativeProxy, mSurfaceWidth, mSurfaceHeight, mLightRadius,
mAmbientShadowAlpha, mSpotShadowAlpha);
+
+ setLightCenter(attachInfo);
+ }
+
+ @Override
+ void setLightCenter(AttachInfo attachInfo) {
+ // Adjust light position for window offsets.
+ final Point displaySize = attachInfo.mPoint;
+ attachInfo.mDisplay.getRealSize(displaySize);
+ final float lightX = displaySize.x / 2f - attachInfo.mWindowLeft;
+ final float lightY = mLightY - attachInfo.mWindowTop;
+
+ nSetLightCenter(mNativeProxy, lightX, lightY, mLightZ);
}
@Override
@@ -500,8 +509,9 @@ public class ThreadedRenderer extends HardwareRenderer {
private static native void nUpdateSurface(long nativeProxy, Surface window);
private static native boolean nPauseSurface(long nativeProxy, Surface window);
private static native void nSetup(long nativeProxy, int width, int height,
- float lightX, float lightY, float lightZ, float lightRadius,
- int ambientShadowAlpha, int spotShadowAlpha);
+ float lightRadius, int ambientShadowAlpha, int spotShadowAlpha);
+ private static native void nSetLightCenter(long nativeProxy,
+ float lightX, float lightY, float lightZ);
private static native void nSetOpaque(long nativeProxy, boolean opaque);
private static native int nSyncAndDrawFrame(long nativeProxy, long[] frameInfo, int size);
private static native void nDestroy(long nativeProxy);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4f2a3fa..b7d902c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -966,6 +966,12 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ invalidateRectOnScreen(dirty);
+
+ return null;
+ }
+
+ private void invalidateRectOnScreen(Rect dirty) {
final Rect localDirty = mDirty;
if (!localDirty.isEmpty() && !localDirty.contains(dirty)) {
mAttachInfo.mSetIgnoreDirtyState = true;
@@ -985,8 +991,6 @@ public final class ViewRootImpl implements ViewParent,
if (!mWillDrawSoon && (intersected || mIsAnimating)) {
scheduleTraversals();
}
-
- return null;
}
void setWindowStopped(boolean stopped) {
@@ -1813,15 +1817,15 @@ public final class ViewRootImpl implements ViewParent,
}
}
- if (mAttachInfo.mHardwareRenderer != null &&
- mAttachInfo.mHardwareRenderer.isEnabled()) {
- if (hwInitialized ||
- mWidth != mAttachInfo.mHardwareRenderer.getWidth() ||
- mHeight != mAttachInfo.mHardwareRenderer.getHeight()) {
- mAttachInfo.mHardwareRenderer.setup(
- mWidth, mHeight, mWindowAttributes.surfaceInsets);
+ final HardwareRenderer hardwareRenderer = mAttachInfo.mHardwareRenderer;
+ if (hardwareRenderer != null && hardwareRenderer.isEnabled()) {
+ if (hwInitialized
+ || mWidth != hardwareRenderer.getWidth()
+ || mHeight != hardwareRenderer.getHeight()) {
+ hardwareRenderer.setup(mWidth, mHeight, mAttachInfo,
+ mWindowAttributes.surfaceInsets);
if (!hwInitialized) {
- mAttachInfo.mHardwareRenderer.invalidate(mSurface);
+ hardwareRenderer.invalidate(mSurface);
mFullRedrawNeeded = true;
}
}
@@ -1897,6 +1901,11 @@ public final class ViewRootImpl implements ViewParent,
}
mAttachInfo.mWindowLeft = frame.left;
mAttachInfo.mWindowTop = frame.top;
+
+ // Update the light position for the new window offsets.
+ if (mAttachInfo.mHardwareRenderer != null) {
+ mAttachInfo.mHardwareRenderer.setLightCenter(mAttachInfo);
+ }
}
}
@@ -2605,7 +2614,7 @@ public final class ViewRootImpl implements ViewParent,
try {
mAttachInfo.mHardwareRenderer.initializeIfNeeded(
- mWidth, mHeight, mSurface, surfaceInsets);
+ mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
} catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
return;
@@ -3300,7 +3309,7 @@ public final class ViewRootImpl implements ViewParent,
final WindowManager.LayoutParams lp = mWindowAttributes;
final Rect surfaceInsets = lp != null ? lp.surfaceInsets : null;
mAttachInfo.mHardwareRenderer.initializeIfNeeded(
- mWidth, mHeight, mSurface, surfaceInsets);
+ mWidth, mHeight, mAttachInfo, mSurface, surfaceInsets);
} catch (OutOfResourcesException e) {
Log.e(TAG, "OutOfResourcesException locking surface", e);
try {
@@ -6393,7 +6402,14 @@ public final class ViewRootImpl implements ViewParent,
}
// Refresh the node for the focused virtual view.
+ final Rect oldBounds = mTempRect;
+ mAccessibilityFocusedVirtualView.getBoundsInScreen(oldBounds);
mAccessibilityFocusedVirtualView = provider.createAccessibilityNodeInfo(focusedChildId);
+ final Rect newBounds = mAccessibilityFocusedVirtualView.getBoundsInScreen();
+ if (!oldBounds.equals(newBounds)) {
+ oldBounds.union(newBounds);
+ invalidateRectOnScreen(oldBounds);
+ }
}
@Override
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 42e6766..901a32d 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -1495,6 +1495,15 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Returns the actual rect containing the node bounds in screen coordinates.
+ *
+ * @hide Not safe to expose outside the framework.
+ */
+ public Rect getBoundsInScreen() {
+ return mBoundsInScreen;
+ }
+
+ /**
* Sets the node bounds in screen coordinates.
* <p>
* <strong>Note:</strong> Cannot be called from an
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 92615f3..ccb98b4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1863,7 +1863,7 @@ public class WebView extends AbsoluteLayout
* practices, the user should not specify a wildcard (*) when
* specifying the origin.
*/
- public void postMessageToMainFrame(WebMessage message, Uri targetOrigin) {
+ public void postWebMessage(WebMessage message, Uri targetOrigin) {
checkThread();
mProvider.postMessageToMainFrame(message, targetOrigin);
}
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 9782d72..b7d529e 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -40,7 +40,10 @@ import com.android.server.LocalServices;
import dalvik.system.VMRuntime;
import java.io.File;
+import java.io.IOException;
import java.util.Arrays;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
/**
* Top level factory, used creating all the main WebView implementation classes.
@@ -323,15 +326,30 @@ public final class WebViewFactory {
long newVmSize = 0L;
for (String path : nativeLibs) {
+ if (path == null || TextUtils.isEmpty(path)) continue;
if (DEBUG) Log.d(LOGTAG, "Checking file size of " + path);
- if (path == null) continue;
File f = new File(path);
if (f.exists()) {
- long length = f.length();
- if (length > newVmSize) {
- newVmSize = length;
+ newVmSize = Math.max(newVmSize, f.length());
+ continue;
+ }
+ if (path.contains("!")) {
+ String[] split = TextUtils.split(path, "!");
+ if (split.length == 2) {
+ try {
+ ZipFile z = new ZipFile(split[0]);
+ ZipEntry e = z.getEntry(split[1]);
+ if (e != null && e.getMethod() == ZipEntry.STORED) {
+ newVmSize = Math.max(newVmSize, e.getSize());
+ continue;
+ }
+ }
+ catch (IOException e) {
+ Log.e(LOGTAG, "error reading APK file " + split[0] + ", ", e);
+ }
}
}
+ Log.e(LOGTAG, "error sizing load for " + path);
}
if (DEBUG) {
@@ -355,6 +373,27 @@ public final class WebViewFactory {
}
// throws MissingWebViewPackageException
+ private static String getLoadFromApkPath(String apkPath,
+ String[] abiList,
+ String nativeLibFileName) {
+ // Search the APK for a native library conforming to a listed ABI.
+ try {
+ ZipFile z = new ZipFile(apkPath);
+ for (String abi : abiList) {
+ final String entry = "lib/" + abi + "/" + nativeLibFileName;
+ ZipEntry e = z.getEntry(entry);
+ if (e != null && e.getMethod() == ZipEntry.STORED) {
+ // Return a path formatted for dlopen() load from APK.
+ return apkPath + "!" + entry;
+ }
+ }
+ } catch (IOException e) {
+ throw new MissingWebViewPackageException(e);
+ }
+ return "";
+ }
+
+ // throws MissingWebViewPackageException
private static String[] getWebViewNativeLibraryPaths() {
ApplicationInfo ai = getWebViewApplicationInfo();
final String NATIVE_LIB_FILE_NAME = getWebViewLibrary(ai);
@@ -382,8 +421,29 @@ public final class WebViewFactory {
path32 = ai.nativeLibraryDir;
path64 = "";
}
- if (!TextUtils.isEmpty(path32)) path32 += "/" + NATIVE_LIB_FILE_NAME;
- if (!TextUtils.isEmpty(path64)) path64 += "/" + NATIVE_LIB_FILE_NAME;
+
+ // Form the full paths to the extracted native libraries.
+ // If libraries were not extracted, try load from APK paths instead.
+ if (!TextUtils.isEmpty(path32)) {
+ path32 += "/" + NATIVE_LIB_FILE_NAME;
+ File f = new File(path32);
+ if (!f.exists()) {
+ path32 = getLoadFromApkPath(ai.sourceDir,
+ Build.SUPPORTED_32_BIT_ABIS,
+ NATIVE_LIB_FILE_NAME);
+ }
+ }
+ if (!TextUtils.isEmpty(path64)) {
+ path64 += "/" + NATIVE_LIB_FILE_NAME;
+ File f = new File(path64);
+ if (!f.exists()) {
+ path64 = getLoadFromApkPath(ai.sourceDir,
+ Build.SUPPORTED_64_BIT_ABIS,
+ NATIVE_LIB_FILE_NAME);
+ }
+ }
+
+ if (DEBUG) Log.v(LOGTAG, "Native 32-bit lib: " + path32 + ", 64-bit lib: " + path64);
return new String[] { path32, path64 };
}
diff --git a/core/java/android/widget/DayPickerPagerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
index d271af2..8fe8252 100644
--- a/core/java/android/widget/DayPickerPagerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -186,11 +186,12 @@ class DayPickerPagerAdapter extends PagerAdapter {
}
private int getMonthForPosition(int position) {
- return position % MONTHS_IN_YEAR + mMinDate.get(Calendar.MONTH);
+ return (position + mMinDate.get(Calendar.MONTH)) % MONTHS_IN_YEAR;
}
private int getYearForPosition(int position) {
- return position / MONTHS_IN_YEAR + mMinDate.get(Calendar.YEAR);
+ final int yearOffset = (position + mMinDate.get(Calendar.MONTH)) / MONTHS_IN_YEAR;
+ return yearOffset + mMinDate.get(Calendar.YEAR);
}
private int getPositionForDay(@Nullable Calendar day) {
@@ -198,8 +199,8 @@ class DayPickerPagerAdapter extends PagerAdapter {
return -1;
}
- final int yearOffset = (day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR));
- final int monthOffset = (day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH));
+ final int yearOffset = day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR);
+ final int monthOffset = day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH);
final int position = yearOffset * MONTHS_IN_YEAR + monthOffset;
return position;
}
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index a434317..dc772fb 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -176,8 +176,6 @@ class DayPickerView extends ViewGroup {
}
}
});
-
- updateButtonVisibility(mViewPager.getCurrentItem());
}
private void updateButtonVisibility(int position) {
@@ -346,6 +344,8 @@ class DayPickerView extends ViewGroup {
// Changing the min/max date changes the selection position since we
// don't really have stable IDs. Jumps immediately to the new position.
setDate(mSelectedDay.getTimeInMillis(), false, false);
+
+ updateButtonVisibility(mViewPager.getCurrentItem());
}
/**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index a1194f7..c829783 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3426,9 +3426,13 @@ public class Editor {
protected void updateDrawable() {
final int offset = getCurrentCursorOffset();
final boolean isRtlCharAtOffset = mTextView.getLayout().isRtlCharAt(offset);
+ final Drawable oldDrawable = mDrawable;
mDrawable = isRtlCharAtOffset ? mDrawableRtl : mDrawableLtr;
mHotspotX = getHotspotX(mDrawable, isRtlCharAtOffset);
mHorizontalGravity = getHorizontalGravity(isRtlCharAtOffset);
+ if (oldDrawable != mDrawable) {
+ postInvalidate();
+ }
}
protected abstract int getHotspotX(Drawable drawable, boolean isRtlRun);
@@ -3893,7 +3897,7 @@ public class Editor {
@Override
protected int getHorizontalGravity(boolean isRtlRun) {
- return isRtlRun ? Gravity.RIGHT : Gravity.LEFT;
+ return isRtlRun ? Gravity.LEFT : Gravity.RIGHT;
}
@Override
@@ -3913,10 +3917,20 @@ public class Editor {
@Override
public void updatePosition(float x, float y) {
- final int trueOffset = mTextView.getOffsetForPosition(x, y);
- final int currLine = mTextView.getLineAtCoordinate(y);
+ final int selectionEnd = mTextView.getSelectionEnd();
+ final Layout layout = mTextView.getLayout();
+ int initialOffset = mTextView.getOffsetForPosition(x, y);
+ int currLine = mTextView.getLineAtCoordinate(y);
boolean positionCursor = false;
- int offset = trueOffset;
+
+ if (initialOffset >= selectionEnd) {
+ // Handles have crossed, bound it to the last selected line and
+ // adjust by word / char as normal.
+ currLine = layout != null ? layout.getLineForOffset(selectionEnd) : mPrevLine;
+ initialOffset = mTextView.getOffsetAtCoordinate(currLine, x);
+ }
+
+ int offset = initialOffset;
int end = getWordEnd(offset);
int start = getWordStart(offset);
@@ -3932,8 +3946,7 @@ public class Editor {
offset = mPreviousOffset;
}
}
- final Layout layout = mTextView.getLayout();
- if (layout != null && offset < trueOffset) {
+ if (layout != null && offset < initialOffset) {
final float adjustedX = layout.getPrimaryHorizontal(offset);
mTouchWordDelta =
mTextView.convertToLocalHorizontalCoordinate(x) - adjustedX;
@@ -3949,8 +3962,7 @@ public class Editor {
if (currLine > mPrevLine) {
// We're on a different line, so we'll snap to word boundaries.
offset = start;
- final Layout layout = mTextView.getLayout();
- if (layout != null && offset < trueOffset) {
+ if (layout != null && offset < initialOffset) {
final float adjustedX = layout.getPrimaryHorizontal(offset);
mTouchWordDelta =
mTextView.convertToLocalHorizontalCoordinate(x) - adjustedX;
@@ -3964,18 +3976,10 @@ public class Editor {
}
}
- // Handles can not cross and selection is at least one character.
if (positionCursor) {
- final int selectionEnd = mTextView.getSelectionEnd();
+ // Handles can not cross and selection is at least one character.
if (offset >= selectionEnd) {
- // We can't cross the handles so let's just constrain the Y value.
- int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x);
- if (alteredOffset >= selectionEnd) {
- // Can't pass the other drag handle.
- offset = getNextCursorOffset(selectionEnd, false);
- } else {
- offset = alteredOffset;
- }
+ offset = getNextCursorOffset(selectionEnd, false);
mTouchWordDelta = 0.0f;
}
mInWord = !getWordIteratorWithText().isBoundary(offset);
@@ -4011,7 +4015,7 @@ public class Editor {
@Override
protected int getHorizontalGravity(boolean isRtlRun) {
- return isRtlRun ? Gravity.LEFT : Gravity.RIGHT;
+ return isRtlRun ? Gravity.RIGHT : Gravity.LEFT;
}
@Override
@@ -4031,10 +4035,20 @@ public class Editor {
@Override
public void updatePosition(float x, float y) {
- final int trueOffset = mTextView.getOffsetForPosition(x, y);
- final int currLine = mTextView.getLineAtCoordinate(y);
- int offset = trueOffset;
+ final int selectionStart = mTextView.getSelectionStart();
+ final Layout layout = mTextView.getLayout();
+ int initialOffset = mTextView.getOffsetForPosition(x, y);
+ int currLine = mTextView.getLineAtCoordinate(y);
boolean positionCursor = false;
+
+ if (initialOffset <= selectionStart) {
+ // Handles have crossed, bound it to the first selected line and
+ // adjust by word / char as normal.
+ currLine = layout != null ? layout.getLineForOffset(selectionStart) : mPrevLine;
+ initialOffset = mTextView.getOffsetAtCoordinate(currLine, x);
+ }
+
+ int offset = initialOffset;
int end = getWordEnd(offset);
int start = getWordStart(offset);
@@ -4050,8 +4064,7 @@ public class Editor {
offset = mPreviousOffset;
}
}
- final Layout layout = mTextView.getLayout();
- if (layout != null && offset > trueOffset) {
+ if (layout != null && offset > initialOffset) {
final float adjustedX = layout.getPrimaryHorizontal(offset);
mTouchWordDelta =
adjustedX - mTextView.convertToLocalHorizontalCoordinate(x);
@@ -4067,8 +4080,7 @@ public class Editor {
if (currLine < mPrevLine) {
// We're on a different line, so we'll snap to word boundaries.
offset = end;
- final Layout layout = mTextView.getLayout();
- if (layout != null && offset > trueOffset) {
+ if (layout != null && offset > initialOffset) {
final float adjustedX = layout.getPrimaryHorizontal(offset);
mTouchWordDelta =
adjustedX - mTextView.convertToLocalHorizontalCoordinate(x);
@@ -4083,17 +4095,9 @@ public class Editor {
}
if (positionCursor) {
- final int selectionStart = mTextView.getSelectionStart();
+ // Handles can not cross and selection is at least one character.
if (offset <= selectionStart) {
- // We can't cross the handles so let's just constrain the Y value.
- int alteredOffset = mTextView.getOffsetAtCoordinate(mPrevLine, x);
- int length = mTextView.getText().length();
- if (alteredOffset <= selectionStart) {
- // Can't pass the other drag handle.
- offset = getNextCursorOffset(selectionStart, true);
- } else {
- offset = Math.min(alteredOffset, length);
- }
+ offset = getNextCursorOffset(selectionStart, true);
mTouchWordDelta = 0.0f;
}
mInWord = !getWordIteratorWithText().isBoundary(offset);