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