diff options
Diffstat (limited to 'core/java/android')
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> * <service android:name=".MyMessagingService" * android:label="@string/service_name" - * android:permission="android.permission.BIND_CARRIER_MESSAGING_SERVICE"> + * android:permission="android.permission.BIND_CARRIER_SERVICES"> * <intent-filter> * <action android:name="android.service.carrier.CarrierMessagingService" /> * </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); |
