summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/BackStackRecord.java40
-rw-r--r--core/java/android/app/EnterTransitionCoordinator.java2
-rw-r--r--core/java/android/app/FragmentTransaction.java20
-rw-r--r--core/java/android/app/Notification.java149
-rw-r--r--core/java/android/app/NotificationManager.java9
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java3
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java39
-rw-r--r--core/java/android/bluetooth/BluetoothDevice.java12
-rw-r--r--core/java/android/bluetooth/BluetoothManager.java5
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java6
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeScanner.java5
-rw-r--r--core/java/android/content/Intent.java16
-rw-r--r--core/java/android/hardware/camera2/CaptureRequest.java2
-rw-r--r--core/java/android/hardware/camera2/CaptureResult.java2
-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/provider/Settings.java11
-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/text/BidiFormatter.java6
-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/Window.java14
-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/widget/DayPickerPagerAdapter.java9
-rw-r--r--core/java/android/widget/DayPickerView.java2
-rw-r--r--core/java/android/widget/Editor.java72
30 files changed, 436 insertions, 202 deletions
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 49644a7..1fb88a9 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -577,46 +577,6 @@ final class BackStackRecord extends FragmentTransaction implements
return this;
}
- /** TODO: remove this */
- @Override
- public FragmentTransaction setSharedElement(View sharedElement, String name) {
- String transitionName = sharedElement.getTransitionName();
- if (transitionName == null) {
- throw new IllegalArgumentException("Unique transitionNames are required for all" +
- " sharedElements");
- }
- mSharedElementSourceNames = new ArrayList<String>(1);
- mSharedElementSourceNames.add(transitionName);
-
- mSharedElementTargetNames = new ArrayList<String>(1);
- mSharedElementTargetNames.add(name);
- return this;
- }
-
- /** TODO: remove this */
- @Override
- public FragmentTransaction setSharedElements(Pair<View, String>... sharedElements) {
- if (sharedElements == null || sharedElements.length == 0) {
- mSharedElementSourceNames = null;
- mSharedElementTargetNames = null;
- } else {
- ArrayList<String> sourceNames = new ArrayList<String>(sharedElements.length);
- ArrayList<String> targetNames = new ArrayList<String>(sharedElements.length);
- for (int i = 0; i < sharedElements.length; i++) {
- String transitionName = sharedElements[i].first.getTransitionName();
- if (transitionName == null) {
- throw new IllegalArgumentException("Unique transitionNames are required for all"
- + " sharedElements");
- }
- sourceNames.add(transitionName);
- targetNames.add(sharedElements[i].second);
- }
- mSharedElementSourceNames = sourceNames;
- mSharedElementTargetNames = targetNames;
- }
- return this;
- }
-
public FragmentTransaction setTransitionStyle(int styleRes) {
mTransitionStyle = styleRes;
return this;
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index 4db4be0..05cf1d4 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -593,7 +593,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
}
private boolean allowOverlappingTransitions() {
- return mIsReturning ? getWindow().getAllowExitTransitionOverlap()
+ return mIsReturning ? getWindow().getAllowReturnTransitionOverlap()
: getWindow().getAllowEnterTransitionOverlap();
}
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index dc7075c..876c0f6 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -172,14 +172,6 @@ public abstract class FragmentTransaction {
public abstract FragmentTransaction setTransition(int transit);
/**
- * TODO: remove from API
- * @hide
- */
- public FragmentTransaction setCustomTransition(int sceneRootId, int transitionId) {
- return this;
- }
-
- /**
* Used with to map a View from a removed or hidden Fragment to a View from a shown
* or added Fragment.
* @param sharedElement A View in a disappearing Fragment to match with a View in an
@@ -190,18 +182,6 @@ public abstract class FragmentTransaction {
public abstract FragmentTransaction addSharedElement(View sharedElement, String name);
/**
- * TODO: remove from API
- * @hide
- */
- public abstract FragmentTransaction setSharedElement(View sharedElement, String name);
-
- /**
- * TODO: remove from API
- * @hide
- */
- public abstract FragmentTransaction setSharedElements(Pair<View, String>... sharedElements);
-
- /**
* Set a custom style resource that will be used for resolving transit
* animations.
*/
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 49b2549..3309443 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -30,6 +30,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.session.MediaSession;
@@ -885,6 +886,9 @@ public class Notification implements Parcelable
*/
public static final int HEADS_UP_REQUESTED = 2;
+ private Icon mSmallIcon;
+ private Icon mLargeIcon;
+
/**
* Structure to encapsulate a named action that can be shown as part of this notification.
* It must include an icon, a label, and a {@link PendingIntent} to be fired when the action is
@@ -1362,7 +1366,7 @@ public class Notification implements Parcelable
int version = parcel.readInt();
when = parcel.readLong();
- icon = parcel.readInt();
+ mSmallIcon = Icon.CREATOR.createFromParcel(parcel);
number = parcel.readInt();
if (parcel.readInt() != 0) {
contentIntent = PendingIntent.CREATOR.createFromParcel(parcel);
@@ -1380,7 +1384,7 @@ public class Notification implements Parcelable
contentView = RemoteViews.CREATOR.createFromParcel(parcel);
}
if (parcel.readInt() != 0) {
- largeIcon = Bitmap.CREATOR.createFromParcel(parcel);
+ mLargeIcon = Icon.CREATOR.createFromParcel(parcel);
}
defaults = parcel.readInt();
flags = parcel.readInt();
@@ -1445,7 +1449,7 @@ public class Notification implements Parcelable
*/
public void cloneInto(Notification that, boolean heavy) {
that.when = this.when;
- that.icon = this.icon;
+ that.mSmallIcon = this.mSmallIcon;
that.number = this.number;
// PendingIntents are global, so there's no reason (or way) to clone them.
@@ -1462,8 +1466,8 @@ public class Notification implements Parcelable
if (heavy && this.contentView != null) {
that.contentView = this.contentView.clone();
}
- if (heavy && this.largeIcon != null) {
- that.largeIcon = Bitmap.createBitmap(this.largeIcon);
+ if (heavy && this.mLargeIcon != null) {
+ that.mLargeIcon = this.mLargeIcon;
}
that.iconLevel = this.iconLevel;
that.sound = this.sound; // android.net.Uri is immutable
@@ -1544,7 +1548,7 @@ public class Notification implements Parcelable
contentView = null;
bigContentView = null;
headsUpContentView = null;
- largeIcon = null;
+ mLargeIcon = null;
if (extras != null) {
extras.remove(Notification.EXTRA_LARGE_ICON);
extras.remove(Notification.EXTRA_LARGE_ICON_BIG);
@@ -1586,7 +1590,7 @@ public class Notification implements Parcelable
parcel.writeInt(1);
parcel.writeLong(when);
- parcel.writeInt(icon);
+ mSmallIcon.writeToParcel(parcel, 0);
parcel.writeInt(number);
if (contentIntent != null) {
parcel.writeInt(1);
@@ -1618,9 +1622,9 @@ public class Notification implements Parcelable
} else {
parcel.writeInt(0);
}
- if (largeIcon != null) {
+ if (mLargeIcon != null) {
parcel.writeInt(1);
- largeIcon.writeToParcel(parcel, 0);
+ mLargeIcon.writeToParcel(parcel, 0);
} else {
parcel.writeInt(0);
}
@@ -1865,6 +1869,35 @@ public class Notification implements Parcelable
}
/**
+ * The small icon representing this notification in the status bar and content view.
+ *
+ * @return the small icon representing this notification.
+ *
+ * @see Builder#getSmallIcon()
+ * @see Builder#setSmallIcon(Icon)
+ */
+ public Icon getSmallIcon() {
+ return mSmallIcon;
+ }
+
+ /**
+ * Used when notifying to clean up legacy small icons.
+ * @hide
+ */
+ public void setSmallIcon(Icon icon) {
+ mSmallIcon = icon;
+ }
+
+ /**
+ * The large icon shown in this notification's content view.
+ * @see Builder#getLargeIcon()
+ * @see Builder#setLargeIcon(Icon)
+ */
+ public Icon getLargeIcon() {
+ return mLargeIcon;
+ }
+
+ /**
* @hide
*/
public boolean isValid() {
@@ -1966,7 +1999,7 @@ public class Notification implements Parcelable
private Context mContext;
private long mWhen;
- private int mSmallIcon;
+ private Icon mSmallIcon, mLargeIcon;
private int mSmallIconLevel;
private int mNumber;
private CharSequence mContentTitle;
@@ -1979,7 +2012,6 @@ public class Notification implements Parcelable
private PendingIntent mFullScreenIntent;
private CharSequence mTickerText;
private RemoteViews mTickerView;
- private Bitmap mLargeIcon;
private Uri mSound;
private int mAudioStreamType;
private AudioAttributes mAudioAttributes;
@@ -2160,8 +2192,9 @@ public class Notification implements Parcelable
* @see Notification#icon
*/
public Builder setSmallIcon(@DrawableRes int icon) {
- mSmallIcon = icon;
- return this;
+ return setSmallIcon(icon != 0
+ ? Icon.createWithResource(mContext, icon)
+ : null);
}
/**
@@ -2176,8 +2209,20 @@ public class Notification implements Parcelable
* @see Notification#iconLevel
*/
public Builder setSmallIcon(@DrawableRes int icon, int level) {
- mSmallIcon = icon;
mSmallIconLevel = level;
+ return setSmallIcon(icon);
+ }
+
+ /**
+ * Set the small icon, which will be used to represent the notification in the
+ * status bar and content view (unless overriden there by a
+ * {@link #setLargeIcon(Bitmap) large icon}).
+ *
+ * @param icon An Icon object to use.
+ * @see Notification#icon
+ */
+ public Builder setSmallIcon(Icon icon) {
+ mSmallIcon = icon;
return this;
}
@@ -2324,14 +2369,24 @@ public class Notification implements Parcelable
}
/**
- * Add a large icon to the notification (and the ticker on some devices).
+ * Add a large icon to the notification content view.
*
* In the platform template, this image will be shown on the left of the notification view
- * in place of the {@link #setSmallIcon(int) small icon} (which will move to the right side).
+ * in place of the {@link #setSmallIcon(Icon) small icon} (which will be placed in a small
+ * badge atop the large icon).
+ */
+ public Builder setLargeIcon(Bitmap b) {
+ return setLargeIcon(b != null ? Icon.createWithBitmap(b) : null);
+ }
+
+ /**
+ * Add a large icon to the notification content view.
*
- * @see Notification#largeIcon
+ * In the platform template, this image will be shown on the left of the notification view
+ * in place of the {@link #setSmallIcon(Icon) small icon} (which will be placed in a small
+ * badge atop the large icon).
*/
- public Builder setLargeIcon(Bitmap icon) {
+ public Builder setLargeIcon(Icon icon) {
mLargeIcon = icon;
return this;
}
@@ -2840,13 +2895,13 @@ public class Notification implements Parcelable
boolean contentTextInLine2 = false;
if (mLargeIcon != null) {
- contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
+ contentView.setImageViewIcon(R.id.icon, mLargeIcon);
processLargeLegacyIcon(mLargeIcon, contentView);
- contentView.setImageViewResource(R.id.right_icon, mSmallIcon);
+ contentView.setImageViewIcon(R.id.right_icon, mSmallIcon);
contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
processSmallRightIcon(mSmallIcon, contentView);
} else { // small icon at left
- contentView.setImageViewResource(R.id.icon, mSmallIcon);
+ contentView.setImageViewIcon(R.id.icon, mSmallIcon);
contentView.setViewVisibility(R.id.icon, View.VISIBLE);
processSmallIconAsLarge(mSmallIcon, contentView);
}
@@ -3086,14 +3141,16 @@ public class Notification implements Parcelable
/**
* Apply any necessary background to smallIcons being used in the largeIcon spot.
*/
- private void processSmallIconAsLarge(int largeIconId, RemoteViews contentView) {
+ private void processSmallIconAsLarge(Icon largeIcon, RemoteViews contentView) {
if (!isLegacy()) {
contentView.setDrawableParameters(R.id.icon, false, -1,
0xFFFFFFFF,
PorterDuff.Mode.SRC_ATOP, -1);
- }
- if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, largeIconId)) {
applyLargeIconBackground(contentView);
+ } else {
+ if (mColorUtil.isGrayscaleIcon(mContext, largeIcon)) {
+ applyLargeIconBackground(contentView);
+ }
}
}
@@ -3102,8 +3159,9 @@ public class Notification implements Parcelable
* if it's grayscale).
*/
// TODO: also check bounds, transparency, that sort of thing.
- private void processLargeLegacyIcon(Bitmap largeIcon, RemoteViews contentView) {
- if (isLegacy() && mColorUtil.isGrayscaleIcon(largeIcon)) {
+ private void processLargeLegacyIcon(Icon largeIcon, RemoteViews contentView) {
+ if (largeIcon != null && isLegacy()
+ && mColorUtil.isGrayscaleIcon(mContext, largeIcon)) {
applyLargeIconBackground(contentView);
} else {
removeLargeIconBackground(contentView);
@@ -3137,14 +3195,16 @@ public class Notification implements Parcelable
/**
* Recolor small icons when used in the R.id.right_icon slot.
*/
- private void processSmallRightIcon(int smallIconDrawableId,
- RemoteViews contentView) {
+ private void processSmallRightIcon(Icon smallIcon, RemoteViews contentView) {
if (!isLegacy()) {
contentView.setDrawableParameters(R.id.right_icon, false, -1,
0xFFFFFFFF,
PorterDuff.Mode.SRC_ATOP, -1);
}
- if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, smallIconDrawableId)) {
+ final boolean gray = isLegacy()
+ && smallIcon.getType() == Icon.TYPE_RESOURCE
+ && mColorUtil.isGrayscaleIcon(mContext, smallIcon.getResId());
+ if (!isLegacy() || gray) {
contentView.setInt(R.id.right_icon,
"setBackgroundResource",
R.drawable.notification_icon_legacy_bg);
@@ -3180,7 +3240,10 @@ public class Notification implements Parcelable
public Notification buildUnstyled() {
Notification n = new Notification();
n.when = mWhen;
- n.icon = mSmallIcon;
+ n.mSmallIcon = mSmallIcon;
+ if (mSmallIcon.getType() == Icon.TYPE_RESOURCE) {
+ n.icon = mSmallIcon.getResId();
+ }
n.iconLevel = mSmallIconLevel;
n.number = mNumber;
@@ -3192,7 +3255,10 @@ public class Notification implements Parcelable
n.fullScreenIntent = mFullScreenIntent;
n.tickerText = mTickerText;
n.tickerView = makeTickerView();
- n.largeIcon = mLargeIcon;
+ n.mLargeIcon = mLargeIcon;
+ if (mLargeIcon != null && mLargeIcon.getType() == Icon.TYPE_BITMAP) {
+ n.largeIcon = mLargeIcon.getBitmap();
+ }
n.sound = mSound;
n.audioStreamType = mAudioStreamType;
n.audioAttributes = mAudioAttributes;
@@ -3242,7 +3308,7 @@ public class Notification implements Parcelable
extras.putCharSequence(EXTRA_TEXT, mContentText);
extras.putCharSequence(EXTRA_SUB_TEXT, mSubText);
extras.putCharSequence(EXTRA_INFO_TEXT, mContentInfo);
- extras.putInt(EXTRA_SMALL_ICON, mSmallIcon);
+ extras.putParcelable(EXTRA_SMALL_ICON, mSmallIcon);
extras.putInt(EXTRA_PROGRESS, mProgress);
extras.putInt(EXTRA_PROGRESS_MAX, mProgressMax);
extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate);
@@ -3430,7 +3496,7 @@ public class Notification implements Parcelable
// Notification fields.
mWhen = n.when;
- mSmallIcon = n.icon;
+ mSmallIcon = n.mSmallIcon;
mSmallIconLevel = n.iconLevel;
mNumber = n.number;
@@ -3441,7 +3507,7 @@ public class Notification implements Parcelable
mFullScreenIntent = n.fullScreenIntent;
mTickerText = n.tickerText;
mTickerView = n.tickerView;
- mLargeIcon = n.largeIcon;
+ mLargeIcon = n.mLargeIcon;
mSound = n.sound;
mAudioStreamType = n.audioStreamType;
mAudioAttributes = n.audioAttributes;
@@ -3472,7 +3538,7 @@ public class Notification implements Parcelable
mContentText = extras.getCharSequence(EXTRA_TEXT);
mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
mContentInfo = extras.getCharSequence(EXTRA_INFO_TEXT);
- mSmallIcon = extras.getInt(EXTRA_SMALL_ICON);
+ mSmallIcon = extras.getParcelable(EXTRA_SMALL_ICON);
mProgress = extras.getInt(EXTRA_PROGRESS);
mProgressMax = extras.getInt(EXTRA_PROGRESS_MAX);
mProgressIndeterminate = extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
@@ -3764,7 +3830,7 @@ public class Notification implements Parcelable
*/
public static class BigPictureStyle extends Style {
private Bitmap mPicture;
- private Bitmap mBigLargeIcon;
+ private Icon mBigLargeIcon;
private boolean mBigLargeIconSet = false;
public BigPictureStyle() {
@@ -3803,8 +3869,15 @@ public class Notification implements Parcelable
* Override the large icon when the big notification is shown.
*/
public BigPictureStyle bigLargeIcon(Bitmap b) {
+ return bigLargeIcon(b != null ? Icon.createWithBitmap(b) : null);
+ }
+
+ /**
+ * Override the large icon when the big notification is shown.
+ */
+ public BigPictureStyle bigLargeIcon(Icon icon) {
mBigLargeIconSet = true;
- mBigLargeIcon = b;
+ mBigLargeIcon = icon;
return this;
}
@@ -3815,7 +3888,7 @@ public class Notification implements Parcelable
// 1. mBigLargeIconSet -> mBigLargeIcon (null or non-null) applies, overrides
// mLargeIcon
// 2. !mBigLargeIconSet -> mLargeIcon applies
- Bitmap oldLargeIcon = null;
+ Icon oldLargeIcon = null;
if (mBigLargeIconSet) {
oldLargeIcon = mBuilder.mLargeIcon;
mBuilder.mLargeIcon = mBigLargeIcon;
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index e4bbe27..557964b 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -23,6 +23,7 @@ import android.app.Notification.Builder;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ParceledListSlice;
+import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -204,6 +205,7 @@ public class NotificationManager
notification.sound.checkFileUriExposed("Notification.sound");
}
}
+ fixLegacySmallIcon(notification, pkg);
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
Notification stripped = notification.clone();
Builder.stripForDelivery(stripped);
@@ -231,6 +233,7 @@ public class NotificationManager
notification.sound.checkFileUriExposed("Notification.sound");
}
}
+ fixLegacySmallIcon(notification, pkg);
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
Notification stripped = notification.clone();
Builder.stripForDelivery(stripped);
@@ -244,6 +247,12 @@ public class NotificationManager
}
}
+ private void fixLegacySmallIcon(Notification n, String pkg) {
+ if (n.getSmallIcon() == null && n.icon != 0) {
+ n.setSmallIcon(Icon.createWithResource(pkg, n.icon));
+ }
+ }
+
/**
* Cancel a previously shown notification. If it's transient, the view
* will be hidden. If it's persistent, it will be removed from the status
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 767f59e..f66b5ff 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
@@ -380,6 +382,7 @@ public final class BluetoothA2dp implements BluetoothProfile {
* @return priority of the device
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
if (mService != null && isEnabled()
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ec6f18d..8768f40 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -17,6 +17,9 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -37,6 +40,8 @@ import android.util.Log;
import android.util.Pair;
import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -133,6 +138,12 @@ public final class BluetoothAdapter {
public static final String EXTRA_PREVIOUS_STATE =
"android.bluetooth.adapter.extra.PREVIOUS_STATE";
+ /** @hide */
+ @IntDef({STATE_OFF, STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF, STATE_BLE_TURNING_ON,
+ STATE_BLE_ON, STATE_BLE_TURNING_OFF})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AdapterState {}
+
/**
* Indicates the local Bluetooth adapter is off.
*/
@@ -273,6 +284,11 @@ public final class BluetoothAdapter {
public static final String EXTRA_PREVIOUS_SCAN_MODE =
"android.bluetooth.adapter.extra.PREVIOUS_SCAN_MODE";
+ /** @hide */
+ @IntDef({SCAN_MODE_NONE, SCAN_MODE_CONNECTABLE, SCAN_MODE_CONNECTABLE_DISCOVERABLE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ScanMode {}
+
/**
* Indicates that both inquiry scan and page scan are disabled on the local
* Bluetooth adapter. Therefore this device is neither discoverable
@@ -578,6 +594,7 @@ public final class BluetoothAdapter {
*
* @return true if the local adapter is turned on
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public boolean isEnabled() {
try {
synchronized(mManagerCallback) {
@@ -752,6 +769,8 @@ public final class BluetoothAdapter {
*
* @return current state of Bluetooth adapter
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @AdapterState
public int getState() {
try {
synchronized(mManagerCallback) {
@@ -792,6 +811,8 @@ public final class BluetoothAdapter {
* @return current state of Bluetooth adapter
* @hide
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @AdapterState
public int getLeState() {
try {
synchronized(mManagerCallback) {
@@ -845,6 +866,7 @@ public final class BluetoothAdapter {
* @return true to indicate adapter startup has begun, or false on
* immediate error
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean enable() {
int state = STATE_OFF;
if (isEnabled() == true){
@@ -893,6 +915,7 @@ public final class BluetoothAdapter {
* @return true to indicate adapter shutdown has begun, or false on
* immediate error
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean disable() {
try {
return mManagerService.disable(true);
@@ -925,6 +948,7 @@ public final class BluetoothAdapter {
*
* @return Bluetooth hardware address as string
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public String getAddress() {
try {
return mManagerService.getAddress();
@@ -998,6 +1022,7 @@ public final class BluetoothAdapter {
* @param name a valid Bluetooth name
* @return true if the name was set, false otherwise
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setName(String name) {
if (getState() != STATE_ON) return false;
try {
@@ -1024,6 +1049,8 @@ public final class BluetoothAdapter {
*
* @return scan mode
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
+ @ScanMode
public int getScanMode() {
if (getState() != STATE_ON) return SCAN_MODE_NONE;
try {
@@ -1062,7 +1089,7 @@ public final class BluetoothAdapter {
* @return true if the scan mode was set, false otherwise
* @hide
*/
- public boolean setScanMode(int mode, int duration) {
+ public boolean setScanMode(@ScanMode int mode, int duration) {
if (getState() != STATE_ON) return false;
try {
synchronized(mManagerCallback) {
@@ -1130,6 +1157,7 @@ public final class BluetoothAdapter {
*
* @return true on success, false on error
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean startDiscovery() {
if (getState() != STATE_ON) return false;
try {
@@ -1157,6 +1185,7 @@ public final class BluetoothAdapter {
*
* @return true on success, false on error
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean cancelDiscovery() {
if (getState() != STATE_ON) return false;
try {
@@ -1186,6 +1215,7 @@ public final class BluetoothAdapter {
*
* @return true if discovering
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public boolean isDiscovering() {
if (getState() != STATE_ON) return false;
try {
@@ -1345,6 +1375,7 @@ public final class BluetoothAdapter {
*
* @return unmodifiable set of {@link BluetoothDevice}, or null on error
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public Set<BluetoothDevice> getBondedDevices() {
if (getState() != STATE_ON) {
return toDeviceSet(new BluetoothDevice[0]);
@@ -1396,6 +1427,7 @@ public final class BluetoothAdapter {
* {@link BluetoothProfile#STATE_CONNECTED},
* {@link BluetoothProfile#STATE_DISCONNECTING}
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getProfileConnectionState(int profile) {
if (getState() != STATE_ON) return BluetoothProfile.STATE_DISCONNECTED;
try {
@@ -1460,6 +1492,7 @@ public final class BluetoothAdapter {
* @throws IOException on error, for example Bluetooth not available, or
* insufficient permissions, or channel in use.
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothServerSocket listenUsingRfcommWithServiceRecord(String name, UUID uuid)
throws IOException {
return createNewRfcommSocketAndRecord(name, uuid, true, true);
@@ -1491,6 +1524,7 @@ public final class BluetoothAdapter {
* @throws IOException on error, for example Bluetooth not available, or
* insufficient permissions, or channel in use.
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String name, UUID uuid)
throws IOException {
return createNewRfcommSocketAndRecord(name, uuid, false, false);
@@ -2032,6 +2066,7 @@ public final class BluetoothAdapter {
* instead.
*/
@Deprecated
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean startLeScan(LeScanCallback callback) {
return startLeScan(null, callback);
}
@@ -2052,6 +2087,7 @@ public final class BluetoothAdapter {
* instead.
*/
@Deprecated
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids);
if (callback == null) {
@@ -2138,6 +2174,7 @@ public final class BluetoothAdapter {
* @deprecated Use {@link BluetoothLeScanner#stopScan(ScanCallback)} instead.
*/
@Deprecated
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void stopLeScan(LeScanCallback callback) {
if (DBG) Log.d(TAG, "stopLeScan()");
BluetoothLeScanner scanner = getBluetoothLeScanner();
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index bfc374f..26a91e4 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -709,6 +711,7 @@ public final class BluetoothDevice implements Parcelable {
*
* @return the Bluetooth name, or null if there was a problem.
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public String getName() {
if (sService == null) {
Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
@@ -729,6 +732,7 @@ public final class BluetoothDevice implements Parcelable {
* {@link #DEVICE_TYPE_DUAL}.
* {@link #DEVICE_TYPE_UNKNOWN} if it's not available
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getType() {
if (sService == null) {
Log.e(TAG, "BT not enabled. Cannot get Remote Device type");
@@ -807,6 +811,7 @@ public final class BluetoothDevice implements Parcelable {
*
* @return false on immediate error, true if bonding will begin
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean createBond() {
if (sService == null) {
Log.e(TAG, "BT not enabled. Cannot create bond to Remote Device");
@@ -948,6 +953,7 @@ public final class BluetoothDevice implements Parcelable {
*
* @return the bond state
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getBondState() {
if (sService == null) {
Log.e(TAG, "BT not enabled. Cannot get bond state");
@@ -1014,6 +1020,7 @@ public final class BluetoothDevice implements Parcelable {
*
* @return Bluetooth class object, or null on error
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothClass getBluetoothClass() {
if (sService == null) {
Log.e(TAG, "BT not enabled. Cannot get Bluetooth Class");
@@ -1039,6 +1046,7 @@ public final class BluetoothDevice implements Parcelable {
* @return the supported features (UUIDs) of the remote device,
* or null on error
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public ParcelUuid[] getUuids() {
if (sService == null || isBluetoothEnabled() == false) {
Log.e(TAG, "BT not enabled. Cannot get remote device Uuids");
@@ -1065,6 +1073,7 @@ public final class BluetoothDevice implements Parcelable {
* of initiating an ACL connection to the remote device
* was started.
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public boolean fetchUuidsWithSdp() {
IBluetooth service = sService;
if (service == null || isBluetoothEnabled() == false) {
@@ -1144,6 +1153,7 @@ public final class BluetoothDevice implements Parcelable {
* @return true confirmation has been sent out
* false for error
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public boolean setPairingConfirmation(boolean confirm) {
if (sService == null) {
Log.e(TAG, "BT not enabled. Cannot set pairing confirmation");
@@ -1405,6 +1415,7 @@ public final class BluetoothDevice implements Parcelable {
* @throws IOException on error, for example Bluetooth not available, or
* insufficient permissions
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException {
if (isBluetoothEnabled() == false) {
Log.e(TAG, "Bluetooth is not enabled");
@@ -1443,6 +1454,7 @@ public final class BluetoothDevice implements Parcelable {
* @throws IOException on error, for example Bluetooth not available, or
* insufficient permissions
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException {
if (isBluetoothEnabled() == false) {
Log.e(TAG, "Bluetooth is not enabled");
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
index b1618cf3..e355a1c 100644
--- a/core/java/android/bluetooth/BluetoothManager.java
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
import android.content.Context;
import android.os.RemoteException;
import android.util.Log;
@@ -89,6 +91,7 @@ public final class BluetoothManager {
* {@link BluetoothProfile#STATE_DISCONNECTED},
* {@link BluetoothProfile#STATE_DISCONNECTING}
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getConnectionState(BluetoothDevice device, int profile) {
if (DBG) Log.d(TAG,"getConnectionState()");
@@ -117,6 +120,7 @@ public final class BluetoothManager {
* @param profile GATT or GATT_SERVER
* @return List of devices. The list will be empty on error.
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public List<BluetoothDevice> getConnectedDevices(int profile) {
if (DBG) Log.d(TAG,"getConnectedDevices");
if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
@@ -161,6 +165,7 @@ public final class BluetoothManager {
* {@link BluetoothProfile#STATE_DISCONNECTING},
* @return List of devices. The list will be empty on error.
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int profile, int[] states) {
if (DBG) Log.d(TAG,"getDevicesMatchingConnectionStates");
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index eecb073..cbce22c 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -17,6 +17,9 @@
package android.bluetooth;
+import android.Manifest;
+import android.annotation.RequiresPermission;
+
import java.util.List;
/**
@@ -163,6 +166,7 @@ public interface BluetoothProfile {
*
* @return List of devices. The list will be empty on error.
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public List<BluetoothDevice> getConnectedDevices();
/**
@@ -179,6 +183,7 @@ public interface BluetoothProfile {
* {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
* @return List of devices. The list will be empty on error.
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states);
/**
@@ -191,6 +196,7 @@ public interface BluetoothProfile {
* {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
* {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getConnectionState(BluetoothDevice device);
/**
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 687bd5d..2e6c4f0 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -16,6 +16,8 @@
package android.bluetooth.le;
+import android.Manifest;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
@@ -80,6 +82,7 @@ public final class BluetoothLeScanner {
* @param callback Callback used to deliver scan results.
* @throws IllegalArgumentException If {@code callback} is null.
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void startScan(final ScanCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback is null");
@@ -97,6 +100,7 @@ public final class BluetoothLeScanner {
* @param callback Callback used to deliver scan results.
* @throws IllegalArgumentException If {@code settings} or {@code callback} is null.
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void startScan(List<ScanFilter> filters, ScanSettings settings,
final ScanCallback callback) {
startScan(filters, settings, callback, null);
@@ -151,6 +155,7 @@ public final class BluetoothLeScanner {
*
* @param callback
*/
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void stopScan(ScanCallback callback) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
synchronized (mLeScanClients) {
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/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 3ec11b7..5fb9abc 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -1355,7 +1355,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
* android.control.* are mostly disabled, and the camera device implements
* one of the scene mode settings (such as ACTION, SUNSET, or PARTY)
* as it wishes. The camera device scene mode 3A settings are provided by
- * android.control.sceneModeOverrides.</p>
+ * {@link android.hardware.camera2.CaptureResult capture results}.</p>
* <p>When set to OFF_KEEP_STATE, it is similar to OFF mode, the only difference
* is that this frame will not be used by camera device background 3A statistics
* update, as if this frame is never captured. This mode can be used in the scenario
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index d931a76..0277c5b 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1921,7 +1921,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
* android.control.* are mostly disabled, and the camera device implements
* one of the scene mode settings (such as ACTION, SUNSET, or PARTY)
* as it wishes. The camera device scene mode 3A settings are provided by
- * android.control.sceneModeOverrides.</p>
+ * {@link android.hardware.camera2.CaptureResult capture results}.</p>
* <p>When set to OFF_KEEP_STATE, it is similar to OFF mode, the only difference
* is that this frame will not be used by camera device background 3A statistics
* update, as if this frame is never captured. This mode can be used in the scenario
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/provider/Settings.java b/core/java/android/provider/Settings.java
index 1f4020d..ef0dc3e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3102,7 +3102,16 @@ public final class Settings {
public static final String EGG_MODE = "egg_mode";
/** @hide */
- public static final Validator EGG_MODE_VALIDATOR = sBooleanValidator;
+ public static final Validator EGG_MODE_VALIDATOR = new Validator() {
+ @Override
+ public boolean validate(String value) {
+ try {
+ return Long.parseLong(value) >= 0;
+ } catch (NumberFormatException e) {
+ return false;
+ }
+ }
+ };
/**
* IMPORTANT: If you add a new public settings you also have to add it to
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/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/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/Window.java b/core/java/android/view/Window.java
index 49a72ce..07984e9 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1784,14 +1784,6 @@ public abstract class Window {
public void setAllowReturnTransitionOverlap(boolean allow) {}
/**
- * TODO: remove this.
- * @hide
- */
- public void setAllowExitTransitionOverlap(boolean allow) {
- setAllowReturnTransitionOverlap(allow);
- }
-
- /**
* Returns how the transition set in
* {@link #setExitTransition(android.transition.Transition)} overlaps with the exit
* transition of the called Activity when reentering after if finishes. When true,
@@ -1805,12 +1797,6 @@ public abstract class Window {
public boolean getAllowReturnTransitionOverlap() { return true; }
/**
- * TODO: remove this.
- * @hide
- */
- public boolean getAllowExitTransitionOverlap() { return getAllowReturnTransitionOverlap(); }
-
- /**
* Returns the duration, in milliseconds, of the window background fade
* when transitioning into or away from an Activity when called with an Activity Transition.
* <p>When executing the enter transition, the background starts transparent
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/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 334afab..dc772fb 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -344,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 3edac3b..c829783 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3897,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
@@ -3917,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);
@@ -3936,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;
@@ -3953,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;
@@ -3968,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);
@@ -4015,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
@@ -4035,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);
@@ -4054,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);
@@ -4071,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);
@@ -4087,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);