diff options
Diffstat (limited to 'core/java')
26 files changed, 518 insertions, 234 deletions
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java index 540376e..d611058 100644 --- a/core/java/android/app/ActivityTransitionCoordinator.java +++ b/core/java/android/app/ActivityTransitionCoordinator.java @@ -222,8 +222,15 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { if (mListener != null) { mListener.onMapSharedElements(mAllSharedElementNames, sharedElements); } - mSharedElementNames.addAll(sharedElements.keySet()); - mSharedElements.addAll(sharedElements.values()); + int numSharedElements = sharedElements.size(); + for (int i = 0; i < numSharedElements; i++) { + View sharedElement = sharedElements.valueAt(i); + String name = sharedElements.keyAt(i); + if (sharedElement != null && sharedElement.isAttachedToWindow() && name != null) { + mSharedElements.add(sharedElement); + mSharedElementNames.add(name); + } + } if (getViewsTransition() != null && mTransitioningViews != null) { ViewGroup decorView = getDecor(); if (decorView != null) { @@ -536,10 +543,10 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver { protected ArrayList<View> createSnapshots(Bundle state, Collection<String> names) { int numSharedElements = names.size(); + ArrayList<View> snapshots = new ArrayList<View>(numSharedElements); if (numSharedElements == 0) { - return null; + return snapshots; } - ArrayList<View> snapshots = new ArrayList<View>(numSharedElements); Context context = getWindow().getContext(); int[] decorLoc = new int[2]; ViewGroup decorView = getDecor(); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 1e1a613..854719d 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1664,6 +1664,17 @@ final class ApplicationPackageManager extends PackageManager { * @hide */ public Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { + Drawable dr = loadUnbadgedItemIcon(itemInfo, appInfo); + if (itemInfo.showUserIcon != UserHandle.USER_NULL) { + return dr; + } + return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId())); + } + + /** + * @hide + */ + public Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo) { if (itemInfo.showUserIcon != UserHandle.USER_NULL) { Bitmap bitmap = getUserManager().getUserIcon(itemInfo.showUserIcon); if (bitmap == null) { @@ -1678,7 +1689,7 @@ final class ApplicationPackageManager extends PackageManager { if (dr == null) { dr = itemInfo.loadDefaultIcon(this); } - return getUserBadgedIcon(dr, new UserHandle(mContext.getUserId())); + return dr; } private Drawable getBadgedDrawable(Drawable drawable, Drawable badgeDrawable, diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index fb10e17..9849c51 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.ColorStateList; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.PorterDuff; @@ -2773,6 +2774,14 @@ public class Notification implements Parcelable contentView.setViewVisibility(R.id.progress, View.VISIBLE); contentView.setProgressBar( R.id.progress, mProgressMax, mProgress, mProgressIndeterminate); + contentView.setProgressBackgroundTintList( + R.id.progress, ColorStateList.valueOf(mContext.getResources().getColor( + R.color.notification_progress_background_color))); + if (mColor != COLOR_DEFAULT) { + ColorStateList colorStateList = ColorStateList.valueOf(mColor); + contentView.setProgressTintList(R.id.progress, colorStateList); + contentView.setProgressIndeterminateTintList(R.id.progress, colorStateList); + } showLine2 = true; } else { contentView.setViewVisibility(R.id.progress, View.GONE); diff --git a/core/java/android/content/pm/PackageItemInfo.java b/core/java/android/content/pm/PackageItemInfo.java index cacdf8e..22a899c 100644 --- a/core/java/android/content/pm/PackageItemInfo.java +++ b/core/java/android/content/pm/PackageItemInfo.java @@ -138,7 +138,7 @@ public class PackageItemInfo { } return packageName; } - + /** * Retrieve the current graphical icon associated with this item. This * will call back on the given PackageManager to load the icon from @@ -156,6 +156,23 @@ public class PackageItemInfo { } /** + * Retrieve the current graphical icon associated with this item without + * the addition of a work badge if applicable. + * This will call back on the given PackageManager to load the icon from + * the application. + * + * @param pm A PackageManager from which the icon can be loaded; usually + * the PackageManager from which you originally retrieved this item. + * + * @return Returns a Drawable containing the item's icon. If the + * item does not have an icon, the item's default icon is returned + * such as the default activity icon. + */ + public Drawable loadUnbadgedIcon(PackageManager pm) { + return pm.loadUnbadgedItemIcon(this, getApplicationInfo()); + } + + /** * Retrieve the current graphical banner associated with this item. This * will call back on the given PackageManager to load the banner from * the application. diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e519163..ab90b66 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -3911,6 +3911,11 @@ public abstract class PackageManager { */ public abstract Drawable loadItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo); + /** + * @hide + */ + public abstract Drawable loadUnbadgedItemIcon(PackageItemInfo itemInfo, ApplicationInfo appInfo); + /** {@hide} */ public abstract boolean isPackageAvailable(String packageName); diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 7f276c2..e34ce3e 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -2323,7 +2323,14 @@ public class Resources { final Drawable dr; if (cs != null) { - dr = cs.newDrawable(this, theme); + final Drawable clonedDr = cs.newDrawable(this); + if (theme != null) { + dr = clonedDr.mutate(); + dr.applyTheme(theme); + dr.clearMutated(); + } else { + dr = clonedDr; + } } else if (isColorDrawable) { dr = new ColorDrawable(value.data); } else { diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java index f514e42..cf6a779 100644 --- a/core/java/android/hardware/Sensor.java +++ b/core/java/android/hardware/Sensor.java @@ -329,7 +329,11 @@ public final class Sensor { * A sensor of this type triggers an event each time a step is taken by the user. The only * allowed value to return is 1.0 and an event is generated for each step. Like with any other * event, the timestamp indicates when the event (here the step) occurred, this corresponds to - * when the foot hit the ground, generating a high variation in acceleration. + * when the foot hit the ground, generating a high variation in acceleration. This sensor is + * only for detecting every individual step as soon as it is taken, for example to perform dead + * reckoning. If you only need aggregate number of steps taken over a period of time, register + * for {@link #TYPE_STEP_COUNTER} instead. It is defined as a + * {@link Sensor#REPORTING_MODE_SPECIAL_TRIGGER} sensor. * <p> * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details. */ @@ -349,7 +353,12 @@ public final class Sensor { * while activated. The value is returned as a float (with the fractional part set to zero) and * is reset to zero only on a system reboot. The timestamp of the event is set to the time when * the last step for that event was taken. This sensor is implemented in hardware and is - * expected to be low power. + * expected to be low power. If you want to continuously track the number of steps over a long + * period of time, do NOT unregister for this sensor, so that it keeps counting steps in the + * background even when the AP is in suspend mode and report the aggregate count when the AP + * is awake. Application needs to stay registered for this sensor because step counter does not + * count steps if it is not activated. This sensor is ideal for fitness tracking applications. + * It is defined as an {@link Sensor#REPORTING_MODE_ON_CHANGE} sensor. * <p> * See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details. */ @@ -750,31 +759,41 @@ public final class Sensor { } /** - * Returns whether this sensor is a wake-up sensor. + * Returns true if the sensor is a wake-up sensor. * <p> - * Wake up sensors wake the application processor up when they have events to deliver. When a - * wake up sensor is registered to without batching enabled, each event will wake the - * application processor up. - * <p> - * When a wake up sensor is registered to with batching enabled, it - * wakes the application processor up when maxReportingLatency has elapsed or when the hardware - * FIFO storing the events from wake up sensors is getting full. - * <p> - * Non-wake up sensors never wake the application processor up. Their events are only reported - * when the application processor is awake, for example because the application holds a wake - * lock, or another source woke the application processor up. + * <b>Application Processor Power modes</b> <p> + * Application Processor(AP), is the processor on which applications run. When no wake lock is held + * and the user is not interacting with the device, this processor can enter a “Suspend” mode, + * reducing the power consumption by 10 times or more. + * </p> * <p> - * When a non-wake up sensor is registered to without batching enabled, the measurements made - * while the application processor is asleep might be lost and never returned. + * <b>Non-wake-up sensors</b> <p> + * Non-wake-up sensors are sensors that do not wake the AP out of suspend to report data. While + * the AP is in suspend mode, the sensors continue to function and generate events, which are + * put in a hardware FIFO. The events in the FIFO are delivered to the application when the AP + * wakes up. If the FIFO was too small to store all events generated while the AP was in + * suspend mode, the older events are lost: the oldest data is dropped to accommodate the newer + * data. In the extreme case where the FIFO is non-existent {@code maxFifoEventCount() == 0}, + * all events generated while the AP was in suspend mode are lost. Applications using + * non-wake-up sensors should usually: + * <ul> + * <li>Either unregister from the sensors when they do not need them, usually in the activity’s + * {@code onPause} method. This is the most common case. + * <li>Or realize that the sensors are consuming some power while the AP is in suspend mode and + * that even then, some events might be lost. + * </ul> + * </p> * <p> - * When a non-wake up sensor is registered to with batching enabled, the measurements made while - * the application processor is asleep are stored in the hardware FIFO for non-wake up sensors. - * When this FIFO gets full, new events start overwriting older events. When the application - * then wakes up, the latest events are returned, and some old events might be lost. The number - * of events actually returned depends on the hardware FIFO size, as well as on what other - * sensors are activated. If losing sensor events is not acceptable during batching, you must - * use the wake-up version of the sensor. - * @return true if this is a wake up sensor, false otherwise. + * <b>Wake-up sensors</b> <p> + * In opposition to non-wake-up sensors, wake-up sensors ensure that their data is delivered + * independently of the state of the AP. While the AP is awake, the wake-up sensors behave + * like non-wake-up-sensors. When the AP is asleep, wake-up sensors wake up the AP to deliver + * events. That is, the AP will wake up and the sensor will deliver the events before the + * maximum reporting latency is elapsed or the hardware FIFO gets full. See {@link + * SensorManager#registerListener(SensorEventListener, Sensor, int, int)} for more details. + * </p> + * + * @return <code>true</code> if this is a wake-up sensor, <code>false</code> otherwise. */ public boolean isWakeUpSensor() { return (mFlags & SENSOR_FLAG_WAKE_UP_SENSOR) != 0; diff --git a/core/java/android/hardware/SensorEventListener2.java b/core/java/android/hardware/SensorEventListener2.java index 70eff08..fd3e62b 100644 --- a/core/java/android/hardware/SensorEventListener2.java +++ b/core/java/android/hardware/SensorEventListener2.java @@ -21,15 +21,16 @@ package android.hardware; */ public interface SensorEventListener2 extends SensorEventListener { /** - * Called after flush() is completed. All the events in the batch at the point when - * the flush was called have been delivered to the applications registered for those - * sensor events. Flush Complete Events are sent ONLY to the application that has - * explicitly called flush(). If the hardware FIFO is flushed due to some other - * application calling flush(), flush complete event is not delivered to this application. + * Called after flush() is completed. All the events in the batch at the point when the flush + * was called have been delivered to the applications registered for those sensor events. In + * {@link android.os.Build.VERSION_CODES#KITKAT}, applications may receive flush complete events + * even if some other application has called flush() on the same sensor. Starting with + * {@link android.os.Build.VERSION_CODES#LOLLIPOP}, flush Complete events are sent ONLY to the + * application that has explicitly called flush(). If the hardware FIFO is flushed due to some + * other application calling flush(), flush complete event is not delivered to this application. * <p> * * @param sensor The {@link android.hardware.Sensor Sensor} on which flush was called. - * * @see android.hardware.SensorManager#flush(SensorEventListener) */ public void onFlushCompleted(Sensor sensor); diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index cccd624..e4e5a8c 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -626,73 +626,90 @@ public abstract class SensorManager { protected abstract void unregisterListenerImpl(SensorEventListener listener, Sensor sensor); /** - * Registers a {@link android.hardware.SensorEventListener - * SensorEventListener} for the given sensor. - * - * <p class="note"></p> - * Note: Don't use this method with a one shot trigger sensor such as - * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. - * Use {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. + * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given + * sensor at the given sampling frequency. + * <p> + * The events will be delivered to the provided {@code SensorEventListener} as soon as they are + * available. To reduce the power consumption, applications can use + * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a + * positive non-zero maximum reporting latency. + * </p> + * <p> + * In the case of non-wake-up sensors, the events are only delivered while the Application + * Processor (AP) is not in suspend mode. See {@link Sensor#isWakeUpSensor()} for more details. + * To ensure delivery of events from non-wake-up sensors even when the screen is OFF, the + * application registering to the sensor must hold a partial wake-lock to keep the AP awake, + * otherwise some events might be lost while the AP is asleep. Note that although events might + * be lost while the AP is asleep, the sensor will still consume power if it is not explicitly + * deactivated by the application. Applications must unregister their {@code + * SensorEventListener}s in their activity's {@code onPause()} method to avoid consuming power + * while the device is inactive. See {@link #registerListener(SensorEventListener, Sensor, int, + * int)} for more details on hardware FIFO (queueing) capabilities and when some sensor events + * might be lost. + * </p> + * <p> + * In the case of wake-up sensors, each event generated by the sensor will cause the AP to + * wake-up, ensuring that each event can be delivered. Because of this, registering to a wake-up + * sensor has very significant power implications. Call {@link Sensor#isWakeUpSensor()} to check + * whether a sensor is a wake-up sensor. See + * {@link #registerListener(SensorEventListener, Sensor, int, int)} for information on how to + * reduce the power impact of registering to wake-up sensors. + * </p> + * <p class="note"> + * Note: Don't use this method with one-shot trigger sensors such as + * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use + * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. Use + * {@link Sensor#getReportingMode()} to obtain the reporting mode of a given sensor. * </p> * - * @param listener - * A {@link android.hardware.SensorEventListener SensorEventListener} - * object. - * - * @param sensor - * The {@link android.hardware.Sensor Sensor} to register to. - * - * @param rateUs - * The rate {@link android.hardware.SensorEvent sensor events} are - * delivered at. This is only a hint to the system. Events may be - * received faster or slower than the specified rate. Usually events - * are received faster. The value must be one of - * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, - * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} - * or, the desired delay between events in microseconds. - * Specifying the delay in microseconds only works from Android - * 2.3 (API level 9) onwards. For earlier releases, you must use - * one of the {@code SENSOR_DELAY_*} constants. - * - * @return <code>true</code> if the sensor is supported and successfully - * enabled. - * + * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object. + * @param sensor The {@link android.hardware.Sensor Sensor} to register to. + * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are + * delivered at. This is only a hint to the system. Events may be received faster or + * slower than the specified rate. Usually events are received faster. The value must + * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, + * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired delay + * between events in microseconds. Specifying the delay in microseconds only works + * from Android 2.3 (API level 9) onwards. For earlier releases, you must use one of + * the {@code SENSOR_DELAY_*} constants. + * @return <code>true</code> if the sensor is supported and successfully enabled. * @see #registerListener(SensorEventListener, Sensor, int, Handler) * @see #unregisterListener(SensorEventListener) * @see #unregisterListener(SensorEventListener, Sensor) - * */ - public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs) { - return registerListener(listener, sensor, rateUs, null); + public boolean registerListener(SensorEventListener listener, Sensor sensor, + int samplingPeriodUs) { + return registerListener(listener, sensor, samplingPeriodUs, null); } /** - * Enables batch mode for a sensor with the given rate and maxBatchReportLatency. If the - * underlying hardware does not support batch mode, this defaults to - * {@link #registerListener(SensorEventListener, Sensor, int)} and other parameters are - * ignored. In non-batch mode, all sensor events must be reported as soon as they are detected. - * While in batch mode, sensor events do not need to be reported as soon as they are detected. - * They can be temporarily stored in batches and reported in batches, as long as no event is - * delayed by more than "maxBatchReportLatency" microseconds. That is, all events since the - * previous batch are recorded and returned all at once. This allows to reduce the amount of - * interrupts sent to the SoC, and allows the SoC to switch to a lower power state (Idle) while - * the sensor is capturing and batching data. - * <p> - * Registering to a sensor in batch mode will not prevent the SoC from going to suspend mode. In - * this case, the sensor will continue to gather events and store it in a hardware FIFO. If the - * FIFO gets full before the AP wakes up again, some events will be lost, as the older events - * get overwritten by new events in the hardware FIFO. This can be avoided by holding a wake - * lock. If the application holds a wake lock, the SoC will not go to suspend mode, so no events - * will be lost, as the events will be reported before the FIFO gets full. - * </p> + * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given + * sensor at the given sampling frequency and the given maximum reporting latency. * <p> - * Batching is always best effort. If a different application requests updates in continuous - * mode, this application will also get events in continuous mode. Batch mode updates can be - * unregistered by calling {@link #unregisterListener(SensorEventListener)}. + * This function is similar to {@link #registerListener(SensorEventListener, Sensor, int)} but + * it allows events to stay temporarily in the hardware FIFO (queue) before being delivered. The + * events can be stored in the hardware FIFO up to {@code maxReportLatencyUs} microseconds. Once + * one of the events in the FIFO needs to be reported, all of the events in the FIFO are + * reported sequentially. This means that some events will be reported before the maximum + * reporting latency has elapsed. + * </p><p> + * When {@code maxReportLatencyUs} is 0, the call is equivalent to a call to + * {@link #registerListener(SensorEventListener, Sensor, int)}, as it requires the events to be + * delivered as soon as possible. + * </p><p> + * When {@code sensor.maxFifoEventCount()} is 0, the sensor does not use a FIFO, so the call + * will also be equivalent to {@link #registerListener(SensorEventListener, Sensor, int)}. + * </p><p> + * Setting {@code maxReportLatencyUs} to a positive value allows to reduce the number of + * interrupts the AP (Application Processor) receives, hence reducing power consumption, as the + * AP can switch to a lower power state while the sensor is capturing the data. This is + * especially important when registering to wake-up sensors, for which each interrupt causes the + * AP to wake up if it was in suspend mode. See {@link Sensor#isWakeUpSensor()} for more + * information on wake-up sensors. * </p> * <p class="note"> * </p> - * Note: Don't use this method with a one shot trigger sensor such as + * Note: Don't use this method with one-shot trigger sensors such as * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p> * @@ -701,118 +718,104 @@ public abstract class SensorManager { * flush complete notifications, it should register with * {@link android.hardware.SensorEventListener SensorEventListener2} instead. * @param sensor The {@link android.hardware.Sensor Sensor} to register to. - * @param rateUs The desired delay between two consecutive events in microseconds. This is only - * a hint to the system. Events may be received faster or slower than the specified - * rate. Usually events are received faster. Can be one of + * @param samplingPeriodUs The desired delay between two consecutive events in microseconds. + * This is only a hint to the system. Events may be received faster or slower than + * the specified rate. Usually events are received faster. Can be one of * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in * microseconds. - * @param maxBatchReportLatencyUs An event in the batch can be delayed by at most - * maxBatchReportLatency microseconds. More events can be batched if this value is - * large. If this is set to zero, batch mode is disabled and events are delivered in - * continuous mode as soon as they are available which is equivalent to calling + * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before + * being reported to the application. A large value allows reducing the power + * consumption associated with the sensor. If maxReportLatencyUs is set to zero, + * events are delivered as soon as they are available, which is equivalent to calling * {@link #registerListener(SensorEventListener, Sensor, int)}. - * @return <code>true</code> if batch mode is successfully enabled for this sensor, - * <code>false</code> otherwise. + * @return <code>true</code> if the sensor is supported and successfully enabled. * @see #registerListener(SensorEventListener, Sensor, int) * @see #unregisterListener(SensorEventListener) * @see #flush(SensorEventListener) */ - public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs, - int maxBatchReportLatencyUs) { - int delay = getDelay(rateUs); - return registerListenerImpl(listener, sensor, delay, null, maxBatchReportLatencyUs, 0); + public boolean registerListener(SensorEventListener listener, Sensor sensor, + int samplingPeriodUs, int maxReportLatencyUs) { + int delay = getDelay(samplingPeriodUs); + return registerListenerImpl(listener, sensor, delay, null, maxReportLatencyUs, 0); } /** * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given * sensor. Events are delivered in continuous mode as soon as they are available. To reduce the - * battery usage, use {@link #registerListener(SensorEventListener, Sensor, int, int)} which - * enables batch mode for the sensor. - * - * <p class="note"></p> - * Note: Don't use this method with a one shot trigger sensor such as - * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. - * Use {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. + * power consumption, applications can use + * {@link #registerListener(SensorEventListener, Sensor, int, int)} instead and specify a + * positive non-zero maximum reporting latency. + * <p class="note"> * </p> + * Note: Don't use this method with a one shot trigger sensor such as + * {@link Sensor#TYPE_SIGNIFICANT_MOTION}. Use + * {@link #requestTriggerSensor(TriggerEventListener, Sensor)} instead. </p> * - * @param listener - * A {@link android.hardware.SensorEventListener SensorEventListener} - * object. - * - * @param sensor - * The {@link android.hardware.Sensor Sensor} to register to. - * - * @param rateUs - * The rate {@link android.hardware.SensorEvent sensor events} are - * delivered at. This is only a hint to the system. Events may be - * received faster or slower than the specified rate. Usually events - * are received faster. The value must be one of - * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, - * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST}. - * or, the desired delay between events in microseconds. - * Specifying the delay in microseconds only works from Android - * 2.3 (API level 9) onwards. For earlier releases, you must use - * one of the {@code SENSOR_DELAY_*} constants. - * - * @param handler - * The {@link android.os.Handler Handler} the - * {@link android.hardware.SensorEvent sensor events} will be - * delivered to. - * + * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object. + * @param sensor The {@link android.hardware.Sensor Sensor} to register to. + * @param samplingPeriodUs The rate {@link android.hardware.SensorEvent sensor events} are + * delivered at. This is only a hint to the system. Events may be received faster or + * slower than the specified rate. Usually events are received faster. The value must + * be one of {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, + * {@link #SENSOR_DELAY_GAME}, or {@link #SENSOR_DELAY_FASTEST} or, the desired + * delay between events in microseconds. Specifying the delay in microseconds only + * works from Android 2.3 (API level 9) onwards. For earlier releases, you must use + * one of the {@code SENSOR_DELAY_*} constants. + * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent + * sensor events} will be delivered to. * @return <code>true</code> if the sensor is supported and successfully enabled. - * * @see #registerListener(SensorEventListener, Sensor, int) * @see #unregisterListener(SensorEventListener) * @see #unregisterListener(SensorEventListener, Sensor) */ - public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs, - Handler handler) { - int delay = getDelay(rateUs); + public boolean registerListener(SensorEventListener listener, Sensor sensor, + int samplingPeriodUs, Handler handler) { + int delay = getDelay(samplingPeriodUs); return registerListenerImpl(listener, sensor, delay, handler, 0, 0); } /** - * Enables batch mode for a sensor with the given rate and maxBatchReportLatency. + * Registers a {@link android.hardware.SensorEventListener SensorEventListener} for the given + * sensor at the given sampling frequency and the given maximum reporting latency. + * * @param listener A {@link android.hardware.SensorEventListener SensorEventListener} object * that will receive the sensor events. If the application is interested in receiving * flush complete notifications, it should register with * {@link android.hardware.SensorEventListener SensorEventListener2} instead. * @param sensor The {@link android.hardware.Sensor Sensor} to register to. - * @param rateUs The desired delay between two consecutive events in microseconds. This is only - * a hint to the system. Events may be received faster or slower than the specified - * rate. Usually events are received faster. Can be one of + * @param samplingPeriodUs The desired delay between two consecutive events in microseconds. + * This is only a hint to the system. Events may be received faster or slower than + * the specified rate. Usually events are received faster. Can be one of * {@link #SENSOR_DELAY_NORMAL}, {@link #SENSOR_DELAY_UI}, * {@link #SENSOR_DELAY_GAME}, {@link #SENSOR_DELAY_FASTEST} or the delay in * microseconds. - * @param maxBatchReportLatencyUs An event in the batch can be delayed by at most - * maxBatchReportLatency microseconds. More events can be batched if this value is - * large. If this is set to zero, batch mode is disabled and events are delivered in - * continuous mode as soon as they are available which is equivalent to calling + * @param maxReportLatencyUs Maximum time in microseconds that events can be delayed before + * being reported to the application. A large value allows reducing the power + * consumption associated with the sensor. If maxReportLatencyUs is set to zero, + * events are delivered as soon as they are available, which is equivalent to calling * {@link #registerListener(SensorEventListener, Sensor, int)}. - * @param handler The {@link android.os.Handler Handler} the - * {@link android.hardware.SensorEvent sensor events} will be delivered to. - * - * @return <code>true</code> if batch mode is successfully enabled for this sensor, - * <code>false</code> otherwise. + * @param handler The {@link android.os.Handler Handler} the {@link android.hardware.SensorEvent + * sensor events} will be delivered to. + * @return <code>true</code> if the sensor is supported and successfully enabled. * @see #registerListener(SensorEventListener, Sensor, int, int) */ - public boolean registerListener(SensorEventListener listener, Sensor sensor, int rateUs, - int maxBatchReportLatencyUs, Handler handler) { - int delayUs = getDelay(rateUs); - return registerListenerImpl(listener, sensor, delayUs, handler, maxBatchReportLatencyUs, 0); + public boolean registerListener(SensorEventListener listener, Sensor sensor, int samplingPeriodUs, + int maxReportLatencyUs, Handler handler) { + int delayUs = getDelay(samplingPeriodUs); + return registerListenerImpl(listener, sensor, delayUs, handler, maxReportLatencyUs, 0); } /** @hide */ protected abstract boolean registerListenerImpl(SensorEventListener listener, Sensor sensor, - int delayUs, Handler handler, int maxBatchReportLatencyUs, int reservedFlags); + int delayUs, Handler handler, int maxReportLatencyUs, int reservedFlags); /** - * Flushes the batch FIFO of all the sensors registered for this listener. If there are events - * in the FIFO of the sensor, they are returned as if the batch timeout in the FIFO of the - * sensors had expired. Events are returned in the usual way through the SensorEventListener. - * This call doesn't affect the batch timeout for this sensor. This call is asynchronous and + * Flushes the FIFO of all the sensors registered for this listener. If there are events + * in the FIFO of the sensor, they are returned as if the maxReportLantecy of the FIFO has + * expired. Events are returned in the usual way through the SensorEventListener. + * This call doesn't affect the maxReportLantecy for this sensor. This call is asynchronous and * returns immediately. * {@link android.hardware.SensorEventListener2#onFlushCompleted onFlushCompleted} is called * after all the events in the batch at the time of calling this method have been delivered diff --git a/core/java/android/hardware/hdmi/HdmiRecordSources.java b/core/java/android/hardware/hdmi/HdmiRecordSources.java index dcc41fa..c294f72 100644 --- a/core/java/android/hardware/hdmi/HdmiRecordSources.java +++ b/core/java/android/hardware/hdmi/HdmiRecordSources.java @@ -55,8 +55,10 @@ public final class HdmiRecordSources { /** * Base class for each record source. + * @hide */ - static abstract class RecordSource { + @SystemApi + public static abstract class RecordSource { protected final int mSourceType; protected final int mExtraDataSize; diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java index 671f722..a680b51 100644 --- a/core/java/android/preference/SeekBarVolumizer.java +++ b/core/java/android/preference/SeekBarVolumizer.java @@ -47,7 +47,6 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } private final Context mContext; - private final Handler mHandler; private final H mUiHandler = new H(); private final Callback mCallback; private final Uri mDefaultUri; @@ -55,8 +54,9 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba private final int mStreamType; private final int mMaxStreamVolume; private final Receiver mReceiver = new Receiver(); - private final Observer mVolumeObserver; + private Handler mHandler; + private Observer mVolumeObserver; private int mOriginalStreamVolume; private Ringtone mRingtone; private int mLastProgress = -1; @@ -75,16 +75,8 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mStreamType = streamType; mMaxStreamVolume = mAudioManager.getStreamMaxVolume(mStreamType); - HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler"); - thread.start(); - mHandler = new Handler(thread.getLooper(), this); mCallback = callback; mOriginalStreamVolume = mAudioManager.getStreamVolume(mStreamType); - mVolumeObserver = new Observer(mHandler); - mContext.getContentResolver().registerContentObserver( - System.getUriFor(System.VOLUME_SETTINGS[mStreamType]), - false, mVolumeObserver); - mReceiver.setListening(true); if (defaultUri == null) { if (mStreamType == AudioManager.STREAM_RING) { defaultUri = Settings.System.DEFAULT_RINGTONE_URI; @@ -95,7 +87,6 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } } mDefaultUri = defaultUri; - mHandler.sendEmptyMessage(MSG_INIT_SAMPLE); } public void setSeekBar(SeekBar seekBar) { @@ -173,11 +164,27 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba } public void stop() { + if (mHandler == null) return; // already stopped postStopSample(); mContext.getContentResolver().unregisterContentObserver(mVolumeObserver); - mSeekBar.setOnSeekBarChangeListener(null); mReceiver.setListening(false); + mSeekBar.setOnSeekBarChangeListener(null); mHandler.getLooper().quitSafely(); + mHandler = null; + mVolumeObserver = null; + } + + public void start() { + if (mHandler != null) return; // already started + HandlerThread thread = new HandlerThread(TAG + ".CallbackHandler"); + thread.start(); + mHandler = new Handler(thread.getLooper(), this); + mHandler.sendEmptyMessage(MSG_INIT_SAMPLE); + mVolumeObserver = new Observer(mHandler); + mContext.getContentResolver().registerContentObserver( + System.getUriFor(System.VOLUME_SETTINGS[mStreamType]), + false, mVolumeObserver); + mReceiver.setListening(true); } public void revertVolume() { diff --git a/core/java/android/preference/VolumePreference.java b/core/java/android/preference/VolumePreference.java index df9e10e..86d96f2 100644 --- a/core/java/android/preference/VolumePreference.java +++ b/core/java/android/preference/VolumePreference.java @@ -67,6 +67,7 @@ public class VolumePreference extends SeekBarDialogPreference implements final SeekBar seekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar); mSeekBarVolumizer = new SeekBarVolumizer(getContext(), mStreamType, null, this); + mSeekBarVolumizer.start(); mSeekBarVolumizer.setSeekBar(seekBar); getPreferenceManager().registerOnActivityStopListener(this); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 79e84d9..75c435e 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -5013,10 +5013,19 @@ public final class Settings { default: throw new IllegalArgumentException("Invalid location mode: " + mode); } - boolean gpsSuccess = Settings.Secure.setLocationProviderEnabledForUser( - cr, LocationManager.GPS_PROVIDER, gps, userId); + // Note it's important that we set the NLP mode first. The Google implementation + // of NLP clears its NLP consent setting any time it receives a + // LocationManager.PROVIDERS_CHANGED_ACTION broadcast and NLP is disabled. Also, + // it shows an NLP consent dialog any time it receives the broadcast, NLP is + // enabled, and the NLP consent is not set. If 1) we were to enable GPS first, + // 2) a setup wizard has its own NLP consent UI that sets the NLP consent setting, + // and 3) the receiver happened to complete before we enabled NLP, then the Google + // NLP would detect the attempt to enable NLP and show a redundant NLP consent + // dialog. Then the people who wrote the setup wizard would be sad. boolean nlpSuccess = Settings.Secure.setLocationProviderEnabledForUser( cr, LocationManager.NETWORK_PROVIDER, network, userId); + boolean gpsSuccess = Settings.Secure.setLocationProviderEnabledForUser( + cr, LocationManager.GPS_PROVIDER, gps, userId); return gpsSuccess && nlpSuccess; } } @@ -6579,6 +6588,14 @@ public final class Settings { public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt"; /** + * Whether the Volte/VT is enabled + * <p> + * Type: int (0 for false, 1 for true) + * @hide + */ + public static final String VOLTE_VT_ENABLED = "volte_vt_enabled"; + + /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. * diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java index 6820f77..e5f3b2c 100644 --- a/core/java/android/util/PathParser.java +++ b/core/java/android/util/PathParser.java @@ -34,7 +34,11 @@ public class PathParser { Path path = new Path(); PathDataNode[] nodes = createNodesFromPathData(pathData); if (nodes != null) { - PathDataNode.nodesToPath(nodes, path); + try { + PathDataNode.nodesToPath(nodes, path); + } catch (RuntimeException e) { + throw new RuntimeException("Error in parsing " + pathData, e); + } return path; } return null; @@ -128,7 +132,12 @@ public class PathParser { while (end < s.length()) { c = s.charAt(end); - if (((c - 'A') * (c - 'Z') <= 0) || (((c - 'a') * (c - 'z') <= 0))) { + // Note that 'e' or 'E' are not valid path commands, but could be + // used for floating point numbers' scientific notation. + // Therefore, when searching for next command, we should ignore 'e' + // and 'E'. + if ((((c - 'A') * (c - 'Z') <= 0) || ((c - 'a') * (c - 'z') <= 0)) + && c != 'e' && c != 'E') { return end; } end++; @@ -142,9 +151,9 @@ public class PathParser { private static class ExtractFloatResult { // We need to return the position of the next separator and whether the - // next float starts with a '-'. + // next float starts with a '-' or a '.'. int mEndPosition; - boolean mEndWithNegSign; + boolean mEndWithNegOrDot; } /** @@ -179,8 +188,8 @@ public class PathParser { s.substring(startPosition, endPosition)); } - if (result.mEndWithNegSign) { - // Keep the '-' sign with next number. + if (result.mEndWithNegOrDot) { + // Keep the '-' or '.' sign with next number. startPosition = endPosition; } else { startPosition = endPosition + 1; @@ -188,8 +197,7 @@ public class PathParser { } return Arrays.copyOf(results, count); } catch (NumberFormatException e) { - Log.e(LOGTAG, "error in parsing \"" + s + "\""); - throw e; + throw new RuntimeException("error in parsing \"" + s + "\"", e); } } @@ -201,11 +209,15 @@ public class PathParser { * the starting position of next number, whether it is ending with a '-'. */ private static void extract(String s, int start, ExtractFloatResult result) { - // Now looking for ' ', ',' or '-' from the start. + // Now looking for ' ', ',', '.' or '-' from the start. int currentIndex = start; boolean foundSeparator = false; - result.mEndWithNegSign = false; + result.mEndWithNegOrDot = false; + boolean secondDot = false; + boolean isExponential = false; for (; currentIndex < s.length(); currentIndex++) { + boolean isPrevExponential = isExponential; + isExponential = false; char currentChar = s.charAt(currentIndex); switch (currentChar) { case ' ': @@ -213,11 +225,25 @@ public class PathParser { foundSeparator = true; break; case '-': - if (currentIndex != start) { + // The negative sign following a 'e' or 'E' is not a separator. + if (currentIndex != start && !isPrevExponential) { foundSeparator = true; - result.mEndWithNegSign = true; + result.mEndWithNegOrDot = true; } break; + case '.': + if (!secondDot) { + secondDot = true; + } else { + // This is the second dot, and it is considered as a separator. + foundSeparator = true; + result.mEndWithNegOrDot = true; + } + break; + case 'e': + case 'E': + isExponential = true; + break; } if (foundSeparator) { break; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 1ecc8d9..8e58cd6 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -16617,8 +16617,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, invalidate(true); refreshDrawableState(); dispatchSetSelected(selected); - notifyViewAccessibilityStateChangedIfNeeded( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + if (selected) { + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + } else { + notifyViewAccessibilityStateChangedIfNeeded( + AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + } } } @@ -17414,17 +17418,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback, long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL; if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2); - if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT || - widthMeasureSpec != mOldWidthMeasureSpec || - heightMeasureSpec != mOldHeightMeasureSpec) { + final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT; + final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY && + MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY; + final boolean matchingSize = isExactly && + getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) && + getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec); + if (forceLayout || !matchingSize && + (widthMeasureSpec != mOldWidthMeasureSpec || + heightMeasureSpec != mOldHeightMeasureSpec)) { // first clears the measured dimension flag mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET; resolveRtlPropertiesIfNeeded(); - int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 : - mMeasureCache.indexOfKey(key); + int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key); if (cacheIndex < 0 || sIgnoreMeasureCache) { // measure ourselves, this should set the measured dimension flag back onMeasure(widthMeasureSpec, heightMeasureSpec); diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 4116b6b..7538dff 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -864,6 +864,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager if (siblingBounds.intersect(bounds)) { // If an interactive sibling completely covers the child, done. if (siblingBounds.equals(bounds)) { + if (orderedList != null) orderedList.clear(); return false; } // Keep track of the intersection rectangle. @@ -871,6 +872,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager intersections.add(intersection); } } + if (orderedList != null) orderedList.clear(); if (mParent instanceof ViewGroup) { ViewGroup parentGroup = (ViewGroup) mParent; @@ -3293,7 +3295,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager /** * Populates (and returns) mPreSortedChildren with a pre-ordered list of the View's children, - * sorted first by Z, then by child drawing order (if applicable). + * sorted first by Z, then by child drawing order (if applicable). This list must be cleared + * after use to avoid leaking child Views. * * Uses a stable, insertion sort which is commonly O(n) for ViewGroups with very few elevated * children. @@ -3668,6 +3671,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * @see #generateDefaultLayoutParams() */ public void addView(View child, int index) { + if (child == null) { + throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup"); + } LayoutParams params = child.getLayoutParams(); if (params == null) { params = generateDefaultLayoutParams(); @@ -3725,6 +3731,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager System.out.println(this + " addView"); } + if (child == null) { + throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup"); + } + // addViewInner() will call child.requestLayout() when setting the new LayoutParams // therefore, we call requestLayout() on ourselves before, so that the child's request // will be blocked at our level @@ -3852,6 +3862,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ protected boolean addViewInLayout(View child, int index, LayoutParams params, boolean preventRequestLayout) { + if (child == null) { + throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup"); + } child.mParent = null; addViewInner(child, index, params, preventRequestLayout); child.mPrivateFlags = (child.mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN; @@ -6488,7 +6501,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager */ public static class MarginLayoutParams extends ViewGroup.LayoutParams { /** - * The left margin in pixels of the child. + * The left margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6496,7 +6509,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public int leftMargin; /** - * The top margin in pixels of the child. + * The top margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6504,7 +6517,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public int topMargin; /** - * The right margin in pixels of the child. + * The right margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6512,7 +6525,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public int rightMargin; /** - * The bottom margin in pixels of the child. + * The bottom margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6520,7 +6533,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public int bottomMargin; /** - * The start margin in pixels of the child. + * The start margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6528,7 +6541,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager private int startMargin = DEFAULT_MARGIN_RELATIVE; /** - * The end margin in pixels of the child. + * The end margin in pixels of the child. Margin values should be positive. * Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value * to this field. */ @@ -6709,6 +6722,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Sets the margins, in pixels. A call to {@link android.view.View#requestLayout()} needs * to be done so that the new margins are taken into account. Left and right margins may be * overriden by {@link android.view.View#requestLayout()} depending on layout direction. + * Margin values should be positive. * * @param left the left margin size * @param top the top margin size @@ -6738,7 +6752,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager * Sets the relative margins, in pixels. A call to {@link android.view.View#requestLayout()} * needs to be done so that the new relative margins are taken into account. Left and right * margins may be overriden by {@link android.view.View#requestLayout()} depending on layout - * direction. + * direction. Margin values should be positive. * * @param start the start margin size * @param top the top margin size @@ -6761,7 +6775,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** - * Sets the relative start margin. + * Sets the relative start margin. Margin values should be positive. * * @param start the start margin size * @@ -6794,7 +6808,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** - * Sets the relative end margin. + * Sets the relative end margin. Margin values should be positive. * * @param end the end margin size * diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java index 10e56c7..5c05b5a 100644 --- a/core/java/android/widget/AppSecurityPermissions.java +++ b/core/java/android/widget/AppSecurityPermissions.java @@ -99,12 +99,12 @@ public class AppSecurityPermissions { public Drawable loadGroupIcon(PackageManager pm) { if (icon != 0) { - return loadIcon(pm); + return loadUnbadgedIcon(pm); } else { ApplicationInfo appInfo; try { appInfo = pm.getApplicationInfo(packageName, 0); - return appInfo.loadIcon(pm); + return appInfo.loadUnbadgedIcon(pm); } catch (NameNotFoundException e) { } } diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java index ea60abb..f380d68 100644 --- a/core/java/android/widget/CalendarView.java +++ b/core/java/android/widget/CalendarView.java @@ -775,9 +775,14 @@ public class CalendarView extends FrameLayout { private ViewGroup mDayNamesHeader; /** - * Cached labels for the week names header. + * Cached abbreviations for day of week names. */ - private String[] mDayLabels; + private String[] mDayNamesShort; + + /** + * Cached full-length day of week names. + */ + private String[] mDayNamesLong; /** * The first day of the week. @@ -1306,11 +1311,14 @@ public class CalendarView extends FrameLayout { * Sets up the strings to be used by the header. */ private void setUpHeader() { - mDayLabels = new String[mDaysPerWeek]; + mDayNamesShort = new String[mDaysPerWeek]; + mDayNamesLong = new String[mDaysPerWeek]; for (int i = mFirstDayOfWeek, count = mFirstDayOfWeek + mDaysPerWeek; i < count; i++) { int calendarDay = (i > Calendar.SATURDAY) ? i - Calendar.SATURDAY : i; - mDayLabels[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay, + mDayNamesShort[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay, DateUtils.LENGTH_SHORTEST); + mDayNamesLong[i - mFirstDayOfWeek] = DateUtils.getDayOfWeekString(calendarDay, + DateUtils.LENGTH_LONG); } TextView label = (TextView) mDayNamesHeader.getChildAt(0); @@ -1325,7 +1333,8 @@ public class CalendarView extends FrameLayout { label.setTextAppearance(mContext, mWeekDayTextAppearanceResId); } if (i < mDaysPerWeek + 1) { - label.setText(mDayLabels[i - 1]); + label.setText(mDayNamesShort[i - 1]); + label.setContentDescription(mDayNamesLong[i - 1]); label.setVisibility(View.VISIBLE); } else { label.setVisibility(View.GONE); diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java index 3c186e3..9f540c0 100644 --- a/core/java/android/widget/ListPopupWindow.java +++ b/core/java/android/widget/ListPopupWindow.java @@ -1639,6 +1639,11 @@ public class ListPopupWindow { setPressed(false); updateSelectorState(); + final View motionView = getChildAt(mMotionPosition - mFirstPosition); + if (motionView != null) { + motionView.setPressed(false); + } + if (mClickAnimation != null) { mClickAnimation.cancel(); mClickAnimation = null; @@ -1653,6 +1658,15 @@ public class ListPopupWindow { setPressed(true); layoutChildren(); + // Manage the pressed view based on motion position. This allows us to + // play nicely with actual touch and scroll events. + final View motionView = getChildAt(mMotionPosition - mFirstPosition); + if (motionView != null) { + motionView.setPressed(false); + } + mMotionPosition = position; + child.setPressed(true); + // Ensure that keyboard focus starts from the last touched position. setSelectedPositionInt(position); positionSelectorLikeTouch(position, child, x, y); diff --git a/core/java/android/widget/PopupMenu.java b/core/java/android/widget/PopupMenu.java index 111dadc..2708398 100644 --- a/core/java/android/widget/PopupMenu.java +++ b/core/java/android/widget/PopupMenu.java @@ -16,6 +16,7 @@ package android.widget; +import com.android.internal.R; import com.android.internal.view.menu.MenuBuilder; import com.android.internal.view.menu.MenuPopupHelper; import com.android.internal.view.menu.MenuPresenter; @@ -37,10 +38,11 @@ import android.widget.ListPopupWindow.ForwardingListener; * of the popup will dismiss it. */ public class PopupMenu implements MenuBuilder.Callback, MenuPresenter.Callback { - private Context mContext; - private MenuBuilder mMenu; - private View mAnchor; - private MenuPopupHelper mPopup; + private final Context mContext; + private final MenuBuilder mMenu; + private final View mAnchor; + private final MenuPopupHelper mPopup; + private OnMenuItemClickListener mMenuItemClickListener; private OnDismissListener mDismissListener; private OnTouchListener mDragListener; @@ -58,31 +60,56 @@ public class PopupMenu implements MenuBuilder.Callback, MenuPresenter.Callback { } /** - * Construct a new PopupMenu. + * Constructor to create a new popup menu with an anchor view. * - * @param context Context for the PopupMenu. - * @param anchor Anchor view for this popup. The popup will appear below the anchor if there - * is room, or above it if there is not. + * @param context Context the popup menu is running in, through which it + * can access the current theme, resources, etc. + * @param anchor Anchor view for this popup. The popup will appear below + * the anchor if there is room, or above it if there is not. */ public PopupMenu(Context context, View anchor) { this(context, anchor, Gravity.NO_GRAVITY); } /** - * Construct a new PopupMenu. + * Constructor to create a new popup menu with an anchor view and alignment + * gravity. * - * @param context Context for the PopupMenu. - * @param anchor Anchor view for this popup. The popup will appear below the anchor if there - * is room, or above it if there is not. - * @param gravity The {@link Gravity} value for aligning the popup with its anchor + * @param context Context the popup menu is running in, through which it + * can access the current theme, resources, etc. + * @param anchor Anchor view for this popup. The popup will appear below + * the anchor if there is room, or above it if there is not. + * @param gravity The {@link Gravity} value for aligning the popup with its + * anchor. */ public PopupMenu(Context context, View anchor, int gravity) { - // TODO Theme? + this(context, anchor, gravity, R.attr.popupMenuStyle, 0); + } + + /** + * Constructor a create a new popup menu with a specific style. + * + * @param context Context the popup menu is running in, through which it + * can access the current theme, resources, etc. + * @param anchor Anchor view for this popup. The popup will appear below + * the anchor if there is room, or above it if there is not. + * @param gravity The {@link Gravity} value for aligning the popup with its + * anchor. + * @param popupStyleAttr An attribute in the current theme that contains a + * reference to a style resource that supplies default values for + * the popup window. Can be 0 to not look for defaults. + * @param popupStyleRes A resource identifier of a style resource that + * supplies default values for the popup window, used only if + * popupStyleAttr is 0 or can not be found in the theme. Can be 0 + * to not look for defaults. + */ + public PopupMenu(Context context, View anchor, int gravity, int popupStyleAttr, + int popupStyleRes) { mContext = context; mMenu = new MenuBuilder(context); mMenu.setCallback(this); mAnchor = anchor; - mPopup = new MenuPopupHelper(context, mMenu, anchor); + mPopup = new MenuPopupHelper(context, mMenu, anchor, false, popupStyleAttr, popupStyleRes); mPopup.setGravity(gravity); mPopup.setCallback(this); } diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java index e9298c2..1c190c3 100644 --- a/core/java/android/widget/ProgressBar.java +++ b/core/java/android/widget/ProgressBar.java @@ -604,6 +604,7 @@ public class ProgressBar extends View { * @see #getIndeterminateTintList() * @see Drawable#setTintList(ColorStateList) */ + @RemotableViewMethod public void setIndeterminateTintList(@Nullable ColorStateList tint) { if (mProgressTintInfo == null) { mProgressTintInfo = new ProgressTintInfo(); @@ -842,6 +843,7 @@ public class ProgressBar extends View { * @see #getProgressTintList() * @see Drawable#setTintList(ColorStateList) */ + @RemotableViewMethod public void setProgressTintList(@Nullable ColorStateList tint) { if (mProgressTintInfo == null) { mProgressTintInfo = new ProgressTintInfo(); @@ -923,6 +925,7 @@ public class ProgressBar extends View { * @see #getProgressBackgroundTintList() * @see Drawable#setTintList(ColorStateList) */ + @RemotableViewMethod public void setProgressBackgroundTintList(@Nullable ColorStateList tint) { if (mProgressTintInfo == null) { mProgressTintInfo = new ProgressTintInfo(); diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 7cb3c37..80f364b 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -27,6 +27,7 @@ import android.content.Intent; import android.content.IntentSender; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Bitmap; @@ -1069,6 +1070,7 @@ public class RemoteViews implements Parcelable, Filter { static final int BITMAP = 12; static final int BUNDLE = 13; static final int INTENT = 14; + static final int COLOR_STATE_LIST = 15; String methodName; int type; @@ -1142,6 +1144,11 @@ public class RemoteViews implements Parcelable, Filter { this.value = Intent.CREATOR.createFromParcel(in); } break; + case COLOR_STATE_LIST: + if (in.readInt() != 0) { + this.value = ColorStateList.CREATOR.createFromParcel(in); + } + break; default: break; } @@ -1212,6 +1219,11 @@ public class RemoteViews implements Parcelable, Filter { ((Intent)this.value).writeToParcel(out, flags); } break; + case COLOR_STATE_LIST: + out.writeInt(this.value != null ? 1 : 0); + if (this.value != null) { + ((ColorStateList)this.value).writeToParcel(out, flags); + } default: break; } @@ -1247,6 +1259,8 @@ public class RemoteViews implements Parcelable, Filter { return Bundle.class; case INTENT: return Intent.class; + case COLOR_STATE_LIST: + return ColorStateList.class; default: return null; } @@ -2207,6 +2221,42 @@ public class RemoteViews implements Parcelable, Filter { } /** + * @hide + * Equivalent to calling {@link android.widget.ProgressBar#setProgressTintList}. + * + * @param viewId The id of the view whose tint should change + * @param tint the tint to apply, may be {@code null} to clear tint + */ + public void setProgressTintList(int viewId, ColorStateList tint) { + addAction(new ReflectionAction(viewId, "setProgressTintList", + ReflectionAction.COLOR_STATE_LIST, tint)); + } + + /** + * @hide + * Equivalent to calling {@link android.widget.ProgressBar#setProgressBackgroundTintList}. + * + * @param viewId The id of the view whose tint should change + * @param tint the tint to apply, may be {@code null} to clear tint + */ + public void setProgressBackgroundTintList(int viewId, ColorStateList tint) { + addAction(new ReflectionAction(viewId, "setProgressBackgroundTintList", + ReflectionAction.COLOR_STATE_LIST, tint)); + } + + /** + * @hide + * Equivalent to calling {@link android.widget.ProgressBar#setIndeterminateTintList}. + * + * @param viewId The id of the view whose tint should change + * @param tint the tint to apply, may be {@code null} to clear tint + */ + public void setProgressIndeterminateTintList(int viewId, ColorStateList tint) { + addAction(new ReflectionAction(viewId, "setIndeterminateTintList", + ReflectionAction.COLOR_STATE_LIST, tint)); + } + + /** * Equivalent to calling {@link android.widget.TextView#setTextColor(int)}. * * @param viewId The id of the view whose text color should change diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java index 1ce19ce..d8e39e3 100644 --- a/core/java/android/widget/Toolbar.java +++ b/core/java/android/widget/Toolbar.java @@ -66,7 +66,9 @@ import java.util.List; * <li><em>A navigation button.</em> This may be an Up arrow, navigation menu toggle, close, * collapse, done or another glyph of the app's choosing. This button should always be used * to access other navigational destinations within the container of the Toolbar and - * its signified content or otherwise leave the current context signified by the Toolbar.</li> + * its signified content or otherwise leave the current context signified by the Toolbar. + * The navigation button is vertically aligned within the Toolbar's + * {@link android.R.styleable#View_minHeight minimum height}, if set.</li> * <li><em>A branded logo image.</em> This may extend to the height of the bar and can be * arbitrarily wide.</li> * <li><em>A title and subtitle.</em> The title should be a signpost for the Toolbar's current @@ -82,8 +84,9 @@ import java.util.List; * <li><em>An {@link ActionMenuView action menu}.</em> The menu of actions will pin to the * end of the Toolbar offering a few * <a href="http://developer.android.com/design/patterns/actionbar.html#ActionButtons"> - * frequent, important or typical</a> actions along with an optional overflow menu for - * additional actions.</li> + * frequent, important or typical</a> actions along with an optional overflow menu for + * additional actions. Action buttons are vertically aligned within the Toolbar's + * {@link android.R.styleable#View_minHeight minimum height}, if set.</li> * </ul> * </p> * diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 0062e2d..b9cbc62 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -74,6 +74,9 @@ import java.util.List; import java.util.Map; import java.util.Set; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; +import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; + /** * This activity is displayed when the system attempts to start an Intent for * which there is more than one matching activity, allowing the user to decide @@ -269,6 +272,9 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic mListView = (ListView) findViewById(R.id.resolver_list); mListView.setVisibility(View.GONE); } + // Prevent the Resolver window from becoming the top fullscreen window and thus from taking + // control of the system bars. + getWindow().clearFlags(FLAG_LAYOUT_IN_SCREEN|FLAG_LAYOUT_INSET_DECOR); final ResolverDrawerLayout rdl = (ResolverDrawerLayout) findViewById(R.id.contentPanel); if (rdl != null) { @@ -819,6 +825,11 @@ public class ResolverActivity extends Activity implements AdapterView.OnItemClic } ResolveInfo ri = new ResolveInfo(); ri.activityInfo = ai; + UserManager userManager = + (UserManager) getSystemService(Context.USER_SERVICE); + if (userManager.isManagedProfile()) { + ri.noResourceId = true; + } if (ii instanceof LabeledIntent) { LabeledIntent li = (LabeledIntent)ii; ri.resolvePackageName = li.getSourcePackage(); diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java index 40f58e9..99bb1ac 100644 --- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java +++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java @@ -54,6 +54,7 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On private final boolean mOverflowOnly; private final int mPopupMaxWidth; private final int mPopupStyleAttr; + private final int mPopupStyleRes; private View mAnchorView; private ListPopupWindow mPopup; @@ -73,21 +74,27 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On private int mDropDownGravity = Gravity.NO_GRAVITY; public MenuPopupHelper(Context context, MenuBuilder menu) { - this(context, menu, null, false, com.android.internal.R.attr.popupMenuStyle); + this(context, menu, null, false, com.android.internal.R.attr.popupMenuStyle, 0); } public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) { - this(context, menu, anchorView, false, com.android.internal.R.attr.popupMenuStyle); + this(context, menu, anchorView, false, com.android.internal.R.attr.popupMenuStyle, 0); } public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView, boolean overflowOnly, int popupStyleAttr) { + this(context, menu, anchorView, overflowOnly, popupStyleAttr, 0); + } + + public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView, + boolean overflowOnly, int popupStyleAttr, int popupStyleRes) { mContext = context; mInflater = LayoutInflater.from(context); mMenu = menu; mAdapter = new MenuAdapter(mMenu); mOverflowOnly = overflowOnly; mPopupStyleAttr = popupStyleAttr; + mPopupStyleRes = popupStyleRes; final Resources res = context.getResources(); mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2, @@ -122,7 +129,7 @@ public class MenuPopupHelper implements AdapterView.OnItemClickListener, View.On } public boolean tryShow() { - mPopup = new ListPopupWindow(mContext, null, mPopupStyleAttr); + mPopup = new ListPopupWindow(mContext, null, mPopupStyleAttr, mPopupStyleRes); mPopup.setOnDismissListener(this); mPopup.setOnItemClickListener(this); mPopup.setAdapter(mAdapter); diff --git a/core/java/com/android/internal/widget/ExploreByTouchHelper.java b/core/java/com/android/internal/widget/ExploreByTouchHelper.java index 11c4ca1..4689179 100644 --- a/core/java/com/android/internal/widget/ExploreByTouchHelper.java +++ b/core/java/com/android/internal/widget/ExploreByTouchHelper.java @@ -54,6 +54,10 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { /** Default class name used for virtual views. */ private static final String DEFAULT_CLASS_NAME = View.class.getName(); + /** Default bounds used to determine if the client didn't set any. */ + private static final Rect INVALID_PARENT_BOUNDS = new Rect( + Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); + // Temporary, reusable data structures. private final Rect mTempScreenRect = new Rect(); private final Rect mTempParentRect = new Rect(); @@ -372,6 +376,7 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { // Ensure the client has good defaults. node.setEnabled(true); node.setClassName(DEFAULT_CLASS_NAME); + node.setBoundsInParent(INVALID_PARENT_BOUNDS); // Allow the client to populate the node. onPopulateNodeForVirtualView(virtualViewId, node); @@ -383,7 +388,7 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate { } node.getBoundsInParent(mTempParentRect); - if (mTempParentRect.isEmpty()) { + if (mTempParentRect.equals(INVALID_PARENT_BOUNDS)) { throw new RuntimeException("Callbacks must set parent bounds in " + "populateNodeForVirtualViewId()"); } |
