Merge "Add Settings theme, fix DialogWhenLarge theme" into lmp-preview-dev
diff --git a/api/current.txt b/api/current.txt
index 59ee01a..52b6de3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16019,46 +16019,34 @@
field public int serverAddress;
}
- public class LinkAddress implements android.os.Parcelable {
+ public final class IpPrefix implements android.os.Parcelable {
method public int describeContents();
method public java.net.InetAddress getAddress();
- method public int getFlags();
- method public int getNetworkPrefixLength();
- method public int getScope();
- method public boolean isSameAddressAs(android.net.LinkAddress);
- method public void writeToParcel(android.os.Parcel, int);
- }
-
- public class LinkProperties implements android.os.Parcelable {
- ctor public LinkProperties();
- ctor public LinkProperties(android.net.LinkProperties);
- method public void addDns(java.net.InetAddress);
- method public boolean addLinkAddress(android.net.LinkAddress);
- method public void addRoute(android.net.RouteInfo);
- method public void clear();
- method public int describeContents();
- method public java.util.Collection<java.lang.String> getAllInterfaceNames();
- method public java.util.Collection<java.net.InetAddress> getDnses();
- method public java.lang.String getDomains();
- method public android.net.ProxyInfo getHttpProxy();
- method public java.lang.String getInterfaceName();
- method public java.util.Collection<android.net.LinkAddress> getLinkAddresses();
- method public java.util.Collection<android.net.RouteInfo> getRoutes();
- method public boolean hasIPv4Address();
- method public boolean hasIPv6Address();
- method public boolean removeLinkAddress(android.net.LinkAddress);
- method public void setDomains(java.lang.String);
- method public void setHttpProxy(android.net.ProxyInfo);
- method public void setInterfaceName(java.lang.String);
- method public void setLinkAddresses(java.util.Collection<android.net.LinkAddress>);
+ method public int getPrefixLength();
+ method public byte[] getRawAddress();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
- public static class LinkProperties.CompareResult {
- ctor public LinkProperties.CompareResult();
- field public java.util.Collection added;
- field public java.util.Collection removed;
+ public class LinkAddress implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.net.InetAddress getAddress();
+ method public int getFlags();
+ method public int getPrefixLength();
+ method public int getScope();
+ method public void writeToParcel(android.os.Parcel, int);
+ }
+
+ public final class LinkProperties implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.util.List<java.net.InetAddress> getDnsServers();
+ method public java.lang.String getDomains();
+ method public android.net.ProxyInfo getHttpProxy();
+ method public java.lang.String getInterfaceName();
+ method public java.util.List<android.net.LinkAddress> getLinkAddresses();
+ method public java.util.List<android.net.RouteInfo> getRoutes();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
}
public class LocalServerSocket {
@@ -16139,21 +16127,12 @@
}
public final class NetworkCapabilities implements android.os.Parcelable {
- ctor public NetworkCapabilities();
ctor public NetworkCapabilities(android.net.NetworkCapabilities);
- method public void addNetworkCapability(int);
- method public void addTransportType(int);
method public int describeContents();
method public int getLinkDownstreamBandwidthKbps();
method public int getLinkUpstreamBandwidthKbps();
- method public java.util.Collection<java.lang.Integer> getNetworkCapabilities();
- method public java.util.Collection<java.lang.Integer> getTransportTypes();
method public boolean hasCapability(int);
method public boolean hasTransport(int);
- method public void removeNetworkCapability(int);
- method public void removeTransportType(int);
- method public void setLinkDownstreamBandwidthKbps(int);
- method public void setLinkUpstreamBandwidthKbps(int);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int NET_CAPABILITY_CBS = 5; // 0x5
@@ -16227,7 +16206,15 @@
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
- field public final android.net.NetworkCapabilities networkCapabilities;
+ }
+
+ public static class NetworkRequest.Builder {
+ ctor public NetworkRequest.Builder();
+ method public android.net.NetworkRequest.Builder addCapability(int);
+ method public android.net.NetworkRequest.Builder addTransportType(int);
+ method public android.net.NetworkRequest build();
+ method public android.net.NetworkRequest.Builder removeCapability(int);
+ method public android.net.NetworkRequest.Builder removeTransportType(int);
}
public class ParseException extends java.lang.RuntimeException {
@@ -16256,18 +16243,15 @@
method public void writeToParcel(android.os.Parcel, int);
}
- public class RouteInfo implements android.os.Parcelable {
- ctor public RouteInfo(android.net.LinkAddress, java.net.InetAddress, java.lang.String);
- ctor public RouteInfo(android.net.LinkAddress, java.net.InetAddress);
- ctor public RouteInfo(java.net.InetAddress);
- ctor public RouteInfo(android.net.LinkAddress);
+ public final class RouteInfo implements android.os.Parcelable {
method public int describeContents();
- method public android.net.LinkAddress getDestination();
+ method public android.net.IpPrefix getDestination();
method public java.net.InetAddress getGateway();
method public java.lang.String getInterface();
method public boolean isDefaultRoute();
method public boolean matches(java.net.InetAddress);
method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator CREATOR;
}
public class SSLCertificateSocketFactory extends javax.net.ssl.SSLSocketFactory {
@@ -25831,21 +25815,28 @@
method public final void cancelNotification(java.lang.String);
method public final void cancelNotifications(java.lang.String[]);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
- method public android.service.notification.NotificationListenerService.Ranking getCurrentRanking();
+ method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
method public android.os.IBinder onBind(android.content.Intent);
method public void onListenerConnected();
- method public abstract void onNotificationPosted(android.service.notification.StatusBarNotification);
- method public void onNotificationRankingUpdate();
- method public abstract void onNotificationRemoved(android.service.notification.StatusBarNotification);
+ method public void onNotificationPosted(android.service.notification.StatusBarNotification);
+ method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
+ method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
+ method public void onNotificationRemoved(android.service.notification.StatusBarNotification);
+ method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
}
- public static class NotificationListenerService.Ranking implements android.os.Parcelable {
+ public static class NotificationListenerService.Ranking {
+ method public java.lang.String getKey();
+ method public int getRank();
+ method public boolean isAmbient();
+ method public boolean isInterceptedByDoNotDisturb();
+ }
+
+ public static class NotificationListenerService.RankingMap implements android.os.Parcelable {
method public int describeContents();
method public java.lang.String[] getOrderedKeys();
- method public int getRank(java.lang.String);
- method public boolean isAmbient(java.lang.String);
- method public boolean isInterceptedByDoNotDisturb(java.lang.String);
+ method public android.service.notification.NotificationListenerService.Ranking getRanking(java.lang.String);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator CREATOR;
}
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index 85e970c..0d947217 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -293,7 +293,7 @@
IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
IVoiceInteractorCallback callback) throws RemoteException {
- return interactor.startConfirmation(packageName, callback, mCommand, mArgs);
+ return interactor.startCommand(packageName, callback, mCommand, mArgs);
}
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index ff56720..9eea545 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -30,7 +30,7 @@
*
* <p>These properties are fixed for a given CameraDevice, and can be queried
* through the {@link CameraManager CameraManager}
- * interface in addition to through the CameraDevice interface.</p>
+ * interface with {@link CameraManager#getCameraCharacteristics}.</p>
*
* <p>{@link CameraCharacteristics} objects are immutable.</p>
*
@@ -555,7 +555,7 @@
* <p>List containing a subset of the optical image
* stabilization (OIS) modes specified in
* {@link CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE android.lens.opticalStabilizationMode}.</p>
- * <p>If OIS is not implemented for a given camera device, this should
+ * <p>If OIS is not implemented for a given camera device, this will
* contain only OFF.</p>
*
* @see CaptureRequest#LENS_OPTICAL_STABILIZATION_MODE
@@ -612,7 +612,7 @@
/**
* <p>Direction the camera faces relative to
- * device screen</p>
+ * device screen.</p>
* @see #LENS_FACING_FRONT
* @see #LENS_FACING_BACK
*/
@@ -622,7 +622,7 @@
/**
* <p>The set of noise reduction modes supported by this camera device.</p>
* <p>This tag lists the valid modes for {@link CaptureRequest#NOISE_REDUCTION_MODE android.noiseReduction.mode}.</p>
- * <p>Full-capability camera devices must laways support OFF and FAST.</p>
+ * <p>Full-capability camera devices must always support OFF and FAST.</p>
*
* @see CaptureRequest#NOISE_REDUCTION_MODE
*/
@@ -778,18 +778,20 @@
new Key<Byte>("android.request.pipelineMaxDepth", byte.class);
/**
- * <p>Optional. Defaults to 1. Defines how many sub-components
+ * <p>Defines how many sub-components
* a result will be composed of.</p>
* <p>In order to combat the pipeline latency, partial results
* may be delivered to the application layer from the camera device as
* soon as they are available.</p>
- * <p>A value of 1 means that partial results are not supported.</p>
+ * <p>Optional; defaults to 1. A value of 1 means that partial
+ * results are not supported, and only the final TotalCaptureResult will
+ * be produced by the camera device.</p>
* <p>A typical use case for this might be: after requesting an
* auto-focus (AF) lock the new AF state might be available 50%
* of the way through the pipeline. The camera device could
* then immediately dispatch this state via a partial result to
- * the framework/application layer, and the rest of the
- * metadata via later partial results.</p>
+ * the application, and the rest of the metadata via later
+ * partial results.</p>
*/
public static final Key<Integer> REQUEST_PARTIAL_RESULT_COUNT =
new Key<Integer>("android.request.partialResultCount", int.class);
@@ -806,8 +808,6 @@
* to do this query each of android.request.availableRequestKeys,
* android.request.availableResultKeys,
* android.request.availableCharacteristicsKeys.</p>
- * <p>XX: Maybe these should go into {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel}
- * as a table instead?</p>
* <p>The following capabilities are guaranteed to be available on
* {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} <code>==</code> FULL devices:</p>
* <ul>
@@ -815,14 +815,11 @@
* <li>MANUAL_POST_PROCESSING</li>
* </ul>
* <p>Other capabilities may be available on either FULL or LIMITED
- * devices, but the app. should query this field to be sure.</p>
+ * devices, but the application should query this field to be sure.</p>
*
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
- * @see #REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
- * @see #REQUEST_AVAILABLE_CAPABILITIES_OPTIONAL
* @see #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR
* @see #REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING
- * @see #REQUEST_AVAILABLE_CAPABILITIES_ZSL
* @see #REQUEST_AVAILABLE_CAPABILITIES_DNG
*/
public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES =
@@ -838,7 +835,6 @@
* at a more granular level than capabilities. This is especially
* important for optional keys that are not listed under any capability
* in {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}.</p>
- * <p>TODO: This should be used by #getAvailableCaptureRequestKeys.</p>
*
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
* @hide
@@ -863,7 +859,6 @@
* at a more granular level than capabilities. This is especially
* important for optional keys that are not listed under any capability
* in {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}.</p>
- * <p>TODO: This should be used by #getAvailableCaptureResultKeys.</p>
*
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
* @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
@@ -879,7 +874,6 @@
* android.request.availableResultKeys (except that it applies for
* CameraCharacteristics instead of CaptureResult). See above for more
* details.</p>
- * <p>TODO: This should be used by CameraCharacteristics#getKeys.</p>
* @hide
*/
public static final Key<int[]> REQUEST_AVAILABLE_CHARACTERISTICS_KEYS =
@@ -927,10 +921,15 @@
new Key<android.util.Size[]>("android.scaler.availableJpegSizes", android.util.Size[].class);
/**
- * <p>The maximum ratio between active area width
- * and crop region width, or between active area height and
- * crop region height, if the crop region height is larger
- * than width</p>
+ * <p>The maximum ratio between both active area width
+ * and crop region width, and active area height and
+ * crop region height.</p>
+ * <p>This represents the maximum amount of zooming possible by
+ * the camera device, or equivalently, the minimum cropping
+ * window size.</p>
+ * <p>Crop regions that have a width or height that is smaller
+ * than this ratio allows will be rounded up to the minimum
+ * allowed size by the camera device.</p>
*/
public static final Key<Float> SCALER_AVAILABLE_MAX_DIGITAL_ZOOM =
new Key<Float>("android.scaler.availableMaxDigitalZoom", float.class);
@@ -1339,9 +1338,9 @@
new Key<android.util.Range<Integer>>("android.sensor.info.sensitivityRange", new TypeReference<android.util.Range<Integer>>() {{ }});
/**
- * <p>Arrangement of color filters on sensor;
+ * <p>The arrangement of color filters on sensor;
* represents the colors in the top-left 2x2 section of
- * the sensor, in reading order</p>
+ * the sensor, in reading order.</p>
* @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB
* @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG
* @see #SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG
@@ -1666,10 +1665,9 @@
new Key<int[]>("android.sensor.availableTestPatternModes", int[].class);
/**
- * <p>Which face detection modes are available,
- * if any.</p>
- * <p>OFF means face detection is disabled, it must
- * be included in the list.</p>
+ * <p>The face detection modes that are available
+ * for this camera device.</p>
+ * <p>OFF is always supported.</p>
* <p>SIMPLE means the device supports the
* android.statistics.faceRectangles and
* android.statistics.faceScores outputs.</p>
@@ -1681,8 +1679,8 @@
new Key<int[]>("android.statistics.info.availableFaceDetectModes", int[].class);
/**
- * <p>Maximum number of simultaneously detectable
- * faces</p>
+ * <p>The maximum number of simultaneously detectable
+ * faces.</p>
*/
public static final Key<Integer> STATISTICS_INFO_MAX_FACE_COUNT =
new Key<Integer>("android.statistics.info.maxFaceCount", int.class);
@@ -1691,7 +1689,7 @@
* <p>The set of hot pixel map output modes supported by this camera device.</p>
* <p>This tag lists valid output modes for {@link CaptureRequest#STATISTICS_HOT_PIXEL_MAP_MODE android.statistics.hotPixelMapMode}.</p>
* <p>If no hotpixel map is available for this camera device, this will contain
- * only OFF. If the hotpixel map is available, this should include both
+ * only OFF. If the hotpixel map is available, this will include both
* the ON and OFF options.</p>
*
* @see CaptureRequest#STATISTICS_HOT_PIXEL_MAP_MODE
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 90e5e4e..33e1915 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -157,8 +157,8 @@
/**
* <p>The lens focus distance is not accurate, and the units used for
- * {@link CaptureRequest#LENS_FOCUS_DISTANCE android.lens.focusDistance} do not correspond to any physical units.
- * Setting the lens to the same focus distance on separate occasions may
+ * {@link CaptureRequest#LENS_FOCUS_DISTANCE android.lens.focusDistance} do not correspond to any physical units.</p>
+ * <p>Setting the lens to the same focus distance on separate occasions may
* result in a different real focus distance, depending on factors such
* as the orientation of the device, the age of the focusing mechanism,
* and the device temperature. The focus distance value will still be
@@ -172,20 +172,24 @@
public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED = 0;
/**
- * <p>The lens focus distance is measured in diopters. However, setting the lens
- * to the same focus distance on separate occasions may result in a
- * different real focus distance, depending on factors such as the
- * orientation of the device, the age of the focusing mechanism, and
- * the device temperature.</p>
+ * <p>The lens focus distance is measured in diopters.</p>
+ * <p>However, setting the lens to the same focus distance
+ * on separate occasions may result in a different real
+ * focus distance, depending on factors such as the
+ * orientation of the device, the age of the focusing
+ * mechanism, and the device temperature.</p>
* @see CameraCharacteristics#LENS_INFO_FOCUS_DISTANCE_CALIBRATION
*/
public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE = 1;
/**
- * <p>The lens focus distance is measured in diopters. The lens mechanism is
- * calibrated so that setting the same focus distance is repeatable on
- * multiple occasions with good accuracy, and the focus distance corresponds
- * to the real physical distance to the plane of best focus.</p>
+ * <p>The lens focus distance is measured in diopters, and
+ * is calibrated.</p>
+ * <p>The lens mechanism is calibrated so that setting the
+ * same focus distance is repeatable on multiple
+ * occasions with good accuracy, and the focus distance
+ * corresponds to the real physical distance to the plane
+ * of best focus.</p>
* @see CameraCharacteristics#LENS_INFO_FOCUS_DISTANCE_CALIBRATION
*/
public static final int LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED = 2;
@@ -195,11 +199,13 @@
//
/**
+ * <p>The camera device faces the same direction as the device's screen.</p>
* @see CameraCharacteristics#LENS_FACING
*/
public static final int LENS_FACING_FRONT = 0;
/**
+ * <p>The camera device faces the opposite direction as the device's screen.</p>
* @see CameraCharacteristics#LENS_FACING
*/
public static final int LENS_FACING_BACK = 1;
@@ -215,11 +221,10 @@
* <p>The full set of features supported by this capability makes
* the camera2 api backwards compatible with the camera1
* (android.hardware.Camera) API.</p>
- * <p>TODO: @hide this. Doesn't really mean anything except
- * act as a catch-all for all the 'base' functionality.</p>
*
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ * @hide
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0;
@@ -228,15 +233,14 @@
* tags or functionality not encapsulated by one of the other
* capabilities.</p>
* <p>A typical example is all tags marked 'optional'.</p>
- * <p>TODO: @hide. We may not need this if we @hide all the optional
- * tags not belonging to a capability.</p>
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ * @hide
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_OPTIONAL = 1;
/**
* <p>The camera device can be manually controlled (3A algorithms such
- * as auto exposure, and auto focus can be bypassed).
+ * as auto-exposure, and auto-focus can be bypassed).
* The camera device supports basic manual control of the sensor image
* acquisition related stages. This means the following controls are
* guaranteed to be supported:</p>
@@ -257,11 +261,11 @@
* <li>{@link CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE android.sensor.info.sensitivityRange}</li>
* </ul>
* </li>
- * <li>Manual lens control<ul>
+ * <li>Manual lens control (if the lens is adjustable)<ul>
* <li>android.lens.*</li>
* </ul>
* </li>
- * <li>Manual flash control<ul>
+ * <li>Manual flash control (if a flash unit is present)<ul>
* <li>android.flash.*</li>
* </ul>
* </li>
@@ -312,8 +316,6 @@
* </ul>
* <p>If auto white balance is enabled, then the camera device
* will accurately report the values applied by AWB in the result.</p>
- * <p>The camera device will also support everything in MANUAL_SENSOR
- * except manual lens control and manual flash control.</p>
* <p>A given camera device may also support additional post-processing
* controls, but this capability only covers the above list of controls.</p>
*
@@ -340,8 +342,8 @@
* (both input/output) will match the maximum available
* resolution of JPEG streams.</li>
* </ul>
- * <p>@hide this, TODO: remove it when input related APIs are ready.</p>
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ * @hide
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_ZSL = 4;
@@ -355,7 +357,7 @@
* <li>RAW16 is reprocessable into both YUV_420_888 and JPEG
* formats.</li>
* <li>The maximum available resolution for RAW16 streams (both
- * input/output) will match the either value in
+ * input/output) will match either the value in
* {@link CameraCharacteristics#SENSOR_INFO_PIXEL_ARRAY_SIZE android.sensor.info.pixelArraySize} or
* {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}.</li>
* <li>All DNG-related optional metadata entries are provided
@@ -373,13 +375,13 @@
//
/**
- * <p>The camera device will only support centered crop regions.</p>
+ * <p>The camera device only supports centered crop regions.</p>
* @see CameraCharacteristics#SCALER_CROPPING_TYPE
*/
public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0;
/**
- * <p>The camera device will support arbitrarily chosen crop regions.</p>
+ * <p>The camera device supports arbitrarily chosen crop regions.</p>
* @see CameraCharacteristics#SCALER_CROPPING_TYPE
*/
public static final int SCALER_CROPPING_TYPE_FREEFORM = 1;
@@ -525,7 +527,7 @@
//
/**
- * <p>android.led.transmit control is used</p>
+ * <p>android.led.transmit control is used.</p>
* @see CameraCharacteristics#LED_AVAILABLE_LEDS
* @hide
*/
@@ -536,11 +538,14 @@
//
/**
+ * <p>This camera device has only limited capabilities.</p>
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
*/
public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0;
/**
+ * <p>This camera device is capable of supporting advanced imaging
+ * applications.</p>
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
*/
public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1;
@@ -550,9 +555,9 @@
//
/**
- * <p>Every frame has the requests immediately applied.
- * (and furthermore for all results,
- * <code>android.sync.frameNumber == android.request.frameCount</code>)</p>
+ * <p>Every frame has the requests immediately applied.</p>
+ * <p>Furthermore for all results,
+ * <code>android.sync.frameNumber == android.request.frameCount</code></p>
* <p>Changing controls over multiple requests one after another will
* produce results that have those controls applied atomically
* each frame.</p>
@@ -592,8 +597,8 @@
public static final int COLOR_CORRECTION_MODE_TRANSFORM_MATRIX = 0;
/**
- * <p>Must not slow down capture rate relative to sensor raw
- * output.</p>
+ * <p>Color correction processing must not slow down
+ * capture rate relative to sensor raw output.</p>
* <p>Advanced white balance adjustments above and beyond
* the specified white balance pipeline may be applied.</p>
* <p>If AWB is enabled with <code>{@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} != OFF</code>, then
@@ -606,8 +611,9 @@
public static final int COLOR_CORRECTION_MODE_FAST = 1;
/**
- * <p>Capture rate (relative to sensor raw output)
- * may be reduced by high quality.</p>
+ * <p>Color correction processing operates at improved
+ * quality but reduced capture rate (relative to sensor raw
+ * output).</p>
* <p>Advanced white balance adjustments above and beyond
* the specified white balance pipeline may be applied.</p>
* <p>If AWB is enabled with <code>{@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} != OFF</code>, then
@@ -658,8 +664,8 @@
//
/**
- * <p>The camera device's autoexposure routine is disabled;
- * the application-selected {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime},
+ * <p>The camera device's autoexposure routine is disabled.</p>
+ * <p>The application-selected {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime},
* {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity} and
* {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} are used by the camera
* device, along with android.flash.* fields, if there's
@@ -674,7 +680,8 @@
/**
* <p>The camera device's autoexposure routine is active,
- * with no flash control. The application's values for
+ * with no flash control.</p>
+ * <p>The application's values for
* {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime},
* {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}, and
* {@link CaptureRequest#SENSOR_FRAME_DURATION android.sensor.frameDuration} are ignored. The
@@ -691,10 +698,10 @@
/**
* <p>Like ON, except that the camera device also controls
* the camera's flash unit, firing it in low-light
- * conditions. The flash may be fired during a
- * precapture sequence (triggered by
- * {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}) and may be fired
- * for captures for which the
+ * conditions.</p>
+ * <p>The flash may be fired during a precapture sequence
+ * (triggered by {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}) and
+ * may be fired for captures for which the
* {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} field is set to
* STILL_CAPTURE</p>
*
@@ -707,10 +714,10 @@
/**
* <p>Like ON, except that the camera device also controls
* the camera's flash unit, always firing it for still
- * captures. The flash may be fired during a precapture
- * sequence (triggered by
- * {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}) and will always
- * be fired for captures for which the
+ * captures.</p>
+ * <p>The flash may be fired during a precapture sequence
+ * (triggered by {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger}) and
+ * will always be fired for captures for which the
* {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} field is set to
* STILL_CAPTURE</p>
*
@@ -722,9 +729,10 @@
/**
* <p>Like ON_AUTO_FLASH, but with automatic red eye
- * reduction. If deemed necessary by the camera device,
- * a red eye reduction flash will fire during the
- * precapture sequence.</p>
+ * reduction.</p>
+ * <p>If deemed necessary by the camera device, a red eye
+ * reduction flash will fire during the precapture
+ * sequence.</p>
* @see CaptureRequest#CONTROL_AE_MODE
*/
public static final int CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE = 4;
@@ -741,8 +749,9 @@
/**
* <p>The precapture metering sequence will be started
- * by the camera device. The exact effect of the precapture
- * trigger depends on the current AE mode and state.</p>
+ * by the camera device.</p>
+ * <p>The exact effect of the precapture trigger depends on
+ * the current AE mode and state.</p>
* @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
*/
public static final int CONTROL_AE_PRECAPTURE_TRIGGER_START = 1;
@@ -754,7 +763,7 @@
/**
* <p>The auto-focus routine does not control the lens;
* {@link CaptureRequest#LENS_FOCUS_DISTANCE android.lens.focusDistance} is controlled by the
- * application</p>
+ * application.</p>
*
* @see CaptureRequest#LENS_FOCUS_DISTANCE
* @see CaptureRequest#CONTROL_AF_MODE
@@ -839,8 +848,11 @@
public static final int CONTROL_AF_MODE_CONTINUOUS_PICTURE = 4;
/**
- * <p>Extended depth of field (digital focus). AF
- * trigger is ignored, AF state should always be
+ * <p>Extended depth of field (digital focus) mode.</p>
+ * <p>The camera device will produce images with an extended
+ * depth of field automatically; no special focusing
+ * operations need to be done before taking a picture.</p>
+ * <p>AF triggers are ignored, and the AF state will always be
* INACTIVE.</p>
* @see CaptureRequest#CONTROL_AF_MODE
*/
@@ -874,8 +886,8 @@
//
/**
- * <p>The camera device's auto white balance routine is disabled;
- * the application-selected color transform matrix
+ * <p>The camera device's auto-white balance routine is disabled.</p>
+ * <p>The application-selected color transform matrix
* ({@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}) and gains
* ({@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}) are used by the camera
* device for manual white balance control.</p>
@@ -887,9 +899,12 @@
public static final int CONTROL_AWB_MODE_OFF = 0;
/**
- * <p>The camera device's auto white balance routine is active;
- * the application's values for {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}
- * and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} are ignored.</p>
+ * <p>The camera device's auto-white balance routine is active.</p>
+ * <p>The application's values for {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}
+ * and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} are ignored.
+ * For devices that support the MANUAL_POST_PROCESSING capability, the
+ * values used by the camera device for the transform and gains
+ * will be available in the capture result for this request.</p>
*
* @see CaptureRequest#COLOR_CORRECTION_GAINS
* @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
@@ -898,65 +913,125 @@
public static final int CONTROL_AWB_MODE_AUTO = 1;
/**
- * <p>The camera device's auto white balance routine is disabled;
+ * <p>The camera device's auto-white balance routine is disabled;
* the camera device uses incandescent light as the assumed scene
- * illumination for white balance. While the exact white balance
- * transforms are up to the camera device, they will approximately
- * match the CIE standard illuminant A.</p>
+ * illumination for white balance.</p>
+ * <p>While the exact white balance transforms are up to the
+ * camera device, they will approximately match the CIE
+ * standard illuminant A.</p>
+ * <p>The application's values for {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}
+ * and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} are ignored.
+ * For devices that support the MANUAL_POST_PROCESSING capability, the
+ * values used by the camera device for the transform and gains
+ * will be available in the capture result for this request.</p>
+ *
+ * @see CaptureRequest#COLOR_CORRECTION_GAINS
+ * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
* @see CaptureRequest#CONTROL_AWB_MODE
*/
public static final int CONTROL_AWB_MODE_INCANDESCENT = 2;
/**
- * <p>The camera device's auto white balance routine is disabled;
+ * <p>The camera device's auto-white balance routine is disabled;
* the camera device uses fluorescent light as the assumed scene
- * illumination for white balance. While the exact white balance
- * transforms are up to the camera device, they will approximately
- * match the CIE standard illuminant F2.</p>
+ * illumination for white balance.</p>
+ * <p>While the exact white balance transforms are up to the
+ * camera device, they will approximately match the CIE
+ * standard illuminant F2.</p>
+ * <p>The application's values for {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}
+ * and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} are ignored.
+ * For devices that support the MANUAL_POST_PROCESSING capability, the
+ * values used by the camera device for the transform and gains
+ * will be available in the capture result for this request.</p>
+ *
+ * @see CaptureRequest#COLOR_CORRECTION_GAINS
+ * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
* @see CaptureRequest#CONTROL_AWB_MODE
*/
public static final int CONTROL_AWB_MODE_FLUORESCENT = 3;
/**
- * <p>The camera device's auto white balance routine is disabled;
+ * <p>The camera device's auto-white balance routine is disabled;
* the camera device uses warm fluorescent light as the assumed scene
- * illumination for white balance. While the exact white balance
- * transforms are up to the camera device, they will approximately
- * match the CIE standard illuminant F4.</p>
+ * illumination for white balance.</p>
+ * <p>While the exact white balance transforms are up to the
+ * camera device, they will approximately match the CIE
+ * standard illuminant F4.</p>
+ * <p>The application's values for {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}
+ * and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} are ignored.
+ * For devices that support the MANUAL_POST_PROCESSING capability, the
+ * values used by the camera device for the transform and gains
+ * will be available in the capture result for this request.</p>
+ *
+ * @see CaptureRequest#COLOR_CORRECTION_GAINS
+ * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
* @see CaptureRequest#CONTROL_AWB_MODE
*/
public static final int CONTROL_AWB_MODE_WARM_FLUORESCENT = 4;
/**
- * <p>The camera device's auto white balance routine is disabled;
+ * <p>The camera device's auto-white balance routine is disabled;
* the camera device uses daylight light as the assumed scene
- * illumination for white balance. While the exact white balance
- * transforms are up to the camera device, they will approximately
- * match the CIE standard illuminant D65.</p>
+ * illumination for white balance.</p>
+ * <p>While the exact white balance transforms are up to the
+ * camera device, they will approximately match the CIE
+ * standard illuminant D65.</p>
+ * <p>The application's values for {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}
+ * and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} are ignored.
+ * For devices that support the MANUAL_POST_PROCESSING capability, the
+ * values used by the camera device for the transform and gains
+ * will be available in the capture result for this request.</p>
+ *
+ * @see CaptureRequest#COLOR_CORRECTION_GAINS
+ * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
* @see CaptureRequest#CONTROL_AWB_MODE
*/
public static final int CONTROL_AWB_MODE_DAYLIGHT = 5;
/**
- * <p>The camera device's auto white balance routine is disabled;
+ * <p>The camera device's auto-white balance routine is disabled;
* the camera device uses cloudy daylight light as the assumed scene
* illumination for white balance.</p>
+ * <p>The application's values for {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}
+ * and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} are ignored.
+ * For devices that support the MANUAL_POST_PROCESSING capability, the
+ * values used by the camera device for the transform and gains
+ * will be available in the capture result for this request.</p>
+ *
+ * @see CaptureRequest#COLOR_CORRECTION_GAINS
+ * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
* @see CaptureRequest#CONTROL_AWB_MODE
*/
public static final int CONTROL_AWB_MODE_CLOUDY_DAYLIGHT = 6;
/**
- * <p>The camera device's auto white balance routine is disabled;
+ * <p>The camera device's auto-white balance routine is disabled;
* the camera device uses twilight light as the assumed scene
* illumination for white balance.</p>
+ * <p>The application's values for {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}
+ * and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} are ignored.
+ * For devices that support the MANUAL_POST_PROCESSING capability, the
+ * values used by the camera device for the transform and gains
+ * will be available in the capture result for this request.</p>
+ *
+ * @see CaptureRequest#COLOR_CORRECTION_GAINS
+ * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
* @see CaptureRequest#CONTROL_AWB_MODE
*/
public static final int CONTROL_AWB_MODE_TWILIGHT = 7;
/**
- * <p>The camera device's auto white balance routine is disabled;
+ * <p>The camera device's auto-white balance routine is disabled;
* the camera device uses shade light as the assumed scene
* illumination for white balance.</p>
+ * <p>The application's values for {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}
+ * and {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} are ignored.
+ * For devices that support the MANUAL_POST_PROCESSING capability, the
+ * values used by the camera device for the transform and gains
+ * will be available in the capture result for this request.</p>
+ *
+ * @see CaptureRequest#COLOR_CORRECTION_GAINS
+ * @see CaptureRequest#COLOR_CORRECTION_TRANSFORM
* @see CaptureRequest#CONTROL_AWB_MODE
*/
public static final int CONTROL_AWB_MODE_SHADE = 8;
@@ -966,38 +1041,43 @@
//
/**
- * <p>This request doesn't fall into the other
- * categories. Default to preview-like
+ * <p>The goal of this request doesn't fall into the other
+ * categories. The camera device will default to preview-like
* behavior.</p>
* @see CaptureRequest#CONTROL_CAPTURE_INTENT
*/
public static final int CONTROL_CAPTURE_INTENT_CUSTOM = 0;
/**
- * <p>This request is for a preview-like usecase. The
- * precapture trigger may be used to start off a metering
- * w/flash sequence</p>
+ * <p>This request is for a preview-like use case.</p>
+ * <p>The precapture trigger may be used to start off a metering
+ * w/flash sequence.</p>
* @see CaptureRequest#CONTROL_CAPTURE_INTENT
*/
public static final int CONTROL_CAPTURE_INTENT_PREVIEW = 1;
/**
* <p>This request is for a still capture-type
- * usecase.</p>
+ * use case.</p>
+ * <p>If the flash unit is under automatic control, it may fire as needed.</p>
* @see CaptureRequest#CONTROL_CAPTURE_INTENT
*/
public static final int CONTROL_CAPTURE_INTENT_STILL_CAPTURE = 2;
/**
* <p>This request is for a video recording
- * usecase.</p>
+ * use case.</p>
* @see CaptureRequest#CONTROL_CAPTURE_INTENT
*/
public static final int CONTROL_CAPTURE_INTENT_VIDEO_RECORD = 3;
/**
* <p>This request is for a video snapshot (still
- * image while recording video) usecase</p>
+ * image while recording video) use case.</p>
+ * <p>The camera device should take the highest-quality image
+ * possible (given the other settings) without disrupting the
+ * frame rate of video recording.<br />
+ * </p>
* @see CaptureRequest#CONTROL_CAPTURE_INTENT
*/
public static final int CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT = 4;
@@ -1006,15 +1086,16 @@
* <p>This request is for a ZSL usecase; the
* application will stream full-resolution images and
* reprocess one or several later for a final
- * capture</p>
+ * capture.</p>
* @see CaptureRequest#CONTROL_CAPTURE_INTENT
*/
public static final int CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG = 5;
/**
* <p>This request is for manual capture use case where
- * the applications want to directly control the capture parameters
- * (e.g. {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}, {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity} etc.).</p>
+ * the applications want to directly control the capture parameters.</p>
+ * <p>For example, the application may wish to manually control
+ * {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}, {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}, etc.</p>
*
* @see CaptureRequest#SENSOR_EXPOSURE_TIME
* @see CaptureRequest#SENSOR_SENSITIVITY
@@ -1034,7 +1115,8 @@
/**
* <p>A "monocolor" effect where the image is mapped into
- * a single color. This will typically be grayscale.</p>
+ * a single color.</p>
+ * <p>This will typically be grayscale.</p>
* @see CaptureRequest#CONTROL_EFFECT_MODE
*/
public static final int CONTROL_EFFECT_MODE_MONO = 1;
@@ -1094,31 +1176,42 @@
//
/**
- * <p>Full application control of pipeline. All 3A
- * routines are disabled, no other settings in
- * android.control.* have any effect</p>
+ * <p>Full application control of pipeline.</p>
+ * <p>All control by the device's metering and focusing (3A)
+ * routines is disabled, and no other settings in
+ * android.control.* have any effect, except that
+ * {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} may be used by the camera
+ * device to select post-processing values for processing
+ * blocks that do not allow for manual control, or are not
+ * exposed by the camera API.</p>
+ * <p>However, the camera device's 3A routines may continue to
+ * collect statistics and update their internal state so that
+ * when control is switched to AUTO mode, good control values
+ * can be immediately applied.</p>
+ *
+ * @see CaptureRequest#CONTROL_CAPTURE_INTENT
* @see CaptureRequest#CONTROL_MODE
*/
public static final int CONTROL_MODE_OFF = 0;
/**
- * <p>Use settings for each individual 3A routine.
- * Manual control of capture parameters is disabled. All
+ * <p>Use settings for each individual 3A routine.</p>
+ * <p>Manual control of capture parameters is disabled. All
* controls in android.control.* besides sceneMode take
- * effect</p>
+ * effect.</p>
* @see CaptureRequest#CONTROL_MODE
*/
public static final int CONTROL_MODE_AUTO = 1;
/**
- * <p>Use specific scene mode. Enabling this disables
- * control.aeMode, control.awbMode and control.afMode
- * controls; the camera device will ignore those settings while
- * USE_SCENE_MODE is active (except for FACE_PRIORITY
- * scene mode). Other control entries are still active.
- * This setting can only be used if scene mode is supported
- * (i.e. {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes} contain some modes
- * other than DISABLED).</p>
+ * <p>Use a specific scene mode.</p>
+ * <p>Enabling this disables control.aeMode, control.awbMode and
+ * control.afMode controls; the camera device will ignore
+ * those settings while USE_SCENE_MODE is active (except for
+ * FACE_PRIORITY scene mode). Other control entries are still
+ * active. This setting can only be used if scene mode is
+ * supported (i.e. {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}
+ * contain some modes other than DISABLED).</p>
*
* @see CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES
* @see CaptureRequest#CONTROL_MODE
@@ -1128,7 +1221,12 @@
/**
* <p>Same as OFF mode, except that this capture will not be
* used by camera device background auto-exposure, auto-white balance and
- * auto-focus algorithms to update their statistics.</p>
+ * auto-focus algorithms (3A) to update their statistics.</p>
+ * <p>Specifically, the 3A routines are locked to the last
+ * values set from a request with AUTO, OFF, or
+ * USE_SCENE_MODE, and any statistics or state updates
+ * collected from manual captures with OFF_KEEP_STATE will be
+ * discarded by the camera device.</p>
* @see CaptureRequest#CONTROL_MODE
*/
public static final int CONTROL_MODE_OFF_KEEP_STATE = 3;
@@ -1146,8 +1244,9 @@
/**
* <p>If face detection support exists, use face
* detection data for auto-focus, auto-white balance, and
- * auto-exposure routines. If face detection statistics are
- * disabled (i.e. {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} is set to OFF),
+ * auto-exposure routines.</p>
+ * <p>If face detection statistics are disabled
+ * (i.e. {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} is set to OFF),
* this should still operate correctly (but will not return
* face detection statistics to the framework).</p>
* <p>Unlike the other scene modes, {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
@@ -1163,8 +1262,8 @@
public static final int CONTROL_SCENE_MODE_FACE_PRIORITY = 1;
/**
- * <p>Optimized for photos of quickly moving objects.
- * Similar to SPORTS.</p>
+ * <p>Optimized for photos of quickly moving objects.</p>
+ * <p>Similar to SPORTS.</p>
* @see CaptureRequest#CONTROL_SCENE_MODE
*/
public static final int CONTROL_SCENE_MODE_ACTION = 2;
@@ -1233,8 +1332,8 @@
public static final int CONTROL_SCENE_MODE_FIREWORKS = 12;
/**
- * <p>Optimized for photos of quickly moving people.
- * Similar to ACTION.</p>
+ * <p>Optimized for photos of quickly moving people.</p>
+ * <p>Similar to ACTION.</p>
* @see CaptureRequest#CONTROL_SCENE_MODE
*/
public static final int CONTROL_SCENE_MODE_SPORTS = 13;
@@ -1266,11 +1365,13 @@
//
/**
+ * <p>Video stabilization is disabled.</p>
* @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
*/
public static final int CONTROL_VIDEO_STABILIZATION_MODE_OFF = 0;
/**
+ * <p>Video stabilization is enabled.</p>
* @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
*/
public static final int CONTROL_VIDEO_STABILIZATION_MODE_ON = 1;
@@ -1280,21 +1381,20 @@
//
/**
- * <p>No edge enhancement is applied</p>
+ * <p>No edge enhancement is applied.</p>
* @see CaptureRequest#EDGE_MODE
*/
public static final int EDGE_MODE_OFF = 0;
/**
- * <p>Must not slow down frame rate relative to sensor
+ * <p>Apply edge enhancement at a quality level that does not slow down frame rate relative to sensor
* output</p>
* @see CaptureRequest#EDGE_MODE
*/
public static final int EDGE_MODE_FAST = 1;
/**
- * <p>Frame rate may be reduced by high
- * quality</p>
+ * <p>Apply high-quality edge enhancement, at a cost of reducing output frame rate.</p>
* @see CaptureRequest#EDGE_MODE
*/
public static final int EDGE_MODE_HIGH_QUALITY = 2;
@@ -1327,10 +1427,10 @@
//
/**
+ * <p>No hot pixel correction is applied.</p>
* <p>The frame rate must not be reduced relative to sensor raw output
* for this option.</p>
- * <p>No hot pixel correction is applied.
- * The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
+ * <p>The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
*
* @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
* @see CaptureRequest#HOT_PIXEL_MODE
@@ -1338,10 +1438,9 @@
public static final int HOT_PIXEL_MODE_OFF = 0;
/**
- * <p>The frame rate must not be reduced relative to sensor raw output
- * for this option.</p>
- * <p>Hot pixel correction is applied.
- * The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
+ * <p>Hot pixel correction is applied, without reducing frame
+ * rate relative to sensor raw output.</p>
+ * <p>The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
*
* @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
* @see CaptureRequest#HOT_PIXEL_MODE
@@ -1349,10 +1448,9 @@
public static final int HOT_PIXEL_MODE_FAST = 1;
/**
- * <p>The frame rate may be reduced relative to sensor raw output
- * for this option.</p>
- * <p>A high-quality hot pixel correction is applied.
- * The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
+ * <p>High-quality hot pixel correction is applied, at a cost
+ * of reducing frame rate relative to sensor raw output.</p>
+ * <p>The hotpixel map may be returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.</p>
*
* @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
* @see CaptureRequest#HOT_PIXEL_MODE
@@ -1380,21 +1478,21 @@
//
/**
- * <p>No noise reduction is applied</p>
+ * <p>No noise reduction is applied.</p>
* @see CaptureRequest#NOISE_REDUCTION_MODE
*/
public static final int NOISE_REDUCTION_MODE_OFF = 0;
/**
- * <p>Must not slow down frame rate relative to sensor
- * output</p>
+ * <p>Noise reduction is applied without reducing frame rate relative to sensor
+ * output.</p>
* @see CaptureRequest#NOISE_REDUCTION_MODE
*/
public static final int NOISE_REDUCTION_MODE_FAST = 1;
/**
- * <p>May slow down frame rate to provide highest
- * quality</p>
+ * <p>High-quality noise reduction is applied, at the cost of reducing frame rate
+ * relative to sensor output.</p>
* @see CaptureRequest#NOISE_REDUCTION_MODE
*/
public static final int NOISE_REDUCTION_MODE_HIGH_QUALITY = 2;
@@ -1404,8 +1502,9 @@
//
/**
- * <p>Default. No test pattern mode is used, and the camera
+ * <p>No test pattern mode is used, and the camera
* device returns captures from the image sensor.</p>
+ * <p>This is the default if the key is not set.</p>
* @see CaptureRequest#SENSOR_TEST_PATTERN_MODE
*/
public static final int SENSOR_TEST_PATTERN_MODE_OFF = 0;
@@ -1509,19 +1608,21 @@
//
/**
- * <p>No lens shading correction is applied</p>
+ * <p>No lens shading correction is applied.</p>
* @see CaptureRequest#SHADING_MODE
*/
public static final int SHADING_MODE_OFF = 0;
/**
- * <p>Must not slow down frame rate relative to sensor raw output</p>
+ * <p>Apply lens shading corrections, without slowing
+ * frame rate relative to sensor raw output</p>
* @see CaptureRequest#SHADING_MODE
*/
public static final int SHADING_MODE_FAST = 1;
/**
- * <p>Frame rate may be reduced by high quality</p>
+ * <p>Apply high-quality lens shading correction, at the
+ * cost of reduced frame rate.</p>
* @see CaptureRequest#SHADING_MODE
*/
public static final int SHADING_MODE_HIGH_QUALITY = 2;
@@ -1531,20 +1632,28 @@
//
/**
+ * <p>Do not include face detection statistics in capture
+ * results.</p>
* @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
*/
public static final int STATISTICS_FACE_DETECT_MODE_OFF = 0;
/**
- * <p>Optional Return rectangle and confidence
- * only</p>
+ * <p>Return face rectangle and confidence values only.</p>
+ * <p>In this mode, only android.statistics.faceRectangles and
+ * android.statistics.faceScores outputs are valid.</p>
* @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
*/
public static final int STATISTICS_FACE_DETECT_MODE_SIMPLE = 1;
/**
- * <p>Optional Return all face
- * metadata</p>
+ * <p>Return all face
+ * metadata.</p>
+ * <p>In this mode,
+ * android.statistics.faceRectangles,
+ * android.statistics.faceScores,
+ * android.statistics.faceIds, and
+ * android.statistics.faceLandmarks outputs are valid.</p>
* @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
*/
public static final int STATISTICS_FACE_DETECT_MODE_FULL = 2;
@@ -1554,11 +1663,13 @@
//
/**
+ * <p>Do not include a lens shading map in the capture result.</p>
* @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
*/
public static final int STATISTICS_LENS_SHADING_MAP_MODE_OFF = 0;
/**
+ * <p>Include a lens shading map in the capture result.</p>
* @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
*/
public static final int STATISTICS_LENS_SHADING_MAP_MODE_ON = 1;
@@ -1582,15 +1693,15 @@
public static final int TONEMAP_MODE_CONTRAST_CURVE = 0;
/**
- * <p>Advanced gamma mapping and color enhancement may be applied.</p>
- * <p>Should not slow down frame rate relative to raw sensor output.</p>
+ * <p>Advanced gamma mapping and color enhancement may be applied, without
+ * reducing frame rate compared to raw sensor output.</p>
* @see CaptureRequest#TONEMAP_MODE
*/
public static final int TONEMAP_MODE_FAST = 1;
/**
- * <p>Advanced gamma mapping and color enhancement may be applied.</p>
- * <p>May slow down frame rate relative to raw sensor output.</p>
+ * <p>High-quality gamma mapping and color enhancement will be applied, at
+ * the cost of reduced frame rate compared to raw sensor output.</p>
* @see CaptureRequest#TONEMAP_MODE
*/
public static final int TONEMAP_MODE_HIGH_QUALITY = 2;
@@ -1600,7 +1711,8 @@
//
/**
- * <p>AE is off or recently reset. When a camera device is opened, it starts in
+ * <p>AE is off or recently reset.</p>
+ * <p>When a camera device is opened, it starts in
* this state. This is a transient state, the camera device may skip reporting
* this state in capture result.</p>
* @see CaptureResult#CONTROL_AE_STATE
@@ -1609,7 +1721,8 @@
/**
* <p>AE doesn't yet have a good set of control values
- * for the current scene. This is a transient state, the camera device may skip
+ * for the current scene.</p>
+ * <p>This is a transient state, the camera device may skip
* reporting this state in capture result.</p>
* @see CaptureResult#CONTROL_AE_STATE
*/
@@ -1638,11 +1751,13 @@
/**
* <p>AE has been asked to do a precapture sequence
- * (through the {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} START),
- * and is currently executing it. Once PRECAPTURE
- * completes, AE will transition to CONVERGED or
- * FLASH_REQUIRED as appropriate. This is a transient state, the
- * camera device may skip reporting this state in capture result.</p>
+ * and is currently executing it.</p>
+ * <p>Precapture can be triggered through setting
+ * {@link CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER android.control.aePrecaptureTrigger} to START.</p>
+ * <p>Once PRECAPTURE completes, AE will transition to CONVERGED
+ * or FLASH_REQUIRED as appropriate. This is a transient
+ * state, the camera device may skip reporting this state in
+ * capture result.</p>
*
* @see CaptureRequest#CONTROL_AE_PRECAPTURE_TRIGGER
* @see CaptureResult#CONTROL_AE_STATE
@@ -1654,61 +1769,78 @@
//
/**
- * <p>AF off or has not yet tried to scan/been asked
- * to scan. When a camera device is opened, it starts in
- * this state. This is a transient state, the camera device may
- * skip reporting this state in capture result.</p>
+ * <p>AF is off or has not yet tried to scan/been asked
+ * to scan.</p>
+ * <p>When a camera device is opened, it starts in this
+ * state. This is a transient state, the camera device may
+ * skip reporting this state in capture
+ * result.</p>
* @see CaptureResult#CONTROL_AF_STATE
*/
public static final int CONTROL_AF_STATE_INACTIVE = 0;
/**
- * <p>if CONTINUOUS_* modes are supported. AF is
- * currently doing an AF scan initiated by a continuous
- * autofocus mode. This is a transient state, the camera device may
- * skip reporting this state in capture result.</p>
+ * <p>AF is currently performing an AF scan initiated the
+ * camera device in a continuous autofocus mode.</p>
+ * <p>Only used by CONTINUOUS_* AF modes. This is a transient
+ * state, the camera device may skip reporting this state in
+ * capture result.</p>
* @see CaptureResult#CONTROL_AF_STATE
*/
public static final int CONTROL_AF_STATE_PASSIVE_SCAN = 1;
/**
- * <p>if CONTINUOUS_* modes are supported. AF currently
- * believes it is in focus, but may restart scanning at
- * any time. This is a transient state, the camera device may skip
- * reporting this state in capture result.</p>
+ * <p>AF currently believes it is in focus, but may
+ * restart scanning at any time.</p>
+ * <p>Only used by CONTINUOUS_* AF modes. This is a transient
+ * state, the camera device may skip reporting this state in
+ * capture result.</p>
* @see CaptureResult#CONTROL_AF_STATE
*/
public static final int CONTROL_AF_STATE_PASSIVE_FOCUSED = 2;
/**
- * <p>if AUTO or MACRO modes are supported. AF is doing
- * an AF scan because it was triggered by AF trigger. This is a
- * transient state, the camera device may skip reporting
- * this state in capture result.</p>
+ * <p>AF is performing an AF scan because it was
+ * triggered by AF trigger.</p>
+ * <p>Only used by AUTO or MACRO AF modes. This is a transient
+ * state, the camera device may skip reporting this state in
+ * capture result.</p>
* @see CaptureResult#CONTROL_AF_STATE
*/
public static final int CONTROL_AF_STATE_ACTIVE_SCAN = 3;
/**
- * <p>if any AF mode besides OFF is supported. AF
- * believes it is focused correctly and is
- * locked.</p>
+ * <p>AF believes it is focused correctly and has locked
+ * focus.</p>
+ * <p>This state is reached only after an explicit START AF trigger has been
+ * sent ({@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger}), when good focus has been obtained.</p>
+ * <p>The lens will remain stationary until the AF mode ({@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}) is changed or
+ * a new AF trigger is sent to the camera device ({@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger}).</p>
+ *
+ * @see CaptureRequest#CONTROL_AF_MODE
+ * @see CaptureRequest#CONTROL_AF_TRIGGER
* @see CaptureResult#CONTROL_AF_STATE
*/
public static final int CONTROL_AF_STATE_FOCUSED_LOCKED = 4;
/**
- * <p>if any AF mode besides OFF is supported. AF has
- * failed to focus successfully and is
- * locked.</p>
+ * <p>AF has failed to focus successfully and has locked
+ * focus.</p>
+ * <p>This state is reached only after an explicit START AF trigger has been
+ * sent ({@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger}), when good focus cannot be obtained.</p>
+ * <p>The lens will remain stationary until the AF mode ({@link CaptureRequest#CONTROL_AF_MODE android.control.afMode}) is changed or
+ * a new AF trigger is sent to the camera device ({@link CaptureRequest#CONTROL_AF_TRIGGER android.control.afTrigger}).</p>
+ *
+ * @see CaptureRequest#CONTROL_AF_MODE
+ * @see CaptureRequest#CONTROL_AF_TRIGGER
* @see CaptureResult#CONTROL_AF_STATE
*/
public static final int CONTROL_AF_STATE_NOT_FOCUSED_LOCKED = 5;
/**
- * <p>if CONTINUOUS_* modes are supported. AF finished a
- * passive scan without finding focus, and may restart
- * scanning at any time. This is a transient state, the camera
+ * <p>AF finished a passive scan without finding focus,
+ * and may restart scanning at any time.</p>
+ * <p>Only used by CONTINUOUS_* AF modes. This is a transient state, the camera
* device may skip reporting this state in capture result.</p>
* @see CaptureResult#CONTROL_AF_STATE
*/
@@ -1719,16 +1851,19 @@
//
/**
- * <p>AWB is not in auto mode. When a camera device is opened, it
- * starts in this state. This is a transient state, the camera device may
- * skip reporting this state in capture result.</p>
+ * <p>AWB is not in auto mode, or has not yet started metering.</p>
+ * <p>When a camera device is opened, it starts in this
+ * state. This is a transient state, the camera device may
+ * skip reporting this state in capture
+ * result.</p>
* @see CaptureResult#CONTROL_AWB_STATE
*/
public static final int CONTROL_AWB_STATE_INACTIVE = 0;
/**
* <p>AWB doesn't yet have a good set of control
- * values for the current scene. This is a transient state, the camera device
+ * values for the current scene.</p>
+ * <p>This is a transient state, the camera device
* may skip reporting this state in capture result.</p>
* @see CaptureResult#CONTROL_AWB_STATE
*/
@@ -1776,8 +1911,9 @@
public static final int FLASH_STATE_FIRED = 3;
/**
- * <p>Flash partially illuminated this frame. This is usually due to the next
- * or previous frame having the flash fire, and the flash spilling into this capture
+ * <p>Flash partially illuminated this frame.</p>
+ * <p>This is usually due to the next or previous frame having
+ * the flash fire, and the flash spilling into this capture
* due to hardware limitations.</p>
* @see CaptureResult#FLASH_STATE
*/
@@ -1800,8 +1936,10 @@
public static final int LENS_STATE_STATIONARY = 0;
/**
- * <p>Any of the lens parameters ({@link CaptureRequest#LENS_FOCAL_LENGTH android.lens.focalLength}, {@link CaptureRequest#LENS_FOCUS_DISTANCE android.lens.focusDistance},
- * {@link CaptureRequest#LENS_FILTER_DENSITY android.lens.filterDensity} or {@link CaptureRequest#LENS_APERTURE android.lens.aperture}) is changing.</p>
+ * <p>One or several of the lens parameters
+ * ({@link CaptureRequest#LENS_FOCAL_LENGTH android.lens.focalLength}, {@link CaptureRequest#LENS_FOCUS_DISTANCE android.lens.focusDistance},
+ * {@link CaptureRequest#LENS_FILTER_DENSITY android.lens.filterDensity} or {@link CaptureRequest#LENS_APERTURE android.lens.aperture}) is
+ * currently changing.</p>
*
* @see CaptureRequest#LENS_APERTURE
* @see CaptureRequest#LENS_FILTER_DENSITY
@@ -1816,16 +1954,22 @@
//
/**
+ * <p>The camera device does not detect any flickering illumination
+ * in the current scene.</p>
* @see CaptureResult#STATISTICS_SCENE_FLICKER
*/
public static final int STATISTICS_SCENE_FLICKER_NONE = 0;
/**
+ * <p>The camera device detects illumination flickering at 50Hz
+ * in the current scene.</p>
* @see CaptureResult#STATISTICS_SCENE_FLICKER
*/
public static final int STATISTICS_SCENE_FLICKER_50HZ = 1;
/**
+ * <p>The camera device detects illumination flickering at 60Hz
+ * in the current scene.</p>
* @see CaptureResult#STATISTICS_SCENE_FLICKER
*/
public static final int STATISTICS_SCENE_FLICKER_60HZ = 2;
@@ -1835,8 +1979,8 @@
//
/**
- * <p>The current result is not yet fully synchronized to any request.
- * Synchronization is in progress, and reading metadata from this
+ * <p>The current result is not yet fully synchronized to any request.</p>
+ * <p>Synchronization is in progress, and reading metadata from this
* result may include a mix of data that have taken effect since the
* last synchronization time.</p>
* <p>In some future result, within {@link CameraCharacteristics#SYNC_MAX_LATENCY android.sync.maxLatency} frames,
@@ -1851,10 +1995,10 @@
public static final int SYNC_FRAME_NUMBER_CONVERGING = -1;
/**
- * <p>The current result's synchronization status is unknown. The
- * result may have already converged, or it may be in progress.
- * Reading from this result may include some mix of settings from
- * past requests.</p>
+ * <p>The current result's synchronization status is unknown.</p>
+ * <p>The result may have already converged, or it may be in
+ * progress. Reading from this result may include some mix
+ * of settings from past requests.</p>
* <p>After a settings change, the new settings will eventually all
* take effect for the output buffers and results. However, this
* value will not change when that happens. Altering settings
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 0ff8cce..bf7bd37 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -733,8 +733,16 @@
* included at all in the request settings. When included and
* set to START, the camera device will trigger the autoexposure
* precapture metering sequence.</p>
- * <p>The effect of auto-exposure (AE) precapture trigger depends
- * on the current AE mode and state; see
+ * <p>The precapture sequence should triggered before starting a
+ * high-quality still capture for final metering decisions to
+ * be made, and for firing pre-capture flash pulses to estimate
+ * scene brightness and required final capture flash power, when
+ * the flash is enabled.</p>
+ * <p>Normally, this entry should be set to START for only a
+ * single request, and the application should wait until the
+ * sequence completes before starting a new one.</p>
+ * <p>The exact effect of auto-exposure (AE) precapture trigger
+ * depends on the current AE mode and state; see
* {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture state transition
* details.</p>
*
@@ -800,7 +808,11 @@
* autofocus algorithm. If autofocus is disabled, this trigger has no effect.</p>
* <p>When set to CANCEL, the camera device will cancel any active trigger,
* and return to its initial AF state.</p>
- * <p>See {@link CaptureResult#CONTROL_AF_STATE android.control.afState} for what that means for each AF mode.</p>
+ * <p>Generally, applications should set this entry to START or CANCEL for only a
+ * single capture, and then return it to IDLE (or not set at all). Specifying
+ * START for multiple captures in a row means restarting the AF operation over
+ * and over again.</p>
+ * <p>See {@link CaptureResult#CONTROL_AF_STATE android.control.afState} for what the trigger means for each AF mode.</p>
*
* @see CaptureResult#CONTROL_AF_STATE
* @see #CONTROL_AF_TRIGGER_IDLE
@@ -813,9 +825,11 @@
/**
* <p>Whether auto-white balance (AWB) is currently locked to its
* latest calculated values.</p>
- * <p>Note that AWB lock is only meaningful for AUTO
- * mode; in other modes, AWB is already fixed to a specific
- * setting.</p>
+ * <p>Note that AWB lock is only meaningful when
+ * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} is in the AUTO mode; in other modes,
+ * AWB is already fixed to a specific setting.</p>
+ *
+ * @see CaptureRequest#CONTROL_AWB_MODE
*/
public static final Key<Boolean> CONTROL_AWB_LOCK =
new Key<Boolean>("android.control.awbLock", boolean.class);
@@ -825,17 +839,21 @@
* transform fields, and what its illumination target
* is.</p>
* <p>This control is only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} is AUTO.</p>
- * <p>When set to the ON mode, the camera device's auto white balance
+ * <p>When set to the ON mode, the camera device's auto-white balance
* routine is enabled, overriding the application's selected
* {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
* {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
- * <p>When set to the OFF mode, the camera device's auto white balance
+ * <p>When set to the OFF mode, the camera device's auto-white balance
* routine is disabled. The application manually controls the white
* balance by {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}
* and {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
- * <p>When set to any other modes, the camera device's auto white balance
- * routine is disabled. The camera device uses each particular illumination
- * target for white balance adjustment.</p>
+ * <p>When set to any other modes, the camera device's auto-white
+ * balance routine is disabled. The camera device uses each
+ * particular illumination target for white balance
+ * adjustment. The application's values for
+ * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform},
+ * {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
+ * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} are ignored.</p>
*
* @see CaptureRequest#COLOR_CORRECTION_GAINS
* @see CaptureRequest#COLOR_CORRECTION_MODE
@@ -886,8 +904,8 @@
* strategy.</p>
* <p>This control (except for MANUAL) is only effective if
* <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
- * <p>ZERO_SHUTTER_LAG must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
- * contains ZSL. MANUAL must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+ * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+ * contains ZSL. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
* contains MANUAL_SENSOR.</p>
*
* @see CaptureRequest#CONTROL_MODE
@@ -962,7 +980,9 @@
* <p>This is the mode that that is active when
* <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY,
* these modes will disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
- * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} while in use.</p>
+ * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} while in use.
+ * The scene modes available for a given camera device are listed in
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}.</p>
* <p>The interpretation and implementation of these scene modes is left
* to the implementor of the camera device. Their behavior will not be
* consistent across all devices, and any given device may only implement
@@ -970,6 +990,7 @@
*
* @see CaptureRequest#CONTROL_AE_MODE
* @see CaptureRequest#CONTROL_AF_MODE
+ * @see CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES
* @see CaptureRequest#CONTROL_AWB_MODE
* @see CaptureRequest#CONTROL_MODE
* @see #CONTROL_SCENE_MODE_DISABLED
@@ -996,6 +1017,8 @@
/**
* <p>Whether video stabilization is
* active.</p>
+ * <p>Video stabilization automatically translates and scales images from the camera
+ * in order to stabilize motion between consecutive frames.</p>
* <p>If enabled, video stabilization can modify the
* {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to keep the video stream
* stabilized</p>
@@ -1110,14 +1133,14 @@
/**
* <p>Compression quality of the final JPEG
* image.</p>
- * <p>85-95 is typical usage range</p>
+ * <p>85-95 is typical usage range.</p>
*/
public static final Key<Byte> JPEG_QUALITY =
new Key<Byte>("android.jpeg.quality", byte.class);
/**
* <p>Compression quality of JPEG
- * thumbnail</p>
+ * thumbnail.</p>
*/
public static final Key<Byte> JPEG_THUMBNAIL_QUALITY =
new Key<Byte>("android.jpeg.thumbnailQuality", byte.class);
@@ -1229,12 +1252,18 @@
/**
* <p>Sets whether the camera device uses optical image stabilization (OIS)
* when capturing images.</p>
- * <p>OIS is used to compensate for motion blur due to small movements of
- * the camera during capture. Unlike digital image stabilization, OIS makes
- * use of mechanical elements to stabilize the camera sensor, and thus
- * allows for longer exposure times before camera shake becomes
- * apparent.</p>
- * <p>This is not expected to be supported on most devices.</p>
+ * <p>OIS is used to compensate for motion blur due to small
+ * movements of the camera during capture. Unlike digital image
+ * stabilization ({@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE android.control.videoStabilizationMode}), OIS
+ * makes use of mechanical elements to stabilize the camera
+ * sensor, and thus allows for longer exposure times before
+ * camera shake becomes apparent.</p>
+ * <p>Not all devices will support OIS; see
+ * {@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization} for
+ * available controls.</p>
+ *
+ * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
+ * @see CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION
* @see #LENS_OPTICAL_STABILIZATION_MODE_OFF
* @see #LENS_OPTICAL_STABILIZATION_MODE_ON
*/
@@ -1242,16 +1271,15 @@
new Key<Integer>("android.lens.opticalStabilizationMode", int.class);
/**
- * <p>Mode of operation for the noise reduction.
- * algorithm</p>
+ * <p>Mode of operation for the noise reduction algorithm.</p>
* <p>Noise filtering control. OFF means no noise reduction
* will be applied by the camera device.</p>
- * <p>This must be set to a valid mode in
+ * <p>This must be set to a valid mode from
* {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}.</p>
* <p>FAST/HIGH_QUALITY both mean camera device determined noise filtering
* will be applied. HIGH_QUALITY mode indicates that the camera device
* will use the highest-quality noise filtering algorithms,
- * even if it slows down capture rate. FAST means the camera device should not
+ * even if it slows down capture rate. FAST means the camera device will not
* slow down capture rate when applying noise filtering.</p>
*
* @see CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES
@@ -1435,7 +1463,7 @@
* <p>When enabled, the sensor sends a test pattern instead of
* doing a real exposure from the camera.</p>
* <p>When a test pattern is enabled, all manual sensor controls specified
- * by android.sensor.* should be ignored. All other controls should
+ * by android.sensor.* will be ignored. All other controls should
* work as normal.</p>
* <p>For example, if manual flash is enabled, flash firing should still
* occur (and that the test pattern remain unmodified, since the flash
@@ -1490,7 +1518,7 @@
new Key<Integer>("android.shading.mode", int.class);
/**
- * <p>State of the face detector
+ * <p>Control for the face detector
* unit.</p>
* <p>Whether face detection is enabled, and whether it
* should output just the basic fields or the full set of
@@ -1508,7 +1536,7 @@
/**
* <p>Operating mode for hotpixel map generation.</p>
* <p>If set to ON, a hotpixel map is returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.
- * If set to OFF, no hotpixel map should be returned.</p>
+ * If set to OFF, no hotpixel map will be returned.</p>
* <p>This must be set to a valid mode from {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES android.statistics.info.availableHotPixelMapModes}.</p>
*
* @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
@@ -1521,7 +1549,7 @@
* <p>Whether the camera device will output the lens
* shading map in output result metadata.</p>
* <p>When set to ON,
- * android.statistics.lensShadingMap must be provided in
+ * android.statistics.lensShadingMap will be provided in
* the output result metadata.</p>
* @see #STATISTICS_LENS_SHADING_MAP_MODE_OFF
* @see #STATISTICS_LENS_SHADING_MAP_MODE_ON
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index ce3de1d..3d17ed3 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -579,8 +579,16 @@
* included at all in the request settings. When included and
* set to START, the camera device will trigger the autoexposure
* precapture metering sequence.</p>
- * <p>The effect of auto-exposure (AE) precapture trigger depends
- * on the current AE mode and state; see
+ * <p>The precapture sequence should triggered before starting a
+ * high-quality still capture for final metering decisions to
+ * be made, and for firing pre-capture flash pulses to estimate
+ * scene brightness and required final capture flash power, when
+ * the flash is enabled.</p>
+ * <p>Normally, this entry should be set to START for only a
+ * single request, and the application should wait until the
+ * sequence completes before starting a new one.</p>
+ * <p>The exact effect of auto-exposure (AE) precapture trigger
+ * depends on the current AE mode and state; see
* {@link CaptureResult#CONTROL_AE_STATE android.control.aeState} for AE precapture state transition
* details.</p>
*
@@ -592,7 +600,7 @@
new Key<Integer>("android.control.aePrecaptureTrigger", int.class);
/**
- * <p>Current state of auto-exposure (AE) algorithm.</p>
+ * <p>Current state of the auto-exposure (AE) algorithm.</p>
* <p>Switching between or enabling AE modes ({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode}) always
* resets the AE state to INACTIVE. Similarly, switching between {@link CaptureRequest#CONTROL_MODE android.control.mode},
* or {@link CaptureRequest#CONTROL_SCENE_MODE android.control.sceneMode} if <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code> resets all
@@ -844,7 +852,11 @@
* autofocus algorithm. If autofocus is disabled, this trigger has no effect.</p>
* <p>When set to CANCEL, the camera device will cancel any active trigger,
* and return to its initial AF state.</p>
- * <p>See {@link CaptureResult#CONTROL_AF_STATE android.control.afState} for what that means for each AF mode.</p>
+ * <p>Generally, applications should set this entry to START or CANCEL for only a
+ * single capture, and then return it to IDLE (or not set at all). Specifying
+ * START for multiple captures in a row means restarting the AF operation over
+ * and over again.</p>
+ * <p>See {@link CaptureResult#CONTROL_AF_STATE android.control.afState} for what the trigger means for each AF mode.</p>
*
* @see CaptureResult#CONTROL_AF_STATE
* @see #CONTROL_AF_TRIGGER_IDLE
@@ -1034,13 +1046,13 @@
* <td align="center">PASSIVE_SCAN</td>
* <td align="center">AF_TRIGGER</td>
* <td align="center">FOCUSED_LOCKED</td>
- * <td align="center">Immediate trans. If focus is good, Lens now locked</td>
+ * <td align="center">Immediate transition, if focus is good. Lens now locked</td>
* </tr>
* <tr>
* <td align="center">PASSIVE_SCAN</td>
* <td align="center">AF_TRIGGER</td>
* <td align="center">NOT_FOCUSED_LOCKED</td>
- * <td align="center">Immediate trans. if focus is bad, Lens now locked</td>
+ * <td align="center">Immediate transition, if focus is bad. Lens now locked</td>
* </tr>
* <tr>
* <td align="center">PASSIVE_SCAN</td>
@@ -1064,13 +1076,13 @@
* <td align="center">PASSIVE_FOCUSED</td>
* <td align="center">AF_TRIGGER</td>
* <td align="center">FOCUSED_LOCKED</td>
- * <td align="center">Immediate trans. Lens now locked</td>
+ * <td align="center">Immediate transition, lens now locked</td>
* </tr>
* <tr>
* <td align="center">PASSIVE_UNFOCUSED</td>
* <td align="center">AF_TRIGGER</td>
* <td align="center">NOT_FOCUSED_LOCKED</td>
- * <td align="center">Immediate trans. Lens now locked</td>
+ * <td align="center">Immediate transition, lens now locked</td>
* </tr>
* <tr>
* <td align="center">FOCUSED_LOCKED</td>
@@ -1137,13 +1149,13 @@
* <td align="center">PASSIVE_SCAN</td>
* <td align="center">AF_TRIGGER</td>
* <td align="center">FOCUSED_LOCKED</td>
- * <td align="center">Eventual trans. once focus good, Lens now locked</td>
+ * <td align="center">Eventual transition once the focus is good. Lens now locked</td>
* </tr>
* <tr>
* <td align="center">PASSIVE_SCAN</td>
* <td align="center">AF_TRIGGER</td>
* <td align="center">NOT_FOCUSED_LOCKED</td>
- * <td align="center">Eventual trans. if cannot focus, Lens now locked</td>
+ * <td align="center">Eventual transition if cannot find focus. Lens now locked</td>
* </tr>
* <tr>
* <td align="center">PASSIVE_SCAN</td>
@@ -1254,9 +1266,11 @@
/**
* <p>Whether auto-white balance (AWB) is currently locked to its
* latest calculated values.</p>
- * <p>Note that AWB lock is only meaningful for AUTO
- * mode; in other modes, AWB is already fixed to a specific
- * setting.</p>
+ * <p>Note that AWB lock is only meaningful when
+ * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} is in the AUTO mode; in other modes,
+ * AWB is already fixed to a specific setting.</p>
+ *
+ * @see CaptureRequest#CONTROL_AWB_MODE
*/
public static final Key<Boolean> CONTROL_AWB_LOCK =
new Key<Boolean>("android.control.awbLock", boolean.class);
@@ -1266,17 +1280,21 @@
* transform fields, and what its illumination target
* is.</p>
* <p>This control is only effective if {@link CaptureRequest#CONTROL_MODE android.control.mode} is AUTO.</p>
- * <p>When set to the ON mode, the camera device's auto white balance
+ * <p>When set to the ON mode, the camera device's auto-white balance
* routine is enabled, overriding the application's selected
* {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
* {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
- * <p>When set to the OFF mode, the camera device's auto white balance
+ * <p>When set to the OFF mode, the camera device's auto-white balance
* routine is disabled. The application manually controls the white
* balance by {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform}, {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains}
* and {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode}.</p>
- * <p>When set to any other modes, the camera device's auto white balance
- * routine is disabled. The camera device uses each particular illumination
- * target for white balance adjustment.</p>
+ * <p>When set to any other modes, the camera device's auto-white
+ * balance routine is disabled. The camera device uses each
+ * particular illumination target for white balance
+ * adjustment. The application's values for
+ * {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform},
+ * {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
+ * {@link CaptureRequest#COLOR_CORRECTION_MODE android.colorCorrection.mode} are ignored.</p>
*
* @see CaptureRequest#COLOR_CORRECTION_GAINS
* @see CaptureRequest#COLOR_CORRECTION_MODE
@@ -1327,8 +1345,8 @@
* strategy.</p>
* <p>This control (except for MANUAL) is only effective if
* <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
- * <p>ZERO_SHUTTER_LAG must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
- * contains ZSL. MANUAL must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+ * <p>ZERO_SHUTTER_LAG will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+ * contains ZSL. MANUAL will be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
* contains MANUAL_SENSOR.</p>
*
* @see CaptureRequest#CONTROL_MODE
@@ -1533,7 +1551,9 @@
* <p>This is the mode that that is active when
* <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == USE_SCENE_MODE</code>. Aside from FACE_PRIORITY,
* these modes will disable {@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode},
- * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} while in use.</p>
+ * {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode}, and {@link CaptureRequest#CONTROL_AF_MODE android.control.afMode} while in use.
+ * The scene modes available for a given camera device are listed in
+ * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}.</p>
* <p>The interpretation and implementation of these scene modes is left
* to the implementor of the camera device. Their behavior will not be
* consistent across all devices, and any given device may only implement
@@ -1541,6 +1561,7 @@
*
* @see CaptureRequest#CONTROL_AE_MODE
* @see CaptureRequest#CONTROL_AF_MODE
+ * @see CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES
* @see CaptureRequest#CONTROL_AWB_MODE
* @see CaptureRequest#CONTROL_MODE
* @see #CONTROL_SCENE_MODE_DISABLED
@@ -1567,6 +1588,8 @@
/**
* <p>Whether video stabilization is
* active.</p>
+ * <p>Video stabilization automatically translates and scales images from the camera
+ * in order to stabilize motion between consecutive frames.</p>
* <p>If enabled, video stabilization can modify the
* {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} to keep the video stream
* stabilized</p>
@@ -1698,14 +1721,14 @@
/**
* <p>Compression quality of the final JPEG
* image.</p>
- * <p>85-95 is typical usage range</p>
+ * <p>85-95 is typical usage range.</p>
*/
public static final Key<Byte> JPEG_QUALITY =
new Key<Byte>("android.jpeg.quality", byte.class);
/**
* <p>Compression quality of JPEG
- * thumbnail</p>
+ * thumbnail.</p>
*/
public static final Key<Byte> JPEG_THUMBNAIL_QUALITY =
new Key<Byte>("android.jpeg.thumbnailQuality", byte.class);
@@ -1817,12 +1840,18 @@
/**
* <p>Sets whether the camera device uses optical image stabilization (OIS)
* when capturing images.</p>
- * <p>OIS is used to compensate for motion blur due to small movements of
- * the camera during capture. Unlike digital image stabilization, OIS makes
- * use of mechanical elements to stabilize the camera sensor, and thus
- * allows for longer exposure times before camera shake becomes
- * apparent.</p>
- * <p>This is not expected to be supported on most devices.</p>
+ * <p>OIS is used to compensate for motion blur due to small
+ * movements of the camera during capture. Unlike digital image
+ * stabilization ({@link CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE android.control.videoStabilizationMode}), OIS
+ * makes use of mechanical elements to stabilize the camera
+ * sensor, and thus allows for longer exposure times before
+ * camera shake becomes apparent.</p>
+ * <p>Not all devices will support OIS; see
+ * {@link CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION android.lens.info.availableOpticalStabilization} for
+ * available controls.</p>
+ *
+ * @see CaptureRequest#CONTROL_VIDEO_STABILIZATION_MODE
+ * @see CameraCharacteristics#LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION
* @see #LENS_OPTICAL_STABILIZATION_MODE_OFF
* @see #LENS_OPTICAL_STABILIZATION_MODE_ON
*/
@@ -1866,16 +1895,15 @@
new Key<Integer>("android.lens.state", int.class);
/**
- * <p>Mode of operation for the noise reduction.
- * algorithm</p>
+ * <p>Mode of operation for the noise reduction algorithm.</p>
* <p>Noise filtering control. OFF means no noise reduction
* will be applied by the camera device.</p>
- * <p>This must be set to a valid mode in
+ * <p>This must be set to a valid mode from
* {@link CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES android.noiseReduction.availableNoiseReductionModes}.</p>
* <p>FAST/HIGH_QUALITY both mean camera device determined noise filtering
* will be applied. HIGH_QUALITY mode indicates that the camera device
* will use the highest-quality noise filtering algorithms,
- * even if it slows down capture rate. FAST means the camera device should not
+ * even if it slows down capture rate. FAST means the camera device will not
* slow down capture rate when applying noise filtering.</p>
*
* @see CameraCharacteristics#NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES
@@ -2170,7 +2198,7 @@
* <p>When enabled, the sensor sends a test pattern instead of
* doing a real exposure from the camera.</p>
* <p>When a test pattern is enabled, all manual sensor controls specified
- * by android.sensor.* should be ignored. All other controls should
+ * by android.sensor.* will be ignored. All other controls should
* work as normal.</p>
* <p>For example, if manual flash is enabled, flash firing should still
* occur (and that the test pattern remain unmodified, since the flash
@@ -2225,7 +2253,7 @@
new Key<Integer>("android.shading.mode", int.class);
/**
- * <p>State of the face detector
+ * <p>Control for the face detector
* unit.</p>
* <p>Whether face detection is enabled, and whether it
* should output just the basic fields or the full set of
@@ -2241,9 +2269,13 @@
new Key<Integer>("android.statistics.faceDetectMode", int.class);
/**
- * <p>List of unique IDs for detected
- * faces</p>
- * <p>Only available if faceDetectMode == FULL</p>
+ * <p>List of unique IDs for detected faces.</p>
+ * <p>Each detected face is given a unique ID that is valid for as long as the face is visible
+ * to the camera device. A face that leaves the field of view and later returns may be
+ * assigned a new ID.</p>
+ * <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} == FULL</p>
+ *
+ * @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
* @hide
*/
public static final Key<int[]> STATISTICS_FACE_IDS =
@@ -2251,8 +2283,13 @@
/**
* <p>List of landmarks for detected
- * faces</p>
- * <p>Only available if faceDetectMode == FULL</p>
+ * faces.</p>
+ * <p>The coordinate system is that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
+ * <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} == FULL</p>
+ *
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
* @hide
*/
public static final Key<int[]> STATISTICS_FACE_LANDMARKS =
@@ -2260,8 +2297,13 @@
/**
* <p>List of the bounding rectangles for detected
- * faces</p>
- * <p>Only available if faceDetectMode != OFF</p>
+ * faces.</p>
+ * <p>The coordinate system is that of {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}, with
+ * <code>(0, 0)</code> being the top-left pixel of the active array.</p>
+ * <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} != OFF</p>
+ *
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
* @hide
*/
public static final Key<android.graphics.Rect[]> STATISTICS_FACE_RECTANGLES =
@@ -2270,8 +2312,9 @@
/**
* <p>List of the face confidence scores for
* detected faces</p>
- * <p>Only available if faceDetectMode != OFF. The value should be
- * meaningful (for example, setting 100 at all times is illegal).</p>
+ * <p>Only available if {@link CaptureRequest#STATISTICS_FACE_DETECT_MODE android.statistics.faceDetectMode} != OFF.</p>
+ *
+ * @see CaptureRequest#STATISTICS_FACE_DETECT_MODE
* @hide
*/
public static final Key<byte[]> STATISTICS_FACE_SCORES =
@@ -2435,12 +2478,13 @@
* The camera device uses this entry to tell the application what the scene
* illuminant frequency is.</p>
* <p>When manual exposure control is enabled
- * (<code>{@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} == OFF</code> or <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} == OFF</code>),
- * the {@link CaptureRequest#CONTROL_AE_ANTIBANDING_MODE android.control.aeAntibandingMode} doesn't do the antibanding, and the
- * application can ensure it selects exposure times that do not cause banding
- * issues by looking into this metadata field. See {@link CaptureRequest#CONTROL_AE_ANTIBANDING_MODE android.control.aeAntibandingMode}
- * for more details.</p>
- * <p>Report NONE if there doesn't appear to be flickering illumination.</p>
+ * (<code>{@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} == OFF</code> or <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} ==
+ * OFF</code>), the {@link CaptureRequest#CONTROL_AE_ANTIBANDING_MODE android.control.aeAntibandingMode} doesn't perform
+ * antibanding, and the application can ensure it selects
+ * exposure times that do not cause banding issues by looking
+ * into this metadata field. See
+ * {@link CaptureRequest#CONTROL_AE_ANTIBANDING_MODE android.control.aeAntibandingMode} for more details.</p>
+ * <p>Reports NONE if there doesn't appear to be flickering illumination.</p>
*
* @see CaptureRequest#CONTROL_AE_ANTIBANDING_MODE
* @see CaptureRequest#CONTROL_AE_MODE
@@ -2455,7 +2499,7 @@
/**
* <p>Operating mode for hotpixel map generation.</p>
* <p>If set to ON, a hotpixel map is returned in {@link CaptureResult#STATISTICS_HOT_PIXEL_MAP android.statistics.hotPixelMap}.
- * If set to OFF, no hotpixel map should be returned.</p>
+ * If set to OFF, no hotpixel map will be returned.</p>
* <p>This must be set to a valid mode from {@link CameraCharacteristics#STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES android.statistics.info.availableHotPixelMapModes}.</p>
*
* @see CaptureResult#STATISTICS_HOT_PIXEL_MAP
@@ -2483,7 +2527,7 @@
* <p>Whether the camera device will output the lens
* shading map in output result metadata.</p>
* <p>When set to ON,
- * android.statistics.lensShadingMap must be provided in
+ * android.statistics.lensShadingMap will be provided in
* the output result metadata.</p>
* @see #STATISTICS_LENS_SHADING_MAP_MODE_OFF
* @see #STATISTICS_LENS_SHADING_MAP_MODE_ON
diff --git a/core/java/android/hardware/camera2/params/StreamConfiguration.java b/core/java/android/hardware/camera2/params/StreamConfiguration.java
index dd862b5..a6fc10f 100644
--- a/core/java/android/hardware/camera2/params/StreamConfiguration.java
+++ b/core/java/android/hardware/camera2/params/StreamConfiguration.java
@@ -30,7 +30,8 @@
* Immutable class to store the available stream
* {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS configurations} to set up
* {@link android.view.Surface Surfaces} for creating a {@link CameraCaptureSession capture session}
- * with {@link CameraDevice#createCaptureSession}. <!-- TODO: link to input stream configuration -->
+ * with {@link CameraDevice#createCaptureSession}.
+ * <!-- TODO: link to input stream configuration -->
*
* <p>This is the authoritative list for all input/output formats (and sizes respectively
* for that format) that are supported by a camera device.</p>
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 60e76e0..65d4726 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -429,6 +429,11 @@
*/
public final static int INVALID_NET_ID = 0;
+ /**
+ * @hide
+ */
+ public final static int REQUEST_ID_UNSET = 0;
+
private final IConnectivityManager mService;
private final String mPackageName;
@@ -883,8 +888,8 @@
* @hide
*/
public static void maybeMarkCapabilitiesRestricted(NetworkCapabilities nc) {
- for (Integer capability : nc.getNetworkCapabilities()) {
- switch (capability.intValue()) {
+ for (int capability : nc.getCapabilities()) {
+ switch (capability) {
case NetworkCapabilities.NET_CAPABILITY_CBS:
case NetworkCapabilities.NET_CAPABILITY_DUN:
case NetworkCapabilities.NET_CAPABILITY_EIMS:
@@ -902,7 +907,7 @@
}
// All the capabilities are typically provided by restricted networks.
// Conclude that this network is restricted.
- nc.removeNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ nc.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
}
private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) {
@@ -926,15 +931,14 @@
return null;
}
NetworkCapabilities netCap = new NetworkCapabilities();
- netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- netCap.addNetworkCapability(cap);
+ netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).addCapability(cap);
maybeMarkCapabilitiesRestricted(netCap);
return netCap;
} else if (networkType == TYPE_WIFI) {
if ("p2p".equals(feature)) {
NetworkCapabilities netCap = new NetworkCapabilities();
netCap.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
- netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P);
+ netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P);
maybeMarkCapabilitiesRestricted(netCap);
return netCap;
}
diff --git a/core/java/android/net/DhcpResults.java b/core/java/android/net/DhcpResults.java
index 22b26b1..49a307e 100644
--- a/core/java/android/net/DhcpResults.java
+++ b/core/java/android/net/DhcpResults.java
@@ -74,8 +74,10 @@
if (linkProperties.getRoutes().size() == 0) {
for (RouteInfo r : orig.linkProperties.getRoutes()) linkProperties.addRoute(r);
}
- if (linkProperties.getDnses().size() == 0) {
- for (InetAddress d : orig.linkProperties.getDnses()) linkProperties.addDns(d);
+ if (linkProperties.getDnsServers().size() == 0) {
+ for (InetAddress d : orig.linkProperties.getDnsServers()) {
+ linkProperties.addDnsServer(d);
+ }
}
}
@@ -211,7 +213,7 @@
public boolean addDns(String addrString) {
if (TextUtils.isEmpty(addrString) == false) {
try {
- linkProperties.addDns(NetworkUtils.numericToInetAddress(addrString));
+ linkProperties.addDnsServer(NetworkUtils.numericToInetAddress(addrString));
} catch (IllegalArgumentException e) {
Log.e(TAG, "addDns failed with addrString " + addrString);
return true;
diff --git a/core/java/android/net/DnsPinger.java b/core/java/android/net/DnsPinger.java
index 66f0fd0..7acf3f5 100644
--- a/core/java/android/net/DnsPinger.java
+++ b/core/java/android/net/DnsPinger.java
@@ -248,7 +248,7 @@
return mDefaultDns;
}
- Collection<InetAddress> dnses = curLinkProps.getDnses();
+ Collection<InetAddress> dnses = curLinkProps.getDnsServers();
if (dnses == null || dnses.size() == 0) {
loge("getDns::LinkProps has null dns - returning default");
return mDefaultDns;
diff --git a/core/java/android/net/IpPrefix.aidl b/core/java/android/net/IpPrefix.aidl
new file mode 100644
index 0000000..9e552c7
--- /dev/null
+++ b/core/java/android/net/IpPrefix.aidl
@@ -0,0 +1,20 @@
+/**
+ *
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+parcelable IpPrefix;
diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java
new file mode 100644
index 0000000..a14d13f
--- /dev/null
+++ b/core/java/android/net/IpPrefix.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+
+/**
+ * This class represents an IP prefix, i.e., a contiguous block of IP addresses aligned on a
+ * power of two boundary (also known as an "IP subnet"). A prefix is specified by two pieces of
+ * information:
+ *
+ * <ul>
+ * <li>A starting IP address (IPv4 or IPv6). This is the first IP address of the prefix.
+ * <li>A prefix length. This specifies the length of the prefix by specifing the number of bits
+ * in the IP address, starting from the most significant bit in network byte order, that
+ * are constant for all addresses in the prefix.
+ * </ul>
+ *
+ * For example, the prefix <code>192.0.2.0/24</code> covers the 256 IPv4 addresses from
+ * <code>192.0.2.0</code> to <code>192.0.2.255</code>, inclusive, and the prefix
+ * <code>2001:db8:1:2</code> covers the 2^64 IPv6 addresses from <code>2001:db8:1:2::</code> to
+ * <code>2001:db8:1:2:ffff:ffff:ffff:ffff</code>, inclusive.
+ *
+ * Objects of this class are immutable.
+ */
+public final class IpPrefix implements Parcelable {
+ private final byte[] address; // network byte order
+ private final int prefixLength;
+
+ /**
+ * Constructs a new {@code IpPrefix} from a byte array containing an IPv4 or IPv6 address in
+ * network byte order and a prefix length.
+ *
+ * @param address the IP address. Must be non-null and exactly 4 or 16 bytes long.
+ * @param prefixLength the prefix length. Must be >= 0 and <= (32 or 128) (IPv4 or IPv6).
+ *
+ * @hide
+ */
+ public IpPrefix(byte[] address, int prefixLength) {
+ if (address.length != 4 && address.length != 16) {
+ throw new IllegalArgumentException(
+ "IpPrefix has " + address.length + " bytes which is neither 4 nor 16");
+ }
+ if (prefixLength < 0 || prefixLength > (address.length * 8)) {
+ throw new IllegalArgumentException("IpPrefix with " + address.length +
+ " bytes has invalid prefix length " + prefixLength);
+ }
+ this.address = address.clone();
+ this.prefixLength = prefixLength;
+ // TODO: Validate that the non-prefix bits are zero
+ }
+
+ /**
+ * @hide
+ */
+ public IpPrefix(InetAddress address, int prefixLength) {
+ this(address.getAddress(), prefixLength);
+ }
+
+ /**
+ * Compares this {@code IpPrefix} object against the specified object in {@code obj}. Two
+ * objects are equal if they have the same startAddress and prefixLength.
+ *
+ * @param obj the object to be tested for equality.
+ * @return {@code true} if both objects are equal, {@code false} otherwise.
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof IpPrefix)) {
+ return false;
+ }
+ IpPrefix that = (IpPrefix) obj;
+ return Arrays.equals(this.address, that.address) && this.prefixLength == that.prefixLength;
+ }
+
+ /**
+ * Gets the hashcode of the represented IP prefix.
+ *
+ * @return the appropriate hashcode value.
+ */
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(address) + 11 * prefixLength;
+ }
+
+ /**
+ * Returns a copy of the first IP address in the prefix. Modifying the returned object does not
+ * change this object's contents.
+ *
+ * @return the address in the form of a byte array.
+ */
+ public InetAddress getAddress() {
+ try {
+ return InetAddress.getByAddress(address);
+ } catch (UnknownHostException e) {
+ // Cannot happen. InetAddress.getByAddress can only throw an exception if the byte
+ // array is the wrong length, but we check that in the constructor.
+ return null;
+ }
+ }
+
+ /**
+ * Returns a copy of the IP address bytes in network order (the highest order byte is the zeroth
+ * element). Modifying the returned array does not change this object's contents.
+ *
+ * @return the address in the form of a byte array.
+ */
+ public byte[] getRawAddress() {
+ return address.clone();
+ }
+
+ /**
+ * Returns the prefix length of this {@code IpAddress}.
+ *
+ * @return the prefix length.
+ */
+ public int getPrefixLength() {
+ return prefixLength;
+ }
+
+ /**
+ * Implement the Parcelable interface.
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Implement the Parcelable interface.
+ */
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeByteArray(address);
+ dest.writeInt(prefixLength);
+ }
+
+ /**
+ * Implement the Parcelable interface.
+ */
+ public static final Creator<IpPrefix> CREATOR =
+ new Creator<IpPrefix>() {
+ public IpPrefix createFromParcel(Parcel in) {
+ byte[] address = in.createByteArray();
+ int prefixLength = in.readInt();
+ return new IpPrefix(address, prefixLength);
+ }
+
+ public IpPrefix[] newArray(int size) {
+ return new IpPrefix[size];
+ }
+ };
+}
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index d07c0b61..5246078 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -39,18 +39,13 @@
* <ul>
* <li>An IP address and prefix length (e.g., {@code 2001:db8::1/64} or {@code 192.0.2.1/24}).
* The address must be unicast, as multicast addresses cannot be assigned to interfaces.
- * <li>Address flags: A bitmask of {@code IFA_F_*} values representing properties
- * of the address.
- * <li>Address scope: An integer defining the scope in which the address is unique (e.g.,
- * {@code RT_SCOPE_LINK} or {@code RT_SCOPE_SITE}).
- * <ul>
- *<p>
- * When constructing a {@code LinkAddress}, the IP address and prefix are required. The flags and
- * scope are optional. If they are not specified, the flags are set to zero, and the scope will be
- * determined based on the IP address (e.g., link-local addresses will be created with a scope of
- * {@code RT_SCOPE_LINK}, global addresses with {@code RT_SCOPE_UNIVERSE},
- * etc.) If they are specified, they are not checked for validity.
- *
+ * <li>Address flags: A bitmask of {@code OsConstants.IFA_F_*} values representing properties
+ * of the address (e.g., {@code android.system.OsConstants.IFA_F_OPTIMISTIC}).
+ * <li>Address scope: One of the {@code OsConstants.IFA_F_*} values; defines the scope in which
+ * the address is unique (e.g.,
+ * {@code android.system.OsConstants.RT_SCOPE_LINK} or
+ * {@code android.system.OsConstants.RT_SCOPE_UNIVERSE}).
+ * </ul>
*/
public class LinkAddress implements Parcelable {
/**
@@ -202,7 +197,9 @@
/**
* Compares this {@code LinkAddress} instance against {@code obj}. Two addresses are equal if
- * their address, prefix length, flags and scope are equal.
+ * their address, prefix length, flags and scope are equal. Thus, for example, two addresses
+ * that have the same address and prefix length are not equal if one of them is deprecated and
+ * the other is not.
*
* @param obj the object to be tested for equality.
* @return {@code true} if both objects are equal, {@code false} otherwise.
@@ -236,6 +233,7 @@
* @param other the {@code LinkAddress} to compare to.
* @return {@code true} if both objects have the same address and prefix length, {@code false}
* otherwise.
+ * @hide
*/
public boolean isSameAddressAs(LinkAddress other) {
return address.equals(other.address) && prefixLength == other.prefixLength;
@@ -251,11 +249,20 @@
/**
* Returns the prefix length of this {@code LinkAddress}.
*/
- public int getNetworkPrefixLength() {
+ public int getPrefixLength() {
return prefixLength;
}
/**
+ * Returns the prefix length of this {@code LinkAddress}.
+ * TODO: Delete all callers and remove in favour of getPrefixLength().
+ * @hide
+ */
+ public int getNetworkPrefixLength() {
+ return getPrefixLength();
+ }
+
+ /**
* Returns the flags of this {@code LinkAddress}.
*/
public int getFlags() {
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 3c36679..8eefa0f 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -30,6 +30,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Hashtable;
+import java.util.List;
/**
* Describes the properties of a network link.
@@ -43,7 +44,7 @@
* does not affect live networks.
*
*/
-public class LinkProperties implements Parcelable {
+public final class LinkProperties implements Parcelable {
// The interface described by the network link.
private String mIfaceName;
private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<LinkAddress>();
@@ -58,10 +59,12 @@
private Hashtable<String, LinkProperties> mStackedLinks =
new Hashtable<String, LinkProperties>();
- // @hide
+ /**
+ * @hide
+ */
public static class CompareResult<T> {
- public Collection<T> removed = new ArrayList<T>();
- public Collection<T> added = new ArrayList<T>();
+ public List<T> removed = new ArrayList<T>();
+ public List<T> added = new ArrayList<T>();
@Override
public String toString() {
@@ -74,14 +77,20 @@
}
}
+ /**
+ * @hide
+ */
public LinkProperties() {
}
+ /**
+ * @hide
+ */
public LinkProperties(LinkProperties source) {
if (source != null) {
mIfaceName = source.getInterfaceName();
for (LinkAddress l : source.getLinkAddresses()) mLinkAddresses.add(l);
- for (InetAddress i : source.getDnses()) mDnses.add(i);
+ for (InetAddress i : source.getDnsServers()) mDnses.add(i);
mDomains = source.getDomains();
for (RouteInfo r : source.getRoutes()) mRoutes.add(r);
mHttpProxy = (source.getHttpProxy() == null) ?
@@ -98,6 +107,7 @@
* will have their interface changed to match this new value.
*
* @param iface The name of the network interface used for this link.
+ * @hide
*/
public void setInterfaceName(String iface) {
mIfaceName = iface;
@@ -117,9 +127,11 @@
return mIfaceName;
}
- // @hide
- public Collection<String> getAllInterfaceNames() {
- Collection interfaceNames = new ArrayList<String>(mStackedLinks.size() + 1);
+ /**
+ * @hide
+ */
+ public List<String> getAllInterfaceNames() {
+ List<String> interfaceNames = new ArrayList<String>(mStackedLinks.size() + 1);
if (mIfaceName != null) interfaceNames.add(new String(mIfaceName));
for (LinkProperties stacked: mStackedLinks.values()) {
interfaceNames.addAll(stacked.getAllInterfaceNames());
@@ -134,23 +146,23 @@
* prefix lengths for each address. This is a simplified utility alternative to
* {@link LinkProperties#getLinkAddresses}.
*
- * @return An umodifiable {@link Collection} of {@link InetAddress} for this link.
+ * @return An umodifiable {@link List} of {@link InetAddress} for this link.
* @hide
*/
- public Collection<InetAddress> getAddresses() {
- Collection<InetAddress> addresses = new ArrayList<InetAddress>();
+ public List<InetAddress> getAddresses() {
+ List<InetAddress> addresses = new ArrayList<InetAddress>();
for (LinkAddress linkAddress : mLinkAddresses) {
addresses.add(linkAddress.getAddress());
}
- return Collections.unmodifiableCollection(addresses);
+ return Collections.unmodifiableList(addresses);
}
/**
* Returns all the addresses on this link and all the links stacked above it.
* @hide
*/
- public Collection<InetAddress> getAllAddresses() {
- Collection<InetAddress> addresses = new ArrayList<InetAddress>();
+ public List<InetAddress> getAllAddresses() {
+ List<InetAddress> addresses = new ArrayList<InetAddress>();
for (LinkAddress linkAddress : mLinkAddresses) {
addresses.add(linkAddress.getAddress());
}
@@ -174,6 +186,7 @@
* same address/prefix does not already exist. If it does exist it is replaced.
* @param address The {@code LinkAddress} to add.
* @return true if {@code address} was added or updated, false otherwise.
+ * @hide
*/
public boolean addLinkAddress(LinkAddress address) {
if (address == null) {
@@ -200,6 +213,7 @@
*
* @param toRemove A {@link LinkAddress} specifying the address to remove.
* @return true if the address was removed, false if it did not exist.
+ * @hide
*/
public boolean removeLinkAddress(LinkAddress toRemove) {
int i = findLinkAddressIndex(toRemove);
@@ -214,18 +228,18 @@
* Returns all the {@link LinkAddress} on this link. Typically a link will have
* one IPv4 address and one or more IPv6 addresses.
*
- * @return An unmodifiable {@link Collection} of {@link LinkAddress} for this link.
+ * @return An unmodifiable {@link List} of {@link LinkAddress} for this link.
*/
- public Collection<LinkAddress> getLinkAddresses() {
- return Collections.unmodifiableCollection(mLinkAddresses);
+ public List<LinkAddress> getLinkAddresses() {
+ return Collections.unmodifiableList(mLinkAddresses);
}
/**
* Returns all the addresses on this link and all the links stacked above it.
* @hide
*/
- public Collection<LinkAddress> getAllLinkAddresses() {
- Collection<LinkAddress> addresses = new ArrayList<LinkAddress>();
+ public List<LinkAddress> getAllLinkAddresses() {
+ List<LinkAddress> addresses = new ArrayList<LinkAddress>();
addresses.addAll(mLinkAddresses);
for (LinkProperties stacked: mStackedLinks.values()) {
addresses.addAll(stacked.getAllLinkAddresses());
@@ -239,6 +253,7 @@
*
* @param addresses The {@link Collection} of {@link LinkAddress} to set in this
* object.
+ * @hide
*/
public void setLinkAddresses(Collection<LinkAddress> addresses) {
mLinkAddresses.clear();
@@ -250,20 +265,21 @@
/**
* Adds the given {@link InetAddress} to the list of DNS servers.
*
- * @param dns The {@link InetAddress} to add to the list of DNS servers.
+ * @param dnsServer The {@link InetAddress} to add to the list of DNS servers.
+ * @hide
*/
- public void addDns(InetAddress dns) {
- if (dns != null) mDnses.add(dns);
+ public void addDnsServer(InetAddress dnsServer) {
+ if (dnsServer != null) mDnses.add(dnsServer);
}
/**
- * Returns all the {@link LinkAddress} for DNS servers on this link.
+ * Returns all the {@link InetAddress} for DNS servers on this link.
*
- * @return An umodifiable {@link Collection} of {@link InetAddress} for DNS servers on
+ * @return An umodifiable {@link List} of {@link InetAddress} for DNS servers on
* this link.
*/
- public Collection<InetAddress> getDnses() {
- return Collections.unmodifiableCollection(mDnses);
+ public List<InetAddress> getDnsServers() {
+ return Collections.unmodifiableList(mDnses);
}
/**
@@ -271,6 +287,7 @@
*
* @param domains A {@link String} listing in priority order the comma separated
* domains to search when resolving host names on this link.
+ * @hide
*/
public void setDomains(String domains) {
mDomains = domains;
@@ -323,6 +340,7 @@
* proper course is to add either un-named or properly named {@link RouteInfo}.
*
* @param route A {@link RouteInfo} to add to this object.
+ * @hide
*/
public void addRoute(RouteInfo route) {
if (route != null) {
@@ -339,18 +357,18 @@
/**
* Returns all the {@link RouteInfo} set on this link.
*
- * @return An unmodifiable {@link Collection} of {@link RouteInfo} for this link.
+ * @return An unmodifiable {@link List} of {@link RouteInfo} for this link.
*/
- public Collection<RouteInfo> getRoutes() {
- return Collections.unmodifiableCollection(mRoutes);
+ public List<RouteInfo> getRoutes() {
+ return Collections.unmodifiableList(mRoutes);
}
/**
* Returns all the routes on this link and all the links stacked above it.
* @hide
*/
- public Collection<RouteInfo> getAllRoutes() {
- Collection<RouteInfo> routes = new ArrayList();
+ public List<RouteInfo> getAllRoutes() {
+ List<RouteInfo> routes = new ArrayList();
routes.addAll(mRoutes);
for (LinkProperties stacked: mStackedLinks.values()) {
routes.addAll(stacked.getAllRoutes());
@@ -364,6 +382,7 @@
* not enforce it and applications may ignore them.
*
* @param proxy A {@link ProxyInfo} defining the Http Proxy to use on this link.
+ * @hide
*/
public void setHttpProxy(ProxyInfo proxy) {
mHttpProxy = proxy;
@@ -419,16 +438,17 @@
* Returns all the links stacked on top of this link.
* @hide
*/
- public Collection<LinkProperties> getStackedLinks() {
- Collection<LinkProperties> stacked = new ArrayList<LinkProperties>();
+ public List<LinkProperties> getStackedLinks() {
+ List<LinkProperties> stacked = new ArrayList<LinkProperties>();
for (LinkProperties link : mStackedLinks.values()) {
stacked.add(new LinkProperties(link));
}
- return Collections.unmodifiableCollection(stacked);
+ return Collections.unmodifiableList(stacked);
}
/**
* Clears this object to its initial state.
+ * @hide
*/
public void clear() {
mIfaceName = null;
@@ -443,7 +463,6 @@
/**
* Implement the Parcelable interface
- * @hide
*/
public int describeContents() {
return 0;
@@ -463,12 +482,12 @@
String domainName = "Domains: " + mDomains;
- String mtu = "MTU: " + mMtu;
+ String mtu = " MTU: " + mMtu;
String routes = " Routes: [";
for (RouteInfo route : mRoutes) routes += route.toString() + ",";
routes += "] ";
- String proxy = (mHttpProxy == null ? "" : "HttpProxy: " + mHttpProxy.toString() + " ");
+ String proxy = (mHttpProxy == null ? "" : " HttpProxy: " + mHttpProxy.toString() + " ");
String stacked = "";
if (mStackedLinks.values().size() > 0) {
@@ -486,6 +505,7 @@
* Returns true if this link has an IPv4 address.
*
* @return {@code true} if there is an IPv4 address, {@code false} otherwise.
+ * @hide
*/
public boolean hasIPv4Address() {
for (LinkAddress address : mLinkAddresses) {
@@ -500,6 +520,7 @@
* Returns true if this link has an IPv6 address.
*
* @return {@code true} if there is an IPv6 address, {@code false} otherwise.
+ * @hide
*/
public boolean hasIPv6Address() {
for (LinkAddress address : mLinkAddresses) {
@@ -543,7 +564,7 @@
* @hide
*/
public boolean isIdenticalDnses(LinkProperties target) {
- Collection<InetAddress> targetDnses = target.getDnses();
+ Collection<InetAddress> targetDnses = target.getDnsServers();
String targetDomains = target.getDomains();
if (mDomains == null) {
if (targetDomains != null) return false;
@@ -696,7 +717,7 @@
result.removed = new ArrayList<InetAddress>(mDnses);
result.added.clear();
if (target != null) {
- for (InetAddress newAddress : target.getDnses()) {
+ for (InetAddress newAddress : target.getDnsServers()) {
if (! result.removed.remove(newAddress)) {
result.added.add(newAddress);
}
@@ -831,7 +852,7 @@
addressCount = in.readInt();
for (int i=0; i<addressCount; i++) {
try {
- netProp.addDns(InetAddress.getByAddress(in.createByteArray()));
+ netProp.addDnsServer(InetAddress.getByAddress(in.createByteArray()));
} catch (UnknownHostException e) { }
}
netProp.setDomains(in.readString());
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 35274f1..fe96287 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -44,6 +44,9 @@
private static final String TAG = "NetworkCapabilities";
private static final boolean DBG = false;
+ /**
+ * @hide
+ */
public NetworkCapabilities() {
}
@@ -154,58 +157,64 @@
* Multiple capabilities may be applied sequentially. Note that when searching
* for a network to satisfy a request, all capabilities requested must be satisfied.
*
- * @param networkCapability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be added.
+ * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be added.
+ * @return This NetworkCapability to facilitate chaining.
+ * @hide
*/
- public void addNetworkCapability(int networkCapability) {
- if (networkCapability < MIN_NET_CAPABILITY ||
- networkCapability > MAX_NET_CAPABILITY) {
+ public NetworkCapabilities addCapability(int capability) {
+ if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
throw new IllegalArgumentException("NetworkCapability out of range");
}
- mNetworkCapabilities |= 1 << networkCapability;
+ mNetworkCapabilities |= 1 << capability;
+ return this;
}
/**
* Removes (if found) the given capability from this {@code NetworkCapability} instance.
*
- * @param networkCapability the {@code NetworkCapabilities.NET_CAPABILTIY_*} to be removed.
+ * @param capability the {@code NetworkCapabilities.NET_CAPABILTIY_*} to be removed.
+ * @return This NetworkCapability to facilitate chaining.
+ * @hide
*/
- public void removeNetworkCapability(int networkCapability) {
- if (networkCapability < MIN_NET_CAPABILITY ||
- networkCapability > MAX_NET_CAPABILITY) {
+ public NetworkCapabilities removeCapability(int capability) {
+ if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
throw new IllegalArgumentException("NetworkCapability out of range");
}
- mNetworkCapabilities &= ~(1 << networkCapability);
+ mNetworkCapabilities &= ~(1 << capability);
+ return this;
}
/**
* Gets all the capabilities set on this {@code NetworkCapability} instance.
*
- * @return a {@link Collection} of {@code NetworkCapabilities.NET_CAPABILITY_*} values
+ * @return an array of {@code NetworkCapabilities.NET_CAPABILITY_*} values
* for this instance.
+ * @hide
*/
- public Collection<Integer> getNetworkCapabilities() {
+ public int[] getCapabilities() {
return enumerateBits(mNetworkCapabilities);
}
/**
* Tests for the presence of a capabilitity on this instance.
*
- * @param networkCapability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be tested for.
+ * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be tested for.
* @return {@code true} if set on this instance.
*/
- public boolean hasCapability(int networkCapability) {
- if (networkCapability < MIN_NET_CAPABILITY ||
- networkCapability > MAX_NET_CAPABILITY) {
+ public boolean hasCapability(int capability) {
+ if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
return false;
}
- return ((mNetworkCapabilities & (1 << networkCapability)) != 0);
+ return ((mNetworkCapabilities & (1 << capability)) != 0);
}
- private Collection<Integer> enumerateBits(long val) {
- ArrayList<Integer> result = new ArrayList<Integer>();
+ private int[] enumerateBits(long val) {
+ int size = Long.bitCount(val);
+ int[] result = new int[size];
+ int index = 0;
int resource = 0;
while (val > 0) {
- if ((val & 1) == 1) result.add(resource);
+ if ((val & 1) == 1) result[index++] = resource;
val = val >> 1;
resource++;
}
@@ -265,33 +274,40 @@
* {@code NetworkCapabilities.NET_CAPABILITY_*} listed above.
*
* @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be added.
+ * @return This NetworkCapability to facilitate chaining.
+ * @hide
*/
- public void addTransportType(int transportType) {
+ public NetworkCapabilities addTransportType(int transportType) {
if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
throw new IllegalArgumentException("TransportType out of range");
}
mTransportTypes |= 1 << transportType;
+ return this;
}
/**
* Removes (if found) the given transport from this {@code NetworkCapability} instance.
*
* @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be removed.
+ * @return This NetworkCapability to facilitate chaining.
+ * @hide
*/
- public void removeTransportType(int transportType) {
+ public NetworkCapabilities removeTransportType(int transportType) {
if (transportType < MIN_TRANSPORT || transportType > MAX_TRANSPORT) {
throw new IllegalArgumentException("TransportType out of range");
}
mTransportTypes &= ~(1 << transportType);
+ return this;
}
/**
* Gets all the transports set on this {@code NetworkCapability} instance.
*
- * @return a {@link Collection} of {@code NetworkCapabilities.TRANSPORT_*} values
+ * @return an array of {@code NetworkCapabilities.TRANSPORT_*} values
* for this instance.
+ * @hide
*/
- public Collection<Integer> getTransportTypes() {
+ public int[] getTransportTypes() {
return enumerateBits(mTransportTypes);
}
@@ -340,6 +356,7 @@
* fast backhauls and slow backhauls.
*
* @param upKbps the estimated first hop upstream (device to network) bandwidth.
+ * @hide
*/
public void setLinkUpstreamBandwidthKbps(int upKbps) {
mLinkUpBandwidthKbps = upKbps;
@@ -368,6 +385,7 @@
* fast backhauls and slow backhauls.
*
* @param downKbps the estimated first hop downstream (network to device) bandwidth.
+ * @hide
*/
public void setLinkDownstreamBandwidthKbps(int downKbps) {
mLinkDownBandwidthKbps = downKbps;
@@ -464,24 +482,22 @@
};
public String toString() {
- Collection<Integer> types = getTransportTypes();
- String transports = (types.size() > 0 ? " Transports: " : "");
- Iterator<Integer> i = types.iterator();
- while (i.hasNext()) {
- switch (i.next()) {
+ int[] types = getTransportTypes();
+ String transports = (types.length > 0 ? " Transports: " : "");
+ for (int i = 0; i < types.length;) {
+ switch (types[i]) {
case TRANSPORT_CELLULAR: transports += "CELLULAR"; break;
case TRANSPORT_WIFI: transports += "WIFI"; break;
case TRANSPORT_BLUETOOTH: transports += "BLUETOOTH"; break;
case TRANSPORT_ETHERNET: transports += "ETHERNET"; break;
}
- if (i.hasNext()) transports += "|";
+ if (++i < types.length) transports += "|";
}
- types = getNetworkCapabilities();
- String capabilities = (types.size() > 0 ? " Capabilities: " : "");
- i = types.iterator();
- while (i.hasNext()) {
- switch (i.next().intValue()) {
+ types = getCapabilities();
+ String capabilities = (types.length > 0 ? " Capabilities: " : "");
+ for (int i = 0; i < types.length; ) {
+ switch (types[i]) {
case NET_CAPABILITY_MMS: capabilities += "MMS"; break;
case NET_CAPABILITY_SUPL: capabilities += "SUPL"; break;
case NET_CAPABILITY_DUN: capabilities += "DUN"; break;
@@ -497,7 +513,7 @@
case NET_CAPABILITY_INTERNET: capabilities += "INTERNET"; break;
case NET_CAPABILITY_NOT_RESTRICTED: capabilities += "NOT_RESTRICTED"; break;
}
- if (i.hasNext()) capabilities += "&";
+ if (++i < types.length) capabilities += "&";
}
String upBand = ((mLinkUpBandwidthKbps > 0) ? " LinkUpBandwidth>=" +
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 47377e9..7911c72 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -22,19 +22,14 @@
import java.util.concurrent.atomic.AtomicInteger;
/**
- * Defines a request for a network, made by calling {@link ConnectivityManager#requestNetwork}
- * or {@link ConnectivityManager#listenForNetwork}.
- *
- * This token records the {@link NetworkCapabilities} used to make the request and identifies
- * the request. It should be used to release the request via
- * {@link ConnectivityManager#releaseNetworkRequest} when the network is no longer desired.
+ * Defines a request for a network, made through {@link NetworkRequest.Builder} and used
+ * to request a network via {@link ConnectivityManager#requestNetwork} or listen for changes
+ * via {@link ConnectivityManager#listenForNetwork}.
*/
public class NetworkRequest implements Parcelable {
/**
- * The {@link NetworkCapabilities} that define this request. This should not be modified.
- * The networkCapabilities of the request are set when
- * {@link ConnectivityManager#requestNetwork} is called and the value is presented here
- * as a convenient reminder of what was requested.
+ * The {@link NetworkCapabilities} that define this request.
+ * @hide
*/
public final NetworkCapabilities networkCapabilities;
@@ -71,6 +66,95 @@
this.legacyType = that.legacyType;
}
+ /**
+ * Builder used to create {@link NetworkRequest} objects. Specify the Network features
+ * needed in terms of {@link NetworkCapabilities} features
+ */
+ public static class Builder {
+ private final NetworkCapabilities mNetworkCapabilities = new NetworkCapabilities();
+
+ /**
+ * Default constructor for Builder.
+ */
+ public Builder() {}
+
+ /**
+ * Build {@link NetworkRequest} give the current set of capabilities.
+ */
+ public NetworkRequest build() {
+ return new NetworkRequest(mNetworkCapabilities, ConnectivityManager.TYPE_NONE,
+ ConnectivityManager.REQUEST_ID_UNSET);
+ }
+
+ /**
+ * Add the given capability requirement to this builder. These represent
+ * the requested network's required capabilities. Note that when searching
+ * for a network to satisfy a request, all capabilities requested must be
+ * satisfied. See {@link NetworkCapabilities} for {@code NET_CAPABILITIY_*}
+ * definitions.
+ *
+ * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to add.
+ * @return The builder to facilitate chaining
+ * {@code builder.addCapability(...).addCapability();}.
+ */
+ public Builder addCapability(int capability) {
+ mNetworkCapabilities.addCapability(capability);
+ return this;
+ }
+
+ /**
+ * Removes (if found) the given capability from this builder instance.
+ *
+ * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to remove.
+ * @return The builder to facilitate chaining.
+ */
+ public Builder removeCapability(int capability) {
+ mNetworkCapabilities.removeCapability(capability);
+ return this;
+ }
+
+ /**
+ * Adds the given transport requirement to this builder. These represent
+ * the set of allowed transports for the request. Only networks using one
+ * of these transports will satisfy the request. If no particular transports
+ * are required, none should be specified here. See {@link NetworkCapabilities}
+ * for {@code TRANSPORT_*} definitions.
+ *
+ * @param transportType The {@code NetworkCapabilities.TRANSPORT_*} to add.
+ * @return The builder to facilitate chaining.
+ */
+ public Builder addTransportType(int transportType) {
+ mNetworkCapabilities.addTransportType(transportType);
+ return this;
+ }
+
+ /**
+ * Removes (if found) the given transport from this builder instance.
+ *
+ * @param transportType The {@code NetworkCapabilities.TRANSPORT_*} to remove.
+ * @return The builder to facilitate chaining.
+ */
+ public Builder removeTransportType(int transportType) {
+ mNetworkCapabilities.removeTransportType(transportType);
+ return this;
+ }
+
+ /**
+ * @hide
+ */
+ public Builder setLinkUpstreamBandwidthKbps(int upKbps) {
+ mNetworkCapabilities.setLinkUpstreamBandwidthKbps(upKbps);
+ return this;
+ }
+ /**
+ * @hide
+ */
+ public Builder setLinkDownstreamBandwidthKbps(int downKbps) {
+ mNetworkCapabilities.setLinkDownstreamBandwidthKbps(downKbps);
+ return this;
+ }
+ }
+
// implement the Parcelable interface
public int describeContents() {
return 0;
diff --git a/core/java/android/net/ProxyDataTracker.java b/core/java/android/net/ProxyDataTracker.java
index 4973b3d..573a8f8 100644
--- a/core/java/android/net/ProxyDataTracker.java
+++ b/core/java/android/net/ProxyDataTracker.java
@@ -107,8 +107,8 @@
mNetworkCapabilities = new NetworkCapabilities();
mNetworkInfo.setIsAvailable(true);
try {
- mLinkProperties.addDns(InetAddress.getByName(DNS1));
- mLinkProperties.addDns(InetAddress.getByName(DNS2));
+ mLinkProperties.addDnsServer(InetAddress.getByName(DNS1));
+ mLinkProperties.addDnsServer(InetAddress.getByName(DNS2));
} catch (UnknownHostException e) {
Log.e(TAG, "Could not add DNS address", e);
}
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index ad8e4f7..c2b888c 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -35,10 +35,10 @@
*
* A route contains three pieces of information:
* <ul>
- * <li>a destination {@link LinkAddress} for directly-connected subnets. If this is
- * {@code null} it indicates a default route of the address family (IPv4 or IPv6)
+ * <li>a destination {@link IpPrefix} specifying the network destinations covered by this route.
+ * If this is {@code null} it indicates a default route of the address family (IPv4 or IPv6)
* implied by the gateway IP address.
- * <li>a gateway {@link InetAddress} for default routes. If this is {@code null} it
+ * <li>a gateway {@link InetAddress} indicating the next hop to use. If this is {@code null} it
* indicates a directly-connected route.
* <li>an interface (which may be unspecified).
* </ul>
@@ -46,9 +46,10 @@
* destination and gateway are both specified, they must be of the same address family
* (IPv4 or IPv6).
*/
-public class RouteInfo implements Parcelable {
+public final class RouteInfo implements Parcelable {
/**
* The IP destination address for this route.
+ * TODO: Make this an IpPrefix.
*/
private final LinkAddress mDestination;
@@ -80,6 +81,19 @@
* @param destination the destination prefix
* @param gateway the IP address to route packets through
* @param iface the interface name to send packets on
+ *
+ * TODO: Convert to use IpPrefix.
+ *
+ * @hide
+ */
+ public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
+ this(destination == null ? null :
+ new LinkAddress(destination.getAddress(), destination.getPrefixLength()),
+ gateway, iface);
+ }
+
+ /**
+ * @hide
*/
public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
if (destination == null) {
@@ -105,7 +119,7 @@
mHasGateway = (!gateway.isAnyLocalAddress());
mDestination = new LinkAddress(NetworkUtils.getNetworkPart(destination.getAddress(),
- destination.getNetworkPrefixLength()), destination.getNetworkPrefixLength());
+ destination.getPrefixLength()), destination.getPrefixLength());
if ((destination.getAddress() instanceof Inet4Address &&
(gateway instanceof Inet4Address == false)) ||
(destination.getAddress() instanceof Inet6Address &&
@@ -128,8 +142,17 @@
* <p>
* Destination and gateway may not both be null.
*
- * @param destination the destination address and prefix in a {@link LinkAddress}
+ * @param destination the destination address and prefix in an {@link IpPrefix}
* @param gateway the {@link InetAddress} to route packets through
+ *
+ * @hide
+ */
+ public RouteInfo(IpPrefix destination, InetAddress gateway) {
+ this(destination, gateway, null);
+ }
+
+ /**
+ * @hide
*/
public RouteInfo(LinkAddress destination, InetAddress gateway) {
this(destination, gateway, null);
@@ -139,16 +162,27 @@
* Constructs a default {@code RouteInfo} object.
*
* @param gateway the {@link InetAddress} to route packets through
+ *
+ * @hide
*/
public RouteInfo(InetAddress gateway) {
- this(null, gateway, null);
+ this((LinkAddress) null, gateway, null);
}
/**
* Constructs a {@code RouteInfo} object representing a direct connected subnet.
*
- * @param destination the {@link LinkAddress} describing the address and prefix
+ * @param destination the {@link IpPrefix} describing the address and prefix
* length of the subnet.
+ *
+ * @hide
+ */
+ public RouteInfo(IpPrefix destination) {
+ this(destination, null, null);
+ }
+
+ /**
+ * @hide
*/
public RouteInfo(LinkAddress destination) {
this(destination, null, null);
@@ -176,29 +210,37 @@
private boolean isHost() {
return (mDestination.getAddress() instanceof Inet4Address &&
- mDestination.getNetworkPrefixLength() == 32) ||
+ mDestination.getPrefixLength() == 32) ||
(mDestination.getAddress() instanceof Inet6Address &&
- mDestination.getNetworkPrefixLength() == 128);
+ mDestination.getPrefixLength() == 128);
}
private boolean isDefault() {
boolean val = false;
if (mGateway != null) {
if (mGateway instanceof Inet4Address) {
- val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
+ val = (mDestination == null || mDestination.getPrefixLength() == 0);
} else {
- val = (mDestination == null || mDestination.getNetworkPrefixLength() == 0);
+ val = (mDestination == null || mDestination.getPrefixLength() == 0);
}
}
return val;
}
/**
- * Retrieves the destination address and prefix length in the form of a {@link LinkAddress}.
+ * Retrieves the destination address and prefix length in the form of an {@link IpPrefix}.
*
- * @return {@link LinkAddress} specifying the destination. This is never {@code null}.
+ * @return {@link IpPrefix} specifying the destination. This is never {@code null}.
*/
- public LinkAddress getDestination() {
+ public IpPrefix getDestination() {
+ return new IpPrefix(mDestination.getAddress(), mDestination.getPrefixLength());
+ }
+
+ /**
+ * TODO: Convert callers to use IpPrefix and then remove.
+ * @hide
+ */
+ public LinkAddress getDestinationLinkAddress() {
return mDestination;
}
@@ -233,7 +275,8 @@
/**
* Indicates if this route is a host route (ie, matches only a single host address).
*
- * @return {@code true} if the destination has a prefix length of 32/128 for v4/v6.
+ * @return {@code true} if the destination has a prefix length of 32 or 128 for IPv4 or IPv6,
+ * respectively.
* @hide
*/
public boolean isHostRoute() {
@@ -263,7 +306,7 @@
// match the route destination and destination with prefix length
InetAddress dstNet = NetworkUtils.getNetworkPart(destination,
- mDestination.getNetworkPrefixLength());
+ mDestination.getPrefixLength());
return mDestination.getAddress().equals(dstNet);
}
@@ -285,8 +328,8 @@
for (RouteInfo route : routes) {
if (NetworkUtils.addressTypeMatches(route.mDestination.getAddress(), dest)) {
if ((bestRoute != null) &&
- (bestRoute.mDestination.getNetworkPrefixLength() >=
- route.mDestination.getNetworkPrefixLength())) {
+ (bestRoute.mDestination.getPrefixLength() >=
+ route.mDestination.getPrefixLength())) {
continue;
}
if (route.matches(dest)) bestRoute = route;
@@ -295,13 +338,22 @@
return bestRoute;
}
+ /**
+ * Returns a human-readable description of this object.
+ */
public String toString() {
String val = "";
if (mDestination != null) val = mDestination.toString();
- if (mGateway != null) val += " -> " + mGateway.getHostAddress();
+ val += " ->";
+ if (mGateway != null) val += " " + mGateway.getHostAddress();
+ if (mInterface != null) val += " " + mInterface;
return val;
}
+ /**
+ * Compares this RouteInfo object against the specified object and indicates if they are equal.
+ * @return {@code true} if the objects are equal, {@code false} otherwise.
+ */
public boolean equals(Object obj) {
if (this == obj) return true;
@@ -309,11 +361,14 @@
RouteInfo target = (RouteInfo) obj;
- return Objects.equals(mDestination, target.getDestination()) &&
+ return Objects.equals(mDestination, target.getDestinationLinkAddress()) &&
Objects.equals(mGateway, target.getGateway()) &&
Objects.equals(mInterface, target.getInterface());
}
+ /**
+ * Returns a hashcode for this <code>RouteInfo</code> object.
+ */
public int hashCode() {
return (mDestination == null ? 0 : mDestination.hashCode() * 41)
+ (mGateway == null ? 0 :mGateway.hashCode() * 47)
@@ -323,7 +378,6 @@
/**
* Implement the Parcelable interface
- * @hide
*/
public int describeContents() {
return 0;
@@ -331,7 +385,6 @@
/**
* Implement the Parcelable interface
- * @hide
*/
public void writeToParcel(Parcel dest, int flags) {
if (mDestination == null) {
@@ -339,7 +392,7 @@
} else {
dest.writeByte((byte) 1);
dest.writeByteArray(mDestination.getAddress().getAddress());
- dest.writeInt(mDestination.getNetworkPrefixLength());
+ dest.writeInt(mDestination.getPrefixLength());
}
if (mGateway == null) {
@@ -354,7 +407,6 @@
/**
* Implement the Parcelable interface.
- * @hide
*/
public static final Creator<RouteInfo> CREATOR =
new Creator<RouteInfo>() {
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index fd475cd..8bd0f4d 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -29,6 +29,7 @@
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.ArrayMap;
import android.util.Log;
import java.util.List;
@@ -54,7 +55,7 @@
+ "[" + getClass().getSimpleName() + "]";
private INotificationListenerWrapper mWrapper = null;
- private Ranking mRanking;
+ private RankingMap mRankingMap;
private INotificationManager mNoMan;
@@ -75,7 +76,22 @@
* object as well as its identifying information (tag and id) and source
* (package name).
*/
- public abstract void onNotificationPosted(StatusBarNotification sbn);
+ public void onNotificationPosted(StatusBarNotification sbn) {
+ // optional
+ }
+
+ /**
+ * Implement this method to learn about new notifications as they are posted by apps.
+ *
+ * @param sbn A data structure encapsulating the original {@link android.app.Notification}
+ * object as well as its identifying information (tag and id) and source
+ * (package name).
+ * @param rankingMap The current ranking map that can be used to retrieve ranking information
+ * for active notifications, including the newly posted one.
+ */
+ public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
+ onNotificationPosted(sbn);
+ }
/**
* Implement this method to learn when notifications are removed.
@@ -94,7 +110,33 @@
* and source (package name) used to post the {@link android.app.Notification} that
* was just removed.
*/
- public abstract void onNotificationRemoved(StatusBarNotification sbn);
+ public void onNotificationRemoved(StatusBarNotification sbn) {
+ // optional
+ }
+
+ /**
+ * Implement this method to learn when notifications are removed.
+ * <P>
+ * This might occur because the user has dismissed the notification using system UI (or another
+ * notification listener) or because the app has withdrawn the notification.
+ * <P>
+ * NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
+ * result from {@link StatusBarNotification#getNotification} may be missing some heavyweight
+ * fields such as {@link android.app.Notification#contentView} and
+ * {@link android.app.Notification#largeIcon}. However, all other fields on
+ * {@link StatusBarNotification}, sufficient to match this call with a prior call to
+ * {@link #onNotificationPosted(StatusBarNotification)}, will be intact.
+ *
+ * @param sbn A data structure encapsulating at least the original information (tag and id)
+ * and source (package name) used to post the {@link android.app.Notification} that
+ * was just removed.
+ * @param rankingMap The current ranking map that can be used to retrieve ranking information
+ * for active notifications.
+ *
+ */
+ public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap) {
+ onNotificationRemoved(sbn);
+ }
/**
* Implement this method to learn about when the listener is enabled and connected to
@@ -107,10 +149,11 @@
/**
* Implement this method to be notified when the notification ranking changes.
- * <P>
- * Call {@link #getCurrentRanking()} to retrieve the new ranking.
+ *
+ * @param rankingMap The current ranking map that can be used to retrieve ranking information
+ * for active notifications.
*/
- public void onNotificationRankingUpdate() {
+ public void onNotificationRankingUpdate(RankingMap rankingMap) {
// optional
}
@@ -241,16 +284,19 @@
*
* <p>
* The returned object represents the current ranking snapshot and only
- * applies for currently active notifications. Hence you must retrieve a
- * new Ranking after each notification event such as
- * {@link #onNotificationPosted(StatusBarNotification)},
- * {@link #onNotificationRemoved(StatusBarNotification)}, etc.
+ * applies for currently active notifications.
+ * <p>
+ * Generally you should use the RankingMap that is passed with events such
+ * as {@link #onNotificationPosted(StatusBarNotification, RankingMap)},
+ * {@link #onNotificationRemoved(StatusBarNotification, RankingMap)}, and
+ * so on. This method should only be used when needing access outside of
+ * such events, for example to retrieve the RankingMap right after
+ * initialization.
*
- * @return A {@link NotificationListenerService.Ranking} object providing
- * access to ranking information
+ * @return A {@link RankingMap} object providing access to ranking information
*/
- public Ranking getCurrentRanking() {
- return mRanking;
+ public RankingMap getCurrentRanking() {
+ return mRankingMap;
}
@Override
@@ -313,7 +359,7 @@
synchronized (mWrapper) {
applyUpdate(update);
try {
- NotificationListenerService.this.onNotificationPosted(sbn);
+ NotificationListenerService.this.onNotificationPosted(sbn, mRankingMap);
} catch (Throwable t) {
Log.w(TAG, "Error running onNotificationPosted", t);
}
@@ -326,7 +372,7 @@
synchronized (mWrapper) {
applyUpdate(update);
try {
- NotificationListenerService.this.onNotificationRemoved(sbn);
+ NotificationListenerService.this.onNotificationRemoved(sbn, mRankingMap);
} catch (Throwable t) {
Log.w(TAG, "Error running onNotificationRemoved", t);
}
@@ -351,7 +397,7 @@
synchronized (mWrapper) {
applyUpdate(update);
try {
- NotificationListenerService.this.onNotificationRankingUpdate();
+ NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap);
} catch (Throwable t) {
Log.w(TAG, "Error running onNotificationRankingUpdate", t);
}
@@ -360,7 +406,65 @@
}
private void applyUpdate(NotificationRankingUpdate update) {
- mRanking = new Ranking(update);
+ mRankingMap = new RankingMap(update);
+ }
+
+ /**
+ * Provides access to ranking information on a currently active
+ * notification.
+ *
+ * <p>
+ * Note that this object is not updated on notification events (such as
+ * {@link #onNotificationPosted(StatusBarNotification, RankingMap)},
+ * {@link #onNotificationRemoved(StatusBarNotification)}, etc.). Make sure
+ * to retrieve a new Ranking from the current {@link RankingMap} whenever
+ * a notification event occurs.
+ */
+ public static class Ranking {
+ private final String mKey;
+ private final int mRank;
+ private final boolean mIsAmbient;
+ private final boolean mIsInterceptedByDnd;
+
+ private Ranking(String key, int rank, boolean isAmbient, boolean isInterceptedByDnd) {
+ mKey = key;
+ mRank = rank;
+ mIsAmbient = isAmbient;
+ mIsInterceptedByDnd = isInterceptedByDnd;
+ }
+
+ /**
+ * Returns the key of the notification this Ranking applies to.
+ */
+ public String getKey() {
+ return mKey;
+ }
+
+ /**
+ * Returns the rank of the notification.
+ *
+ * @return the rank of the notification, that is the 0-based index in
+ * the list of active notifications.
+ */
+ public int getRank() {
+ return mRank;
+ }
+
+ /**
+ * Returns whether the notification is an ambient notification, that is
+ * a notification that doesn't require the user's immediate attention.
+ */
+ public boolean isAmbient() {
+ return mIsAmbient;
+ }
+
+ /**
+ * Returns whether the notification was intercepted by
+ * "Do not disturb".
+ */
+ public boolean isInterceptedByDoNotDisturb() {
+ return mIsInterceptedByDnd;
+ }
}
/**
@@ -371,11 +475,14 @@
* Note that this object represents a ranking snapshot that only applies to
* notifications active at the time of retrieval.
*/
- public static class Ranking implements Parcelable {
+ public static class RankingMap implements Parcelable {
private final NotificationRankingUpdate mRankingUpdate;
+ private final ArrayMap<String, Ranking> mRankingCache;
+ private boolean mRankingCacheInitialized;
- private Ranking(NotificationRankingUpdate rankingUpdate) {
+ private RankingMap(NotificationRankingUpdate rankingUpdate) {
mRankingUpdate = rankingUpdate;
+ mRankingCache = new ArrayMap<>(rankingUpdate.getOrderedKeys().length);
}
/**
@@ -389,56 +496,37 @@
}
/**
- * Returns the rank of the notification with the given key, that is the
- * index of <code>key</code> in the array of keys returned by
- * {@link #getOrderedKeys()}.
+ * Returns the Ranking for the notification with the given key.
*
- * @return The rank of the notification with the given key; -1 when the
- * given key is unknown.
+ * @return the Ranking of the notification with the given key;
+ * <code>null</code> when the key is unknown.
*/
- public int getRank(String key) {
- // TODO: Optimize.
+ public Ranking getRanking(String key) {
+ synchronized (mRankingCache) {
+ if (!mRankingCacheInitialized) {
+ initializeRankingCache();
+ mRankingCacheInitialized = true;
+ }
+ }
+ return mRankingCache.get(key);
+ }
+
+ private void initializeRankingCache() {
String[] orderedKeys = mRankingUpdate.getOrderedKeys();
- for (int i = 0; i < orderedKeys.length; i++) {
- if (orderedKeys[i].equals(key)) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- * Returns whether the notification with the given key was intercepted
- * by "Do not disturb".
- */
- public boolean isInterceptedByDoNotDisturb(String key) {
- // TODO: Optimize.
- for (String interceptedKey : mRankingUpdate.getDndInterceptedKeys()) {
- if (interceptedKey.equals(key)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns whether the notification with the given key is an ambient
- * notification, that is a notification that doesn't require the user's
- * immediate attention.
- */
- public boolean isAmbient(String key) {
- // TODO: Optimize.
int firstAmbientIndex = mRankingUpdate.getFirstAmbientIndex();
- if (firstAmbientIndex < 0) {
- return false;
- }
- String[] orderedKeys = mRankingUpdate.getOrderedKeys();
- for (int i = firstAmbientIndex; i < orderedKeys.length; i++) {
- if (orderedKeys[i].equals(key)) {
- return true;
+ for (int i = 0; i < orderedKeys.length; i++) {
+ String key = orderedKeys[i];
+ boolean isAmbient = firstAmbientIndex > -1 && firstAmbientIndex <= i;
+ boolean isInterceptedByDnd = false;
+ // TODO: Optimize.
+ for (String s : mRankingUpdate.getDndInterceptedKeys()) {
+ if (s.equals(key)) {
+ isInterceptedByDnd = true;
+ break;
+ }
}
+ mRankingCache.put(key, new Ranking(key, i, isAmbient, isInterceptedByDnd));
}
- return false;
}
// ----------- Parcelable
@@ -453,16 +541,16 @@
dest.writeParcelable(mRankingUpdate, flags);
}
- public static final Creator<Ranking> CREATOR = new Creator<Ranking>() {
+ public static final Creator<RankingMap> CREATOR = new Creator<RankingMap>() {
@Override
- public Ranking createFromParcel(Parcel source) {
+ public RankingMap createFromParcel(Parcel source) {
NotificationRankingUpdate rankingUpdate = source.readParcelable(null);
- return new Ranking(rankingUpdate);
+ return new RankingMap(rankingUpdate);
}
@Override
- public Ranking[] newArray(int size) {
- return new Ranking[size];
+ public RankingMap[] newArray(int size) {
+ return new RankingMap[size];
}
};
}
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 11db996..72b9d3e 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -74,7 +74,8 @@
private boolean mProfilingEnabled;
ThreadedRenderer(boolean translucent) {
- AtlasInitializer.sInstance.init();
+ // Temporarily disabled
+ //AtlasInitializer.sInstance.init();
long rootNodePtr = nCreateRootRenderNode();
mRootNode = RenderNode.adopt(rootNodePtr);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 117fe8e..7c70ee4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6105,7 +6105,7 @@
// apply insets path and take things from there.
try {
mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
- return !dispatchApplyWindowInsets(new WindowInsets(insets)).hasInsets();
+ return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
} finally {
mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0f40ee7..eef09ae 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5574,11 +5574,11 @@
@Override
public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
insets = super.dispatchApplyWindowInsets(insets);
- if (insets.hasInsets()) {
+ if (!insets.isConsumed()) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
insets = getChildAt(i).dispatchApplyWindowInsets(insets);
- if (!insets.hasInsets()) {
+ if (insets.isConsumed()) {
break;
}
}
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index 294f472..3a1e826 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -35,6 +35,9 @@
private Rect mTempRect;
private boolean mIsRound;
+ private boolean mSystemWindowInsetsConsumed = false;
+ private boolean mWindowDecorInsetsConsumed = false;
+
private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0);
/**
@@ -52,13 +55,17 @@
/** @hide */
public WindowInsets(Rect systemWindowInsets, boolean isRound) {
- this(systemWindowInsets, EMPTY_RECT, isRound);
+ this(systemWindowInsets, null, isRound);
}
/** @hide */
public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, boolean isRound) {
- mSystemWindowInsets = systemWindowInsets;
- mWindowDecorInsets = windowDecorInsets;
+ mSystemWindowInsetsConsumed = systemWindowInsets == null;
+ mSystemWindowInsets = mSystemWindowInsetsConsumed ? EMPTY_RECT : systemWindowInsets;
+
+ mWindowDecorInsetsConsumed = windowDecorInsets == null;
+ mWindowDecorInsets = mWindowDecorInsetsConsumed ? EMPTY_RECT : windowDecorInsets;
+
mIsRound = isRound;
}
@@ -70,12 +77,14 @@
public WindowInsets(WindowInsets src) {
mSystemWindowInsets = src.mSystemWindowInsets;
mWindowDecorInsets = src.mWindowDecorInsets;
+ mSystemWindowInsetsConsumed = src.mSystemWindowInsetsConsumed;
+ mWindowDecorInsetsConsumed = src.mWindowDecorInsetsConsumed;
mIsRound = src.mIsRound;
}
/** @hide */
public WindowInsets(Rect systemWindowInsets) {
- this(systemWindowInsets, EMPTY_RECT);
+ this(systemWindowInsets, null);
}
/**
@@ -238,6 +247,24 @@
}
/**
+ * Check if these insets have been fully consumed.
+ *
+ * <p>Insets are considered "consumed" if the applicable <code>consume*</code> methods
+ * have been called such that all insets have been set to zero. This affects propagation of
+ * insets through the view hierarchy; insets that have not been fully consumed will continue
+ * to propagate down to child views.</p>
+ *
+ * <p>The result of this method is equivalent to the return value of
+ * {@link View#fitSystemWindows(android.graphics.Rect)}.</p>
+ *
+ * @return true if the insets have been fully consumed.
+ * @hide Pending API
+ */
+ public boolean isConsumed() {
+ return mSystemWindowInsetsConsumed && mWindowDecorInsetsConsumed;
+ }
+
+ /**
* Returns true if the associated window has a round shape.
*
* <p>A round window's left, top, right and bottom edges reach all the way to the
@@ -258,7 +285,8 @@
*/
public WindowInsets consumeSystemWindowInsets() {
final WindowInsets result = new WindowInsets(this);
- result.mSystemWindowInsets = new Rect(0, 0, 0, 0);
+ result.mSystemWindowInsets = EMPTY_RECT;
+ result.mSystemWindowInsetsConsumed = true;
return result;
}
@@ -276,10 +304,12 @@
boolean right, boolean bottom) {
if (left || top || right || bottom) {
final WindowInsets result = new WindowInsets(this);
- result.mSystemWindowInsets = new Rect(left ? 0 : mSystemWindowInsets.left,
+ result.mSystemWindowInsets = new Rect(
+ left ? 0 : mSystemWindowInsets.left,
top ? 0 : mSystemWindowInsets.top,
right ? 0 : mSystemWindowInsets.right,
bottom ? 0 : mSystemWindowInsets.bottom);
+ result.mSystemWindowInsetsConsumed = !hasSystemWindowInsets();
return result;
}
return this;
@@ -299,6 +329,7 @@
int right, int bottom) {
final WindowInsets result = new WindowInsets(this);
result.mSystemWindowInsets = new Rect(left, top, right, bottom);
+ result.mSystemWindowInsetsConsumed = !hasSystemWindowInsets();
return result;
}
@@ -308,6 +339,7 @@
public WindowInsets consumeWindowDecorInsets() {
final WindowInsets result = new WindowInsets(this);
result.mWindowDecorInsets.set(0, 0, 0, 0);
+ result.mWindowDecorInsetsConsumed = true;
return result;
}
@@ -322,6 +354,7 @@
top ? 0 : mWindowDecorInsets.top,
right ? 0 : mWindowDecorInsets.right,
bottom ? 0 : mWindowDecorInsets.bottom);
+ result.mWindowDecorInsetsConsumed = !hasWindowDecorInsets();
return result;
}
return this;
@@ -333,6 +366,7 @@
public WindowInsets replaceWindowDecorInsets(int left, int top, int right, int bottom) {
final WindowInsets result = new WindowInsets(this);
result.mWindowDecorInsets = new Rect(left, top, right, bottom);
+ result.mWindowDecorInsetsConsumed = !hasWindowDecorInsets();
return result;
}
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 8e56eec..432a615 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -828,13 +828,12 @@
: layout(layout), canvas(canvas), x(x), y(y), paint(paint), glyphs(glyphs),
pos(pos) { }
- void operator()(SkTypeface* t, size_t start, size_t end) {
+ void operator()(size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
glyphs[i] = layout.getGlyphId(i);
pos[i].fX = x + layout.getX(i);
pos[i].fY = y + layout.getY(i);
}
- paint->setTypeface(t);
canvas->drawPosText(glyphs + start, (end - start) << 1, pos + start, *paint);
}
private:
@@ -857,7 +856,7 @@
paint->setTextAlign(SkPaint::kLeft_Align);
paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
DrawTextFunctor f(layout, canvas, x, y, paint, glyphs, pos);
- MinikinUtils::forFontRun(layout, f);
+ MinikinUtils::forFontRun(layout, paint, f);
doDrawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
paint->setTextAlign(align);
delete[] glyphs;
diff --git a/core/jni/android/graphics/MinikinSkia.cpp b/core/jni/android/graphics/MinikinSkia.cpp
index 2b96f1b..25eb941 100644
--- a/core/jni/android/graphics/MinikinSkia.cpp
+++ b/core/jni/android/graphics/MinikinSkia.cpp
@@ -43,13 +43,14 @@
return !!glyph;
}
-static void MinikinFontSkia_SetSkiaPaint(SkTypeface* typeface, SkPaint* skPaint, const MinikinPaint& paint) {
- skPaint->setTypeface(typeface);
+static void MinikinFontSkia_SetSkiaPaint(const MinikinFont* font, SkPaint* skPaint, const MinikinPaint& paint) {
skPaint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
skPaint->setTextSize(paint.size);
skPaint->setTextScaleX(paint.scaleX);
skPaint->setTextSkewX(paint.skewX);
MinikinFontSkia::unpackPaintFlags(skPaint, paint.paintFlags);
+ // Apply font fakery on top of user-supplied flags.
+ MinikinFontSkia::populateSkPaint(skPaint, font, paint.fakery);
}
float MinikinFontSkia::GetHorizontalAdvance(uint32_t glyph_id,
@@ -57,7 +58,7 @@
SkPaint skPaint;
uint16_t glyph16 = glyph_id;
SkScalar skWidth;
- MinikinFontSkia_SetSkiaPaint(mTypeface, &skPaint, paint);
+ MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint);
skPaint.getTextWidths(&glyph16, sizeof(glyph16), &skWidth, NULL);
#ifdef VERBOSE
ALOGD("width for typeface %d glyph %d = %f", mTypeface->uniqueID(), glyph_id, skWidth);
@@ -70,7 +71,7 @@
SkPaint skPaint;
uint16_t glyph16 = glyph_id;
SkRect skBounds;
- MinikinFontSkia_SetSkiaPaint(mTypeface, &skPaint, paint);
+ MinikinFontSkia_SetSkiaPaint(this, &skPaint, paint);
skPaint.getTextWidths(&glyph16, sizeof(glyph16), NULL, &skBounds);
bounds->mLeft = skBounds.fLeft;
bounds->mTop = skBounds.fTop;
@@ -90,7 +91,7 @@
}
}
-SkTypeface *MinikinFontSkia::GetSkTypeface() {
+SkTypeface *MinikinFontSkia::GetSkTypeface() const {
return mTypeface;
}
@@ -115,4 +116,12 @@
paint->setHinting(static_cast<SkPaint::Hinting>(paintFlags >> 16));
}
+void MinikinFontSkia::populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery) {
+ paint->setTypeface(reinterpret_cast<const MinikinFontSkia*>(font)->GetSkTypeface());
+ paint->setFakeBoldText(paint->isFakeBoldText() || fakery.isFakeBold());
+ if (fakery.isFakeItalic()) {
+ paint->setTextSkewX(paint->getTextSkewX() - 0.25f);
+ }
+}
+
}
diff --git a/core/jni/android/graphics/MinikinSkia.h b/core/jni/android/graphics/MinikinSkia.h
index 0452c57..ac4d2a0 100644
--- a/core/jni/android/graphics/MinikinSkia.h
+++ b/core/jni/android/graphics/MinikinSkia.h
@@ -36,10 +36,13 @@
int32_t GetUniqueId() const;
- SkTypeface *GetSkTypeface();
+ SkTypeface* GetSkTypeface() const;
static uint32_t packPaintFlags(const SkPaint* paint);
static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags);
+
+ // set typeface and fake bold/italic parameters
+ static void populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery);
private:
SkTypeface *mTypeface;
};
diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h
index ea7eb5d..a96c6b1 100644
--- a/core/jni/android/graphics/MinikinUtils.h
+++ b/core/jni/android/graphics/MinikinUtils.h
@@ -36,23 +36,30 @@
static float xOffsetForTextAlign(SkPaint* paint, const Layout& layout);
- // f is a functor of type void f(SkTypeface *, size_t start, size_t end);
+ // f is a functor of type void f(size_t start, size_t end);
template <typename F>
- static void forFontRun(const Layout& layout, F& f) {
- SkTypeface* lastFace = NULL;
+ static void forFontRun(const Layout& layout, SkPaint* paint, F& f) {
+ float saveSkewX = paint->getTextSkewX();
+ bool savefakeBold = paint->isFakeBoldText();
+ MinikinFont* curFont = NULL;
size_t start = 0;
size_t nGlyphs = layout.nGlyphs();
for (size_t i = 0; i < nGlyphs; i++) {
- MinikinFontSkia* mfs = static_cast<MinikinFontSkia*>(layout.getFont(i));
- SkTypeface* skFace = mfs->GetSkTypeface();
- if (i > 0 && skFace != lastFace) {
- f(lastFace, start, i);
+ MinikinFont* nextFont = layout.getFont(i);
+ if (i > 0 && nextFont != curFont) {
+ MinikinFontSkia::populateSkPaint(paint, curFont, layout.getFakery(start));
+ f(start, i);
+ paint->setTextSkewX(saveSkewX);
+ paint->setFakeBoldText(savefakeBold);
start = i;
}
- lastFace = skFace;
+ curFont = nextFont;
}
if (nGlyphs > start) {
- f(lastFace, start, nGlyphs);
+ MinikinFontSkia::populateSkPaint(paint, curFont, layout.getFakery(start));
+ f(start, nGlyphs);
+ paint->setTextSkewX(saveSkewX);
+ paint->setFakeBoldText(savefakeBold);
}
}
};
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 3dc874e..8b11d31 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -429,27 +429,29 @@
GraphicsJNI::getNativePaint(env, paint)->setTextSkewX(skewX);
}
- static jfloat ascent(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
- SkPaint::FontMetrics metrics;
- (void)GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
- return SkScalarToFloat(metrics.fAscent);
- }
-
- static jfloat descent(JNIEnv* env, jobject paint) {
- NPE_CHECK_RETURN_ZERO(env, paint);
- SkPaint::FontMetrics metrics;
- (void)GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
- return SkScalarToFloat(metrics.fDescent);
- }
-
- static SkScalar getMetricsInternal(SkPaint *paint, SkPaint::FontMetrics *metrics) {
+ static SkScalar getMetricsInternal(JNIEnv* env, jobject jpaint, SkPaint::FontMetrics *metrics) {
const int kElegantTop = 2500;
const int kElegantBottom = -1000;
- const int kElegantAscent = 1946;
- const int kElegantDescent = -512;
+ const int kElegantAscent = 1900;
+ const int kElegantDescent = -500;
const int kElegantLeading = 0;
+ SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);
+#ifdef USE_MINIKIN
+ TypefaceImpl* typeface = GraphicsJNI::getNativeTypeface(env, jpaint);
+ typeface = TypefaceImpl_resolveDefault(typeface);
+ FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle);
+ float saveSkewX = paint->getTextSkewX();
+ bool savefakeBold = paint->isFakeBoldText();
+ MinikinFontSkia::populateSkPaint(paint, baseFont.font, baseFont.fakery);
+#endif
SkScalar spacing = paint->getFontMetrics(metrics);
+#ifdef USE_MINIKIN
+ // The populateSkPaint call may have changed fake bold / text skew
+ // because we want to measure with those effects applied, so now
+ // restore the original settings.
+ paint->setTextSkewX(saveSkewX);
+ paint->setFakeBoldText(savefakeBold);
+#endif
SkPaintOptionsAndroid paintOpts = paint->getPaintOptionsAndroid();
if (paintOpts.getFontVariant() == SkPaintOptionsAndroid::kElegant_Variant) {
SkScalar size = paint->getTextSize();
@@ -463,10 +465,24 @@
return spacing;
}
+ static jfloat ascent(JNIEnv* env, jobject paint) {
+ NPE_CHECK_RETURN_ZERO(env, paint);
+ SkPaint::FontMetrics metrics;
+ getMetricsInternal(env, paint, &metrics);
+ return SkScalarToFloat(metrics.fAscent);
+ }
+
+ static jfloat descent(JNIEnv* env, jobject paint) {
+ NPE_CHECK_RETURN_ZERO(env, paint);
+ SkPaint::FontMetrics metrics;
+ getMetricsInternal(env, paint, &metrics);
+ return SkScalarToFloat(metrics.fDescent);
+ }
+
static jfloat getFontMetrics(JNIEnv* env, jobject paint, jobject metricsObj) {
NPE_CHECK_RETURN_ZERO(env, paint);
SkPaint::FontMetrics metrics;
- SkScalar spacing = getMetricsInternal(GraphicsJNI::getNativePaint(env, paint), &metrics);
+ SkScalar spacing = getMetricsInternal(env, paint, &metrics);
if (metricsObj) {
SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class));
@@ -483,7 +499,7 @@
NPE_CHECK_RETURN_ZERO(env, paint);
SkPaint::FontMetrics metrics;
- getMetricsInternal(GraphicsJNI::getNativePaint(env, paint), &metrics);
+ getMetricsInternal(env, paint, &metrics);
int ascent = SkScalarRoundToInt(metrics.fAscent);
int descent = SkScalarRoundToInt(metrics.fDescent);
int leading = SkScalarRoundToInt(metrics.fLeading);
@@ -830,13 +846,12 @@
: layout(layout), path(path), x(x), y(y), paint(paint), glyphs(glyphs), pos(pos) {
}
- void operator()(SkTypeface* t, size_t start, size_t end) {
+ void operator()(size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
glyphs[i] = layout.getGlyphId(i);
pos[i].fX = x + layout.getX(i);
pos[i].fY = y + layout.getY(i);
}
- paint->setTypeface(t);
if (start == 0) {
paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, path);
} else {
@@ -871,7 +886,7 @@
paint->setTextAlign(SkPaint::kLeft_Align);
paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
GetTextFunctor f(layout, path, x, y, paint, glyphs, pos);
- MinikinUtils::forFontRun(layout, f);
+ MinikinUtils::forFontRun(layout, paint, f);
paint->setTextAlign(align);
delete[] glyphs;
delete[] pos;
diff --git a/core/jni/android/graphics/TypefaceImpl.cpp b/core/jni/android/graphics/TypefaceImpl.cpp
index 27df7cf..1800d0c 100644
--- a/core/jni/android/graphics/TypefaceImpl.cpp
+++ b/core/jni/android/graphics/TypefaceImpl.cpp
@@ -173,7 +173,7 @@
} else {
const FontStyle defaultStyle;
FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]);
- MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle);
+ MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle).font;
SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface();
// TODO: probably better to query more precise style from family, will be important
// when we open up API to access 100..900 weights
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index a46ccd6..d032cb6 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -656,13 +656,12 @@
uirenderer::Rect& bounds)
: layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
pos(pos), totalAdvance(totalAdvance), bounds(bounds) { }
- void operator()(SkTypeface* t, size_t start, size_t end) {
+ void operator()(size_t start, size_t end) {
for (size_t i = start; i < end; i++) {
glyphs[i] = layout.getGlyphId(i);
pos[2 * i] = layout.getX(i);
pos[2 * i + 1] = layout.getY(i);
}
- paint->setTypeface(t);
size_t glyphsCount = end - start;
int bytesCount = glyphsCount * sizeof(jchar);
renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
@@ -692,7 +691,7 @@
float totalAdvance = layout->getAdvance();
RenderTextFunctor f(*layout, renderer, x, y, paint, glyphs, pos, totalAdvance, bounds);
- MinikinUtils::forFontRun(*layout, f);
+ MinikinUtils::forFontRun(*layout, paint, f);
delete[] glyphs;
delete[] pos;
}
diff --git a/core/res/res/layout/preference_material.xml b/core/res/res/layout/preference_material.xml
index a4fe73d..a9599139 100644
--- a/core/res/res/layout/preference_material.xml
+++ b/core/res/res/layout/preference_material.xml
@@ -31,7 +31,7 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:minWidth="58dip"
- android:gravity="left|center_vertical"
+ android:gravity="start|center_vertical"
android:orientation="horizontal">
<ImageView
android:id="@+android:id/icon"
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
index db125e6..116a31e 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/AccessPointParserHelper.java
@@ -336,7 +336,7 @@
if (!InetAddress.isNumeric(dnsAddr)) {
throw new SAXException();
}
- mLinkProperties.addDns(InetAddress.getByName(dnsAddr));
+ mLinkProperties.addDnsServer(InetAddress.getByName(dnsAddr));
} catch (UnknownHostException e) {
throw new SAXException();
}
@@ -348,7 +348,7 @@
if (!InetAddress.isNumeric(dnsAddr)) {
throw new SAXException();
}
- mLinkProperties.addDns(InetAddress.getByName(dnsAddr));
+ mLinkProperties.addDnsServer(InetAddress.getByName(dnsAddr));
} catch (UnknownHostException e) {
throw new SAXException();
}
diff --git a/core/tests/coretests/src/android/net/LinkAddressTest.java b/core/tests/coretests/src/android/net/LinkAddressTest.java
index bccf556..814ecdd 100644
--- a/core/tests/coretests/src/android/net/LinkAddressTest.java
+++ b/core/tests/coretests/src/android/net/LinkAddressTest.java
@@ -56,26 +56,26 @@
// Valid addresses work as expected.
address = new LinkAddress(V4_ADDRESS, 25);
assertEquals(V4_ADDRESS, address.getAddress());
- assertEquals(25, address.getNetworkPrefixLength());
+ assertEquals(25, address.getPrefixLength());
assertEquals(0, address.getFlags());
assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
address = new LinkAddress(V6_ADDRESS, 127);
assertEquals(V6_ADDRESS, address.getAddress());
- assertEquals(127, address.getNetworkPrefixLength());
+ assertEquals(127, address.getPrefixLength());
assertEquals(0, address.getFlags());
assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
// Nonsensical flags/scopes or combinations thereof are acceptable.
address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK);
assertEquals(V6_ADDRESS, address.getAddress());
- assertEquals(64, address.getNetworkPrefixLength());
+ assertEquals(64, address.getPrefixLength());
assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags());
assertEquals(RT_SCOPE_LINK, address.getScope());
address = new LinkAddress(V4 + "/23", 123, 456);
assertEquals(V4_ADDRESS, address.getAddress());
- assertEquals(23, address.getNetworkPrefixLength());
+ assertEquals(23, address.getPrefixLength());
assertEquals(123, address.getFlags());
assertEquals(456, address.getScope());
@@ -94,10 +94,10 @@
}
assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress());
- assertEquals(8, ipv4Loopback.getNetworkPrefixLength());
+ assertEquals(8, ipv4Loopback.getPrefixLength());
assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress());
- assertEquals(128, ipv6Loopback.getNetworkPrefixLength());
+ assertEquals(128, ipv6Loopback.getPrefixLength());
// Null addresses are rejected.
try {
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index 553afe0..e649baa 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -88,8 +88,8 @@
source.addLinkAddress(LINKADDRV4);
source.addLinkAddress(LINKADDRV6);
// set 2 dnses
- source.addDns(DNS1);
- source.addDns(DNS2);
+ source.addDnsServer(DNS1);
+ source.addDnsServer(DNS2);
// set 2 gateways
source.addRoute(new RouteInfo(GATEWAY1));
source.addRoute(new RouteInfo(GATEWAY2));
@@ -101,8 +101,8 @@
target.setInterfaceName(NAME);
target.addLinkAddress(LINKADDRV4);
target.addLinkAddress(LINKADDRV6);
- target.addDns(DNS1);
- target.addDns(DNS2);
+ target.addDnsServer(DNS1);
+ target.addDnsServer(DNS2);
target.addRoute(new RouteInfo(GATEWAY1));
target.addRoute(new RouteInfo(GATEWAY2));
target.setMtu(MTU);
@@ -114,8 +114,8 @@
target.setInterfaceName("qmi1");
target.addLinkAddress(LINKADDRV4);
target.addLinkAddress(LINKADDRV6);
- target.addDns(DNS1);
- target.addDns(DNS2);
+ target.addDnsServer(DNS1);
+ target.addDnsServer(DNS2);
target.addRoute(new RouteInfo(GATEWAY1));
target.addRoute(new RouteInfo(GATEWAY2));
target.setMtu(MTU);
@@ -127,8 +127,8 @@
target.addLinkAddress(new LinkAddress(
NetworkUtils.numericToInetAddress("75.208.6.2"), 32));
target.addLinkAddress(LINKADDRV6);
- target.addDns(DNS1);
- target.addDns(DNS2);
+ target.addDnsServer(DNS1);
+ target.addDnsServer(DNS2);
target.addRoute(new RouteInfo(GATEWAY1));
target.addRoute(new RouteInfo(GATEWAY2));
target.setMtu(MTU);
@@ -139,8 +139,8 @@
target.addLinkAddress(LINKADDRV4);
target.addLinkAddress(LINKADDRV6);
// change dnses
- target.addDns(NetworkUtils.numericToInetAddress("75.208.7.2"));
- target.addDns(DNS2);
+ target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2"));
+ target.addDnsServer(DNS2);
target.addRoute(new RouteInfo(GATEWAY1));
target.addRoute(new RouteInfo(GATEWAY2));
target.setMtu(MTU);
@@ -150,8 +150,8 @@
target.setInterfaceName(NAME);
target.addLinkAddress(LINKADDRV4);
target.addLinkAddress(LINKADDRV6);
- target.addDns(DNS1);
- target.addDns(DNS2);
+ target.addDnsServer(DNS1);
+ target.addDnsServer(DNS2);
// change gateway
target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
target.addRoute(new RouteInfo(GATEWAY2));
@@ -162,8 +162,8 @@
target.setInterfaceName(NAME);
target.addLinkAddress(LINKADDRV4);
target.addLinkAddress(LINKADDRV6);
- target.addDns(DNS1);
- target.addDns(DNS2);
+ target.addDnsServer(DNS1);
+ target.addDnsServer(DNS2);
target.addRoute(new RouteInfo(GATEWAY1));
target.addRoute(new RouteInfo(GATEWAY2));
// change mtu
@@ -185,8 +185,8 @@
source.addLinkAddress(LINKADDRV4);
source.addLinkAddress(LINKADDRV6);
// set 2 dnses
- source.addDns(DNS1);
- source.addDns(DNS2);
+ source.addDnsServer(DNS1);
+ source.addDnsServer(DNS2);
// set 2 gateways
source.addRoute(new RouteInfo(GATEWAY1));
source.addRoute(new RouteInfo(GATEWAY2));
@@ -197,8 +197,8 @@
target.setInterfaceName(NAME);
target.addLinkAddress(LINKADDRV6);
target.addLinkAddress(LINKADDRV4);
- target.addDns(DNS2);
- target.addDns(DNS1);
+ target.addDnsServer(DNS2);
+ target.addDnsServer(DNS1);
target.addRoute(new RouteInfo(GATEWAY2));
target.addRoute(new RouteInfo(GATEWAY1));
target.setMtu(MTU);
diff --git a/core/tests/coretests/src/android/net/RouteInfoTest.java b/core/tests/coretests/src/android/net/RouteInfoTest.java
index 55d6592..f67c39d 100644
--- a/core/tests/coretests/src/android/net/RouteInfoTest.java
+++ b/core/tests/coretests/src/android/net/RouteInfoTest.java
@@ -43,17 +43,17 @@
// Invalid input.
try {
- r = new RouteInfo(null, null, "rmnet0");
+ r = new RouteInfo((LinkAddress) null, null, "rmnet0");
fail("Expected RuntimeException: destination and gateway null");
} catch(RuntimeException e) {}
// Null destination is default route.
- r = new RouteInfo(null, Address("2001:db8::1"), null);
+ r = new RouteInfo((LinkAddress) null, Address("2001:db8::1"), null);
assertEquals(Prefix("::/0"), r.getDestination());
assertEquals(Address("2001:db8::1"), r.getGateway());
assertNull(r.getInterface());
- r = new RouteInfo(null, Address("192.0.2.1"), "wlan0");
+ r = new RouteInfo((LinkAddress) null, Address("192.0.2.1"), "wlan0");
assertEquals(Prefix("0.0.0.0/0"), r.getDestination());
assertEquals(Address("192.0.2.1"), r.getGateway());
assertEquals("wlan0", r.getInterface());
@@ -71,13 +71,15 @@
}
public void testMatches() {
- class PatchedRouteInfo extends RouteInfo {
+ class PatchedRouteInfo {
+ private final RouteInfo mRouteInfo;
+
public PatchedRouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
- super(destination, gateway, iface);
+ mRouteInfo = new RouteInfo(destination, gateway, iface);
}
public boolean matches(InetAddress destination) {
- return super.matches(destination);
+ return mRouteInfo.matches(destination);
}
}
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index 41cc9d2..79fe4d3 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -165,12 +165,12 @@
ShadowTask(const Matrix4* drawTransform, const Rect& localClip, bool opaque,
const SkPath* casterPerimeter, const Matrix4* transformXY, const Matrix4* transformZ,
const Vector3& lightCenter, float lightRadius)
- : drawTransform(drawTransform)
+ : drawTransform(*drawTransform)
, localClip(localClip)
, opaque(opaque)
- , casterPerimeter(casterPerimeter)
- , transformXY(transformXY)
- , transformZ(transformZ)
+ , casterPerimeter(*casterPerimeter)
+ , transformXY(*transformXY)
+ , transformZ(*transformZ)
, lightCenter(lightCenter)
, lightRadius(lightRadius) {
}
@@ -182,14 +182,19 @@
delete bufferPair;
}
- // Note - only the localClip is deep copied, since other pointers point at Allocator controlled
- // objects, which are safe for the entire frame
- const Matrix4* drawTransform;
+ /* Note - we deep copy all task parameters, because *even though* pointers into Allocator
+ * controlled objects (like the SkPath and Matrix4s) should be safe for the entire frame,
+ * certain Allocators are destroyed before trim() is called to flush incomplete tasks.
+ *
+ * These deep copies could be avoided, long term, by cancelling or flushing outstanding tasks
+ * before tearning down single-frame LinearAllocators.
+ */
+ const Matrix4 drawTransform;
const Rect localClip;
bool opaque;
- const SkPath* casterPerimeter;
- const Matrix4* transformXY;
- const Matrix4* transformZ;
+ const SkPath casterPerimeter;
+ const Matrix4 transformXY;
+ const Matrix4 transformZ;
const Vector3 lightCenter;
const float lightRadius;
};
@@ -281,8 +286,8 @@
VertexBuffer* ambientBuffer = new VertexBuffer;
VertexBuffer* spotBuffer = new VertexBuffer;
- tessellateShadows(t->drawTransform, &t->localClip, t->opaque, t->casterPerimeter,
- t->transformXY, t->transformZ, t->lightCenter, t->lightRadius,
+ tessellateShadows(&t->drawTransform, &t->localClip, t->opaque, &t->casterPerimeter,
+ &t->transformXY, &t->transformZ, t->lightCenter, t->lightRadius,
*ambientBuffer, *spotBuffer);
t->setResult(new TessellationCache::vertexBuffer_pair_t(ambientBuffer, spotBuffer));
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index ce9fbb1..458139b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -2344,19 +2344,24 @@
if (rctlr == null) {
return false;
}
- IAudioService service = getService();
- final RemoteController.OnClientUpdateListener l = rctlr.getUpdateListener();
- final ComponentName listenerComponent = new ComponentName(mContext, l.getClass());
- try {
- int[] artworkDimensions = rctlr.getArtworkSize();
- boolean reg = service.registerRemoteController(rctlr.getRcDisplay(),
- artworkDimensions[0]/*w*/, artworkDimensions[1]/*h*/,
- listenerComponent);
- rctlr.setIsRegistered(reg);
- return reg;
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in registerRemoteController " + e);
- return false;
+ if (USE_SESSIONS) {
+ rctlr.startListeningToSessions();
+ return true;
+ } else {
+ IAudioService service = getService();
+ final RemoteController.OnClientUpdateListener l = rctlr.getUpdateListener();
+ final ComponentName listenerComponent = new ComponentName(mContext, l.getClass());
+ try {
+ int[] artworkDimensions = rctlr.getArtworkSize();
+ boolean reg = service.registerRemoteController(rctlr.getRcDisplay(),
+ artworkDimensions[0]/* w */, artworkDimensions[1]/* h */,
+ listenerComponent);
+ rctlr.setIsRegistered(reg);
+ return reg;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in registerRemoteController " + e);
+ return false;
+ }
}
}
@@ -2369,12 +2374,16 @@
if (rctlr == null) {
return;
}
- IAudioService service = getService();
- try {
- service.unregisterRemoteControlDisplay(rctlr.getRcDisplay());
- rctlr.setIsRegistered(false);
- } catch (RemoteException e) {
- Log.e(TAG, "Dead object in unregisterRemoteControlDisplay " + e);
+ if (USE_SESSIONS) {
+ rctlr.stopListeningToSessions();
+ } else {
+ IAudioService service = getService();
+ try {
+ service.unregisterRemoteControlDisplay(rctlr.getRcDisplay());
+ rctlr.setIsRegistered(false);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Dead object in unregisterRemoteControlDisplay " + e);
+ }
}
}
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index 3711585..76c7299 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -19,11 +19,17 @@
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.app.PendingIntent.CanceledException;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.IRemoteControlDisplay;
import android.media.MediaMetadataEditor;
+import android.media.session.MediaController;
+import android.media.session.MediaSession;
+import android.media.session.MediaSessionLegacyHelper;
+import android.media.session.MediaSessionManager;
+import android.media.session.PlaybackState;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -34,6 +40,7 @@
import android.view.KeyEvent;
import java.lang.ref.WeakReference;
+import java.util.List;
/**
* The RemoteController class is used to control media playback, display and update media metadata
@@ -56,6 +63,7 @@
private final static int TRANSPORT_UNKNOWN = 0;
private final static String TAG = "RemoteController";
private final static boolean DEBUG = false;
+ private final static boolean USE_SESSIONS = true;
private final static Object mGenLock = new Object();
private final static Object mInfoLock = new Object();
private final RcDisplay mRcd;
@@ -64,6 +72,11 @@
private final int mMaxBitmapDimension;
private MetadataEditor mMetadataEditor;
+ private MediaSessionManager mSessionManager;
+ private MediaSessionManager.SessionListener mSessionListener
+ = new TopTransportSessionListener();
+ private MediaController.Callback mSessionCb = new MediaControllerCallback();
+
/**
* Synchronized on mGenLock
*/
@@ -79,6 +92,8 @@
private int mArtworkWidth = -1;
private int mArtworkHeight = -1;
private boolean mEnabled = true;
+ // synchronized on mInfoLock, for USE_SESSION apis.
+ private MediaController mCurrentSession;
/**
* Class constructor.
@@ -123,6 +138,8 @@
mContext = context;
mRcd = new RcDisplay(this);
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+ mSessionManager = (MediaSessionManager) context
+ .getSystemService(Context.MEDIA_SESSION_SERVICE);
if (ActivityManager.isLowRamDeviceStatic()) {
mMaxBitmapDimension = MAX_BITMAP_DIMENSION;
@@ -194,8 +211,15 @@
* @hide
*/
public String getRemoteControlClientPackageName() {
- return mClientPendingIntentCurrent != null ?
- mClientPendingIntentCurrent.getCreatorPackage() : null;
+ if (USE_SESSIONS) {
+ synchronized (mInfoLock) {
+ return mCurrentSession != null ? mCurrentSession.getSessionInfo().getPackageName()
+ : null;
+ }
+ } else {
+ return mClientPendingIntentCurrent != null ?
+ mClientPendingIntentCurrent.getCreatorPackage() : null;
+ }
}
/**
@@ -215,22 +239,38 @@
* @see OnClientUpdateListener#onClientPlaybackStateUpdate(int, long, long, float)
*/
public long getEstimatedMediaPosition() {
- if (mLastPlaybackInfo != null) {
- if (!RemoteControlClient.playbackPositionShouldMove(mLastPlaybackInfo.mState)) {
- return mLastPlaybackInfo.mCurrentPosMs;
+ if (USE_SESSIONS) {
+ synchronized (mInfoLock) {
+ if (mCurrentSession != null) {
+ PlaybackState state = mCurrentSession.getPlaybackState();
+ if (state != null) {
+ return state.getPosition();
+ }
+ }
}
-
- // Take the current position at the time of state change and estimate.
- final long thenPos = mLastPlaybackInfo.mCurrentPosMs;
- if (thenPos < 0) {
- return -1;
+ } else {
+ final PlaybackInfo lastPlaybackInfo;
+ synchronized (mInfoLock) {
+ lastPlaybackInfo = mLastPlaybackInfo;
}
+ if (lastPlaybackInfo != null) {
+ if (!RemoteControlClient.playbackPositionShouldMove(lastPlaybackInfo.mState)) {
+ return lastPlaybackInfo.mCurrentPosMs;
+ }
- final long now = SystemClock.elapsedRealtime();
- final long then = mLastPlaybackInfo.mStateChangeTimeMs;
- final long sinceThen = now - then;
- final long scaledSinceThen = (long) (sinceThen * mLastPlaybackInfo.mSpeed);
- return thenPos + scaledSinceThen;
+ // Take the current position at the time of state change and
+ // estimate.
+ final long thenPos = lastPlaybackInfo.mCurrentPosMs;
+ if (thenPos < 0) {
+ return -1;
+ }
+
+ final long now = SystemClock.elapsedRealtime();
+ final long then = lastPlaybackInfo.mStateChangeTimeMs;
+ final long sinceThen = now - then;
+ final long scaledSinceThen = (long) (sinceThen * lastPlaybackInfo.mSpeed);
+ return thenPos + scaledSinceThen;
+ }
}
return -1;
}
@@ -267,30 +307,40 @@
if (!KeyEvent.isMediaKey(keyEvent.getKeyCode())) {
throw new IllegalArgumentException("not a media key event");
}
- final PendingIntent pi;
- synchronized(mInfoLock) {
- if (!mIsRegistered) {
- Log.e(TAG, "Cannot use sendMediaKeyEvent() from an unregistered RemoteController");
- return false;
- }
- if (!mEnabled) {
- Log.e(TAG, "Cannot use sendMediaKeyEvent() from a disabled RemoteController");
- return false;
- }
- pi = mClientPendingIntentCurrent;
- }
- if (pi != null) {
- Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
- intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
- try {
- pi.send(mContext, 0, intent);
- } catch (CanceledException e) {
- Log.e(TAG, "Error sending intent for media button down: ", e);
+ if (USE_SESSIONS) {
+ synchronized (mInfoLock) {
+ if (mCurrentSession != null) {
+ return mCurrentSession.dispatchMediaButtonEvent(keyEvent);
+ }
return false;
}
} else {
- Log.i(TAG, "No-op when sending key click, no receiver right now");
- return false;
+ final PendingIntent pi;
+ synchronized (mInfoLock) {
+ if (!mIsRegistered) {
+ Log.e(TAG,
+ "Cannot use sendMediaKeyEvent() from an unregistered RemoteController");
+ return false;
+ }
+ if (!mEnabled) {
+ Log.e(TAG, "Cannot use sendMediaKeyEvent() from a disabled RemoteController");
+ return false;
+ }
+ pi = mClientPendingIntentCurrent;
+ }
+ if (pi != null) {
+ Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+ intent.putExtra(Intent.EXTRA_KEY_EVENT, keyEvent);
+ try {
+ pi.send(mContext, 0, intent);
+ } catch (CanceledException e) {
+ Log.e(TAG, "Error sending intent for media button down: ", e);
+ return false;
+ }
+ } else {
+ Log.i(TAG, "No-op when sending key click, no receiver right now");
+ return false;
+ }
}
return true;
}
@@ -311,11 +361,19 @@
if (timeMs < 0) {
throw new IllegalArgumentException("illegal negative time value");
}
- final int genId;
- synchronized (mGenLock) {
- genId = mClientGenerationIdCurrent;
+ if (USE_SESSIONS) {
+ synchronized (mInfoLock) {
+ if (mCurrentSession != null) {
+ mCurrentSession.getTransportControls().seekTo(timeMs);
+ }
+ }
+ } else {
+ final int genId;
+ synchronized (mGenLock) {
+ genId = mClientGenerationIdCurrent;
+ }
+ mAudioManager.setRemoteControlClientPlaybackPosition(genId, timeMs);
}
- mAudioManager.setRemoteControlClientPlaybackPosition(genId, timeMs);
return true;
}
@@ -430,7 +488,6 @@
return editor;
}
-
/**
* A class to read the metadata published by a {@link RemoteControlClient}, or send a
* {@link RemoteControlClient} new values for keys that can be edited.
@@ -477,26 +534,41 @@
if (!mMetadataChanged) {
return;
}
- final int genId;
- synchronized(mGenLock) {
- genId = mClientGenerationIdCurrent;
- }
- synchronized(mInfoLock) {
- if (mEditorMetadata.containsKey(
- String.valueOf(MediaMetadataEditor.RATING_KEY_BY_USER))) {
- Rating rating = (Rating) getObject(
- MediaMetadataEditor.RATING_KEY_BY_USER, null);
- mAudioManager.updateRemoteControlClientMetadata(genId,
- MediaMetadataEditor.RATING_KEY_BY_USER,
- rating);
- } else {
- Log.e(TAG, "no metadata to apply");
+ if (USE_SESSIONS) {
+ synchronized (mInfoLock) {
+ if (mCurrentSession != null) {
+ if (mEditorMetadata.containsKey(
+ String.valueOf(MediaMetadataEditor.RATING_KEY_BY_USER))) {
+ Rating rating = (Rating) getObject(
+ MediaMetadataEditor.RATING_KEY_BY_USER, null);
+ if (rating != null) {
+ mCurrentSession.getTransportControls().setRating(rating);
+ }
+ }
+ }
}
- // NOT setting mApplied to true as this type of MetadataEditor will be applied
- // multiple times, whenever the user of a RemoteController needs to change the
- // metadata (e.g. user changes the rating of a song more than once during playback)
- mApplied = false;
+ } else {
+ final int genId;
+ synchronized(mGenLock) {
+ genId = mClientGenerationIdCurrent;
+ }
+ synchronized(mInfoLock) {
+ if (mEditorMetadata.containsKey(
+ String.valueOf(MediaMetadataEditor.RATING_KEY_BY_USER))) {
+ Rating rating = (Rating) getObject(
+ MediaMetadataEditor.RATING_KEY_BY_USER, null);
+ mAudioManager.updateRemoteControlClientMetadata(genId,
+ MediaMetadataEditor.RATING_KEY_BY_USER,
+ rating);
+ } else {
+ Log.e(TAG, "no metadata to apply");
+ }
+ }
}
+ // NOT setting mApplied to true as this type of MetadataEditor will be applied
+ // multiple times, whenever the user of a RemoteController needs to change the
+ // metadata (e.g. user changes the rating of a song more than once during playback)
+ mApplied = false;
}
}
@@ -649,6 +721,46 @@
}
}
+ /**
+ * This receives updates when the current session changes. This is
+ * registered to receive the updates on the handler thread so it can call
+ * directly into the appropriate methods.
+ */
+ private class MediaControllerCallback extends MediaController.Callback {
+ @Override
+ public void onPlaybackStateChanged(PlaybackState state) {
+ onNewPlaybackState(state);
+ }
+
+ @Override
+ public void onMetadataChanged(MediaMetadata metadata) {
+ onNewMediaMetadata(metadata);
+ }
+ }
+
+ /**
+ * Listens for changes to the active session stack and replaces the
+ * currently tracked session if it has changed.
+ */
+ private class TopTransportSessionListener extends MediaSessionManager.SessionListener {
+ @Override
+ public void onActiveSessionsChanged(List<MediaController> controllers) {
+ int size = controllers.size();
+ for (int i = 0; i < size; i++) {
+ MediaController controller = controllers.get(i);
+ long flags = controller.getFlags();
+ // We only care about sessions that handle transport controls,
+ // which will be true for apps using RCC
+ if ((flags & MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS) != 0) {
+ updateController(controller);
+ return;
+ }
+ }
+ updateController(null);
+ }
+
+ }
+
//==================================================
// Event handling
private final EventHandler mEventHandler;
@@ -658,6 +770,8 @@
private final static int MSG_NEW_METADATA = 3; // msg always has non-null obj parameter
private final static int MSG_CLIENT_CHANGE = 4;
private final static int MSG_DISPLAY_ENABLE = 5;
+ private final static int MSG_NEW_PLAYBACK_STATE = 6;
+ private final static int MSG_NEW_MEDIA_METADATA = 7;
private class EventHandler extends Handler {
@@ -686,12 +800,46 @@
case MSG_DISPLAY_ENABLE:
onDisplayEnable(msg.arg1 == 1);
break;
+ case MSG_NEW_PLAYBACK_STATE:
+ // same as new playback info but using new apis
+ onNewPlaybackState((PlaybackState) msg.obj);
+ break;
+ case MSG_NEW_MEDIA_METADATA:
+ onNewMediaMetadata((MediaMetadata) msg.obj);
+ break;
default:
Log.e(TAG, "unknown event " + msg.what);
}
}
}
+ /**
+ * @hide
+ */
+ void startListeningToSessions() {
+ final ComponentName listenerComponent = new ComponentName(mContext,
+ mOnClientUpdateListener.getClass());
+ mSessionManager.addActiveSessionsListener(mSessionListener, listenerComponent,
+ ActivityManager.getCurrentUser());
+ mSessionListener.onActiveSessionsChanged(mSessionManager
+ .getActiveSessions(listenerComponent));
+ if (DEBUG) {
+ Log.d(TAG, "Registered session listener with component " + listenerComponent
+ + " for user " + ActivityManager.getCurrentUser());
+ }
+ }
+
+ /**
+ * @hide
+ */
+ void stopListeningToSessions() {
+ mSessionManager.removeActiveSessionsListener(mSessionListener);
+ if (DEBUG) {
+ Log.d(TAG, "Unregistered session listener for user "
+ + ActivityManager.getCurrentUser());
+ }
+ }
+
/** If the msg is already queued, replace it with this one. */
private static final int SENDMSG_REPLACE = 0;
/** If the msg is already queued, ignore this one and leave the old. */
@@ -713,6 +861,7 @@
handler.sendMessageDelayed(handler.obtainMessage(msg, arg1, arg2, obj), delayMs);
}
+ ///////////// These calls are used by the old APIs with RCC and RCD //////////////////////
private void onNewPendingIntent(int genId, PendingIntent pi) {
synchronized(mGenLock) {
if (mClientGenerationIdCurrent != genId) {
@@ -848,6 +997,86 @@
}
}
+ ///////////// These calls are used by the new APIs with Sessions //////////////////////
+ private void updateController(MediaController controller) {
+ if (DEBUG) {
+ Log.d(TAG, "Updating controller to " + controller + " previous controller is "
+ + mCurrentSession);
+ }
+ synchronized (mInfoLock) {
+ if (controller == null) {
+ if (mCurrentSession != null) {
+ mCurrentSession.removeCallback(mSessionCb);
+ mCurrentSession = null;
+ sendMsg(mEventHandler, MSG_CLIENT_CHANGE, SENDMSG_REPLACE,
+ 0 /* genId */, 1 /* clearing */, null /* obj */, 0 /* delay */);
+ }
+ } else if (mCurrentSession == null
+ || !controller.getSessionInfo().getId()
+ .equals(mCurrentSession.getSessionInfo().getId())) {
+ if (mCurrentSession != null) {
+ mCurrentSession.removeCallback(mSessionCb);
+ }
+ sendMsg(mEventHandler, MSG_CLIENT_CHANGE, SENDMSG_REPLACE,
+ 0 /* genId */, 0 /* clearing */, null /* obj */, 0 /* delay */);
+ mCurrentSession = controller;
+ mCurrentSession.addCallback(mSessionCb, mEventHandler);
+
+ PlaybackState state = controller.getPlaybackState();
+ sendMsg(mEventHandler, MSG_NEW_PLAYBACK_STATE, SENDMSG_REPLACE,
+ 0 /* genId */, 0, state /* obj */, 0 /* delay */);
+
+ MediaMetadata metadata = controller.getMetadata();
+ sendMsg(mEventHandler, MSG_NEW_MEDIA_METADATA, SENDMSG_REPLACE,
+ 0 /* arg1 */, 0 /* arg2 */, metadata /* obj */, 0 /* delay */);
+ }
+ // else same controller, no need to update
+ }
+ }
+
+ private void onNewPlaybackState(PlaybackState state) {
+ final OnClientUpdateListener l;
+ synchronized (mInfoLock) {
+ l = this.mOnClientUpdateListener;
+ }
+ if (l != null) {
+ int playstate = state == null ? RemoteControlClient.PLAYSTATE_NONE : PlaybackState
+ .getRccStateFromState(state.getState());
+ if (state == null || state.getPosition() == PlaybackState.PLAYBACK_POSITION_UNKNOWN) {
+ l.onClientPlaybackStateUpdate(playstate);
+ } else {
+ l.onClientPlaybackStateUpdate(playstate, state.getLastPositionUpdateTime(),
+ state.getPosition(), state.getPlaybackRate());
+ }
+ if (state != null) {
+ l.onClientTransportControlUpdate(PlaybackState.getRccControlFlagsFromActions(state
+ .getActions()));
+ }
+ }
+ }
+
+ private void onNewMediaMetadata(MediaMetadata metadata) {
+ if (metadata == null) {
+ // RemoteController only handles non-null metadata
+ return;
+ }
+ final OnClientUpdateListener l;
+ final MetadataEditor metadataEditor;
+ // prepare the received Bundle to be used inside a MetadataEditor
+ synchronized(mInfoLock) {
+ l = mOnClientUpdateListener;
+ boolean canRate = mCurrentSession != null
+ && mCurrentSession.getRatingType() != Rating.RATING_NONE;
+ long editableKeys = canRate ? MediaMetadataEditor.RATING_KEY_BY_USER : 0;
+ Bundle legacyMetadata = MediaSessionLegacyHelper.getOldMetadata(metadata);
+ mMetadataEditor = new MetadataEditor(legacyMetadata, editableKeys);
+ metadataEditor = mMetadataEditor;
+ }
+ if (l != null) {
+ l.onClientMetadataUpdate(metadataEditor);
+ }
+ }
+
//==================================================
private static class PlaybackInfo {
int mState;
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 7c03907..f0cd785 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -37,6 +37,7 @@
boolean isTransportControlEnabled();
void showRoutePicker();
MediaSessionInfo getSessionInfo();
+ long getFlags();
// These commands are for the TransportController
void play();
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 57a0a54..5ca7daa 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -57,6 +57,7 @@
private final Object mLock = new Object();
private boolean mCbRegistered = false;
+ private MediaSessionInfo mInfo;
private TransportControls mTransportController;
@@ -174,6 +175,21 @@
}
/**
+ * Get the flags for this session.
+ *
+ * @return The current set of flags for the session.
+ * @hide
+ */
+ public long getFlags() {
+ try {
+ return mSessionBinder.getFlags();
+ } catch (RemoteException e) {
+ Log.wtf(TAG, "Error calling getFlags.", e);
+ }
+ return 0;
+ }
+
+ /**
* Adds a callback to receive updates from the Session. Updates will be
* posted on the caller's thread.
*
@@ -253,12 +269,14 @@
* @hide
*/
public MediaSessionInfo getSessionInfo() {
- try {
- return mSessionBinder.getSessionInfo();
- } catch (RemoteException e) {
- Log.e(TAG, "Error in getSessionInfo.", e);
+ if (mInfo == null) {
+ try {
+ mInfo = mSessionBinder.getSessionInfo();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error in getSessionInfo.", e);
+ }
}
- return null;
+ return mInfo;
}
/*
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index 099f601..801844f 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -20,6 +20,10 @@
import android.app.PendingIntent.CanceledException;
import android.content.Context;
import android.content.Intent;
+import android.media.MediaMetadata;
+import android.media.MediaMetadataEditor;
+import android.media.MediaMetadataRetriever;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.ArrayMap;
@@ -64,6 +68,88 @@
return sInstance;
}
+ public static Bundle getOldMetadata(MediaMetadata metadata) {
+ Bundle oldMetadata = new Bundle();
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_ALBUM)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_ALBUM),
+ metadata.getString(MediaMetadata.METADATA_KEY_ALBUM));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_ART)) {
+ oldMetadata.putParcelable(String.valueOf(MediaMetadataEditor.BITMAP_KEY_ARTWORK),
+ metadata.getBitmap(MediaMetadata.METADATA_KEY_ART));
+ } else if (metadata.containsKey(MediaMetadata.METADATA_KEY_ALBUM_ART)) {
+ // Fall back to album art if the track art wasn't available
+ oldMetadata.putParcelable(String.valueOf(MediaMetadataEditor.BITMAP_KEY_ARTWORK),
+ metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_ALBUM_ARTIST)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST),
+ metadata.getString(MediaMetadata.METADATA_KEY_ALBUM_ARTIST));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_ARTIST)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_ARTIST),
+ metadata.getString(MediaMetadata.METADATA_KEY_ARTIST));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_AUTHOR)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_AUTHOR),
+ metadata.getString(MediaMetadata.METADATA_KEY_AUTHOR));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_COMPILATION)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_COMPILATION),
+ metadata.getString(MediaMetadata.METADATA_KEY_COMPILATION));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_COMPOSER)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_COMPOSER),
+ metadata.getString(MediaMetadata.METADATA_KEY_COMPOSER));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_DATE)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_DATE),
+ metadata.getString(MediaMetadata.METADATA_KEY_DATE));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_DISC_NUMBER)) {
+ oldMetadata.putLong(String.valueOf(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER),
+ metadata.getLong(MediaMetadata.METADATA_KEY_DISC_NUMBER));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
+ oldMetadata.putLong(String.valueOf(MediaMetadataRetriever.METADATA_KEY_DURATION),
+ metadata.getLong(MediaMetadata.METADATA_KEY_DURATION));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_GENRE)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_GENRE),
+ metadata.getString(MediaMetadata.METADATA_KEY_GENRE));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_NUM_TRACKS)) {
+ oldMetadata.putLong(String.valueOf(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS),
+ metadata.getLong(MediaMetadata.METADATA_KEY_NUM_TRACKS));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_RATING)) {
+ oldMetadata.putParcelable(String.valueOf(MediaMetadataEditor.RATING_KEY_BY_OTHERS),
+ metadata.getRating(MediaMetadata.METADATA_KEY_RATING));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_USER_RATING)) {
+ oldMetadata.putParcelable(String.valueOf(MediaMetadataEditor.RATING_KEY_BY_USER),
+ metadata.getRating(MediaMetadata.METADATA_KEY_USER_RATING));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_TITLE)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_TITLE),
+ metadata.getString(MediaMetadata.METADATA_KEY_TITLE));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_TRACK_NUMBER)) {
+ oldMetadata.putLong(
+ String.valueOf(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER),
+ metadata.getLong(MediaMetadata.METADATA_KEY_TRACK_NUMBER));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_WRITER)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_WRITER),
+ metadata.getString(MediaMetadata.METADATA_KEY_WRITER));
+ }
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_YEAR)) {
+ oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_YEAR),
+ metadata.getString(MediaMetadata.METADATA_KEY_YEAR));
+ }
+ return oldMetadata;
+ }
+
public MediaSession getSession(PendingIntent pi) {
SessionHolder holder = mSessions.get(pi);
return holder == null ? null : holder.mSession;
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 291bfc8..8eceee8 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -96,10 +96,13 @@
}
/**
- * Get a list of controllers for all ongoing sessions. This requires the
- * android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by
- * the calling app. You may also retrieve this list if your app is an
- * enabled notification listener using the
+ * Get a list of controllers for all ongoing sessions. The controllers will
+ * be provided in priority order with the most important controller at index
+ * 0.
+ * <p>
+ * This requires the android.Manifest.permission.MEDIA_CONTENT_CONTROL
+ * permission be held by the calling app. You may also retrieve this list if
+ * your app is an enabled notification listener using the
* {@link NotificationListenerService} APIs, in which case you must pass the
* {@link ComponentName} of your enabled listener.
*
@@ -239,7 +242,8 @@
/**
* Called when the list of active sessions has changed. This can be due
* to a session being added or removed or the order of sessions
- * changing.
+ * changing. The controllers will be provided in priority order with the
+ * most important controller at index 0.
*
* @param controllers The updated list of controllers for the user that
* changed.
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index e09ac3f..3b3f249 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -432,6 +432,8 @@
return STATE_REWINDING;
case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
return STATE_SKIPPING_TO_PREVIOUS;
+ case RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS:
+ return STATE_SKIPPING_TO_NEXT;
case RemoteControlClient.PLAYSTATE_STOPPED:
return STATE_STOPPED;
default:
@@ -440,6 +442,41 @@
}
/**
+ * Get the {@link RemoteControlClient} state for the given
+ * {@link PlaybackState} state.
+ *
+ * @param state The state used by {@link PlaybackState}.
+ * @return The equivalent state used by {@link RemoteControlClient}.
+ * @hide
+ */
+ public static int getRccStateFromState(int state) {
+ switch (state) {
+ case STATE_BUFFERING:
+ return RemoteControlClient.PLAYSTATE_BUFFERING;
+ case STATE_ERROR:
+ return RemoteControlClient.PLAYSTATE_ERROR;
+ case STATE_FAST_FORWARDING:
+ return RemoteControlClient.PLAYSTATE_FAST_FORWARDING;
+ case STATE_NONE:
+ return RemoteControlClient.PLAYSTATE_NONE;
+ case STATE_PAUSED:
+ return RemoteControlClient.PLAYSTATE_PAUSED;
+ case STATE_PLAYING:
+ return RemoteControlClient.PLAYSTATE_PLAYING;
+ case STATE_REWINDING:
+ return RemoteControlClient.PLAYSTATE_REWINDING;
+ case STATE_SKIPPING_TO_PREVIOUS:
+ return RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS;
+ case STATE_SKIPPING_TO_NEXT:
+ return RemoteControlClient.PLAYSTATE_SKIPPING_FORWARDS;
+ case STATE_STOPPED:
+ return RemoteControlClient.PLAYSTATE_STOPPED;
+ default:
+ return -1;
+ }
+ }
+
+ /**
* @hide
*/
public static long getActionsFromRccControlFlags(int rccFlags) {
@@ -454,6 +491,21 @@
return actions;
}
+ /**
+ * @hide
+ */
+ public static int getRccControlFlagsFromActions(long actions) {
+ int rccFlags = 0;
+ long action = 1;
+ while (action <= actions && action < Integer.MAX_VALUE) {
+ if ((action & actions) != 0) {
+ rccFlags |= getRccFlagForAction(action);
+ }
+ action = action << 1;
+ }
+ return rccFlags;
+ }
+
private static long getActionForRccFlag(int flag) {
switch (flag) {
case RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS:
@@ -480,6 +532,35 @@
return 0;
}
+ private static int getRccFlagForAction(long action) {
+ // We only care about the lower set of actions that can map to rcc
+ // flags.
+ int testAction = action < Integer.MAX_VALUE ? (int) action : 0;
+ switch (testAction) {
+ case (int) ACTION_SKIP_TO_PREVIOUS:
+ return RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS;
+ case (int) ACTION_REWIND:
+ return RemoteControlClient.FLAG_KEY_MEDIA_REWIND;
+ case (int) ACTION_PLAY:
+ return RemoteControlClient.FLAG_KEY_MEDIA_PLAY;
+ case (int) ACTION_PLAY_PAUSE:
+ return RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE;
+ case (int) ACTION_PAUSE:
+ return RemoteControlClient.FLAG_KEY_MEDIA_PAUSE;
+ case (int) ACTION_STOP:
+ return RemoteControlClient.FLAG_KEY_MEDIA_STOP;
+ case (int) ACTION_FAST_FORWARD:
+ return RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD;
+ case (int) ACTION_SKIP_TO_NEXT:
+ return RemoteControlClient.FLAG_KEY_MEDIA_NEXT;
+ case (int) ACTION_SEEK_TO:
+ return RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE;
+ case (int) ACTION_SET_RATING:
+ return RemoteControlClient.FLAG_KEY_MEDIA_RATING;
+ }
+ return 0;
+ }
+
public static final Parcelable.Creator<PlaybackState> CREATOR
= new Parcelable.Creator<PlaybackState>() {
@Override
diff --git a/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml b/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml
index 84d64b9..e220a16 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml
@@ -18,48 +18,13 @@
<com.android.systemui.statusbar.SpeedBumpView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:focusable="true"
- android:clickable="true"
+ android:layout_height="@dimen/speed_bump_height"
android:visibility="gone"
>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="@dimen/speed_bump_height_collapsed"
- android:layout_gravity="top"
- android:orientation="horizontal">
- <com.android.systemui.statusbar.AlphaOptimizedView
- android:id="@+id/speedbump_line_left"
- android:layout_width="0dp"
- android:layout_height="1dp"
- android:layout_weight="1"
- android:background="#6fdddddd"
- android:layout_gravity="center_vertical"/>
- <com.android.systemui.statusbar.SpeedBumpDotsLayout
- android:id="@+id/speed_bump_dots_layout"
- android:layout_width="34dp"
- android:layout_marginStart="8dp"
- android:layout_marginEnd="8dp"
- android:layout_height="match_parent"
- android:layout_weight="0"/>
- <com.android.systemui.statusbar.AlphaOptimizedView
- android:id="@+id/speedbump_line_right"
- android:layout_width="0dp"
- android:layout_height="1dp"
- android:layout_weight="1"
- android:background="#6fdddddd"
- android:layout_gravity="center_vertical"/>
- </LinearLayout>
- <TextView
- android:id="@+id/speed_bump_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="top|center_horizontal"
- android:fontFamily="sans-serif-condensed"
- android:textSize="15sp"
- android:singleLine="true"
- android:textColor="#eeeeee"
- android:visibility="invisible"
- android:text="@string/speed_bump_explanation"
- android:paddingTop="4dp" />
+ <com.android.systemui.statusbar.AlphaOptimizedView
+ android:id="@+id/speedbump_line"
+ android:layout_width="match_parent"
+ android:layout_height="1dp"
+ android:background="#6fdddddd"
+ android:layout_gravity="center_vertical"/>
</com.android.systemui.statusbar.SpeedBumpView>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index bb6f1a9..8c1a9c7 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -45,18 +45,6 @@
<!-- Tint color for the content on the notification overflow card. -->
<color name="keyguard_overflow_content_color">#ff686868</color>
- <!-- The color of the red speed bump dot -->
- <color name="speed_bump_dot_red">#ffd50000</color>
-
- <!-- The color of the blue speed bump dot -->
- <color name="speed_bump_dot_blue">#ff2962ff</color>
-
- <!-- The color of the yellow speed bump dot -->
- <color name="speed_bump_dot_yellow">#ffffd600</color>
-
- <!-- The color of the green speed bump dot -->
- <color name="speed_bump_dot_green">#ff00c853</color>
-
<!-- The default recents task bar background color. -->
<color name="recents_task_bar_default_background_color">#e6444444</color>
<!-- The default recents task bar text color. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f750ee2..b8f9ad3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -275,14 +275,8 @@
<!-- The minimum amount of top overscroll to go to the quick settings. -->
<dimen name="min_top_overscroll_to_qs">36dp</dimen>
- <!-- The height of the collapsed speed bump view. -->
- <dimen name="speed_bump_height_collapsed">24dp</dimen>
-
- <!-- The padding inset the explanation text needs compared to the collapsed height -->
- <dimen name="speed_bump_text_padding_inset">10dp</dimen>
-
- <!-- The height of the speed bump dots. -->
- <dimen name="speed_bump_dots_height">5dp</dimen>
+ <!-- The height of the speed bump view. -->
+ <dimen name="speed_bump_height">16dp</dimen>
<!-- The total height of the stack in its collapsed size (i.e. when quick settings is open) -->
<dimen name="collapsed_stack_height">94dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 0c2c11d..113efe3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -121,6 +121,7 @@
// Send a broadcast to hide recents
Intent intent = new Intent(RecentsService.ACTION_HIDE_RECENTS_ACTIVITY);
intent.setPackage(context.getPackageName());
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
if (msg.arg1 != 0) {
intent.putExtra(RecentsService.EXTRA_TRIGGERED_FROM_ALT_TAB, true);
}
@@ -129,6 +130,7 @@
// Send a broadcast to toggle recents
Intent intent = new Intent(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
intent.setPackage(context.getPackageName());
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
context.sendBroadcast(intent);
// Time this path
@@ -140,6 +142,7 @@
// Send a broadcast to start the enter animation
Intent intent = new Intent(RecentsService.ACTION_START_ENTER_ANIMATION);
intent.setPackage(context.getPackageName());
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
context.sendBroadcast(intent);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 28b2780..5a9fe91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -48,7 +48,7 @@
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.service.notification.NotificationListenerService;
-import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
@@ -293,7 +293,7 @@
public void onListenerConnected() {
if (DEBUG) Log.d(TAG, "onListenerConnected");
final StatusBarNotification[] notifications = getActiveNotifications();
- final Ranking currentRanking = getCurrentRanking();
+ final RankingMap currentRanking = getCurrentRanking();
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -305,41 +305,40 @@
}
@Override
- public void onNotificationPosted(final StatusBarNotification sbn) {
+ public void onNotificationPosted(final StatusBarNotification sbn,
+ final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
- final Ranking currentRanking = getCurrentRanking();
mHandler.post(new Runnable() {
@Override
public void run() {
if (mNotificationData.findByKey(sbn.getKey()) != null) {
- updateNotificationInternal(sbn, currentRanking);
+ updateNotificationInternal(sbn, rankingMap);
} else {
- addNotificationInternal(sbn, currentRanking);
+ addNotificationInternal(sbn, rankingMap);
}
}
});
}
@Override
- public void onNotificationRemoved(final StatusBarNotification sbn) {
+ public void onNotificationRemoved(final StatusBarNotification sbn,
+ final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
- final Ranking currentRanking = getCurrentRanking();
mHandler.post(new Runnable() {
@Override
public void run() {
- removeNotificationInternal(sbn.getKey(), currentRanking);
+ removeNotificationInternal(sbn.getKey(), rankingMap);
}
});
}
@Override
- public void onNotificationRankingUpdate() {
+ public void onNotificationRankingUpdate(final RankingMap rankingMap) {
if (DEBUG) Log.d(TAG, "onRankingUpdate");
- final Ranking currentRanking = getCurrentRanking();
mHandler.post(new Runnable() {
@Override
public void run() {
- updateRankingInternal(currentRanking);
+ updateRankingInternal(rankingMap);
}
});
}
@@ -1177,7 +1176,7 @@
}
}
- protected StatusBarNotification removeNotificationViews(String key, Ranking ranking) {
+ protected StatusBarNotification removeNotificationViews(String key, RankingMap ranking) {
NotificationData.Entry entry = mNotificationData.remove(key, ranking);
if (entry == null) {
Log.w(TAG, "removeNotification for unknown key: " + key);
@@ -1217,7 +1216,7 @@
return entry;
}
- protected void addNotificationViews(Entry entry, Ranking ranking) {
+ protected void addNotificationViews(Entry entry, RankingMap ranking) {
if (entry == null) {
return;
}
@@ -1226,7 +1225,7 @@
updateNotifications();
}
- private void addNotificationViews(StatusBarNotification notification, Ranking ranking) {
+ private void addNotificationViews(StatusBarNotification notification, RankingMap ranking) {
addNotificationViews(createNotificationViews(notification), ranking);
}
@@ -1312,9 +1311,9 @@
}
public abstract void addNotificationInternal(StatusBarNotification notification,
- Ranking ranking);
+ RankingMap ranking);
- protected abstract void updateRankingInternal(Ranking ranking);
+ protected abstract void updateRankingInternal(RankingMap ranking);
@Override
public void removeNotification(String key) {
@@ -1323,7 +1322,7 @@
}
}
- public abstract void removeNotificationInternal(String key, Ranking ranking);
+ public abstract void removeNotificationInternal(String key, RankingMap ranking);
public void updateNotification(StatusBarNotification notification) {
if (!USE_NOTIFICATION_LISTENER) {
@@ -1331,7 +1330,7 @@
}
}
- public void updateNotificationInternal(StatusBarNotification notification, Ranking ranking) {
+ public void updateNotificationInternal(StatusBarNotification notification, RankingMap ranking) {
if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
final NotificationData.Entry oldEntry = mNotificationData.findByKey(notification.getKey());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
index f0a7a4c..bfa74fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
@@ -21,6 +21,7 @@
import android.os.Process;
import android.provider.Settings;
import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -58,17 +59,18 @@
updateSyntheticNotification();
}
- public boolean tryIntercept(StatusBarNotification notification, Ranking ranking) {
- if (ranking == null) return false;
+ public boolean tryIntercept(StatusBarNotification notification, RankingMap rankingMap) {
+ if (rankingMap == null) return false;
if (shouldDisplayIntercepted()) return false;
if (mReleased.contains(notification.getKey())) return false;
- if (!ranking.isInterceptedByDoNotDisturb(notification.getKey())) return false;
+ Ranking ranking = rankingMap.getRanking(notification.getKey());
+ if (!ranking.isInterceptedByDoNotDisturb()) return false;
mIntercepted.put(notification.getKey(), notification);
updateSyntheticNotification();
return true;
}
- public void retryIntercepts(Ranking ranking) {
+ public void retryIntercepts(RankingMap ranking) {
if (ranking == null) return;
final int N = mIntercepted.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index 631e19c..c313c58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -18,6 +18,7 @@
import android.app.Notification;
import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.view.View;
@@ -70,12 +71,16 @@
}
private final ArrayList<Entry> mEntries = new ArrayList<Entry>();
- private Ranking mRanking;
+ private RankingMap mRanking;
private final Comparator<Entry> mRankingComparator = new Comparator<Entry>() {
@Override
public int compare(Entry a, Entry b) {
if (mRanking != null) {
- return mRanking.getRank(a.key) - mRanking.getRank(b.key);
+ Ranking aRanking = mRanking.getRanking(a.key);
+ Ranking bRanking = mRanking.getRanking(b.key);
+ int aRank = aRanking != null ? aRanking.getRank() : -1;
+ int bRank = bRanking != null ? bRanking.getRank() : -1;
+ return aRank - bRank;
}
final StatusBarNotification na = a.notification;
@@ -108,12 +113,12 @@
return null;
}
- public void add(Entry entry, Ranking ranking) {
+ public void add(Entry entry, RankingMap ranking) {
mEntries.add(entry);
updateRankingAndSort(ranking);
}
- public Entry remove(String key, Ranking ranking) {
+ public Entry remove(String key, RankingMap ranking) {
Entry e = findByKey(key);
if (e == null) {
return null;
@@ -123,7 +128,7 @@
return e;
}
- public void updateRanking(Ranking ranking) {
+ public void updateRanking(RankingMap ranking) {
updateRankingAndSort(ranking);
}
@@ -137,12 +142,13 @@
}
}
} else {
- return mRanking.isAmbient(key);
+ Ranking ranking = mRanking.getRanking(key);
+ return ranking != null && ranking.isAmbient();
}
return false;
}
- private void updateRankingAndSort(Ranking ranking) {
+ private void updateRankingAndSort(RankingMap ranking) {
if (ranking != null) {
mRanking = ranking;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java
deleted file mode 100644
index 1503072..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Outline;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.view.View;
-
-/**
- * An single dot of the {@link com.android.systemui.statusbar.SpeedBumpDotsLayout}
- */
-public class SpeedBumpDotView extends View {
-
- private final Paint mPaint = new Paint();
-
- public SpeedBumpDotView(Context context, AttributeSet attrs) {
- super(context, attrs);
- mPaint.setAntiAlias(true);
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- float radius = getWidth() / 2.0f;
- canvas.drawCircle(radius, radius, radius, mPaint);
- }
-
- @Override
- public boolean hasOverlappingRendering() {
- return false;
- }
-
- public void setColor(int color) {
- mPaint.setColor(color);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsAlgorithm.java
deleted file mode 100644
index cac6327..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsAlgorithm.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.view.View;
-import com.android.systemui.R;
-
-/**
- * The Algorithm of the {@link com.android.systemui.statusbar.SpeedBumpDotsLayout} which can be
- * queried for {@link * com.android.systemui.statusbar.SpeedBumpDotsState}
- */
-public class SpeedBumpDotsAlgorithm {
-
- private final float mDotRadius;
-
- public SpeedBumpDotsAlgorithm(Context context) {
- mDotRadius = context.getResources().getDimensionPixelSize(R.dimen.speed_bump_dots_height)
- / 2.0f;
- }
-
- public void getState(SpeedBumpDotsState resultState) {
-
- // First reset the current state and ensure that every View has a ViewState
- resultState.resetViewStates();
-
- SpeedBumpDotsLayout hostView = resultState.getHostView();
- boolean currentlyVisible = hostView.isCurrentlyVisible();
- resultState.setActiveState(currentlyVisible
- ? SpeedBumpDotsState.SHOWN
- : SpeedBumpDotsState.HIDDEN);
- int hostWidth = hostView.getWidth();
- float layoutWidth = hostWidth - 2 * mDotRadius;
- int childCount = hostView.getChildCount();
- float paddingBetween = layoutWidth / (childCount - 1);
- float centerY = hostView.getHeight() / 2.0f;
- for (int i = 0; i < childCount; i++) {
- View child = hostView.getChildAt(i);
- SpeedBumpDotsState.ViewState viewState = resultState.getViewStateForView(child);
- if (currentlyVisible) {
- float xTranslation = i * paddingBetween;
- viewState.xTranslation = xTranslation;
- viewState.yTranslation = calculateYTranslation(hostView, centerY, xTranslation,
- layoutWidth);
- } else {
- viewState.xTranslation = layoutWidth / 2;
- viewState.yTranslation = centerY - mDotRadius;
- }
- viewState.alpha = currentlyVisible ? 1.0f : 0.0f;
- viewState.scale = currentlyVisible ? 1.0f : 0.5f;
- }
- }
-
- private float calculateYTranslation(SpeedBumpDotsLayout hostView, float centerY,
- float xTranslation, float layoutWidth) {
- float t = hostView.getAnimationProgress();
- if (t == 0.0f || t == 1.0f) {
- return centerY - mDotRadius;
- }
- float damping = (0.5f -Math.abs(0.5f - t)) * 1.3f;
- float partialOffset = xTranslation / layoutWidth;
- float indentFactor = (float) (Math.sin((t + partialOffset * 1.5f) * - Math.PI) * damping);
- return (1.0f - indentFactor) * centerY - mDotRadius;
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsLayout.java
deleted file mode 100644
index ddf5215..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsLayout.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.animation.TimeAnimator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import com.android.systemui.R;
-
-/**
- * A layout with a certain number of dots which are integrated in the
- * {@link com.android.systemui.statusbar.SpeedBumpView}
- */
-public class SpeedBumpDotsLayout extends ViewGroup {
-
- private static final float DOT_CLICK_ANIMATION_LENGTH = 300;
- private final int mDotSize;
- private final SpeedBumpDotsAlgorithm mAlgorithm = new SpeedBumpDotsAlgorithm(getContext());
- private final SpeedBumpDotsState mCurrentState = new SpeedBumpDotsState(this);
- private boolean mIsCurrentlyVisible = true;
- private final ValueAnimator mClickAnimator;
- private float mAnimationProgress;
- private ValueAnimator.AnimatorUpdateListener mClickUpdateListener
- = new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mAnimationProgress = animation.getAnimatedFraction();
- updateChildren();
- }
- };
-
- public SpeedBumpDotsLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- mDotSize = getResources().getDimensionPixelSize(R.dimen.speed_bump_dots_height);
- createDots(context, attrs);
- mClickAnimator = TimeAnimator.ofFloat(0, DOT_CLICK_ANIMATION_LENGTH);
- mClickAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
- mClickAnimator.addUpdateListener(mClickUpdateListener);
- }
-
- private void createDots(Context context, AttributeSet attrs) {
- SpeedBumpDotView blueDot = new SpeedBumpDotView(context, attrs);
- blueDot.setColor(getResources().getColor(R.color.speed_bump_dot_blue));
- addView(blueDot);
-
- SpeedBumpDotView redDot = new SpeedBumpDotView(context, attrs);
- redDot.setColor(getResources().getColor(R.color.speed_bump_dot_red));
- addView(redDot);
-
- SpeedBumpDotView yellowDot = new SpeedBumpDotView(context, attrs);
- yellowDot.setColor(getResources().getColor(R.color.speed_bump_dot_yellow));
- addView(yellowDot);
-
- SpeedBumpDotView greenDot = new SpeedBumpDotView(context, attrs);
- greenDot.setColor(getResources().getColor(R.color.speed_bump_dot_green));
- addView(greenDot);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- int childWidthSpec = MeasureSpec.makeMeasureSpec(mDotSize,
- MeasureSpec.getMode(widthMeasureSpec));
- int childHeightSpec = MeasureSpec.makeMeasureSpec(mDotSize,
- MeasureSpec.getMode(heightMeasureSpec));
- measureChildren(childWidthSpec, childHeightSpec);
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- child.layout(0, 0, mDotSize, mDotSize);
- }
- if (changed) {
- updateChildren();
- }
- }
-
- private void updateChildren() {
- mAlgorithm.getState(mCurrentState);
- mCurrentState.apply();
- }
-
- public void performVisibilityAnimation(boolean visible) {
- if (mClickAnimator.isRunning()) {
- mClickAnimator.cancel();
- }
- mIsCurrentlyVisible = visible;
- mAlgorithm.getState(mCurrentState);
- mCurrentState.animateToState();
- }
-
- public void setInvisible() {
- mIsCurrentlyVisible = false;
- mAlgorithm.getState(mCurrentState);
- mCurrentState.apply();
- }
-
- public boolean isCurrentlyVisible() {
- return mIsCurrentlyVisible;
- }
-
- public void performDotClickAnimation() {
- if (mClickAnimator.isRunning()) {
- // don't perform an animation if it's running already
- return;
- }
- mClickAnimator.start();
- }
-
-
- public float getAnimationProgress() {
- return mAnimationProgress;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java
deleted file mode 100644
index 4febab1..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar;
-
-import android.view.View;
-import android.view.ViewPropertyAnimator;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A state of a {@link com.android.systemui.statusbar.SpeedBumpDotsLayout}
- */
-public class SpeedBumpDotsState {
-
- public static final int HIDDEN = 1;
- public static final int SHOWN = 2;
- private static final int VISIBILITY_ANIMATION_DELAY_PER_ELEMENT = 80;
-
- private final SpeedBumpDotsLayout mHostView;
- private final HashMap<View, ViewState> mStateMap = new HashMap<View, ViewState>();
- private final Interpolator mFastOutSlowInInterpolator;
- private int mActiveState = 0;
-
- public SpeedBumpDotsState(SpeedBumpDotsLayout hostLayout) {
- mHostView = hostLayout;
- mFastOutSlowInInterpolator = AnimationUtils
- .loadInterpolator(hostLayout.getContext(),
- android.R.interpolator.fast_out_slow_in);
- }
-
- public SpeedBumpDotsLayout getHostView() {
- return mHostView;
- }
-
- public void resetViewStates() {
- int numChildren = mHostView.getChildCount();
- for (int i = 0; i < numChildren; i++) {
- View child = mHostView.getChildAt(i);
- ViewState viewState = mStateMap.get(child);
- if (viewState == null) {
- viewState = new ViewState();
- mStateMap.put(child, viewState);
- }
- }
- }
-
- public ViewState getViewStateForView(View requestedView) {
- return mStateMap.get(requestedView);
- }
-
- public void apply() {
- int childCount = mHostView.getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = mHostView.getChildAt(i);
- ViewState viewState = mStateMap.get(child);
-
- child.setTranslationX(viewState.xTranslation);
- child.setTranslationY(viewState.yTranslation);
- child.setScaleX(viewState.scale);
- child.setScaleY(viewState.scale);
- child.setAlpha(viewState.alpha);
- }
- }
-
- public void animateToState() {
- int childCount = mHostView.getChildCount();
- int middleIndex = (childCount - 1) / 2;
- long delayPerElement = VISIBILITY_ANIMATION_DELAY_PER_ELEMENT;
- boolean isAppearing = getActiveState() == SHOWN;
- boolean isDisappearing = getActiveState() == HIDDEN;
- for (int i = 0; i < childCount; i++) {
- int delayIndex;
- if (i <= middleIndex) {
- delayIndex = i * 2;
- } else {
- int distToMiddle = i - middleIndex;
- delayIndex = (childCount - 1) - (distToMiddle - 1) * 2;
- }
- long startDelay = 0;
- if (isAppearing || isDisappearing) {
- if (isDisappearing) {
- delayIndex = childCount - 1 - delayIndex;
- }
- startDelay = delayIndex * delayPerElement;
- }
- View child = mHostView.getChildAt(i);
- ViewState viewState = mStateMap.get(child);
- child.animate().setInterpolator(mFastOutSlowInInterpolator)
- .setStartDelay(startDelay)
- .alpha(viewState.alpha)
- .translationX(viewState.xTranslation)
- .translationY(viewState.yTranslation)
- .scaleX(viewState.scale).scaleY(viewState.scale);
- }
- }
-
- public int getActiveState() {
- return mActiveState;
- }
-
- public void setActiveState(int mActiveState) {
- this.mActiveState = mActiveState;
- }
-
- public static class ViewState {
- float xTranslation;
- float yTranslation;
- float alpha;
- float scale;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
index 689d0e9..f80f0fd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
@@ -16,71 +16,26 @@
package com.android.systemui.statusbar;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
import android.content.Context;
-import android.graphics.Outline;
import android.util.AttributeSet;
-import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
-import android.widget.TextView;
import com.android.systemui.R;
/**
* The view representing the separation between important and less important notifications
*/
-public class SpeedBumpView extends ExpandableView implements View.OnClickListener {
+public class SpeedBumpView extends ExpandableView {
- private final int mCollapsedHeight;
- private final int mDotsHeight;
- private final int mTextPaddingInset;
- private SpeedBumpDotsLayout mDots;
- private AlphaOptimizedView mLineLeft;
- private AlphaOptimizedView mLineRight;
- private boolean mIsExpanded;
- private boolean mDividerVisible = true;
- private ValueAnimator mCurrentAnimator;
+ private final int mSpeedBumpHeight;
+ private AlphaOptimizedView mLine;
+ private boolean mIsVisible = true;
private final Interpolator mFastOutSlowInInterpolator;
- private float mCenterX;
- private TextView mExplanationText;
- private boolean mExplanationTextVisible = false;
- private AnimatorListenerAdapter mHideExplanationListener = new AnimatorListenerAdapter() {
- private boolean mCancelled;
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!mCancelled) {
- mExplanationText.setVisibility(View.INVISIBLE);
- }
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- mCancelled = true;
- }
-
- @Override
- public void onAnimationStart(Animator animation) {
- mCancelled = false;
- }
- };
- private Animator.AnimatorListener mAnimationFinishedListener = new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mCurrentAnimator = null;
- }
- };
public SpeedBumpView(Context context, AttributeSet attrs) {
super(context, attrs);
- mCollapsedHeight = getResources()
- .getDimensionPixelSize(R.dimen.speed_bump_height_collapsed);
- mTextPaddingInset = getResources().getDimensionPixelSize(
- R.dimen.speed_bump_text_padding_inset);
- mDotsHeight = getResources().getDimensionPixelSize(R.dimen.speed_bump_dots_height);
- setOnClickListener(this);
+ mSpeedBumpHeight = getResources()
+ .getDimensionPixelSize(R.dimen.speed_bump_height);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
android.R.interpolator.fast_out_slow_in);
}
@@ -88,111 +43,41 @@
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mDots = (SpeedBumpDotsLayout) findViewById(R.id.speed_bump_dots_layout);
- mLineLeft = (AlphaOptimizedView) findViewById(R.id.speedbump_line_left);
- mLineRight = (AlphaOptimizedView) findViewById(R.id.speedbump_line_right);
- mExplanationText = (TextView) findViewById(R.id.speed_bump_text);
- resetExplanationText();
-
+ mLine = (AlphaOptimizedView) findViewById(R.id.speedbump_line);
}
@Override
protected int getInitialHeight() {
- return mCollapsedHeight;
+ return mSpeedBumpHeight;
}
@Override
public int getIntrinsicHeight() {
- if (mCurrentAnimator != null) {
- // expand animation is running
- return getActualHeight();
- }
- return mIsExpanded ? getHeight() : mCollapsedHeight;
+ return mSpeedBumpHeight;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- Outline outline = new Outline();
- mCenterX = getWidth() / 2;
- float centerY = getHeight() / 2;
- // TODO: hide outline better
- // Temporary workaround to hide outline on a transparent view
- int outlineLeft = (int) (mCenterX - getResources().getDisplayMetrics().densityDpi * 8);
- int outlineTop = (int) (centerY - mDotsHeight / 2);
- outline.setOval(outlineLeft, outlineTop, outlineLeft + mDotsHeight,
- outlineTop + mDotsHeight);
- setOutline(outline);
- mLineLeft.setPivotX(mLineLeft.getWidth());
- mLineLeft.setPivotY(mLineLeft.getHeight() / 2);
- mLineRight.setPivotX(0);
- mLineRight.setPivotY(mLineRight.getHeight() / 2);
+ mLine.setPivotX(mLine.getWidth() / 2);
+ mLine.setPivotY(mLine.getHeight() / 2);
+ setOutline(null);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
- int height = mCollapsedHeight + mExplanationText.getMeasuredHeight() - mTextPaddingInset;
+ int height = mSpeedBumpHeight;
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height);
}
@Override
- public void onClick(View v) {
- if (mCurrentAnimator != null) {
- return;
- }
- int startValue = mIsExpanded ? getMaxHeight() : mCollapsedHeight;
- int endValue = mIsExpanded ? mCollapsedHeight : getMaxHeight();
- mCurrentAnimator = ValueAnimator.ofInt(startValue, endValue);
- mCurrentAnimator.setInterpolator(mFastOutSlowInInterpolator);
- mCurrentAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- setActualHeight((int) animation.getAnimatedValue());
- }
- });
- mCurrentAnimator.addListener(mAnimationFinishedListener);
- mCurrentAnimator.start();
- mIsExpanded = !mIsExpanded;
- mDots.performDotClickAnimation();
- animateExplanationTextInternal(mIsExpanded);
- }
-
- private void animateExplanationTextInternal(boolean visible) {
- if (mExplanationTextVisible != visible) {
- float translationY = 0.0f;
- float scale = 0.5f;
- float alpha = 0.0f;
- boolean needsHideListener = true;
- if (visible) {
- mExplanationText.setVisibility(VISIBLE);
- translationY = mDots.getBottom() - mTextPaddingInset;
- scale = 1.0f;
- alpha = 1.0f;
- needsHideListener = false;
- }
- mExplanationText.animate().setInterpolator(mFastOutSlowInInterpolator)
- .alpha(alpha)
- .scaleX(scale)
- .scaleY(scale)
- .translationY(translationY)
- .setListener(needsHideListener ? mHideExplanationListener : null);
- mExplanationTextVisible = visible;
- }
- }
-
- @Override
public boolean isTransparent() {
return true;
}
public void performVisibilityAnimation(boolean nowVisible) {
animateDivider(nowVisible, null /* onFinishedRunnable */);
-
- // Animate explanation Text
- if (mIsExpanded) {
- animateExplanationTextInternal(nowVisible);
- }
}
/**
@@ -203,28 +88,16 @@
* finished.
*/
public void animateDivider(boolean nowVisible, Runnable onFinishedRunnable) {
- if (nowVisible != mDividerVisible) {
+ if (nowVisible != mIsVisible) {
// Animate dividers
float endValue = nowVisible ? 1.0f : 0.0f;
- float endTranslationXLeft = nowVisible ? 0.0f : mCenterX - mLineLeft.getRight();
- float endTranslationXRight = nowVisible ? 0.0f : mCenterX - mLineRight.getLeft();
- mLineLeft.animate()
+ mLine.animate()
.alpha(endValue)
.scaleX(endValue)
.scaleY(endValue)
- .translationX(endTranslationXLeft)
.setInterpolator(mFastOutSlowInInterpolator)
.withEndAction(onFinishedRunnable);
- mLineRight.animate()
- .alpha(endValue)
- .scaleX(endValue)
- .scaleY(endValue)
- .translationX(endTranslationXRight)
- .setInterpolator(mFastOutSlowInInterpolator);
-
- // Animate dots
- mDots.performVisibilityAnimation(nowVisible);
- mDividerVisible = nowVisible;
+ mIsVisible = nowVisible;
} else {
if (onFinishedRunnable != null) {
onFinishedRunnable.run();
@@ -233,34 +106,10 @@
}
public void setInvisible() {
- float endTranslationXLeft = mCenterX - mLineLeft.getRight();
- float endTranslationXRight = mCenterX - mLineRight.getLeft();
- mLineLeft.setAlpha(0.0f);
- mLineLeft.setScaleX(0.0f);
- mLineLeft.setScaleY(0.0f);
- mLineLeft.setTranslationX(endTranslationXLeft);
- mLineRight.setAlpha(0.0f);
- mLineRight.setScaleX(0.0f);
- mLineRight.setScaleY(0.0f);
- mLineRight.setTranslationX(endTranslationXRight);
- mDots.setInvisible();
- resetExplanationText();
-
- mDividerVisible = false;
- }
-
- public void collapse() {
- if (mIsExpanded) {
- setActualHeight(mCollapsedHeight);
- mIsExpanded = false;
- }
- resetExplanationText();
- }
-
- public void animateExplanationText(boolean nowVisible) {
- if (mIsExpanded) {
- animateExplanationTextInternal(nowVisible);
- }
+ mLine.setAlpha(0.0f);
+ mLine.setScaleX(0.0f);
+ mLine.setScaleY(0.0f);
+ mIsVisible = false;
}
@Override
@@ -272,17 +121,4 @@
public void performAddAnimation(long delay) {
performVisibilityAnimation(true);
}
-
- private void resetExplanationText() {
- mExplanationText.setTranslationY(0);
- mExplanationText.setVisibility(INVISIBLE);
- mExplanationText.setAlpha(0.0f);
- mExplanationText.setScaleX(0.5f);
- mExplanationText.setScaleY(0.5f);
- mExplanationTextVisible = false;
- }
-
- public boolean isExpanded() {
- return mIsExpanded;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 1276279..d413f63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -64,7 +64,7 @@
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
-import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.util.ArraySet;
import android.util.DisplayMetrics;
@@ -1064,7 +1064,7 @@
}
@Override
- public void addNotificationInternal(StatusBarNotification notification, Ranking ranking) {
+ public void addNotificationInternal(StatusBarNotification notification, RankingMap ranking) {
if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());
if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(notification, ranking)) {
// Forward the ranking so we can sort the new notification.
@@ -1075,8 +1075,7 @@
displayNotification(notification, ranking);
}
- public void displayNotification(StatusBarNotification notification,
- Ranking ranking) {
+ public void displayNotification(StatusBarNotification notification, RankingMap ranking) {
if (mUseHeadsUp && shouldInterrupt(notification)) {
if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
Entry interruptionCandidate = new Entry(notification, null);
@@ -1160,21 +1159,21 @@
}
@Override
- public void updateNotificationInternal(StatusBarNotification notification, Ranking ranking) {
+ public void updateNotificationInternal(StatusBarNotification notification, RankingMap ranking) {
super.updateNotificationInternal(notification, ranking);
// if we're here, then the notification is already in the shade
mIntercepted.remove(notification.getKey());
}
@Override
- protected void updateRankingInternal(Ranking ranking) {
+ protected void updateRankingInternal(RankingMap ranking) {
mNotificationData.updateRanking(ranking);
mIntercepted.retryIntercepts(ranking);
updateNotifications();
}
@Override
- public void removeNotificationInternal(String key, Ranking ranking) {
+ public void removeNotificationInternal(String key, RankingMap ranking) {
if (ENABLE_HEADS_UP && mHeadsUpNotificationView.getEntry() != null
&& key.equals(mHeadsUpNotificationView.getEntry().notification.getKey())) {
mHeadsUpNotificationView.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index e47f475..94472a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -1723,7 +1723,6 @@
mStackScrollAlgorithm.setIsExpanded(isExpanded);
if (!isExpanded) {
mOwnScrollY = 0;
- mSpeedBumpView.collapse();
}
}
@@ -1792,7 +1791,6 @@
int newVisibility = visible ? VISIBLE : GONE;
mSpeedBumpView.setVisibility(newVisibility);
if (visible) {
- mSpeedBumpView.collapse();
// Make invisible to ensure that the appear animation is played.
mSpeedBumpView.setInvisible();
if (!mIsExpansionChanging) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 94cb16d..1ad4acc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -160,9 +160,8 @@
}
if(child instanceof SpeedBumpView) {
- float speedBumpEnd = newYTranslation + newHeight;
- performSpeedBumpAnimation(i, (SpeedBumpView) child, speedBumpEnd,
- newYTranslation);
+ float lineEnd = newYTranslation + newHeight / 2;
+ performSpeedBumpAnimation(i, (SpeedBumpView) child, lineEnd);
}
}
}
@@ -183,20 +182,12 @@
child.setClipBounds(mClipRect);
}
- private void performSpeedBumpAnimation(int i, SpeedBumpView speedBump, float speedBumpEnd,
- float speedBumpStart) {
+ private void performSpeedBumpAnimation(int i, SpeedBumpView speedBump, float speedBumpEnd) {
View nextChild = getNextChildNotGone(i);
if (nextChild != null) {
ViewState nextState = getViewStateForView(nextChild);
- boolean startIsAboveNext = nextState.yTranslation > speedBumpStart;
+ boolean startIsAboveNext = nextState.yTranslation > speedBumpEnd;
speedBump.animateDivider(startIsAboveNext, null /* onFinishedRunnable */);
-
- // handle expanded case
- if (speedBump.isExpanded()) {
- boolean endIsAboveNext = nextState.yTranslation > speedBumpEnd;
- speedBump.animateExplanationText(endIsAboveNext);
- }
-
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index ac8d1a0..9260aac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.tv;
import android.os.IBinder;
-import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
@@ -51,11 +51,11 @@
}
@Override
- public void addNotificationInternal(StatusBarNotification notification, Ranking ranking) {
+ public void addNotificationInternal(StatusBarNotification notification, RankingMap ranking) {
}
@Override
- protected void updateRankingInternal(Ranking ranking) {
+ protected void updateRankingInternal(RankingMap ranking) {
}
@Override
@@ -63,7 +63,7 @@
}
@Override
- public void removeNotificationInternal(String key, Ranking ranking) {
+ public void removeNotificationInternal(String key, RankingMap ranking) {
}
@Override
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index bd45761..f66f7ac 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -630,8 +630,8 @@
if (DBG) log("ConnectivityService starting up");
NetworkCapabilities netCap = new NetworkCapabilities();
- netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
mDefaultRequest = new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId());
NetworkRequestInfo nri = new NetworkRequestInfo(null, mDefaultRequest, new Binder(),
NetworkRequestInfo.REQUEST);
@@ -1669,7 +1669,7 @@
continue;
}
- int prefix = destination.getNetworkPrefixLength();
+ int prefix = destination.getPrefixLength();
InetAddress addrMasked = NetworkUtils.getNetworkPart(address, prefix);
InetAddress destMasked = NetworkUtils.getNetworkPart(destination.getAddress(),
prefix);
@@ -1871,7 +1871,7 @@
mNetd.addRoute(netId, r);
}
if (exempt) {
- LinkAddress dest = r.getDestination();
+ LinkAddress dest = r.getDestinationLinkAddress();
if (!mExemptAddresses.contains(dest)) {
mNetd.setHostExemption(dest);
mExemptAddresses.add(dest);
@@ -1904,7 +1904,7 @@
} else {
mNetd.removeRoute(netId, r);
}
- LinkAddress dest = r.getDestination();
+ LinkAddress dest = r.getDestinationLinkAddress();
if (mExemptAddresses.contains(dest)) {
mNetd.clearHostExemption(dest);
mExemptAddresses.remove(dest);
@@ -2691,7 +2691,7 @@
dnsDiff = curLp.compareDnses(newLp);
} else if (newLp != null) {
routeDiff.added = newLp.getAllRoutes();
- dnsDiff.added = newLp.getDnses();
+ dnsDiff.added = newLp.getDnsServers();
}
boolean routesChanged = (routeDiff.removed.size() != 0 || routeDiff.added.size() != 0);
@@ -2915,7 +2915,7 @@
if (nt != null && nt.getNetworkInfo().isConnected() && !nt.isTeardownRequested()) {
LinkProperties p = nt.getLinkProperties();
if (p == null) return;
- Collection<InetAddress> dnses = p.getDnses();
+ Collection<InetAddress> dnses = p.getDnsServers();
int netId = nt.getNetwork().netId;
if (mNetConfigs[netType].isDefault()) {
String network = nt.getNetworkInfo().getTypeName();
@@ -5625,7 +5625,7 @@
}
private void updateDnses(LinkProperties newLp, LinkProperties oldLp, int netId) {
if (oldLp == null || (newLp.isIdenticalDnses(oldLp) == false)) {
- Collection<InetAddress> dnses = newLp.getDnses();
+ Collection<InetAddress> dnses = newLp.getDnsServers();
if (dnses.size() == 0 && mDefaultDns != null) {
dnses = new ArrayList();
dnses.add(mDefaultDns);
@@ -5790,7 +5790,8 @@
isNewDefault = true;
updateActiveDefaultNetwork(newNetwork);
if (newNetwork.linkProperties != null) {
- setDefaultDnsSystemProperties(newNetwork.linkProperties.getDnses());
+ setDefaultDnsSystemProperties(
+ newNetwork.linkProperties.getDnsServers());
} else {
setDefaultDnsSystemProperties(new ArrayList<InetAddress>());
}
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index eefe8da..362061e 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -795,7 +795,7 @@
final Command cmd = new Command("interface", "setcfg", iface,
linkAddr.getAddress().getHostAddress(),
- linkAddr.getNetworkPrefixLength());
+ linkAddr.getPrefixLength());
for (String flag : cfg.getFlags()) {
cmd.appendArg(flag);
}
@@ -882,9 +882,9 @@
final Command cmd = new Command("network", "route", action, netId);
// create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
- final LinkAddress la = route.getDestination();
+ final LinkAddress la = route.getDestinationLinkAddress();
cmd.appendArg(route.getInterface());
- cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getNetworkPrefixLength());
+ cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength());
if (route.hasGateway()) {
cmd.appendArg(route.getGateway().getHostAddress());
}
@@ -1697,9 +1697,9 @@
public void setMarkedForwardingRoute(String iface, RouteInfo route) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- LinkAddress dest = route.getDestination();
+ LinkAddress dest = route.getDestinationLinkAddress();
mConnector.execute("interface", "fwmark", "route", "add", iface,
- dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength());
+ dest.getAddress().getHostAddress(), dest.getPrefixLength());
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
@@ -1709,9 +1709,9 @@
public void clearMarkedForwardingRoute(String iface, RouteInfo route) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
try {
- LinkAddress dest = route.getDestination();
+ LinkAddress dest = route.getDestinationLinkAddress();
mConnector.execute("interface", "fwmark", "route", "remove", iface,
- dest.getAddress().getHostAddress(), dest.getNetworkPrefixLength());
+ dest.getAddress().getHostAddress(), dest.getPrefixLength());
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
@@ -1998,9 +1998,9 @@
final Command cmd = new Command("network", "route", "legacy", uid, action, netId);
// create triplet: interface dest-ip-addr/prefixlength gateway-ip-addr
- final LinkAddress la = routeInfo.getDestination();
+ final LinkAddress la = routeInfo.getDestinationLinkAddress();
cmd.appendArg(routeInfo.getInterface());
- cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getNetworkPrefixLength());
+ cmd.appendArg(la.getAddress().getHostAddress() + "/" + la.getPrefixLength());
if (routeInfo.hasGateway()) {
cmd.appendArg(routeInfo.getGateway().getHostAddress());
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 70327a6..bd1baac 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6030,6 +6030,9 @@
IPackageManager pm, ProviderInfo pi, GrantUri grantUri, int uid, final int modeFlags) {
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"checkHoldingPermissionsLocked: uri=" + grantUri + " uid=" + uid);
+ if (UserHandle.getUserId(uid) != grantUri.sourceUserId) {
+ return false;
+ }
if (pi.applicationInfo.uid == uid) {
return true;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 92b5f52..bdf4708 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -1344,7 +1344,7 @@
if (iface != null) {
String[] dnsServers = mDefaultDnsServers;
- Collection<InetAddress> dnses = linkProperties.getDnses();
+ Collection<InetAddress> dnses = linkProperties.getDnsServers();
if (dnses != null) {
// we currently only handle IPv4
ArrayList<InetAddress> v4Dnses =
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 835b094..9ae8aed 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -949,6 +949,11 @@
}
@Override
+ public long getFlags() {
+ return mFlags;
+ }
+
+ @Override
public void play() throws RemoteException {
mSessionCb.play();
}
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index aee7679..907eeb2 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -81,15 +81,15 @@
for (LinkAddress linkAddr : linkProperties.getLinkAddresses()) {
out.writeUTF(LINK_ADDRESS_KEY);
out.writeUTF(linkAddr.getAddress().getHostAddress());
- out.writeInt(linkAddr.getNetworkPrefixLength());
+ out.writeInt(linkAddr.getPrefixLength());
}
for (RouteInfo route : linkProperties.getRoutes()) {
out.writeUTF(GATEWAY_KEY);
- LinkAddress dest = route.getDestination();
+ LinkAddress dest = route.getDestinationLinkAddress();
if (dest != null) {
out.writeInt(1);
out.writeUTF(dest.getAddress().getHostAddress());
- out.writeInt(dest.getNetworkPrefixLength());
+ out.writeInt(dest.getPrefixLength());
} else {
out.writeInt(0);
}
@@ -100,7 +100,7 @@
out.writeInt(0);
}
}
- for (InetAddress inetAddr : linkProperties.getDnses()) {
+ for (InetAddress inetAddr : linkProperties.getDnsServers()) {
out.writeUTF(DNS_KEY);
out.writeUTF(inetAddr.getHostAddress());
}
@@ -232,7 +232,7 @@
}
linkProperties.addRoute(new RouteInfo(dest, gateway));
} else if (key.equals(DNS_KEY)) {
- linkProperties.addDns(
+ linkProperties.addDnsServer(
NetworkUtils.numericToInetAddress(in.readUTF()));
} else if (key.equals(PROXY_SETTINGS_KEY)) {
proxySettings = ProxySettings.valueOf(in.readUTF());
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c7dd849..407ecb8 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -10204,7 +10204,7 @@
synchronized (mPackages) {
// Check whether the newly-scanned package wants to define an already-defined perm
int N = pkg.permissions.size();
- for (int i = 0; i < N; i++) {
+ for (int i = N-1; i >= 0; i--) {
PackageParser.Permission perm = pkg.permissions.get(i);
BasePermission bp = mSettings.mPermissions.get(perm.info.name);
if (bp != null) {
@@ -10212,13 +10212,23 @@
// also includes the "updating the same package" case, of course.
if (compareSignatures(bp.packageSetting.signatures.mSignatures,
pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
- Slog.w(TAG, "Package " + pkg.packageName
- + " attempting to redeclare permission " + perm.info.name
- + " already owned by " + bp.sourcePackage);
- res.returnCode = PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
- res.origPermission = perm.info.name;
- res.origPackage = bp.sourcePackage;
- return;
+ // If the owning package is the system itself, we log but allow
+ // install to proceed; we fail the install on all other permission
+ // redefinitions.
+ if (!bp.sourcePackage.equals("android")) {
+ Slog.w(TAG, "Package " + pkg.packageName
+ + " attempting to redeclare permission " + perm.info.name
+ + " already owned by " + bp.sourcePackage);
+ res.returnCode = PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
+ res.origPermission = perm.info.name;
+ res.origPackage = bp.sourcePackage;
+ return;
+ } else {
+ Slog.w(TAG, "Package " + pkg.packageName
+ + " attempting to redeclare system permission "
+ + perm.info.name + "; ignoring new declaration");
+ pkg.permissions.remove(i);
+ }
}
}
}