Merge "Remove deprecated methods and constants in IntentCompat." into oc-mr1-dev
diff --git a/api/27.0.0-SNAPSHOT.txt b/api/27.0.0-SNAPSHOT.txt
index 237fabf..d4e4ffa 100644
--- a/api/27.0.0-SNAPSHOT.txt
+++ b/api/27.0.0-SNAPSHOT.txt
@@ -1106,11 +1106,13 @@
     method public int getAttributeInt(java.lang.String, int);
     method public deprecated boolean getLatLong(float[]);
     method public double[] getLatLong();
+    method public int getRotationDegrees();
     method public byte[] getThumbnail();
     method public android.graphics.Bitmap getThumbnailBitmap();
     method public byte[] getThumbnailBytes();
     method public long[] getThumbnailRange();
     method public boolean hasThumbnail();
+    method public boolean isFlipped();
     method public boolean isThumbnailCompressed();
     method public void resetOrientation();
     method public void rotate(int);
@@ -1119,6 +1121,102 @@
     method public void setAttribute(java.lang.String, java.lang.String);
     method public void setGpsInfo(android.location.Location);
     method public void setLatLong(double, double);
+    field public static final short ALTITUDE_ABOVE_SEA_LEVEL = 0; // 0x0
+    field public static final short ALTITUDE_BELOW_SEA_LEVEL = 1; // 0x1
+    field public static final int[] BITS_PER_SAMPLE_GREYSCALE_1;
+    field public static final int[] BITS_PER_SAMPLE_GREYSCALE_2;
+    field public static final int[] BITS_PER_SAMPLE_RGB;
+    field public static final int COLOR_SPACE_S_RGB = 1; // 0x1
+    field public static final int COLOR_SPACE_UNCALIBRATED = 65535; // 0xffff
+    field public static final short CONTRAST_HARD = 2; // 0x2
+    field public static final short CONTRAST_NORMAL = 0; // 0x0
+    field public static final short CONTRAST_SOFT = 1; // 0x1
+    field public static final int DATA_DEFLATE_ZIP = 8; // 0x8
+    field public static final int DATA_HUFFMAN_COMPRESSED = 2; // 0x2
+    field public static final int DATA_JPEG = 6; // 0x6
+    field public static final int DATA_JPEG_COMPRESSED = 7; // 0x7
+    field public static final int DATA_LOSSY_JPEG = 34892; // 0x884c
+    field public static final int DATA_PACK_BITS_COMPRESSED = 32773; // 0x8005
+    field public static final int DATA_UNCOMPRESSED = 1; // 0x1
+    field public static final short EXPOSURE_MODE_AUTO = 0; // 0x0
+    field public static final short EXPOSURE_MODE_AUTO_BRACKET = 2; // 0x2
+    field public static final short EXPOSURE_MODE_MANUAL = 1; // 0x1
+    field public static final short EXPOSURE_PROGRAM_ACTION = 6; // 0x6
+    field public static final short EXPOSURE_PROGRAM_APERTURE_PRIORITY = 3; // 0x3
+    field public static final short EXPOSURE_PROGRAM_CREATIVE = 5; // 0x5
+    field public static final short EXPOSURE_PROGRAM_LANDSCAPE_MODE = 8; // 0x8
+    field public static final short EXPOSURE_PROGRAM_MANUAL = 1; // 0x1
+    field public static final short EXPOSURE_PROGRAM_NORMAL = 2; // 0x2
+    field public static final short EXPOSURE_PROGRAM_NOT_DEFINED = 0; // 0x0
+    field public static final short EXPOSURE_PROGRAM_PORTRAIT_MODE = 7; // 0x7
+    field public static final short EXPOSURE_PROGRAM_SHUTTER_PRIORITY = 4; // 0x4
+    field public static final short FILE_SOURCE_DSC = 3; // 0x3
+    field public static final short FILE_SOURCE_OTHER = 0; // 0x0
+    field public static final short FILE_SOURCE_REFLEX_SCANNER = 2; // 0x2
+    field public static final short FILE_SOURCE_TRANSPARENT_SCANNER = 1; // 0x1
+    field public static final short FLAG_FLASH_FIRED = 1; // 0x1
+    field public static final short FLAG_FLASH_MODE_AUTO = 24; // 0x18
+    field public static final short FLAG_FLASH_MODE_COMPULSORY_FIRING = 8; // 0x8
+    field public static final short FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION = 16; // 0x10
+    field public static final short FLAG_FLASH_NO_FLASH_FUNCTION = 32; // 0x20
+    field public static final short FLAG_FLASH_RED_EYE_SUPPORTED = 64; // 0x40
+    field public static final short FLAG_FLASH_RETURN_LIGHT_DETECTED = 6; // 0x6
+    field public static final short FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED = 4; // 0x4
+    field public static final short FORMAT_CHUNKY = 1; // 0x1
+    field public static final short FORMAT_PLANAR = 2; // 0x2
+    field public static final short GAIN_CONTROL_HIGH_GAIN_DOWN = 4; // 0x4
+    field public static final short GAIN_CONTROL_HIGH_GAIN_UP = 2; // 0x2
+    field public static final short GAIN_CONTROL_LOW_GAIN_DOWN = 3; // 0x3
+    field public static final short GAIN_CONTROL_LOW_GAIN_UP = 1; // 0x1
+    field public static final short GAIN_CONTROL_NONE = 0; // 0x0
+    field public static final java.lang.String GPS_DIRECTION_MAGNETIC = "M";
+    field public static final java.lang.String GPS_DIRECTION_TRUE = "T";
+    field public static final java.lang.String GPS_DISTANCE_KILOMETERS = "K";
+    field public static final java.lang.String GPS_DISTANCE_MILES = "M";
+    field public static final java.lang.String GPS_DISTANCE_NAUTICAL_MILES = "N";
+    field public static final java.lang.String GPS_MEASUREMENT_2D = "2";
+    field public static final java.lang.String GPS_MEASUREMENT_3D = "3";
+    field public static final short GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED = 1; // 0x1
+    field public static final java.lang.String GPS_MEASUREMENT_INTERRUPTED = "V";
+    field public static final java.lang.String GPS_MEASUREMENT_IN_PROGRESS = "A";
+    field public static final short GPS_MEASUREMENT_NO_DIFFERENTIAL = 0; // 0x0
+    field public static final java.lang.String GPS_SPEED_KILOMETERS_PER_HOUR = "K";
+    field public static final java.lang.String GPS_SPEED_KNOTS = "N";
+    field public static final java.lang.String GPS_SPEED_MILES_PER_HOUR = "M";
+    field public static final java.lang.String LATITUDE_NORTH = "N";
+    field public static final java.lang.String LATITUDE_SOUTH = "S";
+    field public static final short LIGHT_SOURCE_CLOUDY_WEATHER = 10; // 0xa
+    field public static final short LIGHT_SOURCE_COOL_WHITE_FLUORESCENT = 14; // 0xe
+    field public static final short LIGHT_SOURCE_D50 = 23; // 0x17
+    field public static final short LIGHT_SOURCE_D55 = 20; // 0x14
+    field public static final short LIGHT_SOURCE_D65 = 21; // 0x15
+    field public static final short LIGHT_SOURCE_D75 = 22; // 0x16
+    field public static final short LIGHT_SOURCE_DAYLIGHT = 1; // 0x1
+    field public static final short LIGHT_SOURCE_DAYLIGHT_FLUORESCENT = 12; // 0xc
+    field public static final short LIGHT_SOURCE_DAY_WHITE_FLUORESCENT = 13; // 0xd
+    field public static final short LIGHT_SOURCE_FINE_WEATHER = 9; // 0x9
+    field public static final short LIGHT_SOURCE_FLASH = 4; // 0x4
+    field public static final short LIGHT_SOURCE_FLUORESCENT = 2; // 0x2
+    field public static final short LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN = 24; // 0x18
+    field public static final short LIGHT_SOURCE_OTHER = 255; // 0xff
+    field public static final short LIGHT_SOURCE_SHADE = 11; // 0xb
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_A = 17; // 0x11
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_B = 18; // 0x12
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_C = 19; // 0x13
+    field public static final short LIGHT_SOURCE_TUNGSTEN = 3; // 0x3
+    field public static final short LIGHT_SOURCE_UNKNOWN = 0; // 0x0
+    field public static final short LIGHT_SOURCE_WARM_WHITE_FLUORESCENT = 16; // 0x10
+    field public static final short LIGHT_SOURCE_WHITE_FLUORESCENT = 15; // 0xf
+    field public static final java.lang.String LONGITUDE_EAST = "E";
+    field public static final java.lang.String LONGITUDE_WEST = "W";
+    field public static final short METERING_MODE_AVERAGE = 1; // 0x1
+    field public static final short METERING_MODE_CENTER_WEIGHT_AVERAGE = 2; // 0x2
+    field public static final short METERING_MODE_MULTI_SPOT = 4; // 0x4
+    field public static final short METERING_MODE_OTHER = 255; // 0xff
+    field public static final short METERING_MODE_PARTIAL = 6; // 0x6
+    field public static final short METERING_MODE_PATTERN = 5; // 0x5
+    field public static final short METERING_MODE_SPOT = 3; // 0x3
+    field public static final short METERING_MODE_UNKNOWN = 0; // 0x0
     field public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // 0x2
     field public static final int ORIENTATION_FLIP_VERTICAL = 4; // 0x4
     field public static final int ORIENTATION_NORMAL = 1; // 0x1
@@ -1128,10 +1226,52 @@
     field public static final int ORIENTATION_TRANSPOSE = 5; // 0x5
     field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
     field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
+    field public static final int ORIGINAL_RESOLUTION_IMAGE = 0; // 0x0
+    field public static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1; // 0x1
+    field public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2; // 0x2
+    field public static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0; // 0x0
+    field public static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6; // 0x6
+    field public static final int REDUCED_RESOLUTION_IMAGE = 1; // 0x1
+    field public static final short RENDERED_PROCESS_CUSTOM = 1; // 0x1
+    field public static final short RENDERED_PROCESS_NORMAL = 0; // 0x0
+    field public static final short RESOLUTION_UNIT_CENTIMETERS = 3; // 0x3
+    field public static final short RESOLUTION_UNIT_INCHES = 2; // 0x2
+    field public static final short SATURATION_HIGH = 0; // 0x0
+    field public static final short SATURATION_LOW = 0; // 0x0
+    field public static final short SATURATION_NORMAL = 0; // 0x0
+    field public static final short SCENE_CAPTURE_TYPE_LANDSCAPE = 1; // 0x1
+    field public static final short SCENE_CAPTURE_TYPE_NIGHT = 3; // 0x3
+    field public static final short SCENE_CAPTURE_TYPE_PORTRAIT = 2; // 0x2
+    field public static final short SCENE_CAPTURE_TYPE_STANDARD = 0; // 0x0
+    field public static final short SCENE_TYPE_DIRECTLY_PHOTOGRAPHED = 1; // 0x1
+    field public static final short SENSITIVITY_TYPE_ISO_SPEED = 3; // 0x3
+    field public static final short SENSITIVITY_TYPE_REI = 2; // 0x2
+    field public static final short SENSITIVITY_TYPE_REI_AND_ISO = 6; // 0x6
+    field public static final short SENSITIVITY_TYPE_SOS = 1; // 0x1
+    field public static final short SENSITIVITY_TYPE_SOS_AND_ISO = 5; // 0x5
+    field public static final short SENSITIVITY_TYPE_SOS_AND_REI = 4; // 0x4
+    field public static final short SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO = 7; // 0x7
+    field public static final short SENSITIVITY_TYPE_UNKNOWN = 0; // 0x0
+    field public static final short SENSOR_TYPE_COLOR_SEQUENTIAL = 5; // 0x5
+    field public static final short SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR = 8; // 0x8
+    field public static final short SENSOR_TYPE_NOT_DEFINED = 1; // 0x1
+    field public static final short SENSOR_TYPE_ONE_CHIP = 2; // 0x2
+    field public static final short SENSOR_TYPE_THREE_CHIP = 4; // 0x4
+    field public static final short SENSOR_TYPE_TRILINEAR = 7; // 0x7
+    field public static final short SENSOR_TYPE_TWO_CHIP = 3; // 0x3
+    field public static final short SHARPNESS_HARD = 2; // 0x2
+    field public static final short SHARPNESS_NORMAL = 0; // 0x0
+    field public static final short SHARPNESS_SOFT = 1; // 0x1
+    field public static final short SUBJECT_DISTANCE_RANGE_CLOSE_VIEW = 2; // 0x2
+    field public static final short SUBJECT_DISTANCE_RANGE_DISTANT_VIEW = 3; // 0x3
+    field public static final short SUBJECT_DISTANCE_RANGE_MACRO = 1; // 0x1
+    field public static final short SUBJECT_DISTANCE_RANGE_UNKNOWN = 0; // 0x0
     field public static final java.lang.String TAG_APERTURE_VALUE = "ApertureValue";
     field public static final java.lang.String TAG_ARTIST = "Artist";
     field public static final java.lang.String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final java.lang.String TAG_BODY_SERIAL_NUMBER = "BodySerialNumber";
     field public static final java.lang.String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field public static final java.lang.String TAG_CAMARA_OWNER_NAME = "CameraOwnerName";
     field public static final java.lang.String TAG_CFA_PATTERN = "CFAPattern";
     field public static final java.lang.String TAG_COLOR_SPACE = "ColorSpace";
     field public static final java.lang.String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
@@ -1164,6 +1304,7 @@
     field public static final java.lang.String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
     field public static final java.lang.String TAG_F_NUMBER = "FNumber";
     field public static final java.lang.String TAG_GAIN_CONTROL = "GainControl";
+    field public static final java.lang.String TAG_GAMMA = "Gamma";
     field public static final java.lang.String TAG_GPS_ALTITUDE = "GPSAltitude";
     field public static final java.lang.String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
     field public static final java.lang.String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
@@ -1178,6 +1319,7 @@
     field public static final java.lang.String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
     field public static final java.lang.String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
     field public static final java.lang.String TAG_GPS_DOP = "GPSDOP";
+    field public static final java.lang.String TAG_GPS_H_POSITIONING_ERROR = "GPSHPositioningError";
     field public static final java.lang.String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
     field public static final java.lang.String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
     field public static final java.lang.String TAG_GPS_LATITUDE = "GPSLatitude";
@@ -1200,9 +1342,16 @@
     field public static final java.lang.String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
     field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
     field public static final java.lang.String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
-    field public static final java.lang.String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_ISO_SPEED = "ISOSpeed";
+    field public static final java.lang.String TAG_ISO_SPEED_LATITUDE_YYY = "ISOSpeedLatitudeyyy";
+    field public static final java.lang.String TAG_ISO_SPEED_LATITUDE_ZZZ = "ISOSpeedLatitudezzz";
+    field public static final deprecated java.lang.String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
     field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
     field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
+    field public static final java.lang.String TAG_LENS_MAKE = "LensMake";
+    field public static final java.lang.String TAG_LENS_MODEL = "LensModel";
+    field public static final java.lang.String TAG_LENS_SERIAL_NUMBER = "LensSerialNumber";
+    field public static final java.lang.String TAG_LENS_SPECIFICATION = "LensSpecification";
     field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
     field public static final java.lang.String TAG_MAKE = "Make";
     field public static final java.lang.String TAG_MAKER_NOTE = "MakerNote";
@@ -1216,11 +1365,13 @@
     field public static final java.lang.String TAG_ORF_PREVIEW_IMAGE_START = "PreviewImageStart";
     field public static final java.lang.String TAG_ORF_THUMBNAIL_IMAGE = "ThumbnailImage";
     field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+    field public static final java.lang.String TAG_PHOTOGRAPHIC_SENSITIVITY = "PhotographicSensitivity";
     field public static final java.lang.String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
     field public static final java.lang.String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
     field public static final java.lang.String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
     field public static final java.lang.String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
     field public static final java.lang.String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final java.lang.String TAG_RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex";
     field public static final java.lang.String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
     field public static final java.lang.String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
     field public static final java.lang.String TAG_RESOLUTION_UNIT = "ResolutionUnit";
@@ -1236,11 +1387,13 @@
     field public static final java.lang.String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
     field public static final java.lang.String TAG_SCENE_TYPE = "SceneType";
     field public static final java.lang.String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final java.lang.String TAG_SENSITIVITY_TYPE = "SensitivityType";
     field public static final java.lang.String TAG_SHARPNESS = "Sharpness";
     field public static final java.lang.String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
     field public static final java.lang.String TAG_SOFTWARE = "Software";
     field public static final java.lang.String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
     field public static final java.lang.String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final java.lang.String TAG_STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity";
     field public static final java.lang.String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
     field public static final java.lang.String TAG_STRIP_OFFSETS = "StripOffsets";
     field public static final java.lang.String TAG_SUBFILE_TYPE = "SubfileType";
@@ -1262,8 +1415,12 @@
     field public static final java.lang.String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
     field public static final java.lang.String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
     field public static final java.lang.String TAG_Y_RESOLUTION = "YResolution";
-    field public static final int WHITEBALANCE_AUTO = 0; // 0x0
-    field public static final int WHITEBALANCE_MANUAL = 1; // 0x1
+    field public static final deprecated int WHITEBALANCE_AUTO = 0; // 0x0
+    field public static final deprecated int WHITEBALANCE_MANUAL = 1; // 0x1
+    field public static final short WHITE_BALANCE_AUTO = 0; // 0x0
+    field public static final short WHITE_BALANCE_MANUAL = 1; // 0x1
+    field public static final short Y_CB_CR_POSITIONING_CENTERED = 1; // 0x1
+    field public static final short Y_CB_CR_POSITIONING_CO_SITED = 2; // 0x2
   }
 
 }
@@ -5809,18 +5966,12 @@
     method public static java.lang.String capabilityToString(int);
     method public static java.lang.String feedbackTypeToString(int);
     method public static java.lang.String flagToString(int);
-    method public static deprecated boolean getCanRetrieveWindowContent(android.accessibilityservice.AccessibilityServiceInfo);
     method public static int getCapabilities(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static deprecated java.lang.String getDescription(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static deprecated java.lang.String getId(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static deprecated android.content.pm.ResolveInfo getResolveInfo(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static deprecated java.lang.String getSettingsActivityName(android.accessibilityservice.AccessibilityServiceInfo);
     method public static java.lang.String loadDescription(android.accessibilityservice.AccessibilityServiceInfo, android.content.pm.PackageManager);
     field public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 8; // 0x8
     field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
     field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
     field public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1; // 0x1
-    field public static final deprecated int DEFAULT = 1; // 0x1
     field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
     field public static final int FEEDBACK_BRAILLE = 32; // 0x20
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
@@ -7067,8 +7218,8 @@
 
 package android.support.v4.content.pm {
 
-  public final class ActivityInfoCompat {
-    field public static final int CONFIG_UI_MODE = 512; // 0x200
+  public final deprecated class ActivityInfoCompat {
+    field public static final deprecated int CONFIG_UI_MODE = 512; // 0x200
   }
 
   public class ShortcutInfoCompat {
@@ -7079,6 +7230,7 @@
     method public android.content.Intent[] getIntents();
     method public java.lang.CharSequence getLongLabel();
     method public java.lang.CharSequence getShortLabel();
+    method public android.content.pm.ShortcutInfo toShortcutInfo();
   }
 
   public static class ShortcutInfoCompat.Builder {
@@ -7086,8 +7238,6 @@
     method public android.support.v4.content.pm.ShortcutInfoCompat build();
     method public android.support.v4.content.pm.ShortcutInfoCompat.Builder setActivity(android.content.ComponentName);
     method public android.support.v4.content.pm.ShortcutInfoCompat.Builder setDisabledMessage(java.lang.CharSequence);
-    method public deprecated android.support.v4.content.pm.ShortcutInfoCompat.Builder setIcon(android.graphics.Bitmap);
-    method public deprecated android.support.v4.content.pm.ShortcutInfoCompat.Builder setIcon(int);
     method public android.support.v4.content.pm.ShortcutInfoCompat.Builder setIcon(android.support.v4.graphics.drawable.IconCompat);
     method public android.support.v4.content.pm.ShortcutInfoCompat.Builder setIntent(android.content.Intent);
     method public android.support.v4.content.pm.ShortcutInfoCompat.Builder setIntents(android.content.Intent[]);
@@ -7121,9 +7271,9 @@
 
 package android.support.v4.database {
 
-  public final class DatabaseUtilsCompat {
-    method public static java.lang.String[] appendSelectionArgs(java.lang.String[], java.lang.String[]);
-    method public static java.lang.String concatenateWhere(java.lang.String, java.lang.String);
+  public final deprecated class DatabaseUtilsCompat {
+    method public static deprecated java.lang.String[] appendSelectionArgs(java.lang.String[], java.lang.String[]);
+    method public static deprecated java.lang.String concatenateWhere(java.lang.String, java.lang.String);
   }
 
 }
@@ -7176,7 +7326,7 @@
     method public static int getLayoutDirection(android.graphics.drawable.Drawable);
     method public static void inflate(android.graphics.drawable.Drawable, android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static boolean isAutoMirrored(android.graphics.drawable.Drawable);
-    method public static void jumpToCurrentState(android.graphics.drawable.Drawable);
+    method public static deprecated void jumpToCurrentState(android.graphics.drawable.Drawable);
     method public static void setAutoMirrored(android.graphics.drawable.Drawable, boolean);
     method public static void setHotspot(android.graphics.drawable.Drawable, float, float);
     method public static void setHotspotBounds(android.graphics.drawable.Drawable, int, int, int, int);
@@ -7195,6 +7345,7 @@
     method public static android.support.v4.graphics.drawable.IconCompat createWithContentUri(android.net.Uri);
     method public static android.support.v4.graphics.drawable.IconCompat createWithData(byte[], int, int);
     method public static android.support.v4.graphics.drawable.IconCompat createWithResource(android.content.Context, int);
+    method public android.graphics.drawable.Icon toIcon();
   }
 
   public abstract class RoundedBitmapDrawable extends android.graphics.drawable.Drawable {
diff --git a/compat/api/27.0.0-SNAPSHOT.txt b/compat/api/27.0.0-SNAPSHOT.txt
index 64c45ff..42888f7 100644
--- a/compat/api/27.0.0-SNAPSHOT.txt
+++ b/compat/api/27.0.0-SNAPSHOT.txt
@@ -4,18 +4,12 @@
     method public static java.lang.String capabilityToString(int);
     method public static java.lang.String feedbackTypeToString(int);
     method public static java.lang.String flagToString(int);
-    method public static deprecated boolean getCanRetrieveWindowContent(android.accessibilityservice.AccessibilityServiceInfo);
     method public static int getCapabilities(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static deprecated java.lang.String getDescription(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static deprecated java.lang.String getId(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static deprecated android.content.pm.ResolveInfo getResolveInfo(android.accessibilityservice.AccessibilityServiceInfo);
-    method public static deprecated java.lang.String getSettingsActivityName(android.accessibilityservice.AccessibilityServiceInfo);
     method public static java.lang.String loadDescription(android.accessibilityservice.AccessibilityServiceInfo, android.content.pm.PackageManager);
     field public static final int CAPABILITY_CAN_FILTER_KEY_EVENTS = 8; // 0x8
     field public static final int CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY = 4; // 0x4
     field public static final int CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION = 2; // 0x2
     field public static final int CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT = 1; // 0x1
-    field public static final deprecated int DEFAULT = 1; // 0x1
     field public static final int FEEDBACK_ALL_MASK = -1; // 0xffffffff
     field public static final int FEEDBACK_BRAILLE = 32; // 0x20
     field public static final int FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 2; // 0x2
@@ -659,8 +653,8 @@
 
 package android.support.v4.content.pm {
 
-  public final class ActivityInfoCompat {
-    field public static final int CONFIG_UI_MODE = 512; // 0x200
+  public final deprecated class ActivityInfoCompat {
+    field public static final deprecated int CONFIG_UI_MODE = 512; // 0x200
   }
 
   public class ShortcutInfoCompat {
@@ -671,6 +665,7 @@
     method public android.content.Intent[] getIntents();
     method public java.lang.CharSequence getLongLabel();
     method public java.lang.CharSequence getShortLabel();
+    method public android.content.pm.ShortcutInfo toShortcutInfo();
   }
 
   public static class ShortcutInfoCompat.Builder {
@@ -678,8 +673,6 @@
     method public android.support.v4.content.pm.ShortcutInfoCompat build();
     method public android.support.v4.content.pm.ShortcutInfoCompat.Builder setActivity(android.content.ComponentName);
     method public android.support.v4.content.pm.ShortcutInfoCompat.Builder setDisabledMessage(java.lang.CharSequence);
-    method public deprecated android.support.v4.content.pm.ShortcutInfoCompat.Builder setIcon(android.graphics.Bitmap);
-    method public deprecated android.support.v4.content.pm.ShortcutInfoCompat.Builder setIcon(int);
     method public android.support.v4.content.pm.ShortcutInfoCompat.Builder setIcon(android.support.v4.graphics.drawable.IconCompat);
     method public android.support.v4.content.pm.ShortcutInfoCompat.Builder setIntent(android.content.Intent);
     method public android.support.v4.content.pm.ShortcutInfoCompat.Builder setIntents(android.content.Intent[]);
@@ -713,9 +706,9 @@
 
 package android.support.v4.database {
 
-  public final class DatabaseUtilsCompat {
-    method public static java.lang.String[] appendSelectionArgs(java.lang.String[], java.lang.String[]);
-    method public static java.lang.String concatenateWhere(java.lang.String, java.lang.String);
+  public final deprecated class DatabaseUtilsCompat {
+    method public static deprecated java.lang.String[] appendSelectionArgs(java.lang.String[], java.lang.String[]);
+    method public static deprecated java.lang.String concatenateWhere(java.lang.String, java.lang.String);
   }
 
 }
@@ -745,7 +738,7 @@
     method public static int getLayoutDirection(android.graphics.drawable.Drawable);
     method public static void inflate(android.graphics.drawable.Drawable, android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public static boolean isAutoMirrored(android.graphics.drawable.Drawable);
-    method public static void jumpToCurrentState(android.graphics.drawable.Drawable);
+    method public static deprecated void jumpToCurrentState(android.graphics.drawable.Drawable);
     method public static void setAutoMirrored(android.graphics.drawable.Drawable, boolean);
     method public static void setHotspot(android.graphics.drawable.Drawable, float, float);
     method public static void setHotspotBounds(android.graphics.drawable.Drawable, int, int, int, int);
@@ -764,6 +757,7 @@
     method public static android.support.v4.graphics.drawable.IconCompat createWithContentUri(android.net.Uri);
     method public static android.support.v4.graphics.drawable.IconCompat createWithData(byte[], int, int);
     method public static android.support.v4.graphics.drawable.IconCompat createWithResource(android.content.Context, int);
+    method public android.graphics.drawable.Icon toIcon();
   }
 
 }
diff --git a/compat/api20/android/support/v4/app/NotificationCompatApi20.java b/compat/api20/android/support/v4/app/NotificationCompatApi20.java
index f646b8f..a395648 100644
--- a/compat/api20/android/support/v4/app/NotificationCompatApi20.java
+++ b/compat/api20/android/support/v4/app/NotificationCompatApi20.java
@@ -29,7 +29,6 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.Bundle;
-import android.os.Parcelable;
 import android.support.annotation.RequiresApi;
 import android.widget.RemoteViews;
 
@@ -37,13 +36,10 @@
 
 @RequiresApi(20)
 class NotificationCompatApi20 {
-    public static class Builder implements NotificationBuilderWithBuilderAccessor,
-            NotificationBuilderWithActions {
-        private Notification.Builder b;
+    public static class Builder extends NotificationCompatKitKat.Builder {
+        protected int mGroupAlertBehavior;
+
         private Bundle mExtras;
-        private RemoteViews mContentView;
-        private RemoteViews mBigContentView;
-        private int mGroupAlertBehavior;
 
         public Builder(Context context, Notification n,
                 CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo,
@@ -53,34 +49,13 @@
                 boolean useChronometer, int priority, CharSequence subText, boolean localOnly,
                 ArrayList<String> people, Bundle extras, String groupKey, boolean groupSummary,
                 String sortKey, RemoteViews contentView, RemoteViews bigContentView,
-                int groupAlertBehavior) {
-            b = new Notification.Builder(context)
-                .setWhen(n.when)
-                .setShowWhen(showWhen)
-                .setSmallIcon(n.icon, n.iconLevel)
-                .setContent(n.contentView)
-                .setTicker(n.tickerText, tickerView)
-                .setSound(n.sound, n.audioStreamType)
-                .setVibrate(n.vibrate)
-                .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS)
-                .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0)
-                .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)
-                .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0)
-                .setDefaults(n.defaults)
-                .setContentTitle(contentTitle)
-                .setContentText(contentText)
-                .setSubText(subText)
-                .setContentInfo(contentInfo)
-                .setContentIntent(contentIntent)
-                .setDeleteIntent(n.deleteIntent)
-                .setFullScreenIntent(fullScreenIntent,
-                        (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0)
-                .setLargeIcon(largeIcon)
-                .setNumber(number)
-                .setUsesChronometer(useChronometer)
-                .setPriority(priority)
-                .setProgress(progressMax, progress, progressIndeterminate)
-                .setLocalOnly(localOnly)
+                int groupAlertBehavior, String channelId) {
+            super(context, n, contentTitle, contentText, contentInfo, tickerView, number,
+                    contentIntent, fullScreenIntent, largeIcon, progressMax, progress,
+                    progressIndeterminate, showWhen, useChronometer, priority, subText, localOnly,
+                    people, extras, groupKey, groupSummary, sortKey, contentView, bigContentView,
+                    channelId);
+            mBuilder.setLocalOnly(localOnly)
                 .setGroup(groupKey)
                 .setGroupSummary(groupSummary)
                 .setSortKey(sortKey);
@@ -92,25 +67,19 @@
                 mExtras.putStringArray(Notification.EXTRA_PEOPLE,
                         people.toArray(new String[people.size()]));
             }
-            mContentView = contentView;
-            mBigContentView = bigContentView;
+
             mGroupAlertBehavior = groupAlertBehavior;
         }
 
         @Override
         public void addAction(NotificationCompatBase.Action action) {
-            NotificationCompatApi20.addAction(b, action);
-        }
-
-        @Override
-        public Notification.Builder getBuilder() {
-            return b;
+            NotificationCompatApi20.addAction(mBuilder, action);
         }
 
         @Override
         public Notification build() {
-            b.setExtras(mExtras);
-            Notification notification = b.build();
+            mBuilder.setExtras(mExtras);
+            Notification notification = mBuilder.build();
             if (mContentView != null) {
                 notification.contentView = mContentView;
             }
@@ -136,7 +105,7 @@
             return notification;
         }
 
-        private void removeSoundAndVibration(Notification notification) {
+        protected void removeSoundAndVibration(Notification notification) {
             notification.sound = null;
             notification.vibrate = null;
             notification.defaults &= ~DEFAULT_SOUND;
@@ -171,7 +140,7 @@
         return getActionCompatFromAction(notif.actions[actionIndex], actionFactory, remoteInputFactory);
     }
 
-    private static NotificationCompatBase.Action getActionCompatFromAction(
+    static NotificationCompatBase.Action getActionCompatFromAction(
             Notification.Action action, NotificationCompatBase.Action.Factory actionFactory,
             RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) {
         RemoteInputCompatBase.RemoteInput[] remoteInputs = RemoteInputCompatApi20.toCompat(
@@ -182,7 +151,7 @@
                 action.getExtras(), remoteInputs, null, allowGeneratedReplies);
     }
 
-    private static Notification.Action getActionFromActionCompat(
+    static Notification.Action getActionFromActionCompat(
             NotificationCompatBase.Action actionCompat) {
         Notification.Action.Builder actionBuilder = new Notification.Action.Builder(
                 actionCompat.getIcon(), actionCompat.getTitle(), actionCompat.getActionIntent());
@@ -204,42 +173,4 @@
         }
         return actionBuilder.build();
     }
-
-    /**
-     * Get a list of notification compat actions by parsing actions stored within a list of
-     * parcelables using the {@link Bundle#getParcelableArrayList} function in the same
-     * manner that framework code would do so. In API20, Using Action parcelable directly
-     * is correct.
-     */
-    public static NotificationCompatBase.Action[] getActionsFromParcelableArrayList(
-            ArrayList<Parcelable> parcelables,
-            NotificationCompatBase.Action.Factory actionFactory,
-            RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) {
-        if (parcelables == null) {
-            return null;
-        }
-        NotificationCompatBase.Action[] actions = actionFactory.newArray(parcelables.size());
-        for (int i = 0; i < actions.length; i++) {
-            Notification.Action action = (Notification.Action) parcelables.get(i);
-            actions[i] = getActionCompatFromAction(action, actionFactory, remoteInputFactory);
-        }
-        return actions;
-    }
-
-    /**
-     * Get an array list of parcelables, suitable for {@link Bundle#putParcelableArrayList},
-     * that matches what framework code would do to store an actions list in this way. In API20,
-     * action parcelables were directly placed as entries in the array list.
-     */
-    public static ArrayList<Parcelable> getParcelableArrayListForActions(
-            NotificationCompatBase.Action[] actions) {
-        if (actions == null) {
-            return null;
-        }
-        ArrayList<Parcelable> parcelables = new ArrayList<Parcelable>(actions.length);
-        for (NotificationCompatBase.Action action : actions) {
-            parcelables.add(getActionFromActionCompat(action));
-        }
-        return parcelables;
-    }
 }
diff --git a/compat/api21/android/support/v4/app/NotificationCompatApi21.java b/compat/api21/android/support/v4/app/NotificationCompatApi21.java
index d56d87e..d7cfdc4 100644
--- a/compat/api21/android/support/v4/app/NotificationCompatApi21.java
+++ b/compat/api21/android/support/v4/app/NotificationCompatApi21.java
@@ -16,8 +16,6 @@
 
 package android.support.v4.app;
 
-import static android.support.v4.app.NotificationCompat.DEFAULT_SOUND;
-import static android.support.v4.app.NotificationCompat.DEFAULT_VIBRATE;
 import static android.support.v4.app.NotificationCompat.FLAG_GROUP_SUMMARY;
 import static android.support.v4.app.NotificationCompat.GROUP_ALERT_ALL;
 import static android.support.v4.app.NotificationCompat.GROUP_ALERT_CHILDREN;
@@ -45,14 +43,9 @@
     private static final String KEY_PARTICIPANTS = "participants";
     private static final String KEY_TIMESTAMP = "timestamp";
 
-    public static class Builder implements NotificationBuilderWithBuilderAccessor,
-            NotificationBuilderWithActions {
-        private Notification.Builder b;
+    public static class Builder extends NotificationCompatApi20.Builder {
         private Bundle mExtras;
-        private RemoteViews mContentView;
-        private RemoteViews mBigContentView;
         private RemoteViews mHeadsUpContentView;
-        private int mGroupAlertBehavior;
 
         public Builder(Context context, Notification n,
                 CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo,
@@ -63,38 +56,13 @@
                 String category, ArrayList<String> people, Bundle extras, int color,
                 int visibility, Notification publicVersion, String groupKey, boolean groupSummary,
                 String sortKey, RemoteViews contentView, RemoteViews bigContentView,
-                RemoteViews headsUpContentView, int groupAlertBehavior) {
-            b = new Notification.Builder(context)
-                    .setWhen(n.when)
-                    .setShowWhen(showWhen)
-                    .setSmallIcon(n.icon, n.iconLevel)
-                    .setContent(n.contentView)
-                    .setTicker(n.tickerText, tickerView)
-                    .setSound(n.sound, n.audioStreamType)
-                    .setVibrate(n.vibrate)
-                    .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS)
-                    .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0)
-                    .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)
-                    .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0)
-                    .setDefaults(n.defaults)
-                    .setContentTitle(contentTitle)
-                    .setContentText(contentText)
-                    .setSubText(subText)
-                    .setContentInfo(contentInfo)
-                    .setContentIntent(contentIntent)
-                    .setDeleteIntent(n.deleteIntent)
-                    .setFullScreenIntent(fullScreenIntent,
-                            (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0)
-                    .setLargeIcon(largeIcon)
-                    .setNumber(number)
-                    .setUsesChronometer(useChronometer)
-                    .setPriority(priority)
-                    .setProgress(progressMax, progress, progressIndeterminate)
-                    .setLocalOnly(localOnly)
-                    .setGroup(groupKey)
-                    .setGroupSummary(groupSummary)
-                    .setSortKey(sortKey)
-                    .setCategory(category)
+                RemoteViews headsUpContentView, int groupAlertBehavior, String channelId) {
+            super(context, n, contentTitle, contentText, contentInfo, tickerView, number,
+                    contentIntent, fullScreenIntent, largeIcon, progressMax, progress,
+                    progressIndeterminate, showWhen, useChronometer, priority, subText, localOnly,
+                    people, extras, groupKey, groupSummary, sortKey, contentView, bigContentView,
+                    groupAlertBehavior, channelId);
+            mBuilder.setCategory(category)
                     .setColor(color)
                     .setVisibility(visibility)
                     .setPublicVersion(publicVersion);
@@ -103,28 +71,15 @@
                 mExtras.putAll(extras);
             }
             for (String person: people) {
-                b.addPerson(person);
+                mBuilder.addPerson(person);
             }
-            mContentView = contentView;
-            mBigContentView = bigContentView;
             mHeadsUpContentView = headsUpContentView;
-            mGroupAlertBehavior = groupAlertBehavior;
-        }
-
-        @Override
-        public void addAction(NotificationCompatBase.Action action) {
-            NotificationCompatApi20.addAction(b, action);
-        }
-
-        @Override
-        public Notification.Builder getBuilder() {
-            return b;
         }
 
         @Override
         public Notification build() {
-            b.setExtras(mExtras);
-            Notification notification = b.build();
+            mBuilder.setExtras(mExtras);
+            Notification notification = mBuilder.build();
             if (mContentView != null) {
                 notification.contentView = mContentView;
             }
@@ -151,13 +106,6 @@
             }
             return notification;
         }
-
-        private void removeSoundAndVibration(Notification notification) {
-            notification.sound = null;
-            notification.vibrate = null;
-            notification.defaults &= ~DEFAULT_SOUND;
-            notification.defaults &= ~DEFAULT_VIBRATE;
-        }
     }
 
     static Bundle getBundleForUnreadConversation(NotificationCompatBase.UnreadConversation uc) {
diff --git a/compat/api24/android/support/v4/app/NotificationCompatApi24.java b/compat/api24/android/support/v4/app/NotificationCompatApi24.java
index 67ea5dc..c623036 100644
--- a/compat/api24/android/support/v4/app/NotificationCompatApi24.java
+++ b/compat/api24/android/support/v4/app/NotificationCompatApi24.java
@@ -16,8 +16,6 @@
 
 package android.support.v4.app;
 
-import static android.support.v4.app.NotificationCompat.DEFAULT_SOUND;
-import static android.support.v4.app.NotificationCompat.DEFAULT_VIBRATE;
 import static android.support.v4.app.NotificationCompat.FLAG_GROUP_SUMMARY;
 import static android.support.v4.app.NotificationCompat.GROUP_ALERT_ALL;
 import static android.support.v4.app.NotificationCompat.GROUP_ALERT_CHILDREN;
@@ -28,23 +26,16 @@
 import android.app.RemoteInput;
 import android.content.Context;
 import android.graphics.Bitmap;
-import android.net.Uri;
 import android.os.Bundle;
-import android.os.Parcelable;
 import android.support.annotation.RequiresApi;
 import android.widget.RemoteViews;
 
 import java.util.ArrayList;
-import java.util.List;
 
 @RequiresApi(24)
 class NotificationCompatApi24 {
 
-    public static class Builder implements NotificationBuilderWithBuilderAccessor,
-            NotificationBuilderWithActions {
-        private Notification.Builder b;
-        private int mGroupAlertBehavior;
-
+    public static class Builder extends NotificationCompatApi21.Builder {
         public Builder(Context context, Notification n,
                 CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo,
                 RemoteViews tickerView, int number,
@@ -55,72 +46,34 @@
                 int visibility, Notification publicVersion, String groupKey, boolean groupSummary,
                 String sortKey, CharSequence[] remoteInputHistory, RemoteViews contentView,
                 RemoteViews bigContentView, RemoteViews headsUpContentView,
-                int groupAlertBehavior) {
-            b = new Notification.Builder(context)
-                    .setWhen(n.when)
-                    .setShowWhen(showWhen)
-                    .setSmallIcon(n.icon, n.iconLevel)
-                    .setContent(n.contentView)
-                    .setTicker(n.tickerText, tickerView)
-                    .setSound(n.sound, n.audioStreamType)
-                    .setVibrate(n.vibrate)
-                    .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS)
-                    .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0)
-                    .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)
-                    .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0)
-                    .setDefaults(n.defaults)
-                    .setContentTitle(contentTitle)
-                    .setContentText(contentText)
-                    .setSubText(subText)
-                    .setContentInfo(contentInfo)
-                    .setContentIntent(contentIntent)
-                    .setDeleteIntent(n.deleteIntent)
-                    .setFullScreenIntent(fullScreenIntent,
-                            (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0)
-                    .setLargeIcon(largeIcon)
-                    .setNumber(number)
-                    .setUsesChronometer(useChronometer)
-                    .setPriority(priority)
-                    .setProgress(progressMax, progress, progressIndeterminate)
-                    .setLocalOnly(localOnly)
-                    .setExtras(extras)
-                    .setGroup(groupKey)
-                    .setGroupSummary(groupSummary)
-                    .setSortKey(sortKey)
-                    .setCategory(category)
-                    .setColor(color)
-                    .setVisibility(visibility)
-                    .setPublicVersion(publicVersion)
+                int groupAlertBehavior, String channelId) {
+            super(context, n, contentTitle, contentText, contentInfo, tickerView, number,
+                    contentIntent, fullScreenIntent, largeIcon, progressMax, progress,
+                    progressIndeterminate, showWhen, useChronometer, priority, subText, localOnly,
+                    category, people, extras, color, visibility, publicVersion, groupKey,
+                    groupSummary, sortKey, contentView, bigContentView,
+                    headsUpContentView, groupAlertBehavior, channelId);
+            mBuilder.setExtras(extras)
                     .setRemoteInputHistory(remoteInputHistory);
             if (contentView != null) {
-                b.setCustomContentView(contentView);
+                mBuilder.setCustomContentView(contentView);
             }
             if (bigContentView != null) {
-                b.setCustomBigContentView(bigContentView);
+                mBuilder.setCustomBigContentView(bigContentView);
             }
             if (headsUpContentView != null) {
-                b.setCustomHeadsUpContentView(headsUpContentView);
+                mBuilder.setCustomHeadsUpContentView(headsUpContentView);
             }
-            for (String person: people) {
-                b.addPerson(person);
-            }
-
-            mGroupAlertBehavior = groupAlertBehavior;
         }
 
         @Override
         public void addAction(NotificationCompatBase.Action action) {
-            NotificationCompatApi24.addAction(b, action);
-        }
-
-        @Override
-        public Notification.Builder getBuilder() {
-            return b;
+            NotificationCompatApi24.addAction(mBuilder, action);
         }
 
         @Override
         public Notification build() {
-            Notification notification =  b.build();
+            Notification notification =  mBuilder.build();
 
             if (mGroupAlertBehavior != GROUP_ALERT_ALL) {
                 // if is summary and only children should alert
@@ -139,30 +92,6 @@
 
             return notification;
         }
-
-        private void removeSoundAndVibration(Notification notification) {
-            notification.sound = null;
-            notification.vibrate = null;
-            notification.defaults &= ~DEFAULT_SOUND;
-            notification.defaults &= ~DEFAULT_VIBRATE;
-        }
-    }
-
-    public static void addMessagingStyle(NotificationBuilderWithBuilderAccessor b,
-            CharSequence userDisplayName, CharSequence conversationTitle, List<CharSequence> texts,
-            List<Long> timestamps, List<CharSequence> senders, List<String> dataMimeTypes,
-            List<Uri> dataUris) {
-        Notification.MessagingStyle style = new Notification.MessagingStyle(userDisplayName)
-                .setConversationTitle(conversationTitle);
-        for (int i = 0; i < texts.size(); i++) {
-            Notification.MessagingStyle.Message message = new Notification.MessagingStyle.Message(
-                    texts.get(i), timestamps.get(i), senders.get(i));
-            if (dataMimeTypes.get(i) != null) {
-                message.setData(dataMimeTypes.get(i), dataUris.get(i));
-            }
-            style.addMessage(message);
-        }
-        style.setBuilder(b.getBuilder());
     }
 
     public static void addAction(Notification.Builder b, NotificationCompatBase.Action action) {
@@ -194,7 +123,7 @@
                 remoteInputFactory);
     }
 
-    private static NotificationCompatBase.Action getActionCompatFromAction(
+    static NotificationCompatBase.Action getActionCompatFromAction(
             Notification.Action action, NotificationCompatBase.Action.Factory actionFactory,
             RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) {
         RemoteInputCompatBase.RemoteInput[] remoteInputs = RemoteInputCompatApi20.toCompat(
@@ -206,7 +135,7 @@
                 action.getExtras(), remoteInputs, null, allowGeneratedReplies);
     }
 
-    private static Notification.Action getActionFromActionCompat(
+    static Notification.Action getActionFromActionCompat(
             NotificationCompatBase.Action actionCompat) {
         Notification.Action.Builder actionBuilder = new Notification.Action.Builder(
                 actionCompat.getIcon(), actionCompat.getTitle(), actionCompat.getActionIntent());
@@ -229,42 +158,4 @@
         }
         return actionBuilder.build();
     }
-
-    /**
-     * Get a list of notification compat actions by parsing actions stored within a list of
-     * parcelables using the {@link Bundle#getParcelableArrayList} function in the same
-     * manner that framework code would do so. In API20, Using Action parcelable directly
-     * is correct.
-     */
-    public static NotificationCompatBase.Action[] getActionsFromParcelableArrayList(
-            ArrayList<Parcelable> parcelables,
-            NotificationCompatBase.Action.Factory actionFactory,
-            RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) {
-        if (parcelables == null) {
-            return null;
-        }
-        NotificationCompatBase.Action[] actions = actionFactory.newArray(parcelables.size());
-        for (int i = 0; i < actions.length; i++) {
-            Notification.Action action = (Notification.Action) parcelables.get(i);
-            actions[i] = getActionCompatFromAction(action, actionFactory, remoteInputFactory);
-        }
-        return actions;
-    }
-
-    /**
-     * Get an array list of parcelables, suitable for {@link Bundle#putParcelableArrayList},
-     * that matches what framework code would do to store an actions list in this way. In API20,
-     * action parcelables were directly placed as entries in the array list.
-     */
-    public static ArrayList<Parcelable> getParcelableArrayListForActions(
-            NotificationCompatBase.Action[] actions) {
-        if (actions == null) {
-            return null;
-        }
-        ArrayList<Parcelable> parcelables = new ArrayList<Parcelable>(actions.length);
-        for (NotificationCompatBase.Action action : actions) {
-            parcelables.add(getActionFromActionCompat(action));
-        }
-        return parcelables;
-    }
 }
diff --git a/compat/api26/android/support/v4/app/NotificationCompatApi26.java b/compat/api26/android/support/v4/app/NotificationCompatApi26.java
index ad696a8..802402d 100644
--- a/compat/api26/android/support/v4/app/NotificationCompatApi26.java
+++ b/compat/api26/android/support/v4/app/NotificationCompatApi26.java
@@ -28,11 +28,7 @@
 
 @RequiresApi(26)
 class NotificationCompatApi26 {
-    public static class Builder implements NotificationBuilderWithBuilderAccessor,
-            NotificationBuilderWithActions {
-
-        private Notification.Builder mB;
-
+    public static class Builder extends NotificationCompatApi24.Builder {
         Builder(Context context, Notification n,
                 CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo,
                 RemoteViews tickerView, int number,
@@ -45,77 +41,30 @@
                 RemoteViews bigContentView, RemoteViews headsUpContentView,
                 String channelId, int badgeIcon, String shortcutId, long timeoutMs,
                 boolean colorized, boolean colorizedSet, int groupAlertBehavior) {
-            mB = new Notification.Builder(context, channelId)
-                    .setWhen(n.when)
-                    .setShowWhen(showWhen)
-                    .setSmallIcon(n.icon, n.iconLevel)
-                    .setContent(n.contentView)
-                    .setTicker(n.tickerText, tickerView)
-                    .setSound(n.sound, n.audioStreamType)
-                    .setVibrate(n.vibrate)
-                    .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS)
-                    .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0)
-                    .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)
-                    .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0)
-                    .setDefaults(n.defaults)
-                    .setContentTitle(contentTitle)
-                    .setContentText(contentText)
-                    .setSubText(subText)
-                    .setContentInfo(contentInfo)
-                    .setContentIntent(contentIntent)
-                    .setDeleteIntent(n.deleteIntent)
-                    .setFullScreenIntent(fullScreenIntent,
-                            (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0)
-                    .setLargeIcon(largeIcon)
-                    .setNumber(number)
-                    .setUsesChronometer(useChronometer)
-                    .setPriority(priority)
-                    .setProgress(progressMax, progress, progressIndeterminate)
-                    .setLocalOnly(localOnly)
-                    .setExtras(extras)
-                    .setGroup(groupKey)
-                    .setGroupSummary(groupSummary)
-                    .setSortKey(sortKey)
-                    .setCategory(category)
-                    .setColor(color)
-                    .setVisibility(visibility)
-                    .setPublicVersion(publicVersion)
-                    .setRemoteInputHistory(remoteInputHistory)
-                    .setChannelId(channelId)
+            super(context, n, contentTitle, contentText, contentInfo, tickerView, number,
+                    contentIntent, fullScreenIntent, largeIcon, progressMax, progress,
+                    progressIndeterminate, showWhen, useChronometer, priority, subText, localOnly,
+                    category, people, extras, color, visibility, publicVersion, groupKey,
+                    groupSummary, sortKey, remoteInputHistory, contentView, bigContentView,
+                    headsUpContentView, groupAlertBehavior, channelId);
+            mBuilder.setChannelId(channelId)
                     .setBadgeIconType(badgeIcon)
                     .setShortcutId(shortcutId)
                     .setTimeoutAfter(timeoutMs)
                     .setGroupAlertBehavior(groupAlertBehavior);
             if (colorizedSet) {
-                mB.setColorized(colorized);
+                mBuilder.setColorized(colorized);
             }
-            if (contentView != null) {
-                mB.setCustomContentView(contentView);
-            }
-            if (bigContentView != null) {
-                mB.setCustomBigContentView(bigContentView);
-            }
-            if (headsUpContentView != null) {
-                mB.setCustomHeadsUpContentView(headsUpContentView);
-            }
-            for (String person : people) {
-                mB.addPerson(person);
-            }
-        }
-
-        @Override
-        public void addAction(NotificationCompatBase.Action action) {
-            NotificationCompatApi24.addAction(mB, action);
-        }
-
-        @Override
-        public Notification.Builder getBuilder() {
-            return mB;
         }
 
         @Override
         public Notification build() {
-            return mB.build();
+            return mBuilder.build();
+        }
+
+        @Override
+        protected Notification.Builder newBuilder(Context context, String channelId) {
+            return new Notification.Builder(context, channelId);
         }
     }
 }
diff --git a/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java b/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
index f810253..3905ca5 100644
--- a/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
+++ b/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
@@ -19,12 +19,11 @@
 import android.accessibilityservice.AccessibilityService;
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.os.Build;
 import android.view.View;
 
 /**
- * Helper for accessing features in {@link android.accessibilityservice.AccessibilityService}.
+ * Helper for accessing features in {@link AccessibilityServiceInfo}.
  */
 public final class AccessibilityServiceInfoCompat {
     /**
@@ -71,16 +70,6 @@
     // Flags
 
     /**
-     * If an {@link AccessibilityService} is the default for a given type.
-     * Default service is invoked only if no package specific one exists. In case of
-     * more than one package specific service only the earlier registered is notified.
-     *
-     * @deprecated Use {@link AccessibilityServiceInfo#DEFAULT} directly.
-     */
-    @Deprecated
-    public static final int DEFAULT = AccessibilityServiceInfo.DEFAULT;
-
-    /**
      * If this flag is set the system will regard views that are not important
      * for accessibility in addition to the ones that are important for accessibility.
      * That is, views that are marked as not important for accessibility via
@@ -189,89 +178,6 @@
     private AccessibilityServiceInfoCompat() {}
 
     /**
-     * The accessibility service id.
-     * <p>
-     * <strong>Generated by the system.</strong>
-     * </p>
-     *
-     * @param info The service info of interest
-     * @return The id.
-     *
-     * @deprecated Use {@link AccessibilityServiceInfo#getId()} directly.
-     */
-    @Deprecated
-    public static String getId(AccessibilityServiceInfo info) {
-        return info.getId();
-    }
-
-    /**
-     * The service {@link ResolveInfo}.
-     * <p>
-     * <strong>Generated by the system.</strong>
-     * </p>
-     *
-     * @param info The service info of interest
-     * @return The info.
-     *
-     * @deprecated Use {@link AccessibilityServiceInfo#getResolveInfo()} directly.
-     */
-    @Deprecated
-    public static ResolveInfo getResolveInfo(AccessibilityServiceInfo info) {
-        return info.getResolveInfo();
-    }
-
-    /**
-     * The settings activity name.
-     * <p>
-     * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA
-     * meta-data}.</strong>
-     * </p>
-     *
-     * @param info The service info of interest
-     * @return The settings activity name.
-     *
-     * @deprecated Use {@link AccessibilityServiceInfo#getSettingsActivityName()} directly.
-     */
-    @Deprecated
-    public static String getSettingsActivityName(AccessibilityServiceInfo info) {
-        return info.getSettingsActivityName();
-    }
-
-    /**
-     * Whether this service can retrieve the current window's content.
-     * <p>
-     * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA
-     * meta-data}.</strong>
-     * </p>
-     *
-     * @param info The service info of interest
-     * @return True window content can be retrieved.
-     *
-     * @deprecated Use {@link AccessibilityServiceInfo#getCanRetrieveWindowContent()} directly.
-     */
-    @Deprecated
-    public static boolean getCanRetrieveWindowContent(AccessibilityServiceInfo info) {
-        return info.getCanRetrieveWindowContent();
-    }
-
-    /**
-     * Non-localized description of the accessibility service.
-     * <p>
-     * <strong>Statically set from {@link AccessibilityService#SERVICE_META_DATA
-     * meta-data}.</strong>
-     * </p>
-     *
-     * @param info The service info of interest
-     * @return The description.
-     *
-     * @deprecated Use {@link #loadDescription(AccessibilityServiceInfo, PackageManager)}.
-     */
-    @Deprecated
-    public static String getDescription(AccessibilityServiceInfo info) {
-        return info.getDescription();
-    }
-
-    /**
      * The localized description of the accessibility service.
      * <p>
      *    <strong>Statically set from
diff --git a/compat/java/android/support/v4/app/NotificationCompat.java b/compat/java/android/support/v4/app/NotificationCompat.java
index 8d370ab..d7836b0 100644
--- a/compat/java/android/support/v4/app/NotificationCompat.java
+++ b/compat/java/android/support/v4/app/NotificationCompat.java
@@ -598,8 +598,6 @@
     interface NotificationCompatImpl {
         Notification build(Builder b, BuilderExtender extender);
         Action getAction(Notification n, int actionIndex);
-        Action[] getActionsFromParcelableArrayList(ArrayList<Parcelable> parcelables);
-        ArrayList<Parcelable> getParcelableArrayListForActions(Action[] actions);
         Bundle getBundleForUnreadConversation(NotificationCompatBase.UnreadConversation uc);
         NotificationCompatBase.UnreadConversation getUnreadConversationFromBundle(
                 Bundle b, NotificationCompatBase.UnreadConversation.Factory factory,
@@ -642,15 +640,14 @@
     static class NotificationCompatBaseImpl implements NotificationCompatImpl {
 
         public static class BuilderBase implements NotificationBuilderWithBuilderAccessor {
-
-            private Notification.Builder mBuilder;
+            protected Notification.Builder mBuilder;
 
             BuilderBase(Context context, Notification n, CharSequence contentTitle,
                     CharSequence contentText, CharSequence contentInfo, RemoteViews tickerView,
                     int number, PendingIntent contentIntent, PendingIntent fullScreenIntent,
                     Bitmap largeIcon, int progressMax, int progress,
-                    boolean progressIndeterminate) {
-                mBuilder = new Notification.Builder(context)
+                    boolean progressIndeterminate, String channelId) {
+                mBuilder = newBuilder(context, channelId)
                         .setWhen(n.when)
                         .setSmallIcon(n.icon, n.iconLevel)
                         .setContent(n.contentView)
@@ -683,6 +680,10 @@
             public Notification build() {
                 return mBuilder.getNotification();
             }
+
+            protected Notification.Builder newBuilder(Context context, String channelId) {
+                return new Notification.Builder(context);
+            }
         }
 
         @Override
@@ -691,7 +692,7 @@
                     new BuilderBase(b.mContext, b.mNotification,
                             b.mContentTitle, b.mContentText, b.mContentInfo, b.mTickerView,
                             b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
-                            b.mProgressMax, b.mProgress, b.mProgressIndeterminate);
+                            b.mProgressMax, b.mProgress, b.mProgressIndeterminate, null);
             return extender.build(b, builder);
         }
 
@@ -701,16 +702,6 @@
         }
 
         @Override
-        public Action[] getActionsFromParcelableArrayList(ArrayList<Parcelable> parcelables) {
-            return null;
-        }
-
-        @Override
-        public ArrayList<Parcelable> getParcelableArrayListForActions(Action[] actions) {
-            return null;
-        }
-
-        @Override
         public Bundle getBundleForUnreadConversation(NotificationCompatBase.UnreadConversation uc) {
             return null;
         }
@@ -732,7 +723,8 @@
                     b.mTickerView, b.mNumber, b.mContentIntent, b.mFullScreenIntent, b.mLargeIcon,
                     b.mProgressMax, b.mProgress, b.mProgressIndeterminate,
                     b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mExtras,
-                    b.mGroupKey, b.mGroupSummary, b.mSortKey, b.mContentView, b.mBigContentView);
+                    b.mGroupKey, b.mGroupSummary, b.mSortKey, b.mContentView, b.mBigContentView,
+                    null);
             addActionsToBuilder(builder, b.mActions);
             if (b.mStyle != null) {
                 b.mStyle.apply(builder);
@@ -752,19 +744,6 @@
             return (Action) NotificationCompatJellybean.getAction(n, actionIndex, Action.FACTORY,
                     RemoteInput.FACTORY);
         }
-
-        @Override
-        public Action[] getActionsFromParcelableArrayList(
-                ArrayList<Parcelable> parcelables) {
-            return (Action[]) NotificationCompatJellybean.getActionsFromParcelableArrayList(
-                    parcelables, Action.FACTORY, RemoteInput.FACTORY);
-        }
-
-        @Override
-        public ArrayList<Parcelable> getParcelableArrayListForActions(
-                Action[] actions) {
-            return NotificationCompatJellybean.getParcelableArrayListForActions(actions);
-        }
     }
 
     @RequiresApi(19)
@@ -777,7 +756,7 @@
                     b.mProgressMax, b.mProgress, b.mProgressIndeterminate, b.mShowWhen,
                     b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly,
                     b.mPeople, b.mExtras, b.mGroupKey, b.mGroupSummary, b.mSortKey,
-                    b.mContentView, b.mBigContentView);
+                    b.mContentView, b.mBigContentView, null);
             addActionsToBuilder(builder, b.mActions);
             if (b.mStyle != null) {
                 b.mStyle.apply(builder);
@@ -802,7 +781,7 @@
                     b.mProgressMax, b.mProgress, b.mProgressIndeterminate, b.mShowWhen,
                     b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mPeople, b.mExtras,
                     b.mGroupKey, b.mGroupSummary, b.mSortKey, b.mContentView, b.mBigContentView,
-                    b.mGroupAlertBehavior);
+                    b.mGroupAlertBehavior, null);
             addActionsToBuilder(builder, b.mActions);
             if (b.mStyle != null) {
                 b.mStyle.apply(builder);
@@ -819,19 +798,6 @@
             return (Action) NotificationCompatApi20.getAction(n, actionIndex, Action.FACTORY,
                     RemoteInput.FACTORY);
         }
-
-        @Override
-        public Action[] getActionsFromParcelableArrayList(
-                ArrayList<Parcelable> parcelables) {
-            return (Action[]) NotificationCompatApi20.getActionsFromParcelableArrayList(
-                    parcelables, Action.FACTORY, RemoteInput.FACTORY);
-        }
-
-        @Override
-        public ArrayList<Parcelable> getParcelableArrayListForActions(
-                Action[] actions) {
-            return NotificationCompatApi20.getParcelableArrayListForActions(actions);
-        }
     }
 
     @RequiresApi(21)
@@ -845,7 +811,7 @@
                     b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mCategory,
                     b.mPeople, b.mExtras, b.mColor, b.mVisibility, b.mPublicVersion,
                     b.mGroupKey, b.mGroupSummary, b.mSortKey, b.mContentView, b.mBigContentView,
-                    b.mHeadsUpContentView, b.mGroupAlertBehavior);
+                    b.mHeadsUpContentView, b.mGroupAlertBehavior, null);
             addActionsToBuilder(builder, b.mActions);
             if (b.mStyle != null) {
                 b.mStyle.apply(builder);
@@ -883,7 +849,7 @@
                     b.mUseChronometer, b.mPriority, b.mSubText, b.mLocalOnly, b.mCategory,
                     b.mPeople, b.mExtras, b.mColor, b.mVisibility, b.mPublicVersion,
                     b.mGroupKey, b.mGroupSummary, b.mSortKey, b.mRemoteInputHistory, b.mContentView,
-                    b.mBigContentView, b.mHeadsUpContentView, b.mGroupAlertBehavior);
+                    b.mBigContentView, b.mHeadsUpContentView, b.mGroupAlertBehavior, null);
             addActionsToBuilder(builder, b.mActions);
             if (b.mStyle != null) {
                 b.mStyle.apply(builder);
@@ -900,19 +866,6 @@
             return (Action) NotificationCompatApi24.getAction(n, actionIndex, Action.FACTORY,
                     RemoteInput.FACTORY);
         }
-
-        @Override
-        public Action[] getActionsFromParcelableArrayList(
-                ArrayList<Parcelable> parcelables) {
-            return (Action[]) NotificationCompatApi24.getActionsFromParcelableArrayList(
-                    parcelables, Action.FACTORY, RemoteInput.FACTORY);
-        }
-
-        @Override
-        public ArrayList<Parcelable> getParcelableArrayListForActions(
-                Action[] actions) {
-            return NotificationCompatApi24.getParcelableArrayListForActions(actions);
-        }
     }
 
     @RequiresApi(26)
@@ -2558,22 +2511,21 @@
         @Override
         public void apply(NotificationBuilderWithBuilderAccessor builder) {
             if (Build.VERSION.SDK_INT >= 24) {
-                List<CharSequence> texts = new ArrayList<>();
-                List<Long> timestamps = new ArrayList<>();
-                List<CharSequence> senders = new ArrayList<>();
-                List<String> dataMimeTypes = new ArrayList<>();
-                List<Uri> dataUris = new ArrayList<>();
-
+                Notification.MessagingStyle style =
+                        new Notification.MessagingStyle(mUserDisplayName)
+                                .setConversationTitle(mConversationTitle);
                 for (MessagingStyle.Message message : mMessages) {
-                    texts.add(message.getText());
-                    timestamps.add(message.getTimestamp());
-                    senders.add(message.getSender());
-                    dataMimeTypes.add(message.getDataMimeType());
-                    dataUris.add(message.getDataUri());
+                    Notification.MessagingStyle.Message frameworkMessage =
+                            new Notification.MessagingStyle.Message(
+                                    message.getText(),
+                                    message.getTimestamp(),
+                                    message.getSender());
+                    if (message.getDataMimeType() != null) {
+                        frameworkMessage.setData(message.getDataMimeType(), message.getDataUri());
+                    }
+                    style.addMessage(frameworkMessage);
                 }
-                NotificationCompatApi24.addMessagingStyle(builder, mUserDisplayName,
-                        mConversationTitle, texts, timestamps, senders,
-                        dataMimeTypes, dataUris);
+                style.setBuilder(builder.getBuilder());
             } else {
                 MessagingStyle.Message latestIncomingMessage = findLatestIncomingMessage();
                 // Set the title
@@ -3795,10 +3747,30 @@
             Bundle wearableBundle = extras != null ? extras.getBundle(EXTRA_WEARABLE_EXTENSIONS)
                     : null;
             if (wearableBundle != null) {
-                Action[] actions = IMPL.getActionsFromParcelableArrayList(
-                        wearableBundle.getParcelableArrayList(KEY_ACTIONS));
-                if (actions != null) {
-                    Collections.addAll(mActions, actions);
+                final ArrayList<Parcelable> parcelables =
+                        wearableBundle.getParcelableArrayList(KEY_ACTIONS);
+                if (Build.VERSION.SDK_INT >= 16 && parcelables != null) {
+                    NotificationCompatBase.Action[] actions =
+                            Action.FACTORY.newArray(parcelables.size());
+                    for (int i = 0; i < actions.length; i++) {
+                        if (Build.VERSION.SDK_INT >= 24) {
+                            actions[i] = NotificationCompatApi24.getActionCompatFromAction(
+                                    (Notification.Action) parcelables.get(i),
+                                    Action.FACTORY,
+                                    RemoteInput.FACTORY);
+                        } else if (Build.VERSION.SDK_INT >= 20) {
+                            actions[i] = NotificationCompatApi20.getActionCompatFromAction(
+                                    (Notification.Action) parcelables.get(i),
+                                    Action.FACTORY,
+                                    RemoteInput.FACTORY);
+                        } else if (Build.VERSION.SDK_INT >= 16) {
+                            actions[i] = NotificationCompatJellybean.getActionFromBundle(
+                                    (Bundle) parcelables.get(i),
+                                    Action.FACTORY,
+                                    RemoteInput.FACTORY);
+                        }
+                    }
+                    Collections.addAll(mActions, (Action[]) actions);
                 }
 
                 mFlags = wearableBundle.getInt(KEY_FLAGS, DEFAULT_FLAGS);
@@ -3836,9 +3808,23 @@
             Bundle wearableBundle = new Bundle();
 
             if (!mActions.isEmpty()) {
-                wearableBundle.putParcelableArrayList(KEY_ACTIONS,
-                        IMPL.getParcelableArrayListForActions(mActions.toArray(
-                                new Action[mActions.size()])));
+                if (Build.VERSION.SDK_INT >= 16) {
+                    ArrayList<Parcelable> parcelables = new ArrayList<>(mActions.size());
+                    for (NotificationCompatBase.Action action : mActions) {
+                        if (Build.VERSION.SDK_INT >= 24) {
+                            parcelables.add(
+                                    NotificationCompatApi24.getActionFromActionCompat(action));
+                        } else if (Build.VERSION.SDK_INT >= 20) {
+                            parcelables.add(
+                                    NotificationCompatApi20.getActionFromActionCompat(action));
+                        } else if (Build.VERSION.SDK_INT >= 16) {
+                            parcelables.add(NotificationCompatJellybean.getBundleForAction(action));
+                        }
+                    }
+                    wearableBundle.putParcelableArrayList(KEY_ACTIONS, parcelables);
+                } else {
+                    wearableBundle.putParcelableArrayList(KEY_ACTIONS, null);
+                }
             }
             if (mFlags != DEFAULT_FLAGS) {
                 wearableBundle.putInt(KEY_FLAGS, mFlags);
diff --git a/compat/java/android/support/v4/content/pm/ActivityInfoCompat.java b/compat/java/android/support/v4/content/pm/ActivityInfoCompat.java
index 61bed07..eb40a5e 100644
--- a/compat/java/android/support/v4/content/pm/ActivityInfoCompat.java
+++ b/compat/java/android/support/v4/content/pm/ActivityInfoCompat.java
@@ -18,7 +18,10 @@
 
 /**
  * Helper for accessing features in {@link android.content.pm.ActivityInfo}.
+ *
+ * @deprecated Use {@link android.content.pm.ActivityInfo} directly.
  */
+@Deprecated
 public final class ActivityInfoCompat {
 
     private ActivityInfoCompat() {
@@ -29,6 +32,9 @@
      * Bit in ActivityInfo#configChanges that indicates that the
      * activity can itself handle the ui mode. Set from the
      * {@link android.R.attr#configChanges} attribute.
+     *
+     * @deprecated Use {@link android.content.pm.ActivityInfo#CONFIG_UI_MODE} directly.
      */
+    @Deprecated
     public static final int CONFIG_UI_MODE = 0x0200;
 }
diff --git a/compat/java/android/support/v4/content/pm/ShortcutInfoCompat.java b/compat/java/android/support/v4/content/pm/ShortcutInfoCompat.java
index eb892c6..3ae7470 100644
--- a/compat/java/android/support/v4/content/pm/ShortcutInfoCompat.java
+++ b/compat/java/android/support/v4/content/pm/ShortcutInfoCompat.java
@@ -19,8 +19,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ShortcutInfo;
-import android.graphics.Bitmap;
-import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.RequiresApi;
@@ -48,8 +46,11 @@
 
     private ShortcutInfoCompat() { }
 
-    @RequiresApi(26)
-    ShortcutInfo toShortcutInfo() {
+    /**
+     * @return {@link ShortcutInfo} object from this compat object.
+     */
+    @RequiresApi(25)
+    public ShortcutInfo toShortcutInfo() {
         ShortcutInfo.Builder builder = new ShortcutInfo.Builder(mContext, mId)
                 .setShortLabel(mLabel)
                 .setIntents(mIntents);
@@ -237,24 +238,6 @@
 
         /**
          * Sets an icon of a shortcut.
-         * @deprecated use {@link #setIcon(IconCompat)} instead
-         */
-        @NonNull
-        public Builder setIcon(@NonNull Bitmap icon) {
-            return setIcon(IconCompat.createWithBitmap(icon));
-        }
-
-        /**
-         * Sets an icon of a shortcut.
-         * @deprecated use {@link #setIcon(IconCompat)} instead
-         */
-        @NonNull
-        public Builder setIcon(@DrawableRes int icon) {
-            return setIcon(IconCompat.createWithResource(mInfo.mContext, icon));
-        }
-
-        /**
-         * Sets an icon of a shortcut.
          */
         @NonNull
         public Builder setIcon(IconCompat icon) {
diff --git a/compat/java/android/support/v4/database/DatabaseUtilsCompat.java b/compat/java/android/support/v4/database/DatabaseUtilsCompat.java
index f3d3077..419ae09 100644
--- a/compat/java/android/support/v4/database/DatabaseUtilsCompat.java
+++ b/compat/java/android/support/v4/database/DatabaseUtilsCompat.java
@@ -20,7 +20,10 @@
 
 /**
  * Helper for accessing features in {@link android.database.DatabaseUtils}.
+ *
+ * @deprecated Use {@link android.database.DatabaseUtils} directly.
  */
+@Deprecated
 public final class DatabaseUtilsCompat {
 
     private DatabaseUtilsCompat() {
@@ -29,7 +32,11 @@
 
     /**
      * Concatenates two SQL WHERE clauses, handling empty or null values.
+     *
+     * @deprecated Use {@link android.database.DatabaseUtils#concatenateWhere(String, String)}
+     * directly.
      */
+    @Deprecated
     public static String concatenateWhere(String a, String b) {
         if (TextUtils.isEmpty(a)) {
             return b;
@@ -44,7 +51,11 @@
     /**
      * Appends one set of selection args to another. This is useful when adding a selection
      * argument to a user provided set.
+     *
+     * @deprecated Use
+     * {@link android.database.DatabaseUtils#appendSelectionArgs(String[], String[])} directly.
      */
+    @Deprecated
     public static String[] appendSelectionArgs(String[] originalValues, String[] newValues) {
         if (originalValues == null || originalValues.length == 0) {
             return newValues;
diff --git a/compat/java/android/support/v4/graphics/drawable/DrawableCompat.java b/compat/java/android/support/v4/graphics/drawable/DrawableCompat.java
index 79fb9c6..4e988ea 100644
--- a/compat/java/android/support/v4/graphics/drawable/DrawableCompat.java
+++ b/compat/java/android/support/v4/graphics/drawable/DrawableCompat.java
@@ -27,7 +27,6 @@
 import android.support.annotation.ColorInt;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.annotation.RequiresApi;
 import android.support.v4.view.ViewCompat;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -42,230 +41,186 @@
  * Helper for accessing features in {@link android.graphics.drawable.Drawable}.
  */
 public final class DrawableCompat {
+    private static final String TAG = "DrawableCompat";
+
+    private static Method sSetLayoutDirectionMethod;
+    private static boolean sSetLayoutDirectionMethodFetched;
+
+    private static Method sGetLayoutDirectionMethod;
+    private static boolean sGetLayoutDirectionMethodFetched;
+
     /**
-     * Interface implementation that doesn't use anything about platform-specific APIs.
+     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}.
+     *
+     * @param drawable The Drawable against which to invoke the method.
+     *
+     * @deprecated Use {@link Drawable#jumpToCurrentState()} directly.
      */
-    static class DrawableCompatBaseImpl {
-        public void jumpToCurrentState(Drawable drawable) {
-            drawable.jumpToCurrentState();
-        }
-
-        public void setAutoMirrored(Drawable drawable, boolean mirrored) {
-        }
-
-        public boolean isAutoMirrored(Drawable drawable) {
-            return false;
-        }
-
-        public void setHotspot(Drawable drawable, float x, float y) {
-        }
-
-        public void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) {
-        }
-
-        public void setTint(Drawable drawable, int tint) {
-            if (drawable instanceof TintAwareDrawable) {
-                ((TintAwareDrawable) drawable).setTint(tint);
-            }
-        }
-
-        public void setTintList(Drawable drawable, ColorStateList tint) {
-            if (drawable instanceof TintAwareDrawable) {
-                ((TintAwareDrawable) drawable).setTintList(tint);
-            }
-        }
-
-        public void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) {
-            if (drawable instanceof TintAwareDrawable) {
-                ((TintAwareDrawable) drawable).setTintMode(tintMode);
-            }
-        }
-
-        public Drawable wrap(Drawable drawable) {
-            if (!(drawable instanceof TintAwareDrawable)) {
-                return new DrawableWrapperApi14(drawable);
-            }
-            return drawable;
-        }
-
-        public boolean setLayoutDirection(Drawable drawable, int layoutDirection) {
-            // No op for API < 23
-            return false;
-        }
-
-        public int getLayoutDirection(Drawable drawable) {
-            return ViewCompat.LAYOUT_DIRECTION_LTR;
-        }
-
-        public int getAlpha(Drawable drawable) {
-            return 0;
-        }
-
-        public void applyTheme(Drawable drawable, Resources.Theme t) {
-        }
-
-        public boolean canApplyTheme(Drawable drawable) {
-            return false;
-        }
-
-        public ColorFilter getColorFilter(Drawable drawable) {
-            return null;
-        }
-
-        public void clearColorFilter(Drawable drawable) {
-            drawable.clearColorFilter();
-        }
-
-        public void inflate(Drawable drawable, Resources res, XmlPullParser parser,
-                            AttributeSet attrs, Resources.Theme t)
-                throws IOException, XmlPullParserException {
-            drawable.inflate(res, parser, attrs);
-        }
-    }
-
-    @RequiresApi(17)
-    static class DrawableCompatApi17Impl extends DrawableCompatBaseImpl {
-        private static final String TAG = "DrawableCompatApi17";
-
-        private static Method sSetLayoutDirectionMethod;
-        private static boolean sSetLayoutDirectionMethodFetched;
-
-        private static Method sGetLayoutDirectionMethod;
-        private static boolean sGetLayoutDirectionMethodFetched;
-
-        @Override
-        public boolean setLayoutDirection(Drawable drawable, int layoutDirection) {
-            if (!sSetLayoutDirectionMethodFetched) {
-                try {
-                    sSetLayoutDirectionMethod =
-                            Drawable.class.getDeclaredMethod("setLayoutDirection", int.class);
-                    sSetLayoutDirectionMethod.setAccessible(true);
-                } catch (NoSuchMethodException e) {
-                    Log.i(TAG, "Failed to retrieve setLayoutDirection(int) method", e);
-                }
-                sSetLayoutDirectionMethodFetched = true;
-            }
-
-            if (sSetLayoutDirectionMethod != null) {
-                try {
-                    sSetLayoutDirectionMethod.invoke(drawable, layoutDirection);
-                    return true;
-                } catch (Exception e) {
-                    Log.i(TAG, "Failed to invoke setLayoutDirection(int) via reflection", e);
-                    sSetLayoutDirectionMethod = null;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public int getLayoutDirection(Drawable drawable) {
-            if (!sGetLayoutDirectionMethodFetched) {
-                try {
-                    sGetLayoutDirectionMethod = Drawable.class.getDeclaredMethod("getLayoutDirection");
-                    sGetLayoutDirectionMethod.setAccessible(true);
-                } catch (NoSuchMethodException e) {
-                    Log.i(TAG, "Failed to retrieve getLayoutDirection() method", e);
-                }
-                sGetLayoutDirectionMethodFetched = true;
-            }
-
-            if (sGetLayoutDirectionMethod != null) {
-                try {
-                    return (int) sGetLayoutDirectionMethod.invoke(drawable);
-                } catch (Exception e) {
-                    Log.i(TAG, "Failed to invoke getLayoutDirection() via reflection", e);
-                    sGetLayoutDirectionMethod = null;
-                }
-            }
-            return ViewCompat.LAYOUT_DIRECTION_LTR;
-        }
+    @Deprecated
+    public static void jumpToCurrentState(@NonNull Drawable drawable) {
+        drawable.jumpToCurrentState();
     }
 
     /**
-     * Interface implementation for devices with at least KitKat APIs.
+     * Set whether this Drawable is automatically mirrored when its layout
+     * direction is RTL (right-to left). See
+     * {@link android.util.LayoutDirection}.
+     * <p>
+     * If running on a pre-{@link android.os.Build.VERSION_CODES#KITKAT} device
+     * this method does nothing.
+     *
+     * @param drawable The Drawable against which to invoke the method.
+     * @param mirrored Set to true if the Drawable should be mirrored, false if
+     *            not.
      */
-    @RequiresApi(19)
-    static class DrawableCompatApi19Impl extends DrawableCompatApi17Impl {
-        @Override
-        public void setAutoMirrored(Drawable drawable, boolean mirrored) {
+    public static void setAutoMirrored(@NonNull Drawable drawable, boolean mirrored) {
+        if (Build.VERSION.SDK_INT >= 19) {
             drawable.setAutoMirrored(mirrored);
         }
+    }
 
-        @Override
-        public boolean isAutoMirrored(Drawable drawable) {
+    /**
+     * Tells if this Drawable will be automatically mirrored when its layout
+     * direction is RTL right-to-left. See {@link android.util.LayoutDirection}.
+     * <p>
+     * If running on a pre-{@link android.os.Build.VERSION_CODES#KITKAT} device
+     * this method returns false.
+     *
+     * @param drawable The Drawable against which to invoke the method.
+     * @return boolean Returns true if this Drawable will be automatically
+     *         mirrored.
+     */
+    public static boolean isAutoMirrored(@NonNull Drawable drawable) {
+        if (Build.VERSION.SDK_INT >= 19) {
             return drawable.isAutoMirrored();
-        }
-
-        @Override
-        public Drawable wrap(Drawable drawable) {
-            if (!(drawable instanceof TintAwareDrawable)) {
-                return new DrawableWrapperApi19(drawable);
-            }
-            return drawable;
-        }
-
-        @Override
-        public int getAlpha(Drawable drawable) {
-            return drawable.getAlpha();
+        } else {
+            return false;
         }
     }
 
     /**
-     * Interface implementation for devices with at least L APIs.
+     * Specifies the hotspot's location within the drawable.
+     *
+     * @param drawable The Drawable against which to invoke the method.
+     * @param x The X coordinate of the center of the hotspot
+     * @param y The Y coordinate of the center of the hotspot
      */
-    @RequiresApi(21)
-    static class DrawableCompatApi21Impl extends DrawableCompatApi19Impl {
-        @Override
-        public void setHotspot(Drawable drawable, float x, float y) {
+    public static void setHotspot(@NonNull Drawable drawable, float x, float y) {
+        if (Build.VERSION.SDK_INT >= 21) {
             drawable.setHotspot(x, y);
         }
+    }
 
-        @Override
-        public void setHotspotBounds(Drawable drawable, int left, int top, int right, int bottom) {
+    /**
+     * Sets the bounds to which the hotspot is constrained, if they should be
+     * different from the drawable bounds.
+     *
+     * @param drawable The Drawable against which to invoke the method.
+     */
+    public static void setHotspotBounds(@NonNull Drawable drawable, int left, int top,
+            int right, int bottom) {
+        if (Build.VERSION.SDK_INT >= 21) {
             drawable.setHotspotBounds(left, top, right, bottom);
         }
+    }
 
-        @Override
-        public void setTint(Drawable drawable, int tint) {
+    /**
+     * Specifies a tint for {@code drawable}.
+     *
+     * @param drawable The Drawable against which to invoke the method.
+     * @param tint     Color to use for tinting this drawable
+     */
+    public static void setTint(@NonNull Drawable drawable, @ColorInt int tint) {
+        if (Build.VERSION.SDK_INT >= 21) {
             drawable.setTint(tint);
+        } else if (drawable instanceof TintAwareDrawable) {
+            ((TintAwareDrawable) drawable).setTint(tint);
         }
+    }
 
-        @Override
-        public void setTintList(Drawable drawable, ColorStateList tint) {
+    /**
+     * Specifies a tint for {@code drawable} as a color state list.
+     *
+     * @param drawable The Drawable against which to invoke the method.
+     * @param tint     Color state list to use for tinting this drawable, or null to clear the tint
+     */
+    public static void setTintList(@NonNull Drawable drawable, @Nullable ColorStateList tint) {
+        if (Build.VERSION.SDK_INT >= 21) {
             drawable.setTintList(tint);
+        } else if (drawable instanceof TintAwareDrawable) {
+            ((TintAwareDrawable) drawable).setTintList(tint);
         }
+    }
 
-        @Override
-        public void setTintMode(Drawable drawable, PorterDuff.Mode tintMode) {
+    /**
+     * Specifies a tint blending mode for {@code drawable}.
+     *
+     * @param drawable The Drawable against which to invoke the method.
+     * @param tintMode A Porter-Duff blending mode
+     */
+    public static void setTintMode(@NonNull Drawable drawable, @NonNull PorterDuff.Mode tintMode) {
+        if (Build.VERSION.SDK_INT >= 21) {
             drawable.setTintMode(tintMode);
+        } else if (drawable instanceof TintAwareDrawable) {
+            ((TintAwareDrawable) drawable).setTintMode(tintMode);
         }
+    }
 
-        @Override
-        public Drawable wrap(Drawable drawable) {
-            if (!(drawable instanceof TintAwareDrawable)) {
-                return new DrawableWrapperApi21(drawable);
-            }
-            return drawable;
+    /**
+     * Get the alpha value of the {@code drawable}.
+     * 0 means fully transparent, 255 means fully opaque.
+     *
+     * @param drawable The Drawable against which to invoke the method.
+     */
+    public static int getAlpha(@NonNull Drawable drawable) {
+        if (Build.VERSION.SDK_INT >= 19) {
+            return drawable.getAlpha();
+        } else {
+            return 0;
         }
+    }
 
-        @Override
-        public void applyTheme(Drawable drawable, Resources.Theme t) {
-            drawable.applyTheme(t);
+    /**
+     * Applies the specified theme to this Drawable and its children.
+     */
+    public static void applyTheme(@NonNull Drawable drawable, @NonNull Resources.Theme theme) {
+        if (Build.VERSION.SDK_INT >= 21) {
+            drawable.applyTheme(theme);
         }
+    }
 
-        @Override
-        public boolean canApplyTheme(Drawable drawable) {
+    /**
+     * Whether a theme can be applied to this Drawable and its children.
+     */
+    public static boolean canApplyTheme(@NonNull Drawable drawable) {
+        if (Build.VERSION.SDK_INT >= 21) {
             return drawable.canApplyTheme();
+        } else {
+            return false;
         }
+    }
 
-        @Override
-        public ColorFilter getColorFilter(Drawable drawable) {
+    /**
+     * Returns the current color filter, or {@code null} if none set.
+     *
+     * @return the current color filter, or {@code null} if none set
+     */
+    public static ColorFilter getColorFilter(@NonNull Drawable drawable) {
+        if (Build.VERSION.SDK_INT >= 21) {
             return drawable.getColorFilter();
+        } else {
+            return null;
         }
+    }
 
-        @Override
-        public void clearColorFilter(Drawable drawable) {
+    /**
+     * Removes the color filter from the given drawable.
+     */
+    public static void clearColorFilter(@NonNull Drawable drawable) {
+        if (Build.VERSION.SDK_INT >= 23) {
+            // We can use clearColorFilter() safely on M+
+            drawable.clearColorFilter();
+        } else if (Build.VERSION.SDK_INT >= 21) {
             drawable.clearColorFilter();
 
             // API 21 + 22 have an issue where clearing a color filter on a DrawableContainer
@@ -290,198 +245,12 @@
                     }
                 }
             }
-        }
-
-        @Override
-        public void inflate(Drawable drawable, Resources res, XmlPullParser parser,
-                            AttributeSet attrs, Resources.Theme t)
-                throws IOException, XmlPullParserException {
-            drawable.inflate(res, parser, attrs, t);
-        }
-    }
-
-    /**
-     * Interface implementation for devices with at least M APIs.
-     */
-    @RequiresApi(23)
-    static class DrawableCompatApi23Impl extends DrawableCompatApi21Impl {
-        @Override
-        public boolean setLayoutDirection(Drawable drawable, int layoutDirection) {
-            return drawable.setLayoutDirection(layoutDirection);
-        }
-
-        @Override
-        public int getLayoutDirection(Drawable drawable) {
-            return drawable.getLayoutDirection();
-        }
-
-        @Override
-        public Drawable wrap(Drawable drawable) {
-            // No need to wrap on M+
-            return drawable;
-        }
-
-        @Override
-        public void clearColorFilter(Drawable drawable) {
-            // We can use clearColorFilter() safely on M+
+        } else {
             drawable.clearColorFilter();
         }
     }
 
     /**
-     * Select the correct implementation to use for the current platform.
-     */
-    static final DrawableCompatBaseImpl IMPL;
-    static {
-        if (Build.VERSION.SDK_INT >= 23) {
-            IMPL = new DrawableCompatApi23Impl();
-        } else if (Build.VERSION.SDK_INT >= 21) {
-            IMPL = new DrawableCompatApi21Impl();
-        } else if (Build.VERSION.SDK_INT >= 19) {
-            IMPL = new DrawableCompatApi19Impl();
-        } else if (Build.VERSION.SDK_INT >= 17) {
-            IMPL = new DrawableCompatApi17Impl();
-        } else {
-            IMPL = new DrawableCompatBaseImpl();
-        }
-    }
-
-    /**
-     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}.
-     * <p>
-     * If running on a pre-{@link android.os.Build.VERSION_CODES#HONEYCOMB}
-     * device this method does nothing.
-     *
-     * @param drawable The Drawable against which to invoke the method.
-     */
-    public static void jumpToCurrentState(@NonNull Drawable drawable) {
-        IMPL.jumpToCurrentState(drawable);
-    }
-
-    /**
-     * Set whether this Drawable is automatically mirrored when its layout
-     * direction is RTL (right-to left). See
-     * {@link android.util.LayoutDirection}.
-     * <p>
-     * If running on a pre-{@link android.os.Build.VERSION_CODES#KITKAT} device
-     * this method does nothing.
-     *
-     * @param drawable The Drawable against which to invoke the method.
-     * @param mirrored Set to true if the Drawable should be mirrored, false if
-     *            not.
-     */
-    public static void setAutoMirrored(@NonNull Drawable drawable, boolean mirrored) {
-        IMPL.setAutoMirrored(drawable, mirrored);
-    }
-
-    /**
-     * Tells if this Drawable will be automatically mirrored when its layout
-     * direction is RTL right-to-left. See {@link android.util.LayoutDirection}.
-     * <p>
-     * If running on a pre-{@link android.os.Build.VERSION_CODES#KITKAT} device
-     * this method returns false.
-     *
-     * @param drawable The Drawable against which to invoke the method.
-     * @return boolean Returns true if this Drawable will be automatically
-     *         mirrored.
-     */
-    public static boolean isAutoMirrored(@NonNull Drawable drawable) {
-        return IMPL.isAutoMirrored(drawable);
-    }
-
-    /**
-     * Specifies the hotspot's location within the drawable.
-     *
-     * @param drawable The Drawable against which to invoke the method.
-     * @param x The X coordinate of the center of the hotspot
-     * @param y The Y coordinate of the center of the hotspot
-     */
-    public static void setHotspot(@NonNull Drawable drawable, float x, float y) {
-        IMPL.setHotspot(drawable, x, y);
-    }
-
-    /**
-     * Sets the bounds to which the hotspot is constrained, if they should be
-     * different from the drawable bounds.
-     *
-     * @param drawable The Drawable against which to invoke the method.
-     */
-    public static void setHotspotBounds(@NonNull Drawable drawable, int left, int top,
-            int right, int bottom) {
-        IMPL.setHotspotBounds(drawable, left, top, right, bottom);
-    }
-
-    /**
-     * Specifies a tint for {@code drawable}.
-     *
-     * @param drawable The Drawable against which to invoke the method.
-     * @param tint     Color to use for tinting this drawable
-     */
-    public static void setTint(@NonNull Drawable drawable, @ColorInt int tint) {
-        IMPL.setTint(drawable, tint);
-    }
-
-    /**
-     * Specifies a tint for {@code drawable} as a color state list.
-     *
-     * @param drawable The Drawable against which to invoke the method.
-     * @param tint     Color state list to use for tinting this drawable, or null to clear the tint
-     */
-    public static void setTintList(@NonNull Drawable drawable, @Nullable ColorStateList tint) {
-        IMPL.setTintList(drawable, tint);
-    }
-
-    /**
-     * Specifies a tint blending mode for {@code drawable}.
-     *
-     * @param drawable The Drawable against which to invoke the method.
-     * @param tintMode A Porter-Duff blending mode
-     */
-    public static void setTintMode(@NonNull Drawable drawable, @Nullable PorterDuff.Mode tintMode) {
-        IMPL.setTintMode(drawable, tintMode);
-    }
-
-    /**
-     * Get the alpha value of the {@code drawable}.
-     * 0 means fully transparent, 255 means fully opaque.
-     *
-     * @param drawable The Drawable against which to invoke the method.
-     */
-    public static int getAlpha(@NonNull Drawable drawable) {
-        return IMPL.getAlpha(drawable);
-    }
-
-    /**
-     * Applies the specified theme to this Drawable and its children.
-     */
-    public static void applyTheme(@NonNull Drawable drawable, @NonNull Resources.Theme t) {
-        IMPL.applyTheme(drawable, t);
-    }
-
-    /**
-     * Whether a theme can be applied to this Drawable and its children.
-     */
-    public static boolean canApplyTheme(@NonNull Drawable drawable) {
-        return IMPL.canApplyTheme(drawable);
-    }
-
-    /**
-     * Returns the current color filter, or {@code null} if none set.
-     *
-     * @return the current color filter, or {@code null} if none set
-     */
-    public static ColorFilter getColorFilter(@NonNull Drawable drawable) {
-        return IMPL.getColorFilter(drawable);
-    }
-
-    /**
-     * Removes the color filter from the given drawable.
-     */
-    public static void clearColorFilter(@NonNull Drawable drawable) {
-        IMPL.clearColorFilter(drawable);
-    }
-
-    /**
      * Inflate this Drawable from an XML resource optionally styled by a theme.
      *
      * @param res Resources used to resolve attribute values
@@ -495,7 +264,11 @@
             @NonNull XmlPullParser parser, @NonNull AttributeSet attrs,
             @Nullable Resources.Theme theme)
             throws XmlPullParserException, IOException {
-        IMPL.inflate(drawable, res, parser, attrs, theme);
+        if (Build.VERSION.SDK_INT >= 21) {
+            drawable.inflate(res, parser, attrs, theme);
+        } else {
+            drawable.inflate(res, parser, attrs);
+        }
     }
 
     /**
@@ -530,7 +303,24 @@
      * @see #unwrap(Drawable)
      */
     public static Drawable wrap(@NonNull Drawable drawable) {
-        return IMPL.wrap(drawable);
+        if (Build.VERSION.SDK_INT >= 23) {
+            return drawable;
+        } else if (Build.VERSION.SDK_INT >= 21) {
+            if (!(drawable instanceof TintAwareDrawable)) {
+                return new DrawableWrapperApi21(drawable);
+            }
+            return drawable;
+        } else if (Build.VERSION.SDK_INT >= 19) {
+            if (!(drawable instanceof TintAwareDrawable)) {
+                return new DrawableWrapperApi19(drawable);
+            }
+            return drawable;
+        } else {
+            if (!(drawable instanceof TintAwareDrawable)) {
+                return new DrawableWrapperApi14(drawable);
+            }
+            return drawable;
+        }
     }
 
     /**
@@ -565,7 +355,33 @@
      * @see #getLayoutDirection(Drawable)
      */
     public static boolean setLayoutDirection(@NonNull Drawable drawable, int layoutDirection) {
-        return IMPL.setLayoutDirection(drawable, layoutDirection);
+        if (Build.VERSION.SDK_INT >= 23) {
+            return drawable.setLayoutDirection(layoutDirection);
+        } else if (Build.VERSION.SDK_INT >= 17) {
+            if (!sSetLayoutDirectionMethodFetched) {
+                try {
+                    sSetLayoutDirectionMethod =
+                            Drawable.class.getDeclaredMethod("setLayoutDirection", int.class);
+                    sSetLayoutDirectionMethod.setAccessible(true);
+                } catch (NoSuchMethodException e) {
+                    Log.i(TAG, "Failed to retrieve setLayoutDirection(int) method", e);
+                }
+                sSetLayoutDirectionMethodFetched = true;
+            }
+
+            if (sSetLayoutDirectionMethod != null) {
+                try {
+                    sSetLayoutDirectionMethod.invoke(drawable, layoutDirection);
+                    return true;
+                } catch (Exception e) {
+                    Log.i(TAG, "Failed to invoke setLayoutDirection(int) via reflection", e);
+                    sSetLayoutDirectionMethod = null;
+                }
+            }
+            return false;
+        } else {
+            return false;
+        }
     }
 
     /**
@@ -576,7 +392,32 @@
      * @see #setLayoutDirection(Drawable, int)
      */
     public static int getLayoutDirection(@NonNull Drawable drawable) {
-        return IMPL.getLayoutDirection(drawable);
+        if (Build.VERSION.SDK_INT >= 23) {
+            return drawable.getLayoutDirection();
+        } else if (Build.VERSION.SDK_INT >= 17) {
+            if (!sGetLayoutDirectionMethodFetched) {
+                try {
+                    sGetLayoutDirectionMethod =
+                            Drawable.class.getDeclaredMethod("getLayoutDirection");
+                    sGetLayoutDirectionMethod.setAccessible(true);
+                } catch (NoSuchMethodException e) {
+                    Log.i(TAG, "Failed to retrieve getLayoutDirection() method", e);
+                }
+                sGetLayoutDirectionMethodFetched = true;
+            }
+
+            if (sGetLayoutDirectionMethod != null) {
+                try {
+                    return (int) sGetLayoutDirectionMethod.invoke(drawable);
+                } catch (Exception e) {
+                    Log.i(TAG, "Failed to invoke getLayoutDirection() via reflection", e);
+                    sGetLayoutDirectionMethod = null;
+                }
+            }
+            return ViewCompat.LAYOUT_DIRECTION_LTR;
+        } else {
+            return ViewCompat.LAYOUT_DIRECTION_LTR;
+        }
     }
 
     private DrawableCompat() {}
diff --git a/compat/ics/android/support/v4/graphics/drawable/DrawableWrapper.java b/compat/java/android/support/v4/graphics/drawable/DrawableWrapper.java
similarity index 100%
rename from compat/ics/android/support/v4/graphics/drawable/DrawableWrapper.java
rename to compat/java/android/support/v4/graphics/drawable/DrawableWrapper.java
diff --git a/compat/ics/android/support/v4/graphics/drawable/DrawableWrapperApi14.java b/compat/java/android/support/v4/graphics/drawable/DrawableWrapperApi14.java
similarity index 100%
rename from compat/ics/android/support/v4/graphics/drawable/DrawableWrapperApi14.java
rename to compat/java/android/support/v4/graphics/drawable/DrawableWrapperApi14.java
diff --git a/compat/kitkat/android/support/v4/graphics/drawable/DrawableWrapperApi19.java b/compat/java/android/support/v4/graphics/drawable/DrawableWrapperApi19.java
similarity index 100%
rename from compat/kitkat/android/support/v4/graphics/drawable/DrawableWrapperApi19.java
rename to compat/java/android/support/v4/graphics/drawable/DrawableWrapperApi19.java
diff --git a/compat/api21/android/support/v4/graphics/drawable/DrawableWrapperApi21.java b/compat/java/android/support/v4/graphics/drawable/DrawableWrapperApi21.java
similarity index 100%
rename from compat/api21/android/support/v4/graphics/drawable/DrawableWrapperApi21.java
rename to compat/java/android/support/v4/graphics/drawable/DrawableWrapperApi21.java
diff --git a/compat/java/android/support/v4/graphics/drawable/IconCompat.java b/compat/java/android/support/v4/graphics/drawable/IconCompat.java
index d6ef5de..a2ad67f 100644
--- a/compat/java/android/support/v4/graphics/drawable/IconCompat.java
+++ b/compat/java/android/support/v4/graphics/drawable/IconCompat.java
@@ -18,7 +18,6 @@
 
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
 
-import android.annotation.TargetApi;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
@@ -32,6 +31,7 @@
 import android.net.Uri;
 import android.os.Build;
 import android.support.annotation.DrawableRes;
+import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
 import android.support.annotation.VisibleForTesting;
 
@@ -174,10 +174,11 @@
     }
 
     /**
-     * @hide
+     * Convert this compat object to {@link Icon} object.
+     *
+     * @return {@link Icon} object
      */
-    @RestrictTo(LIBRARY_GROUP)
-    @TargetApi(Build.VERSION_CODES.O)
+    @RequiresApi(23)
     public Icon toIcon() {
         switch (mType) {
             case TYPE_BITMAP:
diff --git a/compat/ics/android/support/v4/graphics/drawable/TintAwareDrawable.java b/compat/java/android/support/v4/graphics/drawable/TintAwareDrawable.java
similarity index 100%
rename from compat/ics/android/support/v4/graphics/drawable/TintAwareDrawable.java
rename to compat/java/android/support/v4/graphics/drawable/TintAwareDrawable.java
diff --git a/compat/java/android/support/v4/util/ObjectsCompat.java b/compat/java/android/support/v4/util/ObjectsCompat.java
index 4a4c844..4650060 100644
--- a/compat/java/android/support/v4/util/ObjectsCompat.java
+++ b/compat/java/android/support/v4/util/ObjectsCompat.java
@@ -16,7 +16,6 @@
 package android.support.v4.util;
 
 import android.os.Build;
-import android.support.annotation.RequiresApi;
 
 import java.util.Objects;
 
@@ -24,16 +23,6 @@
  * This class consists of static utility methods for operating on objects.
  */
 public class ObjectsCompat {
-    private static final ImplBase IMPL;
-
-    static {
-        if (Build.VERSION.SDK_INT >= 19) {
-            IMPL = new ImplApi19();
-        } else {
-            IMPL = new ImplBase();
-        }
-    }
-
     private ObjectsCompat() {
         // Non-instantiable.
     }
@@ -55,20 +44,10 @@
      * @see Object#equals(Object)
      */
     public static boolean equals(Object a, Object b) {
-        return IMPL.equals(a, b);
-    }
-
-    private static class ImplBase {
-        public boolean equals(Object a, Object b) {
-            return (a == b) || (a != null && a.equals(b));
-        }
-    }
-
-    @RequiresApi(19)
-    private static class ImplApi19 extends ImplBase {
-        @Override
-        public boolean equals(Object a, Object b) {
+        if (Build.VERSION.SDK_INT >= 19) {
             return Objects.equals(a, b);
+        } else {
+            return (a == b) || (a != null && a.equals(b));
         }
     }
 }
diff --git a/compat/java/android/support/v4/widget/AutoSizeableTextView.java b/compat/java/android/support/v4/widget/AutoSizeableTextView.java
index c0b13e3..a0430c6 100644
--- a/compat/java/android/support/v4/widget/AutoSizeableTextView.java
+++ b/compat/java/android/support/v4/widget/AutoSizeableTextView.java
@@ -20,6 +20,7 @@
 
 import android.support.annotation.NonNull;
 import android.support.annotation.RestrictTo;
+import android.support.v4.os.BuildCompat;
 import android.util.TypedValue;
 
 /**
@@ -31,6 +32,12 @@
 @RestrictTo(LIBRARY_GROUP)
 public interface AutoSizeableTextView {
     /**
+     * @hide
+     */
+    @RestrictTo(LIBRARY_GROUP)
+    boolean PLATFORM_SUPPORTS_AUTOSIZE = BuildCompat.isAtLeastOMR1();
+
+    /**
      * Specify whether this widget should automatically scale the text to try to perfectly fit
      * within the layout bounds by using the default auto-size configuration.
      *
diff --git a/compat/java/android/support/v4/widget/TextViewCompat.java b/compat/java/android/support/v4/widget/TextViewCompat.java
index 5654c3e..8d9e4ab 100644
--- a/compat/java/android/support/v4/widget/TextViewCompat.java
+++ b/compat/java/android/support/v4/widget/TextViewCompat.java
@@ -27,6 +27,7 @@
 import android.support.annotation.RequiresApi;
 import android.support.annotation.RestrictTo;
 import android.support.annotation.StyleRes;
+import android.support.v4.os.BuildCompat;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.View;
@@ -313,8 +314,8 @@
         }
     }
 
-    @RequiresApi(26)
-    static class TextViewCompatApi26Impl extends TextViewCompatApi23Impl {
+    @RequiresApi(27)
+    static class TextViewCompatApi27Impl extends TextViewCompatApi23Impl {
         @Override
         public void setAutoSizeTextTypeWithDefaults(TextView textView, int autoSizeTextType) {
             textView.setAutoSizeTextTypeWithDefaults(autoSizeTextType);
@@ -366,8 +367,8 @@
     static final TextViewCompatBaseImpl IMPL;
 
     static {
-        if (Build.VERSION.SDK_INT >= 26) {
-            IMPL = new TextViewCompatApi26Impl();
+        if (BuildCompat.isAtLeastOMR1()) {
+            IMPL = new TextViewCompatApi27Impl();
         } else if (Build.VERSION.SDK_INT >= 23) {
             IMPL = new TextViewCompatApi23Impl();
         } else if (Build.VERSION.SDK_INT >= 18) {
diff --git a/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java b/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java
index 426dad9..b639c55 100644
--- a/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java
+++ b/compat/jellybean/android/support/v4/app/NotificationCompatJellybean.java
@@ -21,7 +21,6 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.os.Bundle;
-import android.os.Parcelable;
 import android.support.annotation.RequiresApi;
 import android.util.Log;
 import android.util.SparseArray;
@@ -59,13 +58,13 @@
     private static Field sActionIntentField;
     private static boolean sActionsAccessFailed;
 
-    public static class Builder implements NotificationBuilderWithBuilderAccessor,
-            NotificationBuilderWithActions {
-        private Notification.Builder b;
+    public static class Builder extends NotificationCompat.NotificationCompatBaseImpl.BuilderBase
+            implements NotificationBuilderWithActions {
+        protected RemoteViews mContentView;
+        protected RemoteViews mBigContentView;
+        protected List<Bundle> mActionExtrasList = new ArrayList<>();
+
         private final Bundle mExtras;
-        private List<Bundle> mActionExtrasList = new ArrayList<Bundle>();
-        private RemoteViews mContentView;
-        private RemoteViews mBigContentView;
 
         public Builder(Context context, Notification n,
                 CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo,
@@ -74,32 +73,13 @@
                 int progressMax, int progress, boolean progressIndeterminate,
                 boolean useChronometer, int priority, CharSequence subText, boolean localOnly,
                 Bundle extras, String groupKey, boolean groupSummary, String sortKey,
-                RemoteViews contentView, RemoteViews bigContentView) {
-            b = new Notification.Builder(context)
-                .setWhen(n.when)
-                .setSmallIcon(n.icon, n.iconLevel)
-                .setContent(n.contentView)
-                .setTicker(n.tickerText, tickerView)
-                .setSound(n.sound, n.audioStreamType)
-                .setVibrate(n.vibrate)
-                .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS)
-                .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0)
-                .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)
-                .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0)
-                .setDefaults(n.defaults)
-                .setContentTitle(contentTitle)
-                .setContentText(contentText)
-                .setSubText(subText)
-                .setContentInfo(contentInfo)
-                .setContentIntent(contentIntent)
-                .setDeleteIntent(n.deleteIntent)
-                .setFullScreenIntent(fullScreenIntent,
-                        (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0)
-                .setLargeIcon(largeIcon)
-                .setNumber(number)
+                RemoteViews contentView, RemoteViews bigContentView, String channelId) {
+            super(context, n, contentTitle, contentText, contentInfo, tickerView, number,
+                    contentIntent, fullScreenIntent, largeIcon, progressMax, progress,
+                    progressIndeterminate, channelId);
+            mBuilder.setSubText(subText)
                 .setUsesChronometer(useChronometer)
-                .setPriority(priority)
-                .setProgress(progressMax, progress, progressIndeterminate);
+                .setPriority(priority);
             mExtras = new Bundle();
             if (extras != null) {
                 mExtras.putAll(extras);
@@ -124,17 +104,12 @@
 
         @Override
         public void addAction(NotificationCompatBase.Action action) {
-            mActionExtrasList.add(writeActionAndGetExtras(b, action));
-        }
-
-        @Override
-        public Notification.Builder getBuilder() {
-            return b;
+            mActionExtrasList.add(writeActionAndGetExtras(mBuilder, action));
         }
 
         @Override
         public Notification build() {
-            Notification notif = b.build();
+            Notification notif = mBuilder.build();
             // Merge in developer provided extras, but let the values already set
             // for keys take precedence.
             Bundle extras = getExtras(notif);
@@ -366,22 +341,7 @@
         return !sActionsAccessFailed;
     }
 
-    public static NotificationCompatBase.Action[] getActionsFromParcelableArrayList(
-            ArrayList<Parcelable> parcelables,
-            NotificationCompatBase.Action.Factory actionFactory,
-            RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) {
-        if (parcelables == null) {
-            return null;
-        }
-        NotificationCompatBase.Action[] actions = actionFactory.newArray(parcelables.size());
-        for (int i = 0; i < actions.length; i++) {
-            actions[i] = getActionFromBundle((Bundle) parcelables.get(i),
-                    actionFactory, remoteInputFactory);
-        }
-        return actions;
-    }
-
-    private static NotificationCompatBase.Action getActionFromBundle(Bundle bundle,
+    static NotificationCompatBase.Action getActionFromBundle(Bundle bundle,
             NotificationCompatBase.Action.Factory actionFactory,
             RemoteInputCompatBase.RemoteInput.Factory remoteInputFactory) {
         Bundle extras = bundle.getBundle(KEY_EXTRAS);
@@ -403,19 +363,7 @@
                 allowGeneratedReplies);
     }
 
-    public static ArrayList<Parcelable> getParcelableArrayListForActions(
-            NotificationCompatBase.Action[] actions) {
-        if (actions == null) {
-            return null;
-        }
-        ArrayList<Parcelable> parcelables = new ArrayList<Parcelable>(actions.length);
-        for (NotificationCompatBase.Action action : actions) {
-            parcelables.add(getBundleForAction(action));
-        }
-        return parcelables;
-    }
-
-    private static Bundle getBundleForAction(NotificationCompatBase.Action action) {
+    static Bundle getBundleForAction(NotificationCompatBase.Action action) {
         Bundle bundle = new Bundle();
         bundle.putInt(KEY_ICON, action.getIcon());
         bundle.putCharSequence(KEY_TITLE, action.getTitle());
diff --git a/compat/kitkat/android/support/v4/app/NotificationCompatKitKat.java b/compat/kitkat/android/support/v4/app/NotificationCompatKitKat.java
index f40fd1b..d101ba6 100644
--- a/compat/kitkat/android/support/v4/app/NotificationCompatKitKat.java
+++ b/compat/kitkat/android/support/v4/app/NotificationCompatKitKat.java
@@ -30,13 +30,9 @@
 
 @RequiresApi(19)
 class NotificationCompatKitKat {
-    public static class Builder implements NotificationBuilderWithBuilderAccessor,
-            NotificationBuilderWithActions {
-        private Notification.Builder b;
+    public static class Builder extends NotificationCompatJellybean.Builder {
         private Bundle mExtras;
         private List<Bundle> mActionExtrasList = new ArrayList<Bundle>();
-        private RemoteViews mContentView;
-        private RemoteViews mBigContentView;
 
         public Builder(Context context, Notification n,
                 CharSequence contentTitle, CharSequence contentText, CharSequence contentInfo,
@@ -45,33 +41,15 @@
                 int progressMax, int progress, boolean progressIndeterminate, boolean showWhen,
                 boolean useChronometer, int priority, CharSequence subText, boolean localOnly,
                 ArrayList<String> people, Bundle extras, String groupKey, boolean groupSummary,
-                String sortKey, RemoteViews contentView, RemoteViews bigContentView) {
-            b = new Notification.Builder(context)
-                .setWhen(n.when)
-                .setShowWhen(showWhen)
-                .setSmallIcon(n.icon, n.iconLevel)
-                .setContent(n.contentView)
-                .setTicker(n.tickerText, tickerView)
-                .setSound(n.sound, n.audioStreamType)
-                .setVibrate(n.vibrate)
-                .setLights(n.ledARGB, n.ledOnMS, n.ledOffMS)
-                .setOngoing((n.flags & Notification.FLAG_ONGOING_EVENT) != 0)
-                .setOnlyAlertOnce((n.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0)
-                .setAutoCancel((n.flags & Notification.FLAG_AUTO_CANCEL) != 0)
-                .setDefaults(n.defaults)
-                .setContentTitle(contentTitle)
-                .setContentText(contentText)
-                .setSubText(subText)
-                .setContentInfo(contentInfo)
-                .setContentIntent(contentIntent)
-                .setDeleteIntent(n.deleteIntent)
-                .setFullScreenIntent(fullScreenIntent,
-                        (n.flags & Notification.FLAG_HIGH_PRIORITY) != 0)
-                .setLargeIcon(largeIcon)
-                .setNumber(number)
-                .setUsesChronometer(useChronometer)
-                .setPriority(priority)
-                .setProgress(progressMax, progress, progressIndeterminate);
+                String sortKey, RemoteViews contentView, RemoteViews bigContentView,
+                String channelId) {
+            super(context, n, contentTitle, contentText, contentInfo, tickerView, number,
+                    contentIntent, fullScreenIntent, largeIcon, progressMax, progress,
+                    progressIndeterminate, useChronometer, priority, subText, localOnly,
+                    extras, groupKey, groupSummary, sortKey, contentView, bigContentView,
+                    channelId);
+            mBuilder.setShowWhen(showWhen);
+
             mExtras = new Bundle();
             if (extras != null) {
                 mExtras.putAll(extras);
@@ -99,16 +77,6 @@
         }
 
         @Override
-        public void addAction(NotificationCompatBase.Action action) {
-            mActionExtrasList.add(NotificationCompatJellybean.writeActionAndGetExtras(b, action));
-        }
-
-        @Override
-        public Notification.Builder getBuilder() {
-            return b;
-        }
-
-        @Override
         public Notification build() {
             SparseArray<Bundle> actionExtrasMap = NotificationCompatJellybean.buildActionExtrasMap(
                     mActionExtrasList);
@@ -117,8 +85,8 @@
                 mExtras.putSparseParcelableArray(
                         NotificationCompatExtras.EXTRA_ACTION_EXTRAS, actionExtrasMap);
             }
-            b.setExtras(mExtras);
-            Notification notification = b.build();
+            mBuilder.setExtras(mExtras);
+            Notification notification = mBuilder.build();
             if (mContentView != null) {
                 notification.contentView = mContentView;
             }
diff --git a/compat/tests/java/android/support/v4/content/pm/ShortcutManagerCompatTest.java b/compat/tests/java/android/support/v4/content/pm/ShortcutManagerCompatTest.java
index 2d6cd67..3a48a6bd 100644
--- a/compat/tests/java/android/support/v4/content/pm/ShortcutManagerCompatTest.java
+++ b/compat/tests/java/android/support/v4/content/pm/ShortcutManagerCompatTest.java
@@ -51,6 +51,7 @@
 import android.support.test.runner.AndroidJUnit4;
 import android.support.v4.BaseInstrumentationTestCase;
 import android.support.v4.app.TestSupportActivity;
+import android.support.v4.graphics.drawable.IconCompat;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -75,7 +76,8 @@
     public void setup() {
         mContext = spy(mActivityTestRule.getActivity());
         mInfoCompat = new ShortcutInfoCompat.Builder(mContext, "test-id")
-                .setIcon(Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888))
+                .setIcon(IconCompat.createWithBitmap(Bitmap.createBitmap(
+                        10, 10, Bitmap.Config.ARGB_8888)))
                 .setShortLabel("Test shortcut")
                 .setIntent(new Intent("Dummy"))
                 .build();
diff --git a/compat/java/android/support/v4/content/ModernAsyncTask.java b/core-utils/java/android/support/v4/content/ModernAsyncTask.java
similarity index 98%
rename from compat/java/android/support/v4/content/ModernAsyncTask.java
rename to core-utils/java/android/support/v4/content/ModernAsyncTask.java
index 8e2991a..06404ce 100644
--- a/compat/java/android/support/v4/content/ModernAsyncTask.java
+++ b/core-utils/java/android/support/v4/content/ModernAsyncTask.java
@@ -71,8 +71,8 @@
     /**
      * An {@link Executor} that can be used to execute tasks in parallel.
      */
-    public static final Executor THREAD_POOL_EXECUTOR
-            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
+    public static final Executor THREAD_POOL_EXECUTOR =
+            new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                     TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
 
     private static final int MESSAGE_POST_RESULT = 0x1;
@@ -126,7 +126,7 @@
     /**
      * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
      */
-    public ModernAsyncTask() {
+    ModernAsyncTask() {
         mWorker = new WorkerRunnable<Params, Result>() {
             @Override
             public Result call() throws Exception {
@@ -490,7 +490,7 @@
     }
 
     private static class InternalHandler extends Handler {
-        public InternalHandler() {
+        InternalHandler() {
             super(Looper.getMainLooper());
         }
 
@@ -510,7 +510,7 @@
         }
     }
 
-    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
+    private abstract static class WorkerRunnable<Params, Result> implements Callable<Result> {
         Params[] mParams;
 
         WorkerRunnable() {
diff --git a/compat/tests/java/android/support/v4/content/ModernAsyncTaskTest.java b/core-utils/tests/java/android/support/v4/content/ModernAsyncTaskTest.java
similarity index 97%
rename from compat/tests/java/android/support/v4/content/ModernAsyncTaskTest.java
rename to core-utils/tests/java/android/support/v4/content/ModernAsyncTaskTest.java
index 0697950..e597025 100644
--- a/compat/tests/java/android/support/v4/content/ModernAsyncTaskTest.java
+++ b/core-utils/tests/java/android/support/v4/content/ModernAsyncTaskTest.java
@@ -11,7 +11,7 @@
  * 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
+ * limitations under the License.
  */
 
 package android.support.v4.content;
@@ -55,7 +55,7 @@
                         readyToCancel.countDown();
                         try {
                             readyToThrow.await();
-                        } catch (InterruptedException e) {}
+                        } catch (InterruptedException e) { }
                         // This exception is expected to be caught and ignored
                         throw new RuntimeException();
                     }
diff --git a/dynamic-animation/build.gradle b/dynamic-animation/build.gradle
index 8ceaaf3..a5ec572 100644
--- a/dynamic-animation/build.gradle
+++ b/dynamic-animation/build.gradle
@@ -11,7 +11,7 @@
 
 android {
     defaultConfig {
-        minSdkVersion 16
+        minSdkVersion 14
     }
 
     sourceSets {
diff --git a/dynamic-animation/src/android/support/animation/AnimationHandler.java b/dynamic-animation/src/android/support/animation/AnimationHandler.java
index e4cf7c7..9f63bd1 100644
--- a/dynamic-animation/src/android/support/animation/AnimationHandler.java
+++ b/dynamic-animation/src/android/support/animation/AnimationHandler.java
@@ -16,6 +16,10 @@
 
 package android.support.animation;
 
+import android.annotation.TargetApi;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.SystemClock;
 import android.support.v4.util.SimpleArrayMap;
 import android.view.Choreographer;
@@ -47,28 +51,37 @@
     }
 
     /**
+     * This class is responsible for interacting with the available frame provider by either
+     * registering frame callback or posting runnable, and receiving a callback for when a
+     * new frame has arrived. This dispatcher class then notifies all the on-going animations of
+     * the new frame, so that they can update animation values as needed.
+     */
+    class AnimationCallbackDispatcher {
+        public void dispatchAnimationFrame() {
+            mCurrentFrameTime = SystemClock.uptimeMillis();
+            AnimationHandler.this.doAnimationFrame(mCurrentFrameTime);
+            if (mAnimationCallbacks.size() > 0) {
+                getProvider().postFrameCallback();
+            }
+        }
+    }
+
+    private static final long FRAME_DELAY_MS = 10;
+    public static final ThreadLocal<AnimationHandler> sAnimatorHandler = new ThreadLocal<>();
+
+    /**
      * Internal per-thread collections used to avoid set collisions as animations start and end
      * while being processed.
      * @hide
      */
     private final SimpleArrayMap<AnimationFrameCallback, Long> mDelayedCallbackStartTime =
             new SimpleArrayMap<>();
-    public static final ThreadLocal<AnimationHandler> sAnimatorHandler = new ThreadLocal<>();
     private final ArrayList<AnimationFrameCallback> mAnimationCallbacks = new ArrayList<>();
+    private final AnimationCallbackDispatcher mCallbackDispatcher =
+            new AnimationCallbackDispatcher();
+
     private AnimationFrameCallbackProvider mProvider;
-
     private long mCurrentFrameTime = 0;
-    private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
-        @Override
-        public void doFrame(long frameTimeNanos) {
-            mCurrentFrameTime = System.currentTimeMillis();
-            doAnimationFrame(mCurrentFrameTime);
-            if (mAnimationCallbacks.size() > 0) {
-                getProvider().postFrameCallback(this);
-            }
-        }
-    };
-
     private boolean mListDirty = false;
 
     public static AnimationHandler getInstance() {
@@ -90,16 +103,16 @@
      * provider can be used here to provide different timing pulse.
      */
     public void setProvider(AnimationFrameCallbackProvider provider) {
-        if (provider == null) {
-            mProvider = new MyFrameCallbackProvider();
-        } else {
-            mProvider = provider;
-        }
+        mProvider = provider;
     }
 
     private AnimationFrameCallbackProvider getProvider() {
         if (mProvider == null) {
-            mProvider = new MyFrameCallbackProvider();
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+                mProvider = new FrameCallbackProvider16(mCallbackDispatcher);
+            } else {
+                mProvider = new FrameCallbackProvider14(mCallbackDispatcher);
+            }
         }
         return mProvider;
     }
@@ -109,7 +122,7 @@
      */
     public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
         if (mAnimationCallbacks.size() == 0) {
-            getProvider().postFrameCallback(mFrameCallback);
+            getProvider().postFrameCallback();
         }
         if (!mAnimationCallbacks.contains(callback)) {
             mAnimationCallbacks.add(callback);
@@ -178,13 +191,55 @@
     /**
      * Default provider of timing pulse that uses Choreographer for frame callbacks.
      */
-    private static class MyFrameCallbackProvider implements AnimationFrameCallbackProvider {
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+    private static class FrameCallbackProvider16 extends AnimationFrameCallbackProvider {
 
-        final Choreographer mChoreographer = Choreographer.getInstance();
+        private final Choreographer mChoreographer = Choreographer.getInstance();
+        private final Choreographer.FrameCallback mChoreographerCallback;
+
+        FrameCallbackProvider16(AnimationCallbackDispatcher dispatcher) {
+            super(dispatcher);
+            mChoreographerCallback = new Choreographer.FrameCallback() {
+                    @Override
+                    public void doFrame(long frameTimeNanos) {
+                        mDispatcher.dispatchAnimationFrame();
+                    }
+                };
+        }
 
         @Override
-        public void postFrameCallback(Choreographer.FrameCallback callback) {
-            mChoreographer.postFrameCallback(callback);
+        void postFrameCallback() {
+            mChoreographer.postFrameCallback(mChoreographerCallback);
+        }
+    }
+
+    /**
+     * Frame provider for ICS and ICS-MR1 releases. The frame callback is achieved via posting
+     * a Runnable to the main thread Handler with a delay.
+     */
+    private static class FrameCallbackProvider14 extends AnimationFrameCallbackProvider {
+
+        private final Runnable mRunnable;
+        private final Handler mHandler;
+        private long mLastFrameTime = -1;
+
+        FrameCallbackProvider14(AnimationCallbackDispatcher dispatcher) {
+            super(dispatcher);
+            mRunnable = new Runnable() {
+                @Override
+                public void run() {
+                    mLastFrameTime = SystemClock.uptimeMillis();
+                    mDispatcher.dispatchAnimationFrame();
+                }
+            };
+            mHandler = new Handler(Looper.myLooper());
+        }
+
+        @Override
+        void postFrameCallback() {
+            long delay = FRAME_DELAY_MS - (SystemClock.uptimeMillis() - mLastFrameTime);
+            delay = Math.max(delay, 0);
+            mHandler.postDelayed(mRunnable, delay);
         }
     }
 
@@ -193,10 +248,13 @@
      * Specifically, we can have a custom implementation of the interface below and provide
      * timing pulse without using Choreographer. That way we could use any arbitrary interval for
      * our timing pulse in the tests.
-     *
-     * @hide
      */
-    public interface AnimationFrameCallbackProvider {
-        void postFrameCallback(Choreographer.FrameCallback callback);
+    public abstract static class AnimationFrameCallbackProvider {
+        final AnimationCallbackDispatcher mDispatcher;
+        AnimationFrameCallbackProvider(AnimationCallbackDispatcher dispatcher) {
+            mDispatcher = dispatcher;
+        }
+
+        abstract void postFrameCallback();
     }
 }
diff --git a/exifinterface/api/27.0.0-SNAPSHOT.txt b/exifinterface/api/27.0.0-SNAPSHOT.txt
index 916a769..8533011 100644
--- a/exifinterface/api/27.0.0-SNAPSHOT.txt
+++ b/exifinterface/api/27.0.0-SNAPSHOT.txt
@@ -11,11 +11,13 @@
     method public int getAttributeInt(java.lang.String, int);
     method public deprecated boolean getLatLong(float[]);
     method public double[] getLatLong();
+    method public int getRotationDegrees();
     method public byte[] getThumbnail();
     method public android.graphics.Bitmap getThumbnailBitmap();
     method public byte[] getThumbnailBytes();
     method public long[] getThumbnailRange();
     method public boolean hasThumbnail();
+    method public boolean isFlipped();
     method public boolean isThumbnailCompressed();
     method public void resetOrientation();
     method public void rotate(int);
@@ -24,6 +26,102 @@
     method public void setAttribute(java.lang.String, java.lang.String);
     method public void setGpsInfo(android.location.Location);
     method public void setLatLong(double, double);
+    field public static final short ALTITUDE_ABOVE_SEA_LEVEL = 0; // 0x0
+    field public static final short ALTITUDE_BELOW_SEA_LEVEL = 1; // 0x1
+    field public static final int[] BITS_PER_SAMPLE_GREYSCALE_1;
+    field public static final int[] BITS_PER_SAMPLE_GREYSCALE_2;
+    field public static final int[] BITS_PER_SAMPLE_RGB;
+    field public static final int COLOR_SPACE_S_RGB = 1; // 0x1
+    field public static final int COLOR_SPACE_UNCALIBRATED = 65535; // 0xffff
+    field public static final short CONTRAST_HARD = 2; // 0x2
+    field public static final short CONTRAST_NORMAL = 0; // 0x0
+    field public static final short CONTRAST_SOFT = 1; // 0x1
+    field public static final int DATA_DEFLATE_ZIP = 8; // 0x8
+    field public static final int DATA_HUFFMAN_COMPRESSED = 2; // 0x2
+    field public static final int DATA_JPEG = 6; // 0x6
+    field public static final int DATA_JPEG_COMPRESSED = 7; // 0x7
+    field public static final int DATA_LOSSY_JPEG = 34892; // 0x884c
+    field public static final int DATA_PACK_BITS_COMPRESSED = 32773; // 0x8005
+    field public static final int DATA_UNCOMPRESSED = 1; // 0x1
+    field public static final short EXPOSURE_MODE_AUTO = 0; // 0x0
+    field public static final short EXPOSURE_MODE_AUTO_BRACKET = 2; // 0x2
+    field public static final short EXPOSURE_MODE_MANUAL = 1; // 0x1
+    field public static final short EXPOSURE_PROGRAM_ACTION = 6; // 0x6
+    field public static final short EXPOSURE_PROGRAM_APERTURE_PRIORITY = 3; // 0x3
+    field public static final short EXPOSURE_PROGRAM_CREATIVE = 5; // 0x5
+    field public static final short EXPOSURE_PROGRAM_LANDSCAPE_MODE = 8; // 0x8
+    field public static final short EXPOSURE_PROGRAM_MANUAL = 1; // 0x1
+    field public static final short EXPOSURE_PROGRAM_NORMAL = 2; // 0x2
+    field public static final short EXPOSURE_PROGRAM_NOT_DEFINED = 0; // 0x0
+    field public static final short EXPOSURE_PROGRAM_PORTRAIT_MODE = 7; // 0x7
+    field public static final short EXPOSURE_PROGRAM_SHUTTER_PRIORITY = 4; // 0x4
+    field public static final short FILE_SOURCE_DSC = 3; // 0x3
+    field public static final short FILE_SOURCE_OTHER = 0; // 0x0
+    field public static final short FILE_SOURCE_REFLEX_SCANNER = 2; // 0x2
+    field public static final short FILE_SOURCE_TRANSPARENT_SCANNER = 1; // 0x1
+    field public static final short FLAG_FLASH_FIRED = 1; // 0x1
+    field public static final short FLAG_FLASH_MODE_AUTO = 24; // 0x18
+    field public static final short FLAG_FLASH_MODE_COMPULSORY_FIRING = 8; // 0x8
+    field public static final short FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION = 16; // 0x10
+    field public static final short FLAG_FLASH_NO_FLASH_FUNCTION = 32; // 0x20
+    field public static final short FLAG_FLASH_RED_EYE_SUPPORTED = 64; // 0x40
+    field public static final short FLAG_FLASH_RETURN_LIGHT_DETECTED = 6; // 0x6
+    field public static final short FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED = 4; // 0x4
+    field public static final short FORMAT_CHUNKY = 1; // 0x1
+    field public static final short FORMAT_PLANAR = 2; // 0x2
+    field public static final short GAIN_CONTROL_HIGH_GAIN_DOWN = 4; // 0x4
+    field public static final short GAIN_CONTROL_HIGH_GAIN_UP = 2; // 0x2
+    field public static final short GAIN_CONTROL_LOW_GAIN_DOWN = 3; // 0x3
+    field public static final short GAIN_CONTROL_LOW_GAIN_UP = 1; // 0x1
+    field public static final short GAIN_CONTROL_NONE = 0; // 0x0
+    field public static final java.lang.String GPS_DIRECTION_MAGNETIC = "M";
+    field public static final java.lang.String GPS_DIRECTION_TRUE = "T";
+    field public static final java.lang.String GPS_DISTANCE_KILOMETERS = "K";
+    field public static final java.lang.String GPS_DISTANCE_MILES = "M";
+    field public static final java.lang.String GPS_DISTANCE_NAUTICAL_MILES = "N";
+    field public static final java.lang.String GPS_MEASUREMENT_2D = "2";
+    field public static final java.lang.String GPS_MEASUREMENT_3D = "3";
+    field public static final short GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED = 1; // 0x1
+    field public static final java.lang.String GPS_MEASUREMENT_INTERRUPTED = "V";
+    field public static final java.lang.String GPS_MEASUREMENT_IN_PROGRESS = "A";
+    field public static final short GPS_MEASUREMENT_NO_DIFFERENTIAL = 0; // 0x0
+    field public static final java.lang.String GPS_SPEED_KILOMETERS_PER_HOUR = "K";
+    field public static final java.lang.String GPS_SPEED_KNOTS = "N";
+    field public static final java.lang.String GPS_SPEED_MILES_PER_HOUR = "M";
+    field public static final java.lang.String LATITUDE_NORTH = "N";
+    field public static final java.lang.String LATITUDE_SOUTH = "S";
+    field public static final short LIGHT_SOURCE_CLOUDY_WEATHER = 10; // 0xa
+    field public static final short LIGHT_SOURCE_COOL_WHITE_FLUORESCENT = 14; // 0xe
+    field public static final short LIGHT_SOURCE_D50 = 23; // 0x17
+    field public static final short LIGHT_SOURCE_D55 = 20; // 0x14
+    field public static final short LIGHT_SOURCE_D65 = 21; // 0x15
+    field public static final short LIGHT_SOURCE_D75 = 22; // 0x16
+    field public static final short LIGHT_SOURCE_DAYLIGHT = 1; // 0x1
+    field public static final short LIGHT_SOURCE_DAYLIGHT_FLUORESCENT = 12; // 0xc
+    field public static final short LIGHT_SOURCE_DAY_WHITE_FLUORESCENT = 13; // 0xd
+    field public static final short LIGHT_SOURCE_FINE_WEATHER = 9; // 0x9
+    field public static final short LIGHT_SOURCE_FLASH = 4; // 0x4
+    field public static final short LIGHT_SOURCE_FLUORESCENT = 2; // 0x2
+    field public static final short LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN = 24; // 0x18
+    field public static final short LIGHT_SOURCE_OTHER = 255; // 0xff
+    field public static final short LIGHT_SOURCE_SHADE = 11; // 0xb
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_A = 17; // 0x11
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_B = 18; // 0x12
+    field public static final short LIGHT_SOURCE_STANDARD_LIGHT_C = 19; // 0x13
+    field public static final short LIGHT_SOURCE_TUNGSTEN = 3; // 0x3
+    field public static final short LIGHT_SOURCE_UNKNOWN = 0; // 0x0
+    field public static final short LIGHT_SOURCE_WARM_WHITE_FLUORESCENT = 16; // 0x10
+    field public static final short LIGHT_SOURCE_WHITE_FLUORESCENT = 15; // 0xf
+    field public static final java.lang.String LONGITUDE_EAST = "E";
+    field public static final java.lang.String LONGITUDE_WEST = "W";
+    field public static final short METERING_MODE_AVERAGE = 1; // 0x1
+    field public static final short METERING_MODE_CENTER_WEIGHT_AVERAGE = 2; // 0x2
+    field public static final short METERING_MODE_MULTI_SPOT = 4; // 0x4
+    field public static final short METERING_MODE_OTHER = 255; // 0xff
+    field public static final short METERING_MODE_PARTIAL = 6; // 0x6
+    field public static final short METERING_MODE_PATTERN = 5; // 0x5
+    field public static final short METERING_MODE_SPOT = 3; // 0x3
+    field public static final short METERING_MODE_UNKNOWN = 0; // 0x0
     field public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // 0x2
     field public static final int ORIENTATION_FLIP_VERTICAL = 4; // 0x4
     field public static final int ORIENTATION_NORMAL = 1; // 0x1
@@ -33,10 +131,52 @@
     field public static final int ORIENTATION_TRANSPOSE = 5; // 0x5
     field public static final int ORIENTATION_TRANSVERSE = 7; // 0x7
     field public static final int ORIENTATION_UNDEFINED = 0; // 0x0
+    field public static final int ORIGINAL_RESOLUTION_IMAGE = 0; // 0x0
+    field public static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1; // 0x1
+    field public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2; // 0x2
+    field public static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0; // 0x0
+    field public static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6; // 0x6
+    field public static final int REDUCED_RESOLUTION_IMAGE = 1; // 0x1
+    field public static final short RENDERED_PROCESS_CUSTOM = 1; // 0x1
+    field public static final short RENDERED_PROCESS_NORMAL = 0; // 0x0
+    field public static final short RESOLUTION_UNIT_CENTIMETERS = 3; // 0x3
+    field public static final short RESOLUTION_UNIT_INCHES = 2; // 0x2
+    field public static final short SATURATION_HIGH = 0; // 0x0
+    field public static final short SATURATION_LOW = 0; // 0x0
+    field public static final short SATURATION_NORMAL = 0; // 0x0
+    field public static final short SCENE_CAPTURE_TYPE_LANDSCAPE = 1; // 0x1
+    field public static final short SCENE_CAPTURE_TYPE_NIGHT = 3; // 0x3
+    field public static final short SCENE_CAPTURE_TYPE_PORTRAIT = 2; // 0x2
+    field public static final short SCENE_CAPTURE_TYPE_STANDARD = 0; // 0x0
+    field public static final short SCENE_TYPE_DIRECTLY_PHOTOGRAPHED = 1; // 0x1
+    field public static final short SENSITIVITY_TYPE_ISO_SPEED = 3; // 0x3
+    field public static final short SENSITIVITY_TYPE_REI = 2; // 0x2
+    field public static final short SENSITIVITY_TYPE_REI_AND_ISO = 6; // 0x6
+    field public static final short SENSITIVITY_TYPE_SOS = 1; // 0x1
+    field public static final short SENSITIVITY_TYPE_SOS_AND_ISO = 5; // 0x5
+    field public static final short SENSITIVITY_TYPE_SOS_AND_REI = 4; // 0x4
+    field public static final short SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO = 7; // 0x7
+    field public static final short SENSITIVITY_TYPE_UNKNOWN = 0; // 0x0
+    field public static final short SENSOR_TYPE_COLOR_SEQUENTIAL = 5; // 0x5
+    field public static final short SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR = 8; // 0x8
+    field public static final short SENSOR_TYPE_NOT_DEFINED = 1; // 0x1
+    field public static final short SENSOR_TYPE_ONE_CHIP = 2; // 0x2
+    field public static final short SENSOR_TYPE_THREE_CHIP = 4; // 0x4
+    field public static final short SENSOR_TYPE_TRILINEAR = 7; // 0x7
+    field public static final short SENSOR_TYPE_TWO_CHIP = 3; // 0x3
+    field public static final short SHARPNESS_HARD = 2; // 0x2
+    field public static final short SHARPNESS_NORMAL = 0; // 0x0
+    field public static final short SHARPNESS_SOFT = 1; // 0x1
+    field public static final short SUBJECT_DISTANCE_RANGE_CLOSE_VIEW = 2; // 0x2
+    field public static final short SUBJECT_DISTANCE_RANGE_DISTANT_VIEW = 3; // 0x3
+    field public static final short SUBJECT_DISTANCE_RANGE_MACRO = 1; // 0x1
+    field public static final short SUBJECT_DISTANCE_RANGE_UNKNOWN = 0; // 0x0
     field public static final java.lang.String TAG_APERTURE_VALUE = "ApertureValue";
     field public static final java.lang.String TAG_ARTIST = "Artist";
     field public static final java.lang.String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    field public static final java.lang.String TAG_BODY_SERIAL_NUMBER = "BodySerialNumber";
     field public static final java.lang.String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    field public static final java.lang.String TAG_CAMARA_OWNER_NAME = "CameraOwnerName";
     field public static final java.lang.String TAG_CFA_PATTERN = "CFAPattern";
     field public static final java.lang.String TAG_COLOR_SPACE = "ColorSpace";
     field public static final java.lang.String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
@@ -69,6 +209,7 @@
     field public static final java.lang.String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
     field public static final java.lang.String TAG_F_NUMBER = "FNumber";
     field public static final java.lang.String TAG_GAIN_CONTROL = "GainControl";
+    field public static final java.lang.String TAG_GAMMA = "Gamma";
     field public static final java.lang.String TAG_GPS_ALTITUDE = "GPSAltitude";
     field public static final java.lang.String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
     field public static final java.lang.String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
@@ -83,6 +224,7 @@
     field public static final java.lang.String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
     field public static final java.lang.String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
     field public static final java.lang.String TAG_GPS_DOP = "GPSDOP";
+    field public static final java.lang.String TAG_GPS_H_POSITIONING_ERROR = "GPSHPositioningError";
     field public static final java.lang.String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
     field public static final java.lang.String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
     field public static final java.lang.String TAG_GPS_LATITUDE = "GPSLatitude";
@@ -105,9 +247,16 @@
     field public static final java.lang.String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
     field public static final java.lang.String TAG_IMAGE_WIDTH = "ImageWidth";
     field public static final java.lang.String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
-    field public static final java.lang.String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    field public static final java.lang.String TAG_ISO_SPEED = "ISOSpeed";
+    field public static final java.lang.String TAG_ISO_SPEED_LATITUDE_YYY = "ISOSpeedLatitudeyyy";
+    field public static final java.lang.String TAG_ISO_SPEED_LATITUDE_ZZZ = "ISOSpeedLatitudezzz";
+    field public static final deprecated java.lang.String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
     field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
     field public static final java.lang.String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
+    field public static final java.lang.String TAG_LENS_MAKE = "LensMake";
+    field public static final java.lang.String TAG_LENS_MODEL = "LensModel";
+    field public static final java.lang.String TAG_LENS_SERIAL_NUMBER = "LensSerialNumber";
+    field public static final java.lang.String TAG_LENS_SPECIFICATION = "LensSpecification";
     field public static final java.lang.String TAG_LIGHT_SOURCE = "LightSource";
     field public static final java.lang.String TAG_MAKE = "Make";
     field public static final java.lang.String TAG_MAKER_NOTE = "MakerNote";
@@ -121,11 +270,13 @@
     field public static final java.lang.String TAG_ORF_PREVIEW_IMAGE_START = "PreviewImageStart";
     field public static final java.lang.String TAG_ORF_THUMBNAIL_IMAGE = "ThumbnailImage";
     field public static final java.lang.String TAG_ORIENTATION = "Orientation";
+    field public static final java.lang.String TAG_PHOTOGRAPHIC_SENSITIVITY = "PhotographicSensitivity";
     field public static final java.lang.String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
     field public static final java.lang.String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
     field public static final java.lang.String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
     field public static final java.lang.String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
     field public static final java.lang.String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    field public static final java.lang.String TAG_RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex";
     field public static final java.lang.String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
     field public static final java.lang.String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
     field public static final java.lang.String TAG_RESOLUTION_UNIT = "ResolutionUnit";
@@ -141,11 +292,13 @@
     field public static final java.lang.String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
     field public static final java.lang.String TAG_SCENE_TYPE = "SceneType";
     field public static final java.lang.String TAG_SENSING_METHOD = "SensingMethod";
+    field public static final java.lang.String TAG_SENSITIVITY_TYPE = "SensitivityType";
     field public static final java.lang.String TAG_SHARPNESS = "Sharpness";
     field public static final java.lang.String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
     field public static final java.lang.String TAG_SOFTWARE = "Software";
     field public static final java.lang.String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
     field public static final java.lang.String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    field public static final java.lang.String TAG_STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity";
     field public static final java.lang.String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
     field public static final java.lang.String TAG_STRIP_OFFSETS = "StripOffsets";
     field public static final java.lang.String TAG_SUBFILE_TYPE = "SubfileType";
@@ -167,8 +320,12 @@
     field public static final java.lang.String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
     field public static final java.lang.String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
     field public static final java.lang.String TAG_Y_RESOLUTION = "YResolution";
-    field public static final int WHITEBALANCE_AUTO = 0; // 0x0
-    field public static final int WHITEBALANCE_MANUAL = 1; // 0x1
+    field public static final deprecated int WHITEBALANCE_AUTO = 0; // 0x0
+    field public static final deprecated int WHITEBALANCE_MANUAL = 1; // 0x1
+    field public static final short WHITE_BALANCE_AUTO = 0; // 0x0
+    field public static final short WHITE_BALANCE_MANUAL = 1; // 0x1
+    field public static final short Y_CB_CR_POSITIONING_CENTERED = 1; // 0x1
+    field public static final short Y_CB_CR_POSITIONING_CO_SITED = 2; // 0x2
   }
 
 }
diff --git a/exifinterface/src/android/support/media/ExifInterface.java b/exifinterface/src/android/support/media/ExifInterface.java
index aa19cbe..6cde44e 100644
--- a/exifinterface/src/android/support/media/ExifInterface.java
+++ b/exifinterface/src/android/support/media/ExifInterface.java
@@ -68,256 +68,1974 @@
     private static final String TAG = "ExifInterface";
     private static final boolean DEBUG = false;
 
-    // The Exif tag names. See Tiff 6.0 Section 3 and Section 8.
-    /** Type is String. */
-    public static final String TAG_ARTIST = "Artist";
-    /** Type is int. */
-    public static final String TAG_BITS_PER_SAMPLE = "BitsPerSample";
-    /** Type is int. */
-    public static final String TAG_COMPRESSION = "Compression";
-    /** Type is String. */
-    public static final String TAG_COPYRIGHT = "Copyright";
-    /** Type is String. */
-    public static final String TAG_DATETIME = "DateTime";
-    /** Type is String. */
-    public static final String TAG_IMAGE_DESCRIPTION = "ImageDescription";
-    /** Type is int. */
-    public static final String TAG_IMAGE_LENGTH = "ImageLength";
-    /** Type is int. */
+    // The Exif tag names. See JEITA CP-3451C specifications (Exif 2.3) Section 3-8.
+    // A. Tags related to image data structure
+    /**
+     *  <p>The number of columns of image data, equal to the number of pixels per row. In JPEG
+     *  compressed data, this tag shall not be used because a JPEG marker is used instead of it.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 256</li>
+     *      <li>Type = Unsigned short or Unsigned long</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
     public static final String TAG_IMAGE_WIDTH = "ImageWidth";
-    /** Type is int. */
-    public static final String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
-    /** Type is int. */
-    public static final String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
-    /** Type is String. */
-    public static final String TAG_MAKE = "Make";
-    /** Type is String. */
-    public static final String TAG_MODEL = "Model";
-    /** Type is int. */
-    public static final String TAG_ORIENTATION = "Orientation";
-    /** Type is int. */
+    /**
+     *  <p>The number of rows of image data. In JPEG compressed data, this tag shall not be used
+     *  because a JPEG marker is used instead of it.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 257</li>
+     *      <li>Type = Unsigned short or Unsigned long</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_IMAGE_LENGTH = "ImageLength";
+    /**
+     *  <p>The number of bits per image component. In this standard each component of the image is
+     *  8 bits, so the value for this tag is 8. See also {@link #TAG_SAMPLES_PER_PIXEL}. In JPEG
+     *  compressed data, this tag shall not be used because a JPEG marker is used instead of it.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 258</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 3</li>
+     *      <li>Default = {@link #BITS_PER_SAMPLE_RGB}</li>
+     *  </ul>
+     */
+    public static final String TAG_BITS_PER_SAMPLE = "BitsPerSample";
+    /**
+     *  <p>The compression scheme used for the image data. When a primary image is JPEG compressed,
+     *  this designation is not necessary. So, this tag shall not be recorded. When thumbnails use
+     *  JPEG compression, this tag value is set to 6.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 259</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #DATA_UNCOMPRESSED
+     *  @see #DATA_JPEG
+     */
+    public static final String TAG_COMPRESSION = "Compression";
+    /**
+     *  <p>The pixel composition. In JPEG compressed data, this tag shall not be used because a JPEG
+     *  marker is used instead of it.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 262</li>
+     *      <li>Type = SHORT</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #PHOTOMETRIC_INTERPRETATION_RGB
+     *  @see #PHOTOMETRIC_INTERPRETATION_YCBCR
+     */
     public static final String TAG_PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation";
-    /** Type is int. */
-    public static final String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
-    /** Type is rational. */
-    public static final String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
-    /** Type is rational. */
-    public static final String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
-    /** Type is int. */
-    public static final String TAG_RESOLUTION_UNIT = "ResolutionUnit";
-    /** Type is int. */
-    public static final String TAG_ROWS_PER_STRIP = "RowsPerStrip";
-    /** Type is int. */
+    /**
+     *  <p>The image orientation viewed in terms of rows and columns.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 274</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #ORIENTATION_NORMAL}</li>
+     *  </ul>
+     *
+     *  @see #ORIENTATION_UNDEFINED
+     *  @see #ORIENTATION_NORMAL
+     *  @see #ORIENTATION_FLIP_HORIZONTAL
+     *  @see #ORIENTATION_ROTATE_180
+     *  @see #ORIENTATION_FLIP_VERTICAL
+     *  @see #ORIENTATION_TRANSPOSE
+     *  @see #ORIENTATION_ROTATE_90
+     *  @see #ORIENTATION_TRANSVERSE
+     *  @see #ORIENTATION_ROTATE_270
+     */
+    public static final String TAG_ORIENTATION = "Orientation";
+    /**
+     *  <p>The number of components per pixel. Since this standard applies to RGB and YCbCr images,
+     *  the value set for this tag is 3. In JPEG compressed data, this tag shall not be used because
+     *  a JPEG marker is used instead of it.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 277</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = 3</li>
+     *  </ul>
+     */
     public static final String TAG_SAMPLES_PER_PIXEL = "SamplesPerPixel";
-    /** Type is String. */
-    public static final String TAG_SOFTWARE = "Software";
-    /** Type is int. */
-    public static final String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
-    /** Type is int. */
-    public static final String TAG_STRIP_OFFSETS = "StripOffsets";
-    /** Type is int. */
-    public static final String TAG_TRANSFER_FUNCTION = "TransferFunction";
-    /** Type is rational. */
-    public static final String TAG_WHITE_POINT = "WhitePoint";
-    /** Type is rational. */
-    public static final String TAG_X_RESOLUTION = "XResolution";
-    /** Type is rational. */
-    public static final String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
-    /** Type is int. */
-    public static final String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
-    /** Type is int. */
+    /**
+     *  <p>Indicates whether pixel components are recorded in chunky or planar format. In JPEG
+     *  compressed data, this tag shall not be used because a JPEG marker is used instead of it.
+     *  If this field does not exist, the TIFF default, {@link #FORMAT_CHUNKY}, is assumed.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 284</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *  </ul>
+     *
+     *  @see #FORMAT_CHUNKY
+     *  @see #FORMAT_PLANAR
+     */
+    public static final String TAG_PLANAR_CONFIGURATION = "PlanarConfiguration";
+    /**
+     *  <p>The sampling ratio of chrominance components in relation to the luminance component.
+     *  In JPEG compressed data a JPEG marker is used instead of this tag. So, this tag shall not
+     *  be recorded.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 530</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 2</li>
+     *      <ul>
+     *          <li>[2, 1] = YCbCr4:2:2</li>
+     *          <li>[2, 2] = YCbCr4:2:0</li>
+     *          <li>Other = reserved</li>
+     *      </ul>
+     *  </ul>
+     */
     public static final String TAG_Y_CB_CR_SUB_SAMPLING = "YCbCrSubSampling";
-    /** Type is rational. */
+    /**
+     *  <p>The position of chrominance components in relation to the luminance component. This field
+     *  is designated only for JPEG compressed data or uncompressed YCbCr data. The TIFF default is
+     *  {@link #Y_CB_CR_POSITIONING_CENTERED}; but when Y:Cb:Cr = 4:2:2 it is recommended in this
+     *  standard that {@link #Y_CB_CR_POSITIONING_CO_SITED} be used to record data, in order to
+     *  improve the image quality when viewed on TV systems. When this field does not exist,
+     *  the reader shall assume the TIFF default. In the case of Y:Cb:Cr = 4:2:0, the TIFF default
+     *  ({@link #Y_CB_CR_POSITIONING_CENTERED}) is recommended. If the Exif/DCF reader does not
+     *  have the capability of supporting both kinds of positioning, it shall follow the TIFF
+     *  default regardless of the value in this field. It is preferable that readers can support
+     *  both centered and co-sited positioning.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 531</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #Y_CB_CR_POSITIONING_CENTERED}</li>
+     *  </ul>
+     *
+     *  @see #Y_CB_CR_POSITIONING_CENTERED
+     *  @see #Y_CB_CR_POSITIONING_CO_SITED
+     */
+    public static final String TAG_Y_CB_CR_POSITIONING = "YCbCrPositioning";
+    /**
+     *  <p>The number of pixels per {@link #TAG_RESOLUTION_UNIT} in the {@link #TAG_IMAGE_WIDTH}
+     *  direction. When the image resolution is unknown, 72 [dpi] shall be designated.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 282</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = 72</li>
+     *  </ul>
+     *
+     *  @see #TAG_Y_RESOLUTION
+     *  @see #TAG_RESOLUTION_UNIT
+     */
+    public static final String TAG_X_RESOLUTION = "XResolution";
+    /**
+     *  <p>The number of pixels per {@link #TAG_RESOLUTION_UNIT} in the {@link #TAG_IMAGE_WIDTH}
+     *  direction. The same value as {@link #TAG_X_RESOLUTION} shall be designated.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 283</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = 72</li>
+     *  </ul>
+     *
+     *  @see #TAG_X_RESOLUTION
+     *  @see #TAG_RESOLUTION_UNIT
+     */
     public static final String TAG_Y_RESOLUTION = "YResolution";
-    /** Type is rational. */
-    public static final String TAG_APERTURE_VALUE = "ApertureValue";
-    /** Type is rational. */
-    public static final String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
-    /** Type is String. */
-    public static final String TAG_CFA_PATTERN = "CFAPattern";
-    /** Type is int. */
-    public static final String TAG_COLOR_SPACE = "ColorSpace";
-    /** Type is String. */
-    public static final String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
-    /** Type is rational. */
-    public static final String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
-    /** Type is int. */
-    public static final String TAG_CONTRAST = "Contrast";
-    /** Type is int. */
-    public static final String TAG_CUSTOM_RENDERED = "CustomRendered";
-    /** Type is String. */
-    public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
-    /** Type is String. */
-    public static final String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
-    /** Type is String. */
-    public static final String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
-    /** Type is double. */
-    public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
-    /** Type is String. */
+    /**
+     *  <p>The unit for measuring {@link #TAG_X_RESOLUTION} and {@link #TAG_Y_RESOLUTION}. The same
+     *  unit is used for both {@link #TAG_X_RESOLUTION} and {@link #TAG_Y_RESOLUTION}. If the image
+     *  resolution is unknown, {@link #RESOLUTION_UNIT_INCHES} shall be designated.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 296</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #RESOLUTION_UNIT_INCHES}</li>
+     *  </ul>
+     *
+     *  @see #RESOLUTION_UNIT_INCHES
+     *  @see #RESOLUTION_UNIT_CENTIMETERS
+     *  @see #TAG_X_RESOLUTION
+     *  @see #TAG_Y_RESOLUTION
+     */
+    public static final String TAG_RESOLUTION_UNIT = "ResolutionUnit";
+
+    // B. Tags related to recording offset
+    /**
+     *  <p>For each strip, the byte offset of that strip. It is recommended that this be selected
+     *  so the number of strip bytes does not exceed 64 KBytes.In the case of JPEG compressed data,
+     *  this designation is not necessary. So, this tag shall not be recorded.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 273</li>
+     *      <li>Type = Unsigned short or Unsigned long</li>
+     *      <li>Count = StripsPerImage (for {@link #FORMAT_CHUNKY})
+     *               or {@link #TAG_SAMPLES_PER_PIXEL} * StripsPerImage
+     *               (for {@link #FORMAT_PLANAR})</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  <p>StripsPerImage = floor(({@link #TAG_IMAGE_LENGTH} + {@link #TAG_ROWS_PER_STRIP} - 1)
+     *  / {@link #TAG_ROWS_PER_STRIP})</p>
+     *
+     *  @see #TAG_ROWS_PER_STRIP
+     *  @see #TAG_STRIP_BYTE_COUNTS
+     */
+    public static final String TAG_STRIP_OFFSETS = "StripOffsets";
+    /**
+     *  <p>The number of rows per strip. This is the number of rows in the image of one strip when
+     *  an image is divided into strips. In the case of JPEG compressed data, this designation is
+     *  not necessary. So, this tag shall not be recorded.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 278</li>
+     *      <li>Type = Unsigned short or Unsigned long</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #TAG_STRIP_OFFSETS
+     *  @see #TAG_STRIP_BYTE_COUNTS
+     */
+    public static final String TAG_ROWS_PER_STRIP = "RowsPerStrip";
+    /**
+     *  <p>The total number of bytes in each strip. In the case of JPEG compressed data, this
+     *  designation is not necessary. So, this tag shall not be recorded.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 279</li>
+     *      <li>Type = Unsigned short or Unsigned long</li>
+     *      <li>Count = StripsPerImage (when using {@link #FORMAT_CHUNKY})
+     *               or {@link #TAG_SAMPLES_PER_PIXEL} * StripsPerImage
+     *               (when using {@link #FORMAT_PLANAR})</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  <p>StripsPerImage = floor(({@link #TAG_IMAGE_LENGTH} + {@link #TAG_ROWS_PER_STRIP} - 1)
+     *  / {@link #TAG_ROWS_PER_STRIP})</p>
+     */
+    public static final String TAG_STRIP_BYTE_COUNTS = "StripByteCounts";
+    /**
+     *  <p>The offset to the start byte (SOI) of JPEG compressed thumbnail data. This shall not be
+     *  used for primary image JPEG data.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 513</li>
+     *      <li>Type = Unsigned long</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat";
+    /**
+     *  <p>The number of bytes of JPEG compressed thumbnail data. This is not used for primary image
+     *  JPEG data. JPEG thumbnails are not divided but are recorded as a continuous JPEG bitstream
+     *  from SOI to EOI. APPn and COM markers should not be recorded. Compressed thumbnails shall be
+     *  recorded in no more than 64 KBytes, including all other data to be recorded in APP1.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 514</li>
+     *      <li>Type = Unsigned long</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength";
+
+    // C. Tags related to Image Data Characteristics
+    /**
+     *  <p>A transfer function for the image, described in tabular style. Normally this tag need not
+     *  be used, since color space is specified in {@link #TAG_COLOR_SPACE}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 301</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 3 * 256</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_TRANSFER_FUNCTION = "TransferFunction";
+    /**
+     *  <p>The chromaticity of the white point of the image. Normally this tag need not be used,
+     *  since color space is specified in {@link #TAG_COLOR_SPACE}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 318</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 2</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_WHITE_POINT = "WhitePoint";
+    /**
+     *  <p>The chromaticity of the three primary colors of the image. Normally this tag need not
+     *  be used, since color space is specified in {@link #TAG_COLOR_SPACE}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 319</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 6</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_PRIMARY_CHROMATICITIES = "PrimaryChromaticities";
+    /**
+     *  <p>The matrix coefficients for transformation from RGB to YCbCr image data. About
+     *  the default value, please refer to JEITA CP-3451C Spec, Annex D.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 529</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 3</li>
+     *  </ul>
+     */
+    public static final String TAG_Y_CB_CR_COEFFICIENTS = "YCbCrCoefficients";
+    /**
+     *  <p>The reference black point value and reference white point value. No defaults are given
+     *  in TIFF, but the values below are given as defaults here. The color space is declared in
+     *  a color space information tag, with the default being the value that gives the optimal image
+     *  characteristics Interoperability these conditions</p>
+     *
+     *  <ul>
+     *      <li>Tag = 532</li>
+     *      <li>Type = RATIONAL</li>
+     *      <li>Count = 6</li>
+     *      <li>Default = [0, 255, 0, 255, 0, 255] (when {@link #TAG_PHOTOMETRIC_INTERPRETATION}
+     *                 is {@link #PHOTOMETRIC_INTERPRETATION_RGB})
+     *                 or [0, 255, 0, 128, 0, 128] (when {@link #TAG_PHOTOMETRIC_INTERPRETATION}
+     *                 is {@link #PHOTOMETRIC_INTERPRETATION_YCBCR})</li>
+     *  </ul>
+     */
+    public static final String TAG_REFERENCE_BLACK_WHITE = "ReferenceBlackWhite";
+
+    // D. Other tags
+    /**
+     *  <p>The date and time of image creation. In this standard it is the date and time the file
+     *  was changed. The format is "YYYY:MM:DD HH:MM:SS" with time shown in 24-hour format, and
+     *  the date and time separated by one blank character ({@code 0x20}). When the date and time
+     *  are unknown, all the character spaces except colons (":") should be filled with blank
+     *  characters, or else the Interoperability field should be filled with blank characters.
+     *  The character string length is 20 Bytes including NULL for termination. When the field is
+     *  left blank, it is treated as unknown.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 306</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 19</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_DATETIME = "DateTime";
+    /**
+     *  <p>An ASCII string giving the title of the image. It is possible to be added a comment
+     *  such as "1988 company picnic" or the like. Two-byte character codes cannot be used. When
+     *  a 2-byte code is necessary, {@link #TAG_USER_COMMENT} is to be used.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 270</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_IMAGE_DESCRIPTION = "ImageDescription";
+    /**
+     *  <p>The manufacturer of the recording equipment. This is the manufacturer of the DSC,
+     *  scanner, video digitizer or other equipment that generated the image. When the field is left
+     *  blank, it is treated as unknown.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 271</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_MAKE = "Make";
+    /**
+     *  <p>The model name or model number of the equipment. This is the model name of number of
+     *  the DSC, scanner, video digitizer or other equipment that generated the image. When
+     *  the field is left blank, it is treated as unknown.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 272</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_MODEL = "Model";
+    /**
+     *  <p>This tag records the name and version of the software or firmware of the camera or image
+     *  input device used to generate the image. The detailed format is not specified, but it is
+     *  recommended that the example shown below be followed. When the field is left blank, it is
+     *  treated as unknown.</p>
+     *
+     *  <p>Ex.) "Exif Software Version 1.00a".</p>
+     *
+     *  <ul>
+     *      <li>Tag = 305</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_SOFTWARE = "Software";
+    /**
+     *  <p>This tag records the name of the camera owner, photographer or image creator.
+     *  The detailed format is not specified, but it is recommended that the information be written
+     *  as in the example below for ease of Interoperability. When the field is left blank, it is
+     *  treated as unknown.</p>
+     *
+     *  <p>Ex.) "Camera owner, John Smith; Photographer, Michael Brown; Image creator,
+     *  Ken James"</p>
+     *
+     *  <ul>
+     *      <li>Tag = 315</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_ARTIST = "Artist";
+    /**
+     *  <p>Copyright information. In this standard the tag is used to indicate both the photographer
+     *  and editor copyrights. It is the copyright notice of the person or organization claiming
+     *  rights to the image. The Interoperability copyright statement including date and rights
+     *  should be written in this field; e.g., "Copyright, John Smith, 19xx. All rights reserved."
+     *  In this standard the field records both the photographer and editor copyrights, with each
+     *  recorded in a separate part of the statement. When there is a clear distinction between
+     *  the photographer and editor copyrights, these are to be written in the order of photographer
+     *  followed by editor copyright, separated by NULL (in this case, since the statement also ends
+     *  with a NULL, there are two NULL codes) (see example 1). When only the photographer copyright
+     *  is given, it is terminated by one NULL code (see example 2). When only the editor copyright
+     *  is given, the photographer copyright part consists of one space followed by a terminating
+     *  NULL code, then the editor copyright is given (see example 3). When the field is left blank,
+     *  it is treated as unknown.</p>
+     *
+     *  <p>Ex. 1) When both the photographer copyright and editor copyright are given.
+     *  <ul><li>Photographer copyright + NULL + editor copyright + NULL</li></ul></p>
+     *  <p>Ex. 2) When only the photographer copyright is given.
+     *  <ul><li>Photographer copyright + NULL</li></ul></p>
+     *  <p>Ex. 3) When only the editor copyright is given.
+     *  <ul><li>Space ({@code 0x20}) + NULL + editor copyright + NULL</li></ul></p>
+     *
+     *  <ul>
+     *      <li>Tag = 315</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_COPYRIGHT = "Copyright";
+
+    // Exif IFD Attribute Information
+    // A. Tags related to version
+    /**
+     *  <p>The version of this standard supported. Nonexistence of this field is taken to mean
+     *  nonconformance to the standard. In according with conformance to this standard, this tag
+     *  shall be recorded like "0230” as 4-byte ASCII.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 36864</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Length = 4</li>
+     *      <li>Default = "0230"</li>
+     *  </ul>
+     */
     public static final String TAG_EXIF_VERSION = "ExifVersion";
-    /** Type is double. */
-    public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
-    /** Type is rational. */
-    public static final String TAG_EXPOSURE_INDEX = "ExposureIndex";
-    /** Type is int. */
-    public static final String TAG_EXPOSURE_MODE = "ExposureMode";
-    /** Type is int. */
-    public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
-    /** Type is double. */
-    public static final String TAG_EXPOSURE_TIME = "ExposureTime";
-    /** Type is double. */
-    public static final String TAG_F_NUMBER = "FNumber";
-    /** Type is String. */
-    public static final String TAG_FILE_SOURCE = "FileSource";
-    /** Type is int. */
-    public static final String TAG_FLASH = "Flash";
-    /** Type is rational. */
-    public static final String TAG_FLASH_ENERGY = "FlashEnergy";
-    /** Type is String. */
+    /**
+     *  <p>The Flashpix format version supported by a FPXR file. If the FPXR function supports
+     *  Flashpix format Ver. 1.0, this is indicated similarly to {@link #TAG_EXIF_VERSION} by
+     *  recording "0100" as 4-byte ASCII.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 40960</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Length = 4</li>
+     *      <li>Default = "0100"</li>
+     *  </ul>
+     */
     public static final String TAG_FLASHPIX_VERSION = "FlashpixVersion";
-    /** Type is rational. */
-    public static final String TAG_FOCAL_LENGTH = "FocalLength";
-    /** Type is int. */
-    public static final String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
-    /** Type is int. */
-    public static final String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
-    /** Type is rational. */
-    public static final String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
-    /** Type is rational. */
-    public static final String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
-    /** Type is int. */
-    public static final String TAG_GAIN_CONTROL = "GainControl";
-    /** Type is int. */
-    public static final String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
-    /** Type is String. */
-    public static final String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
-    /** Type is int. */
-    public static final String TAG_LIGHT_SOURCE = "LightSource";
-    /** Type is String. */
-    public static final String TAG_MAKER_NOTE = "MakerNote";
-    /** Type is rational. */
-    public static final String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
-    /** Type is int. */
-    public static final String TAG_METERING_MODE = "MeteringMode";
-    /** Type is int. */
-    public static final String TAG_NEW_SUBFILE_TYPE = "NewSubfileType";
-    /** Type is String. */
-    public static final String TAG_OECF = "OECF";
-    /** Type is int. */
+
+    // B. Tags related to image data characteristics
+    /**
+     *  <p>The color space information tag is always recorded as the color space specifier.
+     *  Normally {@link #COLOR_SPACE_S_RGB} is used to define the color space based on the PC
+     *  monitor conditions and environment. If a color space other than {@link #COLOR_SPACE_S_RGB}
+     *  is used, {@link #COLOR_SPACE_UNCALIBRATED} is set. Image data recorded as
+     *  {@link #COLOR_SPACE_UNCALIBRATED} may be treated as {@link #COLOR_SPACE_S_RGB} when it is
+     *  converted to Flashpix.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 40961</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *  </ul>
+     *
+     *  @see #COLOR_SPACE_S_RGB
+     *  @see #COLOR_SPACE_UNCALIBRATED
+     */
+    public static final String TAG_COLOR_SPACE = "ColorSpace";
+    /**
+     *  <p>Indicates the value of coefficient gamma. The formula of transfer function used for image
+     *  reproduction is expressed as follows.</p>
+     *
+     *  <p>(Reproduced value) = (Input value) ^ gamma</p>
+     *
+     *  <p>Both reproduced value and input value indicate normalized value, whose minimum value is
+     *  0 and maximum value is 1.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 42240</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GAMMA = "Gamma";
+
+    // C. Tags related to image configuration
+    /**
+     *  <p>Information specific to compressed data. When a compressed file is recorded, the valid
+     *  width of the meaningful image shall be recorded in this tag, whether or not there is padding
+     *  data or a restart marker. This tag shall not exist in an uncompressed file.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 40962</li>
+     *      <li>Type = Unsigned short or Unsigned long</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
     public static final String TAG_PIXEL_X_DIMENSION = "PixelXDimension";
-    /** Type is int. */
+    /**
+     *  <p>Information specific to compressed data. When a compressed file is recorded, the valid
+     *  height of the meaningful image shall be recorded in this tag, whether or not there is
+     *  padding data or a restart marker. This tag shall not exist in an uncompressed file.
+     *  Since data padding is unnecessary in the vertical direction, the number of lines recorded
+     *  in this valid image height tag will in fact be the same as that recorded in the SOF.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 40963</li>
+     *      <li>Type = Unsigned short or Unsigned long</li>
+     *      <li>Count = 1</li>
+     *  </ul>
+     */
     public static final String TAG_PIXEL_Y_DIMENSION = "PixelYDimension";
-    /** Type is String. */
-    public static final String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
-    /** Type is int. */
-    public static final String TAG_SATURATION = "Saturation";
-    /** Type is int. */
-    public static final String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
-    /** Type is String. */
-    public static final String TAG_SCENE_TYPE = "SceneType";
-    /** Type is int. */
-    public static final String TAG_SENSING_METHOD = "SensingMethod";
-    /** Type is int. */
-    public static final String TAG_SHARPNESS = "Sharpness";
-    /** Type is rational. */
-    public static final String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
-    /** Type is String. */
-    public static final String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
-    /** Type is String. */
-    public static final String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
-    /** Type is int. */
-    public static final String TAG_SUBFILE_TYPE = "SubfileType";
-    /** Type is String. */
-    public static final String TAG_SUBSEC_TIME = "SubSecTime";
-    /** Type is String. */
-    public static final String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
-    /** Type is String. */
-    public static final String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
-    /** Type is int. */
-    public static final String TAG_SUBJECT_AREA = "SubjectArea";
-    /** Type is double. */
-    public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
-    /** Type is int. */
-    public static final String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
-    /** Type is int. */
-    public static final String TAG_SUBJECT_LOCATION = "SubjectLocation";
-    /** Type is String. */
+    /**
+     *  <p>Information specific to compressed data. The channels of each component are arranged
+     *  in order from the 1st component to the 4th. For uncompressed data the data arrangement is
+     *  given in the {@link #TAG_PHOTOMETRIC_INTERPRETATION}. However, since
+     *  {@link #TAG_PHOTOMETRIC_INTERPRETATION} can only express the order of Y, Cb and Cr, this tag
+     *  is provided for cases when compressed data uses components other than Y, Cb, and Cr and to
+     *  enable support of other sequences.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37121</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Length = 4</li>
+     *      <li>Default = 4 5 6 0 (if RGB uncompressed) or 1 2 3 0 (other cases)</li>
+     *      <ul>
+     *          <li>0 = does not exist</li>
+     *          <li>1 = Y</li>
+     *          <li>2 = Cb</li>
+     *          <li>3 = Cr</li>
+     *          <li>4 = R</li>
+     *          <li>5 = G</li>
+     *          <li>6 = B</li>
+     *          <li>other = reserved</li>
+     *      </ul>
+     *  </ul>
+     */
+    public static final String TAG_COMPONENTS_CONFIGURATION = "ComponentsConfiguration";
+    /**
+     *  <p>Information specific to compressed data. The compression mode used for a compressed image
+     *  is indicated in unit bits per pixel.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37122</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel";
+
+    // D. Tags related to user information
+    /**
+     *  <p>A tag for manufacturers of Exif/DCF writers to record any desired information.
+     *  The contents are up to the manufacturer, but this tag shall not be used for any other than
+     *  its intended purpose.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37500</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_MAKER_NOTE = "MakerNote";
+    /**
+     *  <p>A tag for Exif users to write keywords or comments on the image besides those in
+     *  {@link #TAG_IMAGE_DESCRIPTION}, and without the character code limitations of it.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37510</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
     public static final String TAG_USER_COMMENT = "UserComment";
-    /** Type is int. */
+
+    // E. Tags related to related file information
+    /**
+     *  <p>This tag is used to record the name of an audio file related to the image data. The only
+     *  relational information recorded here is the Exif audio file name and extension (an ASCII
+     *  string consisting of 8 characters + '.' + 3 characters). The path is not recorded.</p>
+     *
+     *  <p>When using this tag, audio files shall be recorded in conformance to the Exif audio
+     *  format. Writers can also store the data such as Audio within APP2 as Flashpix extension
+     *  stream data. Audio files shall be recorded in conformance to the Exif audio format.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 40964</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 12</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_RELATED_SOUND_FILE = "RelatedSoundFile";
+
+    // F. Tags related to date and time
+    /**
+     *  <p>The date and time when the original image data was generated. For a DSC the date and time
+     *  the picture was taken are recorded. The format is "YYYY:MM:DD HH:MM:SS" with time shown in
+     *  24-hour format, and the date and time separated by one blank character ({@code 0x20}).
+     *  When the date and time are unknown, all the character spaces except colons (":") should be
+     *  filled with blank characters, or else the Interoperability field should be filled with blank
+     *  characters. When the field is left blank, it is treated as unknown.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 36867</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 19</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_DATETIME_ORIGINAL = "DateTimeOriginal";
+    /**
+     *  <p>The date and time when the image was stored as digital data. If, for example, an image
+     *  was captured by DSC and at the same time the file was recorded, then
+     *  {@link #TAG_DATETIME_ORIGINAL} and this tag will have the same contents. The format is
+     *  "YYYY:MM:DD HH:MM:SS" with time shown in 24-hour format, and the date and time separated by
+     *  one blank character ({@code 0x20}). When the date and time are unknown, all the character
+     *  spaces except colons (":")should be filled with blank characters, or else
+     *  the Interoperability field should be filled with blank characters. When the field is left
+     *  blank, it is treated as unknown.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 36868</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 19</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_DATETIME_DIGITIZED = "DateTimeDigitized";
+    /**
+     *  <p>A tag used to record fractions of seconds for {@link #TAG_DATETIME}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37520</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_SUBSEC_TIME = "SubSecTime";
+    /**
+     *  <p>A tag used to record fractions of seconds for {@link #TAG_DATETIME_ORIGINAL}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37521</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_SUBSEC_TIME_ORIGINAL = "SubSecTimeOriginal";
+    /**
+     *  <p>A tag used to record fractions of seconds for {@link #TAG_DATETIME_DIGITIZED}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37522</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_SUBSEC_TIME_DIGITIZED = "SubSecTimeDigitized";
+
+    // G. Tags related to picture-taking condition
+    /**
+     *  <p>Exposure time, given in seconds.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 33434</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_EXPOSURE_TIME = "ExposureTime";
+    /**
+     *  <p>The F number.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 33437</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_F_NUMBER = "FNumber";
+    /**
+     *  <p>TThe class of the program used by the camera to set exposure when the picture is taken.
+     *  The tag values are as follows.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 34850</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #EXPOSURE_PROGRAM_NOT_DEFINED}</li>
+     *  </ul>
+     *
+     *  @see #EXPOSURE_PROGRAM_NOT_DEFINED
+     *  @see #EXPOSURE_PROGRAM_MANUAL
+     *  @see #EXPOSURE_PROGRAM_NORMAL
+     *  @see #EXPOSURE_PROGRAM_APERTURE_PRIORITY
+     *  @see #EXPOSURE_PROGRAM_SHUTTER_PRIORITY
+     *  @see #EXPOSURE_PROGRAM_CREATIVE
+     *  @see #EXPOSURE_PROGRAM_ACTION
+     *  @see #EXPOSURE_PROGRAM_PORTRAIT_MODE
+     *  @see #EXPOSURE_PROGRAM_LANDSCAPE_MODE
+     */
+    public static final String TAG_EXPOSURE_PROGRAM = "ExposureProgram";
+    /**
+     *  <p>Indicates the spectral sensitivity of each channel of the camera used. The tag value is
+     *  an ASCII string compatible with the standard developed by the ASTM Technical committee.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 34852</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_SPECTRAL_SENSITIVITY = "SpectralSensitivity";
+    /**
+     *  @deprecated Use {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} instead.
+     *  @see #TAG_PHOTOGRAPHIC_SENSITIVITY
+     */
+    @Deprecated public static final String TAG_ISO_SPEED_RATINGS = "ISOSpeedRatings";
+    /**
+     *  <p>This tag indicates the sensitivity of the camera or input device when the image was shot.
+     *  More specifically, it indicates one of the following values that are parameters defined in
+     *  ISO 12232: standard output sensitivity (SOS), recommended exposure index (REI), or ISO
+     *  speed. Accordingly, if a tag corresponding to a parameter that is designated by
+     *  {@link #TAG_SENSITIVITY_TYPE} is recorded, the values of the tag and of this tag are
+     *  the same. However, if the value is 65535 or higher, the value of this tag shall be 65535.
+     *  When recording this tag, {@link #TAG_SENSITIVITY_TYPE} should also be recorded. In addition,
+     *  while “Count = Any”, only 1 count should be used when recording this tag.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 34855</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = Any</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_PHOTOGRAPHIC_SENSITIVITY = "PhotographicSensitivity";
+    /**
+     *  <p>Indicates the Opto-Electric Conversion Function (OECF) specified in ISO 14524. OECF is
+     *  the relationship between the camera optical input and the image values.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 34856</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_OECF = "OECF";
+    /**
+     *  <p>This tag indicates which one of the parameters of ISO12232 is
+     *  {@link #TAG_PHOTOGRAPHIC_SENSITIVITY}. Although it is an optional tag, it should be recorded
+     *  when {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} is recorded.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 34864</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #SENSITIVITY_TYPE_UNKNOWN
+     *  @see #SENSITIVITY_TYPE_SOS
+     *  @see #SENSITIVITY_TYPE_REI
+     *  @see #SENSITIVITY_TYPE_ISO_SPEED
+     *  @see #SENSITIVITY_TYPE_SOS_AND_REI
+     *  @see #SENSITIVITY_TYPE_SOS_AND_ISO
+     *  @see #SENSITIVITY_TYPE_REI_AND_ISO
+     *  @see #SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO
+     */
+    public static final String TAG_SENSITIVITY_TYPE = "SensitivityType";
+    /**
+     *  <p>This tag indicates the standard output sensitivity value of a camera or input device
+     *  defined in ISO 12232. When recording this tag, {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} and
+     *  {@link #TAG_SENSITIVITY_TYPE} shall also be recorded.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 34865</li>
+     *      <li>Type = Unsigned long</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity";
+    /**
+     *  <p>This tag indicates the recommended exposure index value of a camera or input device
+     *  defined in ISO 12232. When recording this tag, {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} and
+     *  {@link #TAG_SENSITIVITY_TYPE} shall also be recorded.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 34866</li>
+     *      <li>Type = Unsigned long</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex";
+    /**
+     *  <p>This tag indicates the ISO speed value of a camera or input device that is defined in
+     *  ISO 12232. When recording this tag, {@link #TAG_PHOTOGRAPHIC_SENSITIVITY} and
+     *  {@link #TAG_SENSITIVITY_TYPE} shall also be recorded.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 34867</li>
+     *      <li>Type = Unsigned long</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_ISO_SPEED = "ISOSpeed";
+    /**
+     *  <p>This tag indicates the ISO speed latitude yyy value of a camera or input device that is
+     *  defined in ISO 12232. However, this tag shall not be recorded without {@link #TAG_ISO_SPEED}
+     *  and {@link #TAG_ISO_SPEED_LATITUDE_ZZZ}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 34868</li>
+     *      <li>Type = Unsigned long</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_ISO_SPEED_LATITUDE_YYY = "ISOSpeedLatitudeyyy";
+    /**
+     *  <p>This tag indicates the ISO speed latitude zzz value of a camera or input device that is
+     *  defined in ISO 12232. However, this tag shall not be recorded without {@link #TAG_ISO_SPEED}
+     *  and {@link #TAG_ISO_SPEED_LATITUDE_YYY}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 34869</li>
+     *      <li>Type = Unsigned long</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_ISO_SPEED_LATITUDE_ZZZ = "ISOSpeedLatitudezzz";
+    /**
+     *  <p>Shutter speed. The unit is the APEX setting.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37377</li>
+     *      <li>Type = Signed rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_SHUTTER_SPEED_VALUE = "ShutterSpeedValue";
+    /**
+     *  <p>The lens aperture. The unit is the APEX value.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37378</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_APERTURE_VALUE = "ApertureValue";
+    /**
+     *  <p>The value of brightness. The unit is the APEX value. Ordinarily it is given in the range
+     *  of -99.99 to 99.99. Note that if the numerator of the recorded value is 0xFFFFFFFF,
+     *  Unknown shall be indicated.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37379</li>
+     *      <li>Type = Signed rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_BRIGHTNESS_VALUE = "BrightnessValue";
+    /**
+     *  <p>The exposure bias. The unit is the APEX value. Ordinarily it is given in the range of
+     *  -99.99 to 99.99.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37380</li>
+     *      <li>Type = Signed rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_EXPOSURE_BIAS_VALUE = "ExposureBiasValue";
+    /**
+     *  <p>The smallest F number of the lens. The unit is the APEX value. Ordinarily it is given
+     *  in the range of 00.00 to 99.99, but it is not limited to this range.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37381</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_MAX_APERTURE_VALUE = "MaxApertureValue";
+    /**
+     *  <p>The distance to the subject, given in meters. Note that if the numerator of the recorded
+     *  value is 0xFFFFFFFF, Infinity shall be indicated; and if the numerator is 0, Distance
+     *  unknown shall be indicated.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37382</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_SUBJECT_DISTANCE = "SubjectDistance";
+    /**
+     *  <p>The metering mode.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37383</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #METERING_MODE_UNKNOWN}</li>
+     *  </ul>
+     *
+     *  @see #METERING_MODE_UNKNOWN
+     *  @see #METERING_MODE_AVERAGE
+     *  @see #METERING_MODE_CENTER_WEIGHT_AVERAGE
+     *  @see #METERING_MODE_SPOT
+     *  @see #METERING_MODE_MULTI_SPOT
+     *  @see #METERING_MODE_PATTERN
+     *  @see #METERING_MODE_PARTIAL
+     *  @see #METERING_MODE_OTHER
+     */
+    public static final String TAG_METERING_MODE = "MeteringMode";
+    /**
+     *  <p>The kind of light source.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37384</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #LIGHT_SOURCE_UNKNOWN}</li>
+     *  </ul>
+     *
+     *  @see #LIGHT_SOURCE_UNKNOWN
+     *  @see #LIGHT_SOURCE_DAYLIGHT
+     *  @see #LIGHT_SOURCE_FLUORESCENT
+     *  @see #LIGHT_SOURCE_TUNGSTEN
+     *  @see #LIGHT_SOURCE_FLASH
+     *  @see #LIGHT_SOURCE_FINE_WEATHER
+     *  @see #LIGHT_SOURCE_CLOUDY_WEATHER
+     *  @see #LIGHT_SOURCE_SHADE
+     *  @see #LIGHT_SOURCE_DAYLIGHT_FLUORESCENT
+     *  @see #LIGHT_SOURCE_DAY_WHITE_FLUORESCENT
+     *  @see #LIGHT_SOURCE_COOL_WHITE_FLUORESCENT
+     *  @see #LIGHT_SOURCE_WHITE_FLUORESCENT
+     *  @see #LIGHT_SOURCE_WARM_WHITE_FLUORESCENT
+     *  @see #LIGHT_SOURCE_STANDARD_LIGHT_A
+     *  @see #LIGHT_SOURCE_STANDARD_LIGHT_B
+     *  @see #LIGHT_SOURCE_STANDARD_LIGHT_C
+     *  @see #LIGHT_SOURCE_D55
+     *  @see #LIGHT_SOURCE_D65
+     *  @see #LIGHT_SOURCE_D75
+     *  @see #LIGHT_SOURCE_D50
+     *  @see #LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN
+     *  @see #LIGHT_SOURCE_OTHER
+     */
+    public static final String TAG_LIGHT_SOURCE = "LightSource";
+    /**
+     *  <p>This tag indicates the status of flash when the image was shot. Bit 0 indicates the flash
+     *  firing status, bits 1 and 2 indicate the flash return status, bits 3 and 4 indicate
+     *  the flash mode, bit 5 indicates whether the flash function is present, and bit 6 indicates
+     *  "red eye" mode.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37385</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *  </ul>
+     *
+     *  @see #FLAG_FLASH_FIRED
+     *  @see #FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED
+     *  @see #FLAG_FLASH_RETURN_LIGHT_DETECTED
+     *  @see #FLAG_FLASH_MODE_COMPULSORY_FIRING
+     *  @see #FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION
+     *  @see #FLAG_FLASH_MODE_AUTO
+     *  @see #FLAG_FLASH_NO_FLASH_FUNCTION
+     *  @see #FLAG_FLASH_RED_EYE_SUPPORTED
+     */
+    public static final String TAG_FLASH = "Flash";
+    /**
+     *  <p>This tag indicates the location and area of the main subject in the overall scene.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37396</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 2 or 3 or 4</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  <p>The subject location and area are defined by Count values as follows.</p>
+     *
+     *  <ul>
+     *      <li>Count = 2 Indicates the location of the main subject as coordinates. The first value
+     *                    is the X coordinate and the second is the Y coordinate.</li>
+     *      <li>Count = 3 The area of the main subject is given as a circle. The circular area is
+     *                    expressed as center coordinates and diameter. The first value is
+     *                    the center X coordinate, the second is the center Y coordinate, and
+     *                    the third is the diameter.</li>
+     *      <li>Count = 4 The area of the main subject is given as a rectangle. The rectangular
+     *                    area is expressed as center coordinates and area dimensions. The first
+     *                    value is the center X coordinate, the second is the center Y coordinate,
+     *                    the third is the width of the area, and the fourth is the height of
+     *                    the area.</li>
+     *  </ul>
+     *
+     *  <p>Note that the coordinate values, width, and height are expressed in relation to the upper
+     *  left as origin, prior to rotation processing as per {@link #TAG_ORIENTATION}.</p>
+     */
+    public static final String TAG_SUBJECT_AREA = "SubjectArea";
+    /**
+     *  <p>The actual focal length of the lens, in mm. Conversion is not made to the focal length
+     *  of a 35mm film camera.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 37386</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_FOCAL_LENGTH = "FocalLength";
+    /**
+     *  <p>Indicates the strobe energy at the time the image is captured, as measured in Beam Candle
+     *  Power Seconds (BCPS).</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41483</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_FLASH_ENERGY = "FlashEnergy";
+    /**
+     *  <p>This tag records the camera or input device spatial frequency table and SFR values in
+     *  the direction of image width, image height, and diagonal direction, as specified in
+     *  ISO 12233.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41484</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse";
+    /**
+     *  <p>Indicates the number of pixels in the image width (X) direction per
+     *  {@link #TAG_FOCAL_PLANE_RESOLUTION_UNIT} on the camera focal plane.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41486</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution";
+    /**
+     *  <p>Indicates the number of pixels in the image height (Y) direction per
+     *  {@link #TAG_FOCAL_PLANE_RESOLUTION_UNIT} on the camera focal plane.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41487</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution";
+    /**
+     *  <p>Indicates the unit for measuring {@link #TAG_FOCAL_PLANE_X_RESOLUTION} and
+     *  {@link #TAG_FOCAL_PLANE_Y_RESOLUTION}. This value is the same as
+     *  {@link #TAG_RESOLUTION_UNIT}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41488</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #RESOLUTION_UNIT_INCHES}</li>
+     *  </ul>
+     *
+     *  @see #TAG_RESOLUTION_UNIT
+     *  @see #RESOLUTION_UNIT_INCHES
+     *  @see #RESOLUTION_UNIT_CENTIMETERS
+     */
+    public static final String TAG_FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit";
+    /**
+     *  <p>Indicates the location of the main subject in the scene. The value of this tag represents
+     *  the pixel at the center of the main subject relative to the left edge, prior to rotation
+     *  processing as per {@link #TAG_ORIENTATION}. The first value indicates the X column number
+     *  and second indicates the Y row number. When a camera records the main subject location,
+     *  it is recommended that {@link #TAG_SUBJECT_AREA} be used instead of this tag.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41492</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 2</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_SUBJECT_LOCATION = "SubjectLocation";
+    /**
+     *  <p>Indicates the exposure index selected on the camera or input device at the time the image
+     *  is captured.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41493</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_EXPOSURE_INDEX = "ExposureIndex";
+    /**
+     *  <p>Indicates the image sensor type on the camera or input device.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41495</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #SENSOR_TYPE_NOT_DEFINED
+     *  @see #SENSOR_TYPE_ONE_CHIP
+     *  @see #SENSOR_TYPE_TWO_CHIP
+     *  @see #SENSOR_TYPE_THREE_CHIP
+     *  @see #SENSOR_TYPE_COLOR_SEQUENTIAL
+     *  @see #SENSOR_TYPE_TRILINEAR
+     *  @see #SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR
+     */
+    public static final String TAG_SENSING_METHOD = "SensingMethod";
+    /**
+     *  <p>Indicates the image source. If a DSC recorded the image, this tag value always shall
+     *  be set to {@link #FILE_SOURCE_DSC}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41728</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = {@link #FILE_SOURCE_DSC}</li>
+     *  </ul>
+     *
+     *  @see #FILE_SOURCE_OTHER
+     *  @see #FILE_SOURCE_TRANSPARENT_SCANNER
+     *  @see #FILE_SOURCE_REFLEX_SCANNER
+     *  @see #FILE_SOURCE_DSC
+     */
+    public static final String TAG_FILE_SOURCE = "FileSource";
+    /**
+     *  <p>Indicates the type of scene. If a DSC recorded the image, this tag value shall always
+     *  be set to {@link #SCENE_TYPE_DIRECTLY_PHOTOGRAPHED}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41729</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = 1</li>
+     *  </ul>
+     *
+     *  @see #SCENE_TYPE_DIRECTLY_PHOTOGRAPHED
+     */
+    public static final String TAG_SCENE_TYPE = "SceneType";
+    /**
+     *  <p>Indicates the color filter array (CFA) geometric pattern of the image sensor when
+     *  a one-chip color area sensor is used. It does not apply to all sensing methods.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41730</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #TAG_SENSING_METHOD
+     *  @see #SENSOR_TYPE_ONE_CHIP
+     */
+    public static final String TAG_CFA_PATTERN = "CFAPattern";
+    /**
+     *  <p>This tag indicates the use of special processing on image data, such as rendering geared
+     *  to output. When special processing is performed, the Exif/DCF reader is expected to disable
+     *  or minimize any further processing.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41985</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #RENDERED_PROCESS_NORMAL}</li>
+     *  </ul>
+     *
+     *  @see #RENDERED_PROCESS_NORMAL
+     *  @see #RENDERED_PROCESS_CUSTOM
+     */
+    public static final String TAG_CUSTOM_RENDERED = "CustomRendered";
+    /**
+     *  <p>This tag indicates the exposure mode set when the image was shot.
+     *  In {@link #EXPOSURE_MODE_AUTO_BRACKET}, the camera shoots a series of frames of the same
+     *  scene at different exposure settings.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41986</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #EXPOSURE_MODE_AUTO
+     *  @see #EXPOSURE_MODE_MANUAL
+     *  @see #EXPOSURE_MODE_AUTO_BRACKET
+     */
+    public static final String TAG_EXPOSURE_MODE = "ExposureMode";
+    /**
+     *  <p>This tag indicates the white balance mode set when the image was shot.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41987</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #WHITEBALANCE_AUTO
+     *  @see #WHITEBALANCE_MANUAL
+     */
     public static final String TAG_WHITE_BALANCE = "WhiteBalance";
     /**
-     * The altitude (in meters) based on the reference in TAG_GPS_ALTITUDE_REF.
-     * Type is rational.
+     *  <p>This tag indicates the digital zoom ratio when the image was shot. If the numerator of
+     *  the recorded value is 0, this indicates that digital zoom was not used.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41988</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_DIGITAL_ZOOM_RATIO = "DigitalZoomRatio";
+    /**
+     *  <p>This tag indicates the equivalent focal length assuming a 35mm film camera, in mm.
+     *  A value of 0 means the focal length is unknown. Note that this tag differs from
+     *  {@link #TAG_FOCAL_LENGTH}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41989</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_FOCAL_LENGTH_IN_35MM_FILM = "FocalLengthIn35mmFilm";
+    /**
+     *  <p>This tag indicates the type of scene that was shot. It may also be used to record
+     *  the mode in which the image was shot. Note that this differs from
+     *  {@link #TAG_SCENE_TYPE}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41990</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = 0</li>
+     *  </ul>
+     *
+     *  @see #SCENE_CAPTURE_TYPE_STANDARD
+     *  @see #SCENE_CAPTURE_TYPE_LANDSCAPE
+     *  @see #SCENE_CAPTURE_TYPE_PORTRAIT
+     *  @see #SCENE_CAPTURE_TYPE_NIGHT
+     */
+    public static final String TAG_SCENE_CAPTURE_TYPE = "SceneCaptureType";
+    /**
+     *  <p>This tag indicates the degree of overall image gain adjustment.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41991</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #GAIN_CONTROL_NONE
+     *  @see #GAIN_CONTROL_LOW_GAIN_UP
+     *  @see #GAIN_CONTROL_HIGH_GAIN_UP
+     *  @see #GAIN_CONTROL_LOW_GAIN_DOWN
+     *  @see #GAIN_CONTROL_HIGH_GAIN_DOWN
+     */
+    public static final String TAG_GAIN_CONTROL = "GainControl";
+    /**
+     *  <p>This tag indicates the direction of contrast processing applied by the camera when
+     *  the image was shot.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41992</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #CONTRAST_NORMAL}</li>
+     *  </ul>
+     *
+     *  @see #CONTRAST_NORMAL
+     *  @see #CONTRAST_SOFT
+     *  @see #CONTRAST_HARD
+     */
+    public static final String TAG_CONTRAST = "Contrast";
+    /**
+     *  <p>This tag indicates the direction of saturation processing applied by the camera when
+     *  the image was shot.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41993</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #SATURATION_NORMAL}</li>
+     *  </ul>
+     *
+     *  @see #SATURATION_NORMAL
+     *  @see #SATURATION_LOW
+     *  @see #SATURATION_HIGH
+     */
+    public static final String TAG_SATURATION = "Saturation";
+    /**
+     *  <p>This tag indicates the direction of sharpness processing applied by the camera when
+     *  the image was shot.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41994</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = {@link #SHARPNESS_NORMAL}</li>
+     *  </ul>
+     *
+     *  @see #SHARPNESS_NORMAL
+     *  @see #SHARPNESS_SOFT
+     *  @see #SHARPNESS_HARD
+     */
+    public static final String TAG_SHARPNESS = "Sharpness";
+    /**
+     *  <p>This tag indicates information on the picture-taking conditions of a particular camera
+     *  model. The tag is used only to indicate the picture-taking conditions in the Exif/DCF
+     *  reader.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41995</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription";
+    /**
+     *  <p>This tag indicates the distance to the subject.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 41996</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #SUBJECT_DISTANCE_RANGE_UNKNOWN
+     *  @see #SUBJECT_DISTANCE_RANGE_MACRO
+     *  @see #SUBJECT_DISTANCE_RANGE_CLOSE_VIEW
+     *  @see #SUBJECT_DISTANCE_RANGE_DISTANT_VIEW
+     */
+    public static final String TAG_SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange";
+
+    // H. Other tags
+    /**
+     *  <p>This tag indicates an identifier assigned uniquely to each image. It is recorded as
+     *  an ASCII string equivalent to hexadecimal notation and 128-bit fixed length.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 42016</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 32</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_IMAGE_UNIQUE_ID = "ImageUniqueID";
+    /**
+     *  <p>This tag records the owner of a camera used in photography as an ASCII string.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 42032</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_CAMARA_OWNER_NAME = "CameraOwnerName";
+    /**
+     *  <p>This tag records the serial number of the body of the camera that was used in photography
+     *  as an ASCII string.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 42033</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_BODY_SERIAL_NUMBER = "BodySerialNumber";
+    /**
+     *  <p>This tag notes minimum focal length, maximum focal length, minimum F number in the
+     *  minimum focal length, and minimum F number in the maximum focal length, which are
+     *  specification information for the lens that was used in photography. When the minimum
+     *  F number is unknown, the notation is 0/0.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 42034</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 4</li>
+     *      <li>Default = None</li>
+     *      <ul>
+     *          <li>Value 1 := Minimum focal length (unit: mm)</li>
+     *          <li>Value 2 : = Maximum focal length (unit: mm)</li>
+     *          <li>Value 3 : = Minimum F number in the minimum focal length</li>
+     *          <li>Value 4 : = Minimum F number in the maximum focal length</li>
+     *      </ul>
+     *  </ul>
+     */
+    public static final String TAG_LENS_SPECIFICATION = "LensSpecification";
+    /**
+     *  <p>This tag records the lens manufacturer as an ASCII string.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 42035</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_LENS_MAKE = "LensMake";
+    /**
+     *  <p>This tag records the lens’s model name and model number as an ASCII string.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 42036</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_LENS_MODEL = "LensModel";
+    /**
+     *  <p>This tag records the serial number of the interchangeable lens that was used in
+     *  photography as an ASCII string.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 42037</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_LENS_SERIAL_NUMBER = "LensSerialNumber";
+
+    // GPS Attribute Information
+    /**
+     *  <p>Indicates the version of GPS Info IFD. The version is given as 2.3.0.0. This tag is
+     *  mandatory when GPS-related tags are present. Note that this tag is written as a different
+     *  byte than {@link #TAG_EXIF_VERSION}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 0</li>
+     *      <li>Type = Byte</li>
+     *      <li>Count = 4</li>
+     *      <li>Default = 2.3.0.0</li>
+     *      <ul>
+     *          <li>2300 = Version 2.3</li>
+     *          <li>Other = reserved</li>
+     *      </ul>
+     *  </ul>
+     */
+    public static final String TAG_GPS_VERSION_ID = "GPSVersionID";
+    /**
+     *  <p>Indicates whether the latitude is north or south latitude.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 1</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #LATITUDE_NORTH
+     *  @see #LATITUDE_SOUTH
+     */
+    public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
+    /**
+     *  <p>Indicates the latitude. The latitude is expressed as three RATIONAL values giving
+     *  the degrees, minutes, and seconds, respectively. If latitude is expressed as degrees,
+     *  minutes and seconds, a typical format would be dd/1,mm/1,ss/1. When degrees and minutes are
+     *  used and, for example, fractions of minutes are given up to two decimal places, the format
+     *  would be dd/1,mmmm/100,0/1.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 2</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 3</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_LATITUDE = "GPSLatitude";
+    /**
+     *  <p>Indicates whether the longitude is east or west longitude.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 3</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #LONGITUDE_EAST
+     *  @see #LONGITUDE_WEST
+     */
+    public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
+    /**
+     *  <p>Indicates the longitude. The longitude is expressed as three RATIONAL values giving
+     *  the degrees, minutes, and seconds, respectively. If longitude is expressed as degrees,
+     *  minutes and seconds, a typical format would be ddd/1,mm/1,ss/1. When degrees and minutes
+     *  are used and, for example, fractions of minutes are given up to two decimal places,
+     *  the format would be ddd/1,mmmm/100,0/1.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 4</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 3</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
+    /**
+     *  <p>Indicates the altitude used as the reference altitude. If the reference is sea level
+     *  and the altitude is above sea level, 0 is given. If the altitude is below sea level,
+     *  a value of 1 is given and the altitude is indicated as an absolute value in
+     *  {@link #TAG_GPS_ALTITUDE}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 5</li>
+     *      <li>Type = Byte</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = 0</li>
+     *  </ul>
+     *
+     *  @see #ALTITUDE_ABOVE_SEA_LEVEL
+     *  @see #ALTITUDE_BELOW_SEA_LEVEL
+     */
+    public static final String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
+    /**
+     *  <p>Indicates the altitude based on the reference in {@link #TAG_GPS_ALTITUDE_REF}.
+     *  The reference unit is meters.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 6</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
      */
     public static final String TAG_GPS_ALTITUDE = "GPSAltitude";
     /**
-     * 0 if the altitude is above sea level. 1 if the altitude is below sea
-     * level. Type is int.
+     *  <p>Indicates the time as UTC (Coordinated Universal Time). TimeStamp is expressed as three
+     *  unsigned rational values giving the hour, minute, and second.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 7</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 3</li>
+     *      <li>Default = None</li>
+     *  </ul>
      */
-    public static final String TAG_GPS_ALTITUDE_REF = "GPSAltitudeRef";
-    /** Type is String. */
-    public static final String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
-    /** Type is rational. */
-    public static final String TAG_GPS_DOP = "GPSDOP";
-    /** Type is String. */
-    public static final String TAG_GPS_DATESTAMP = "GPSDateStamp";
-    /** Type is rational. */
-    public static final String TAG_GPS_DEST_BEARING = "GPSDestBearing";
-    /** Type is String. */
-    public static final String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
-    /** Type is rational. */
-    public static final String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
-    /** Type is String. */
-    public static final String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
-    /** Type is rational. */
-    public static final String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
-    /** Type is String. */
-    public static final String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
-    /** Type is rational. */
-    public static final String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
-    /** Type is String. */
-    public static final String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
-    /** Type is int. */
-    public static final String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
-    /** Type is rational. */
-    public static final String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
-    /** Type is String. */
-    public static final String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
-    /** Type is rational. Format is "num1/denom1,num2/denom2,num3/denom3". */
-    public static final String TAG_GPS_LATITUDE = "GPSLatitude";
-    /** Type is String. */
-    public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
-    /** Type is rational. Format is "num1/denom1,num2/denom2,num3/denom3". */
-    public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
-    /** Type is String. */
-    public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
-    /** Type is String. */
-    public static final String TAG_GPS_MAP_DATUM = "GPSMapDatum";
-    /** Type is String. */
-    public static final String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
-    /** Type is String. Name of GPS processing method used for location finding. */
-    public static final String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
-    /** Type is String. */
-    public static final String TAG_GPS_SATELLITES = "GPSSatellites";
-    /** Type is rational. */
-    public static final String TAG_GPS_SPEED = "GPSSpeed";
-    /** Type is String. */
-    public static final String TAG_GPS_SPEED_REF = "GPSSpeedRef";
-    /** Type is String. */
-    public static final String TAG_GPS_STATUS = "GPSStatus";
-    /** Type is String. Format is "hh:mm:ss". */
     public static final String TAG_GPS_TIMESTAMP = "GPSTimeStamp";
-    /** Type is rational. */
-    public static final String TAG_GPS_TRACK = "GPSTrack";
-    /** Type is String. */
+    /**
+     *  <p>Indicates the GPS satellites used for measurements. This tag may be used to describe
+     *  the number of satellites, their ID number, angle of elevation, azimuth, SNR and other
+     *  information in ASCII notation. The format is not specified. If the GPS receiver is incapable
+     *  of taking measurements, value of the tag shall be set to {@code null}.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 8</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_SATELLITES = "GPSSatellites";
+    /**
+     *  <p>Indicates the status of the GPS receiver when the image is recorded. 'A' means
+     *  measurement is in progress, and 'V' means the measurement is interrupted.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 9</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #GPS_MEASUREMENT_IN_PROGRESS
+     *  @see #GPS_MEASUREMENT_INTERRUPTED
+     */
+    public static final String TAG_GPS_STATUS = "GPSStatus";
+    /**
+     *  <p>Indicates the GPS measurement mode. Originally it was defined for GPS, but it may
+     *  be used for recording a measure mode to record the position information provided from
+     *  a mobile base station or wireless LAN as well as GPS.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 10</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #GPS_MEASUREMENT_2D
+     *  @see #GPS_MEASUREMENT_3D
+     */
+    public static final String TAG_GPS_MEASURE_MODE = "GPSMeasureMode";
+    /**
+     *  <p>Indicates the GPS DOP (data degree of precision). An HDOP value is written during
+     *  two-dimensional measurement, and PDOP during three-dimensional measurement.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 11</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_DOP = "GPSDOP";
+    /**
+     *  <p>Indicates the unit used to express the GPS receiver speed of movement.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 12</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = {@link #GPS_SPEED_KILOMETERS_PER_HOUR}</li>
+     *  </ul>
+     *
+     *  @see #GPS_SPEED_KILOMETERS_PER_HOUR
+     *  @see #GPS_SPEED_MILES_PER_HOUR
+     *  @see #GPS_SPEED_KNOTS
+     */
+    public static final String TAG_GPS_SPEED_REF = "GPSSpeedRef";
+    /**
+     *  <p>Indicates the speed of GPS receiver movement.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 13</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_SPEED = "GPSSpeed";
+    /**
+     *  <p>Indicates the reference for giving the direction of GPS receiver movement.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 14</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = {@link #GPS_DIRECTION_TRUE}</li>
+     *  </ul>
+     *
+     *  @see #GPS_DIRECTION_TRUE
+     *  @see #GPS_DIRECTION_MAGNETIC
+     */
     public static final String TAG_GPS_TRACK_REF = "GPSTrackRef";
-    /** Type is String. */
-    public static final String TAG_GPS_VERSION_ID = "GPSVersionID";
-    /** Type is String. */
+    /**
+     *  <p>Indicates the direction of GPS receiver movement.
+     *  The range of values is from 0.00 to 359.99.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 15</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_TRACK = "GPSTrack";
+    /**
+     *  <p>Indicates the reference for giving the direction of the image when it is captured.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 16</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = {@link #GPS_DIRECTION_TRUE}</li>
+     *  </ul>
+     *
+     *  @see #GPS_DIRECTION_TRUE
+     *  @see #GPS_DIRECTION_MAGNETIC
+     */
+    public static final String TAG_GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef";
+    /**
+     *  <p>ndicates the direction of the image when it was captured.
+     *  The range of values is from 0.00 to 359.99.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 17</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_IMG_DIRECTION = "GPSImgDirection";
+    /**
+     *  <p>Indicates the geodetic survey data used by the GPS receiver. If the survey data is
+     *  restricted to Japan,the value of this tag is 'TOKYO' or 'WGS-84'. If a GPS Info tag is
+     *  recorded, it is strongly recommended that this tag be recorded.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 18</li>
+     *      <li>Type = String</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_MAP_DATUM = "GPSMapDatum";
+    /**
+     *  <p>Indicates whether the latitude of the destination point is north or south latitude.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 19</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #LATITUDE_NORTH
+     *  @see #LATITUDE_SOUTH
+     */
+    public static final String TAG_GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef";
+    /**
+     *  <p>Indicates the latitude of the destination point. The latitude is expressed as three
+     *  unsigned rational values giving the degrees, minutes, and seconds, respectively.
+     *  If latitude is expressed as degrees, minutes and seconds, a typical format would be
+     *  dd/1,mm/1,ss/1. When degrees and minutes are used and, for example, fractions of minutes
+     *  are given up to two decimal places, the format would be dd/1, mmmm/100, 0/1.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 20</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 3</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_DEST_LATITUDE = "GPSDestLatitude";
+    /**
+     *  <p>Indicates whether the longitude of the destination point is east or west longitude.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 21</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #LONGITUDE_EAST
+     *  @see #LONGITUDE_WEST
+     */
+    public static final String TAG_GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef";
+    /**
+     *  <p>Indicates the longitude of the destination point. The longitude is expressed as three
+     *  unsigned rational values giving the degrees, minutes, and seconds, respectively.
+     *  If longitude is expressed as degrees, minutes and seconds, a typical format would be ddd/1,
+     *  mm/1, ss/1. When degrees and minutes are used and, for example, fractions of minutes are
+     *  given up to two decimal places, the format would be ddd/1, mmmm/100, 0/1.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 22</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 3</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_DEST_LONGITUDE = "GPSDestLongitude";
+    /**
+     *  <p>Indicates the reference used for giving the bearing to the destination point.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 23</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = {@link #GPS_DIRECTION_TRUE}</li>
+     *  </ul>
+     *
+     *  @see #GPS_DIRECTION_TRUE
+     *  @see #GPS_DIRECTION_MAGNETIC
+     */
+    public static final String TAG_GPS_DEST_BEARING_REF = "GPSDestBearingRef";
+    /**
+     *  <p>Indicates the bearing to the destination point.
+     *  The range of values is from 0.00 to 359.99.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 24</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_DEST_BEARING = "GPSDestBearing";
+    /**
+     *  <p>Indicates the unit used to express the distance to the destination point.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 25</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 1</li>
+     *      <li>Default = {@link #GPS_DISTANCE_KILOMETERS}</li>
+     *  </ul>
+     *
+     *  @see #GPS_DISTANCE_KILOMETERS
+     *  @see #GPS_DISTANCE_MILES
+     *  @see #GPS_DISTANCE_NAUTICAL_MILES
+     */
+    public static final String TAG_GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef";
+    /**
+     *  <p>Indicates the distance to the destination point.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 26</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_DEST_DISTANCE = "GPSDestDistance";
+    /**
+     *  <p>A character string recording the name of the method used for location finding.
+     *  The first byte indicates the character code used, and this is followed by the name of
+     *  the method.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 27</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_PROCESSING_METHOD = "GPSProcessingMethod";
+    /**
+     *  <p>A character string recording the name of the GPS area. The first byte indicates
+     *  the character code used, and this is followed by the name of the GPS area.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 28</li>
+     *      <li>Type = Undefined</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_AREA_INFORMATION = "GPSAreaInformation";
+    /**
+     *  <p>A character string recording date and time information relative to UTC (Coordinated
+     *  Universal Time). The format is "YYYY:MM:DD".</p>
+     *
+     *  <ul>
+     *      <li>Tag = 29</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 10</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_DATESTAMP = "GPSDateStamp";
+    /**
+     *  <p>Indicates whether differential correction is applied to the GPS receiver.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 30</li>
+     *      <li>Type = Unsigned short</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     *
+     *  @see #GPS_MEASUREMENT_NO_DIFFERENTIAL
+     *  @see #GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED
+     */
+    public static final String TAG_GPS_DIFFERENTIAL = "GPSDifferential";
+    /**
+     *  <p>This tag indicates horizontal positioning errors in meters.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 31</li>
+     *      <li>Type = Unsigned rational</li>
+     *      <li>Count = 1</li>
+     *      <li>Default = None</li>
+     *  </ul>
+     */
+    public static final String TAG_GPS_H_POSITIONING_ERROR = "GPSHPositioningError";
+
+    // Interoperability IFD Attribute Information
+    /**
+     *  <p>Indicates the identification of the Interoperability rule.</p>
+     *
+     *  <ul>
+     *      <li>Tag = 1</li>
+     *      <li>Type = String</li>
+     *      <li>Length = 4</li>
+     *      <li>Default = None</li>
+     *      <ul>
+     *          <li>"R98" = Indicates a file conforming to R98 file specification of Recommended
+     *                      Exif Interoperability Rules (Exif R 98) or to DCF basic file stipulated
+     *                      by Design Rule for Camera File System.</li>
+     *          <li>"THM" = Indicates a file conforming to DCF thumbnail file stipulated by Design
+     *                      rule for Camera File System.</li>
+     *          <li>“R03” = Indicates a file conforming to DCF Option File stipulated by Design rule
+     *                      for Camera File System.</li>
+     *      </ul>
+     *  </ul>
+     */
     public static final String TAG_INTEROPERABILITY_INDEX = "InteroperabilityIndex";
-    /** Type is int. */
+
+    /**
+     * @see #TAG_IMAGE_LENGTH
+     */
     public static final String TAG_THUMBNAIL_IMAGE_LENGTH = "ThumbnailImageLength";
-    /** Type is int. */
+    /**
+     * @see #TAG_IMAGE_WIDTH
+     */
     public static final String TAG_THUMBNAIL_IMAGE_WIDTH = "ThumbnailImageWidth";
     /** Type is int. DNG Specification 1.4.0.0. Section 4 */
     public static final String TAG_DNG_VERSION = "DNGVersion";
@@ -361,6 +2079,10 @@
      * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PanasonicRaw.html
      */
     public static final String TAG_RW2_JPG_FROM_RAW = "JpgFromRaw";
+    /** Type is int. See JEITA CP-3451C Spec Section 3: Bilevel Images. */
+    public static final String TAG_NEW_SUBFILE_TYPE = "NewSubfileType";
+    /** Type is int. See JEITA CP-3451C Spec Section 3: Bilevel Images. */
+    public static final String TAG_SUBFILE_TYPE = "SubfileType";
 
     /**
      * Private tags used for pointing the other IFD offsets.
@@ -387,24 +2109,717 @@
     // Constants used for the Orientation Exif tag.
     public static final int ORIENTATION_UNDEFINED = 0;
     public static final int ORIENTATION_NORMAL = 1;
-    public static final int ORIENTATION_FLIP_HORIZONTAL = 2;  // left right reversed mirror
+    /**
+     * Indicates the image is left right reversed mirror.
+     */
+    public static final int ORIENTATION_FLIP_HORIZONTAL = 2;
+    /**
+     * Indicates the image is rotated by 180 degree clockwise.
+     */
     public static final int ORIENTATION_ROTATE_180 = 3;
-    public static final int ORIENTATION_FLIP_VERTICAL = 4;  // upside down mirror
-    // flipped about top-left <--> bottom-right axis
+    /**
+     * Indicates the image is upside down mirror, it can also be represented by flip
+     * horizontally firstly and rotate 180 degree clockwise.
+     */
+    public static final int ORIENTATION_FLIP_VERTICAL = 4;
+    /**
+     * Indicates the image is flipped about top-left <--> bottom-right axis, it can also be
+     * represented by flip horizontally firstly and rotate 270 degree clockwise.
+     */
     public static final int ORIENTATION_TRANSPOSE = 5;
-    public static final int ORIENTATION_ROTATE_90 = 6;  // rotate 90 degree clockwise
-    // flipped about top-right <--> bottom-left axis
+    /**
+     * Indicates the image is rotated by 90 degree clockwise.
+     */
+    public static final int ORIENTATION_ROTATE_90 = 6;
+    /**
+     * Indicates the image is flipped about top-right <--> bottom-left axis, it can also be
+     * represented by flip horizontally firstly and rotate 90 degree clockwise.
+     */
     public static final int ORIENTATION_TRANSVERSE = 7;
-    public static final int ORIENTATION_ROTATE_270 = 8;  // rotate 270 degree clockwise
+    /**
+     * Indicates the image is rotated by 270 degree clockwise.
+     */
+    public static final int ORIENTATION_ROTATE_270 = 8;
     private static final List<Integer> ROTATION_ORDER = Arrays.asList(ORIENTATION_NORMAL,
             ORIENTATION_ROTATE_90, ORIENTATION_ROTATE_180, ORIENTATION_ROTATE_270);
     private static final List<Integer> FLIPPED_ROTATION_ORDER = Arrays.asList(
             ORIENTATION_FLIP_HORIZONTAL, ORIENTATION_TRANSVERSE, ORIENTATION_FLIP_VERTICAL,
             ORIENTATION_TRANSPOSE);
 
-    // Constants used for white balance
-    public static final int WHITEBALANCE_AUTO = 0;
-    public static final int WHITEBALANCE_MANUAL = 1;
+    /**
+     * The contant used by {@link #TAG_PLANAR_CONFIGURATION} to denote Chunky format.
+     */
+    public static final short FORMAT_CHUNKY = 1;
+    /**
+     * The contant used by {@link #TAG_PLANAR_CONFIGURATION} to denote Planar format.
+     */
+    public static final short FORMAT_PLANAR = 2;
+
+    /**
+     * The contant used by {@link #TAG_Y_CB_CR_POSITIONING} to denote Centered positioning.
+     */
+    public static final short Y_CB_CR_POSITIONING_CENTERED = 1;
+    /**
+     * The contant used by {@link #TAG_Y_CB_CR_POSITIONING} to denote Co-sited positioning.
+     */
+    public static final short Y_CB_CR_POSITIONING_CO_SITED = 2;
+
+    /**
+     * The contant used to denote resolution unit as inches.
+     */
+    public static final short RESOLUTION_UNIT_INCHES = 2;
+    /**
+     * The contant used to denote resolution unit as centimeters.
+     */
+    public static final short RESOLUTION_UNIT_CENTIMETERS = 3;
+
+    /**
+     * The contant used by {@link #TAG_COLOR_SPACE} to denote sRGB color space.
+     */
+    public static final int COLOR_SPACE_S_RGB = 1;
+    /**
+     * The contant used by {@link #TAG_COLOR_SPACE} to denote Uncalibrated.
+     */
+    public static final int COLOR_SPACE_UNCALIBRATED = 65535;
+
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is not defined.
+     */
+    public static final short EXPOSURE_PROGRAM_NOT_DEFINED = 0;
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Manual.
+     */
+    public static final short EXPOSURE_PROGRAM_MANUAL = 1;
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Normal.
+     */
+    public static final short EXPOSURE_PROGRAM_NORMAL = 2;
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is
+     * Aperture priority.
+     */
+    public static final short EXPOSURE_PROGRAM_APERTURE_PRIORITY = 3;
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is
+     * Shutter priority.
+     */
+    public static final short EXPOSURE_PROGRAM_SHUTTER_PRIORITY = 4;
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Creative
+     * program (biased toward depth of field).
+     */
+    public static final short EXPOSURE_PROGRAM_CREATIVE = 5;
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Action
+     * program (biased toward fast shutter speed).
+     */
+    public static final short EXPOSURE_PROGRAM_ACTION = 6;
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Portrait mode
+     * (for closeup photos with the background out of focus).
+     */
+    public static final short EXPOSURE_PROGRAM_PORTRAIT_MODE = 7;
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_PROGRAM} to denote exposure program is Landscape
+     * mode (for landscape photos with the background in focus).
+     */
+    public static final short EXPOSURE_PROGRAM_LANDSCAPE_MODE = 8;
+
+    /**
+     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is unknown.
+     */
+    public static final short SENSITIVITY_TYPE_UNKNOWN = 0;
+    /**
+     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard
+     * output sensitivity (SOS).
+     */
+    public static final short SENSITIVITY_TYPE_SOS = 1;
+    /**
+     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Recommended
+     * exposure index (REI).
+     */
+    public static final short SENSITIVITY_TYPE_REI = 2;
+    /**
+     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is ISO speed.
+     */
+    public static final short SENSITIVITY_TYPE_ISO_SPEED = 3;
+    /**
+     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard
+     * output sensitivity (SOS) and recommended exposure index (REI).
+     */
+    public static final short SENSITIVITY_TYPE_SOS_AND_REI = 4;
+    /**
+     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard
+     * output sensitivity (SOS) and ISO speed.
+     */
+    public static final short SENSITIVITY_TYPE_SOS_AND_ISO = 5;
+    /**
+     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Recommended
+     * exposure index (REI) and ISO speed.
+     */
+    public static final short SENSITIVITY_TYPE_REI_AND_ISO = 6;
+    /**
+     * The contant used by {@link #TAG_SENSITIVITY_TYPE} to denote sensitivity type is Standard
+     * output sensitivity (SOS) and recommended exposure index (REI) and ISO speed.
+     */
+    public static final short SENSITIVITY_TYPE_SOS_AND_REI_AND_ISO = 7;
+
+    /**
+     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is unknown.
+     */
+    public static final short METERING_MODE_UNKNOWN = 0;
+    /**
+     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Average.
+     */
+    public static final short METERING_MODE_AVERAGE = 1;
+    /**
+     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is
+     * CenterWeightedAverage.
+     */
+    public static final short METERING_MODE_CENTER_WEIGHT_AVERAGE = 2;
+    /**
+     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Spot.
+     */
+    public static final short METERING_MODE_SPOT = 3;
+    /**
+     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is MultiSpot.
+     */
+    public static final short METERING_MODE_MULTI_SPOT = 4;
+    /**
+     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Pattern.
+     */
+    public static final short METERING_MODE_PATTERN = 5;
+    /**
+     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is Partial.
+     */
+    public static final short METERING_MODE_PARTIAL = 6;
+    /**
+     * The contant used by {@link #TAG_METERING_MODE} to denote metering mode is other.
+     */
+    public static final short METERING_MODE_OTHER = 255;
+
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is unknown.
+     */
+    public static final short LIGHT_SOURCE_UNKNOWN = 0;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Daylight.
+     */
+    public static final short LIGHT_SOURCE_DAYLIGHT = 1;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Fluorescent.
+     */
+    public static final short LIGHT_SOURCE_FLUORESCENT = 2;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Tungsten
+     * (incandescent light).
+     */
+    public static final short LIGHT_SOURCE_TUNGSTEN = 3;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Flash.
+     */
+    public static final short LIGHT_SOURCE_FLASH = 4;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Fine weather.
+     */
+    public static final short LIGHT_SOURCE_FINE_WEATHER = 9;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Cloudy weather.
+     */
+    public static final short LIGHT_SOURCE_CLOUDY_WEATHER = 10;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Shade.
+     */
+    public static final short LIGHT_SOURCE_SHADE = 11;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Daylight fluorescent
+     * (D 5700 - 7100K).
+     */
+    public static final short LIGHT_SOURCE_DAYLIGHT_FLUORESCENT = 12;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Day white fluorescent
+     * (N 4600 - 5500K).
+     */
+    public static final short LIGHT_SOURCE_DAY_WHITE_FLUORESCENT = 13;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Cool white
+     * fluorescent (W 3800 - 4500K).
+     */
+    public static final short LIGHT_SOURCE_COOL_WHITE_FLUORESCENT = 14;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is White fluorescent
+     * (WW 3250 - 3800K).
+     */
+    public static final short LIGHT_SOURCE_WHITE_FLUORESCENT = 15;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Warm white
+     * fluorescent (L 2600 - 3250K).
+     */
+    public static final short LIGHT_SOURCE_WARM_WHITE_FLUORESCENT = 16;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Standard light A.
+     */
+    public static final short LIGHT_SOURCE_STANDARD_LIGHT_A = 17;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Standard light B.
+     */
+    public static final short LIGHT_SOURCE_STANDARD_LIGHT_B = 18;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is Standard light C.
+     */
+    public static final short LIGHT_SOURCE_STANDARD_LIGHT_C = 19;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D55.
+     */
+    public static final short LIGHT_SOURCE_D55 = 20;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D65.
+     */
+    public static final short LIGHT_SOURCE_D65 = 21;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D75.
+     */
+    public static final short LIGHT_SOURCE_D75 = 22;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is D50.
+     */
+    public static final short LIGHT_SOURCE_D50 = 23;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is ISO studio tungsten.
+     */
+    public static final short LIGHT_SOURCE_ISO_STUDIO_TUNGSTEN = 24;
+    /**
+     * The contant used by {@link #TAG_LIGHT_SOURCE} to denote light source is other.
+     */
+    public static final short LIGHT_SOURCE_OTHER = 255;
+
+    /**
+     * The flag used by {@link #TAG_FLASH} to indicate whether the flash is fired.
+     */
+    public static final short FLAG_FLASH_FIRED = 0b0000_0001;
+    /**
+     * The flag used by {@link #TAG_FLASH} to indicate strobe return light is not detected.
+     */
+    public static final short FLAG_FLASH_RETURN_LIGHT_NOT_DETECTED = 0b0000_0100;
+    /**
+     * The flag used by {@link #TAG_FLASH} to indicate strobe return light is detected.
+     */
+    public static final short FLAG_FLASH_RETURN_LIGHT_DETECTED = 0b0000_0110;
+    /**
+     * The flag used by {@link #TAG_FLASH} to indicate the camera's flash mode is Compulsory flash
+     * firing.
+     *
+     * @see #FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION
+     * @see #FLAG_FLASH_MODE_AUTO
+     */
+    public static final short FLAG_FLASH_MODE_COMPULSORY_FIRING = 0b0000_1000;
+    /**
+     * The flag used by {@link #TAG_FLASH} to indicate the camera's flash mode is Compulsory flash
+     * suppression.
+     *
+     * @see #FLAG_FLASH_MODE_COMPULSORY_FIRING
+     * @see #FLAG_FLASH_MODE_AUTO
+     */
+    public static final short FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION = 0b0001_0000;
+    /**
+     * The flag used by {@link #TAG_FLASH} to indicate the camera's flash mode is Auto.
+     *
+     * @see #FLAG_FLASH_MODE_COMPULSORY_FIRING
+     * @see #FLAG_FLASH_MODE_COMPULSORY_SUPPRESSION
+     */
+    public static final short FLAG_FLASH_MODE_AUTO = 0b0001_1000;
+    /**
+     * The flag used by {@link #TAG_FLASH} to indicate no flash function is present.
+     */
+    public static final short FLAG_FLASH_NO_FLASH_FUNCTION = 0b0010_0000;
+    /**
+     * The flag used by {@link #TAG_FLASH} to indicate red-eye reduction is supported.
+     */
+    public static final short FLAG_FLASH_RED_EYE_SUPPORTED = 0b0100_0000;
+
+    /**
+     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is not
+     * defined.
+     */
+    public static final short SENSOR_TYPE_NOT_DEFINED = 1;
+    /**
+     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is One-chip
+     * color area sensor.
+     */
+    public static final short SENSOR_TYPE_ONE_CHIP = 2;
+    /**
+     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Two-chip
+     * color area sensor.
+     */
+    public static final short SENSOR_TYPE_TWO_CHIP = 3;
+    /**
+     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Three-chip
+     * color area sensor.
+     */
+    public static final short SENSOR_TYPE_THREE_CHIP = 4;
+    /**
+     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Color
+     * sequential area sensor.
+     */
+    public static final short SENSOR_TYPE_COLOR_SEQUENTIAL = 5;
+    /**
+     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Trilinear
+     * sensor.
+     */
+    public static final short SENSOR_TYPE_TRILINEAR = 7;
+    /**
+     * The contant used by {@link #TAG_SENSING_METHOD} to denote the image sensor type is Color
+     * sequential linear sensor.
+     */
+    public static final short SENSOR_TYPE_COLOR_SEQUENTIAL_LINEAR = 8;
+
+    /**
+     * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is other.
+     */
+    public static final short FILE_SOURCE_OTHER = 0;
+    /**
+     * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is scanner of transparent
+     * type.
+     */
+    public static final short FILE_SOURCE_TRANSPARENT_SCANNER = 1;
+    /**
+     * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is scanner of reflex type.
+     */
+    public static final short FILE_SOURCE_REFLEX_SCANNER = 2;
+    /**
+     * The contant used by {@link #TAG_FILE_SOURCE} to denote the source is DSC.
+     */
+    public static final short FILE_SOURCE_DSC = 3;
+
+    /**
+     * The contant used by {@link #TAG_SCENE_TYPE} to denote the scene is directly photographed.
+     */
+    public static final short SCENE_TYPE_DIRECTLY_PHOTOGRAPHED = 1;
+
+    /**
+     * The contant used by {@link #TAG_CUSTOM_RENDERED} to denote no special processing is used.
+     */
+    public static final short RENDERED_PROCESS_NORMAL = 0;
+    /**
+     * The contant used by {@link #TAG_CUSTOM_RENDERED} to denote special processing is used.
+     */
+    public static final short RENDERED_PROCESS_CUSTOM = 1;
+
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_MODE} to denote the exposure mode is Auto.
+     */
+    public static final short EXPOSURE_MODE_AUTO = 0;
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_MODE} to denote the exposure mode is Manual.
+     */
+    public static final short EXPOSURE_MODE_MANUAL = 1;
+    /**
+     * The contant used by {@link #TAG_EXPOSURE_MODE} to denote the exposure mode is Auto bracket.
+     */
+    public static final short EXPOSURE_MODE_AUTO_BRACKET = 2;
+
+    /**
+     * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Auto.
+     *
+     * @deprecated Use {@link #WHITE_BALANCE_AUTO} instead.
+     */
+    @Deprecated public static final int WHITEBALANCE_AUTO = 0;
+    /**
+     * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Manual.
+     *
+     * @deprecated Use {@link #WHITE_BALANCE_MANUAL} instead.
+     */
+    @Deprecated public static final int WHITEBALANCE_MANUAL = 1;
+    /**
+     * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Auto.
+     */
+    public static final short WHITE_BALANCE_AUTO = 0;
+    /**
+     * The contant used by {@link #TAG_WHITE_BALANCE} to denote the white balance is Manual.
+     */
+    public static final short WHITE_BALANCE_MANUAL = 1;
+
+    /**
+     * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is
+     * Standard.
+     */
+    public static final short SCENE_CAPTURE_TYPE_STANDARD = 0;
+    /**
+     * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is
+     * Landscape.
+     */
+    public static final short SCENE_CAPTURE_TYPE_LANDSCAPE = 1;
+    /**
+     * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is
+     * Portrait.
+     */
+    public static final short SCENE_CAPTURE_TYPE_PORTRAIT = 2;
+    /**
+     * The contant used by {@link #TAG_SCENE_CAPTURE_TYPE} to denote the scene capture type is Night
+     * scene.
+     */
+    public static final short SCENE_CAPTURE_TYPE_NIGHT = 3;
+
+    /**
+     * The contant used by {@link #TAG_GAIN_CONTROL} to denote none gain adjustment.
+     */
+    public static final short GAIN_CONTROL_NONE = 0;
+    /**
+     * The contant used by {@link #TAG_GAIN_CONTROL} to denote low gain up.
+     */
+    public static final short GAIN_CONTROL_LOW_GAIN_UP = 1;
+    /**
+     * The contant used by {@link #TAG_GAIN_CONTROL} to denote high gain up.
+     */
+    public static final short GAIN_CONTROL_HIGH_GAIN_UP = 2;
+    /**
+     * The contant used by {@link #TAG_GAIN_CONTROL} to denote low gain down.
+     */
+    public static final short GAIN_CONTROL_LOW_GAIN_DOWN = 3;
+    /**
+     * The contant used by {@link #TAG_GAIN_CONTROL} to denote high gain down.
+     */
+    public static final short GAIN_CONTROL_HIGH_GAIN_DOWN = 4;
+
+    /**
+     * The contant used by {@link #TAG_CONTRAST} to denote normal contrast.
+     */
+    public static final short CONTRAST_NORMAL = 0;
+    /**
+     * The contant used by {@link #TAG_CONTRAST} to denote soft contrast.
+     */
+    public static final short CONTRAST_SOFT = 1;
+    /**
+     * The contant used by {@link #TAG_CONTRAST} to denote hard contrast.
+     */
+    public static final short CONTRAST_HARD = 2;
+
+    /**
+     * The contant used by {@link #TAG_SATURATION} to denote normal saturation.
+     */
+    public static final short SATURATION_NORMAL = 0;
+    /**
+     * The contant used by {@link #TAG_SATURATION} to denote low saturation.
+     */
+    public static final short SATURATION_LOW = 0;
+    /**
+     * The contant used by {@link #TAG_SHARPNESS} to denote high saturation.
+     */
+    public static final short SATURATION_HIGH = 0;
+
+    /**
+     * The contant used by {@link #TAG_SHARPNESS} to denote normal sharpness.
+     */
+    public static final short SHARPNESS_NORMAL = 0;
+    /**
+     * The contant used by {@link #TAG_SHARPNESS} to denote soft sharpness.
+     */
+    public static final short SHARPNESS_SOFT = 1;
+    /**
+     * The contant used by {@link #TAG_SHARPNESS} to denote hard sharpness.
+     */
+    public static final short SHARPNESS_HARD = 2;
+
+    /**
+     * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range
+     * is unknown.
+     */
+    public static final short SUBJECT_DISTANCE_RANGE_UNKNOWN = 0;
+    /**
+     * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range
+     * is Macro.
+     */
+    public static final short SUBJECT_DISTANCE_RANGE_MACRO = 1;
+    /**
+     * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range
+     * is Close view.
+     */
+    public static final short SUBJECT_DISTANCE_RANGE_CLOSE_VIEW = 2;
+    /**
+     * The contant used by {@link #TAG_SUBJECT_DISTANCE_RANGE} to denote the subject distance range
+     * is Distant view.
+     */
+    public static final short SUBJECT_DISTANCE_RANGE_DISTANT_VIEW = 3;
+
+    /**
+     * The contant used by GPS latitude-related tags to denote the latitude is North latitude.
+     *
+     * @see #TAG_GPS_LATITUDE_REF
+     * @see #TAG_GPS_DEST_LATITUDE_REF
+     */
+    public static final String LATITUDE_NORTH = "N";
+    /**
+     * The contant used by GPS latitude-related tags to denote the latitude is South latitude.
+     *
+     * @see #TAG_GPS_LATITUDE_REF
+     * @see #TAG_GPS_DEST_LATITUDE_REF
+     */
+    public static final String LATITUDE_SOUTH = "S";
+
+    /**
+     * The contant used by GPS longitude-related tags to denote the longitude is East longitude.
+     *
+     * @see #TAG_GPS_LONGITUDE_REF
+     * @see #TAG_GPS_DEST_LONGITUDE_REF
+     */
+    public static final String LONGITUDE_EAST = "E";
+    /**
+     * The contant used by GPS longitude-related tags to denote the longitude is West longitude.
+     *
+     * @see #TAG_GPS_LONGITUDE_REF
+     * @see #TAG_GPS_DEST_LONGITUDE_REF
+     */
+    public static final String LONGITUDE_WEST = "W";
+
+    /**
+     * The contant used by {@link #TAG_GPS_ALTITUDE_REF} to denote the altitude is above sea level.
+     */
+    public static final short ALTITUDE_ABOVE_SEA_LEVEL = 0;
+    /**
+     * The contant used by {@link #TAG_GPS_ALTITUDE_REF} to denote the altitude is below sea level.
+     */
+    public static final short ALTITUDE_BELOW_SEA_LEVEL = 1;
+
+    /**
+     * The contant used by {@link #TAG_GPS_STATUS} to denote GPS measurement is in progress.
+     */
+    public static final String GPS_MEASUREMENT_IN_PROGRESS = "A";
+    /**
+     * The contant used by {@link #TAG_GPS_STATUS} to denote GPS measurement is interrupted.
+     */
+    public static final String GPS_MEASUREMENT_INTERRUPTED = "V";
+
+    /**
+     * The contant used by {@link #TAG_GPS_MEASURE_MODE} to denote GPS measurement is 2-dimensional.
+     */
+    public static final String GPS_MEASUREMENT_2D = "2";
+    /**
+     * The contant used by {@link #TAG_GPS_MEASURE_MODE} to denote GPS measurement is 3-dimensional.
+     */
+    public static final String GPS_MEASUREMENT_3D = "3";
+
+    /**
+     * The contant used by {@link #TAG_GPS_SPEED_REF} to denote the speed unit is kilometers per
+     * hour.
+     */
+    public static final String GPS_SPEED_KILOMETERS_PER_HOUR = "K";
+    /**
+     * The contant used by {@link #TAG_GPS_SPEED_REF} to denote the speed unit is miles per hour.
+     */
+    public static final String GPS_SPEED_MILES_PER_HOUR = "M";
+    /**
+     * The contant used by {@link #TAG_GPS_SPEED_REF} to denote the speed unit is knots.
+     */
+    public static final String GPS_SPEED_KNOTS = "N";
+
+    /**
+     * The contant used by GPS attributes to denote the direction is true direction.
+     */
+    public static final String GPS_DIRECTION_TRUE = "T";
+    /**
+     * The contant used by GPS attributes to denote the direction is magnetic direction.
+     */
+    public static final String GPS_DIRECTION_MAGNETIC = "M";
+
+    /**
+     * The contant used by {@link #TAG_GPS_DEST_DISTANCE_REF} to denote the distance unit is
+     * kilometers.
+     */
+    public static final String GPS_DISTANCE_KILOMETERS = "K";
+    /**
+     * The contant used by {@link #TAG_GPS_DEST_DISTANCE_REF} to denote the distance unit is miles.
+     */
+    public static final String GPS_DISTANCE_MILES = "M";
+    /**
+     * The contant used by {@link #TAG_GPS_DEST_DISTANCE_REF} to denote the distance unit is
+     * nautical miles.
+     */
+    public static final String GPS_DISTANCE_NAUTICAL_MILES = "N";
+
+    /**
+     * The contant used by {@link #TAG_GPS_DIFFERENTIAL} to denote no differential correction is
+     * applied.
+     */
+    public static final short GPS_MEASUREMENT_NO_DIFFERENTIAL = 0;
+    /**
+     * The contant used by {@link #TAG_GPS_DIFFERENTIAL} to denote differential correction is
+     * applied.
+     */
+    public static final short GPS_MEASUREMENT_DIFFERENTIAL_CORRECTED = 1;
+
+    /**
+     * The constant used by {@link #TAG_COMPRESSION} to denote the image is not compressed.
+     */
+    public static final int DATA_UNCOMPRESSED = 1;
+    /**
+     * The constant used by {@link #TAG_COMPRESSION} to denote the image is huffman compressed.
+     */
+    public static final int DATA_HUFFMAN_COMPRESSED = 2;
+    /**
+     * The constant used by {@link #TAG_COMPRESSION} to denote the image is JPEG.
+     */
+    public static final int DATA_JPEG = 6;
+    /**
+     * The constant used by {@link #TAG_COMPRESSION}, see DNG Specification 1.4.0.0.
+     * Section 3, Compression
+     */
+    public static final int DATA_JPEG_COMPRESSED = 7;
+    /**
+     * The constant used by {@link #TAG_COMPRESSION}, see DNG Specification 1.4.0.0.
+     * Section 3, Compression
+     */
+    public static final int DATA_DEFLATE_ZIP = 8;
+    /**
+     * The constant used by {@link #TAG_COMPRESSION} to denote the image is pack-bits compressed.
+     */
+    public static final int DATA_PACK_BITS_COMPRESSED = 32773;
+    /**
+     * The constant used by {@link #TAG_COMPRESSION}, see DNG Specification 1.4.0.0.
+     * Section 3, Compression
+     */
+    public static final int DATA_LOSSY_JPEG = 34892;
+
+    /**
+     * The constant used by {@link #TAG_BITS_PER_SAMPLE}.
+     * See JEITA CP-3451C Spec Section 6, Differences from Palette Color Images
+     */
+    public static final int[] BITS_PER_SAMPLE_RGB = new int[] { 8, 8, 8 };
+    /**
+     * The constant used by {@link #TAG_BITS_PER_SAMPLE}.
+     * See JEITA CP-3451C Spec Section 4, Differences from Bilevel Images
+     */
+    public static final int[] BITS_PER_SAMPLE_GREYSCALE_1 = new int[] { 4 };
+    /**
+     * The constant used by {@link #TAG_BITS_PER_SAMPLE}.
+     * See JEITA CP-3451C Spec Section 4, Differences from Bilevel Images
+     */
+    public static final int[] BITS_PER_SAMPLE_GREYSCALE_2 = new int[] { 8 };
+
+    /**
+     * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}.
+     */
+    public static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0;
+    /**
+     * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}.
+     */
+    public static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1;
+    /**
+     * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}.
+     */
+    public static final int PHOTOMETRIC_INTERPRETATION_RGB = 2;
+    /**
+     * The constant used by {@link #TAG_PHOTOMETRIC_INTERPRETATION}.
+     */
+    public static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6;
+
+    /**
+     * The constant used by {@link #TAG_NEW_SUBFILE_TYPE}. See JEITA CP-3451C Spec Section 8.
+     */
+    public static final int ORIGINAL_RESOLUTION_IMAGE = 0;
+    /**
+     * The constant used by {@link #TAG_NEW_SUBFILE_TYPE}. See JEITA CP-3451C Spec Section 8.
+     */
+    public static final int REDUCED_RESOLUTION_IMAGE = 1;
 
     // Maximum size for checking file type signature (see image_type_recognition_lite.cc)
     private static final int SIGNATURE_CHECK_SIZE = 5000;
@@ -480,46 +2895,6 @@
             0x41, 0x53, 0x43, 0x49, 0x49, 0x0, 0x0, 0x0
     };
 
-    /**
-     * Constants used for Compression tag.
-     * For Value 1, 2, 32773, see TIFF 6.0 Spec Section 3: Bilevel Images, Compression
-     * For Value 6, see TIFF 6.0 Spec Section 22: JPEG Compression, Extensions to Existing Fields
-     * For Value 7, 8, 34892, see DNG Specification 1.4.0.0. Section 3, Compression
-     */
-    private static final int DATA_UNCOMPRESSED = 1;
-    private static final int DATA_HUFFMAN_COMPRESSED = 2;
-    private static final int DATA_JPEG = 6;
-    private static final int DATA_JPEG_COMPRESSED = 7;
-    private static final int DATA_DEFLATE_ZIP = 8;
-    private static final int DATA_PACK_BITS_COMPRESSED = 32773;
-    private static final int DATA_LOSSY_JPEG = 34892;
-
-    /**
-     * Constants used for BitsPerSample tag.
-     * For RGB, see TIFF 6.0 Spec Section 6, Differences from Palette Color Images
-     * For Greyscale, see TIFF 6.0 Spec Section 4, Differences from Bilevel Images
-     */
-    private static final int[] BITS_PER_SAMPLE_RGB = new int[] { 8, 8, 8 };
-    private static final int[] BITS_PER_SAMPLE_GREYSCALE_1 = new int[] { 4 };
-    private static final int[] BITS_PER_SAMPLE_GREYSCALE_2 = new int[] { 8 };
-
-    /**
-     * Constants used for PhotometricInterpretation tag.
-     * For White/Black, see Section 3, Color.
-     * See TIFF 6.0 Spec Section 22, Minimum Requirements for TIFF with JPEG Compression.
-     */
-    private static final int PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO = 0;
-    private static final int PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO = 1;
-    private static final int PHOTOMETRIC_INTERPRETATION_RGB = 2;
-    private static final int PHOTOMETRIC_INTERPRETATION_YCBCR = 6;
-
-    /**
-     * Constants used for NewSubfileType tag.
-     * See TIFF 6.0 Spec Section 8
-     * */
-    private static final int ORIGINAL_RESOLUTION_IMAGE = 0;
-    private static final int REDUCED_RESOLUTION_IMAGE = 1;
-
     // A class for indicating EXIF rational type.
     private static class Rational {
         public final long numerator;
@@ -1009,7 +3384,7 @@
             new ExifTag(TAG_F_NUMBER, 33437, IFD_FORMAT_URATIONAL),
             new ExifTag(TAG_EXPOSURE_PROGRAM, 34850, IFD_FORMAT_USHORT),
             new ExifTag(TAG_SPECTRAL_SENSITIVITY, 34852, IFD_FORMAT_STRING),
-            new ExifTag(TAG_ISO_SPEED_RATINGS, 34855, IFD_FORMAT_USHORT),
+            new ExifTag(TAG_PHOTOGRAPHIC_SENSITIVITY, 34855, IFD_FORMAT_USHORT),
             new ExifTag(TAG_OECF, 34856, IFD_FORMAT_UNDEFINED),
             new ExifTag(TAG_EXIF_VERSION, 36864, IFD_FORMAT_STRING),
             new ExifTag(TAG_DATETIME_ORIGINAL, 36867, IFD_FORMAT_STRING),
@@ -1713,6 +4088,55 @@
     }
 
     /**
+     * Returns if the current image orientation is flipped.
+     *
+     * @see #getRotationDegrees()
+     */
+    public boolean isFlipped() {
+        int orientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
+        switch (orientation) {
+            case ORIENTATION_FLIP_HORIZONTAL:
+            case ORIENTATION_TRANSVERSE:
+            case ORIENTATION_FLIP_VERTICAL:
+            case ORIENTATION_TRANSPOSE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    /**
+     * Returns the rotation degrees for the current image orientation. If the image is flipped,
+     * i.e., {@link #isFlipped()} returns {@code true}, the rotation degrees will be base on
+     * the assumption that the image is first flipped horizontally (along Y-axis), and then do
+     * the rotation. For example, {@link #ORIENTATION_TRANSPOSE} will be interpreted as flipped
+     * horizontally first, and then rotate 270 degrees clockwise.
+     *
+     * @return The rotation degrees of the image after the horizontal flipping is applied, if any.
+     *
+     * @see #isFlipped()
+     */
+    public int getRotationDegrees() {
+        int orientation = getAttributeInt(TAG_ORIENTATION, ORIENTATION_NORMAL);
+        switch (orientation) {
+            case ORIENTATION_ROTATE_90:
+            case ORIENTATION_TRANSVERSE:
+                return 90;
+            case ORIENTATION_ROTATE_180:
+            case ORIENTATION_FLIP_VERTICAL:
+                return 180;
+            case ORIENTATION_ROTATE_270:
+            case ORIENTATION_TRANSPOSE:
+                return 270;
+            case ORIENTATION_UNDEFINED:
+            case ORIENTATION_NORMAL:
+            case ORIENTATION_FLIP_HORIZONTAL:
+            default:
+                return 0;
+        }
+    }
+
+    /**
      * Update the values of the tags in the tag groups if any value for the tag already was stored.
      *
      * @param tag the name of the tag.
@@ -2674,10 +5098,10 @@
         ExifAttribute rw2IsoAttribute =
                 (ExifAttribute) mAttributes[IFD_TYPE_PRIMARY].get(TAG_RW2_ISO);
         ExifAttribute exifIsoAttribute =
-                (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_ISO_SPEED_RATINGS);
+                (ExifAttribute) mAttributes[IFD_TYPE_EXIF].get(TAG_PHOTOGRAPHIC_SENSITIVITY);
         if (rw2IsoAttribute != null && exifIsoAttribute == null) {
             // Place this attribute only if it doesn't exist
-            mAttributes[IFD_TYPE_EXIF].put(TAG_ISO_SPEED_RATINGS, rw2IsoAttribute);
+            mAttributes[IFD_TYPE_EXIF].put(TAG_PHOTOGRAPHIC_SENSITIVITY, rw2IsoAttribute);
         }
     }
 
diff --git a/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java b/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
index d58a79f..4c6018f 100644
--- a/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
+++ b/exifinterface/tests/src/android/support/media/ExifInterfaceTest.java
@@ -32,6 +32,7 @@
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 import android.util.Log;
+import android.util.Pair;
 
 import org.junit.After;
 import org.junit.Before;
@@ -48,6 +49,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
+import java.util.HashMap;
 import java.util.Random;
 import java.util.concurrent.TimeUnit;
 
@@ -168,6 +170,27 @@
             {ExifInterface.ORIENTATION_TRANSPOSE, ExifInterface.ORIENTATION_ROTATE_90},
             {ExifInterface.ORIENTATION_TRANSVERSE, ExifInterface.ORIENTATION_ROTATE_270}
     };
+    private static final HashMap<Integer, Pair> FLIP_STATE_AND_ROTATION_DEGREES = new HashMap<>();
+    static {
+        FLIP_STATE_AND_ROTATION_DEGREES.put(
+                ExifInterface.ORIENTATION_UNDEFINED, new Pair(false, 0));
+        FLIP_STATE_AND_ROTATION_DEGREES.put(
+                ExifInterface.ORIENTATION_NORMAL, new Pair(false, 0));
+        FLIP_STATE_AND_ROTATION_DEGREES.put(
+                ExifInterface.ORIENTATION_ROTATE_90, new Pair(false, 90));
+        FLIP_STATE_AND_ROTATION_DEGREES.put(
+                ExifInterface.ORIENTATION_ROTATE_180, new Pair(false, 180));
+        FLIP_STATE_AND_ROTATION_DEGREES.put(
+                ExifInterface.ORIENTATION_ROTATE_270, new Pair(false, 270));
+        FLIP_STATE_AND_ROTATION_DEGREES.put(
+                ExifInterface.ORIENTATION_FLIP_HORIZONTAL, new Pair(true, 0));
+        FLIP_STATE_AND_ROTATION_DEGREES.put(
+                ExifInterface.ORIENTATION_TRANSVERSE, new Pair(true, 90));
+        FLIP_STATE_AND_ROTATION_DEGREES.put(
+                ExifInterface.ORIENTATION_FLIP_VERTICAL, new Pair(true, 180));
+        FLIP_STATE_AND_ROTATION_DEGREES.put(
+                ExifInterface.ORIENTATION_TRANSPOSE, new Pair(true, 270));
+    }
 
     private static final String[] EXIF_TAGS = {
             ExifInterface.TAG_MAKE,
@@ -581,6 +604,16 @@
             assertIntTag(exif, ExifInterface.TAG_ORIENTATION, TEST_ROTATION_STATE_MACHINE[num][2]);
         }
 
+        // Test get flip state and rotation degrees.
+        for (Integer key : FLIP_STATE_AND_ROTATION_DEGREES.keySet()) {
+            exif.setAttribute(ExifInterface.TAG_ORIENTATION, key.toString());
+            exif.saveAttributes();
+            exif = new ExifInterface(imageFile.getAbsolutePath());
+            assertEquals(FLIP_STATE_AND_ROTATION_DEGREES.get(key).first, exif.isFlipped());
+            assertEquals(FLIP_STATE_AND_ROTATION_DEGREES.get(key).second,
+                    exif.getRotationDegrees());
+        }
+
         // Test reset the rotation.
         exif.setAttribute(ExifInterface.TAG_ORIENTATION,
                 Integer.toString(ExifInterface.ORIENTATION_FLIP_HORIZONTAL));
diff --git a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java
index 22267884..4da1e74 100644
--- a/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java
+++ b/samples/Support4Demos/src/com/example/android/supportv4/app/LoaderCustomSupport.java
@@ -34,7 +34,6 @@
 import android.support.v4.content.AsyncTaskLoader;
 import android.support.v4.content.ContextCompat;
 import android.support.v4.content.Loader;
-import android.support.v4.content.pm.ActivityInfoCompat;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -166,8 +165,8 @@
         boolean applyNewConfig(Resources res) {
             int configChanges = mLastConfiguration.updateFrom(res.getConfiguration());
             boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi;
-            if (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE
-                    |ActivityInfoCompat.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) {
+            if (densityChanged || (configChanges & (ActivityInfo.CONFIG_LOCALE
+                    | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) {
                 mLastDensity = res.getDisplayMetrics().densityDpi;
                 return true;
             }
diff --git a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
index 6869e46..02d2a58 100644
--- a/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
+++ b/samples/SupportLeanbackJank/src/com/google/android/leanbackjank/ui/MainFragment.java
@@ -144,6 +144,11 @@
             }
         };
         listRowPresenter.setShadowEnabled(!disableShadows);
+        // see b/64451726, leanback bug causes child rounded corner is incorrectly disabled when
+        // shadow is disabled. To make the test data consistent and comparable, by default treat
+        // the rounded corner option same as shadow option.
+        boolean disableRoundedCorner = disableShadows;
+        listRowPresenter.enableChildRoundedCorners(!disableRoundedCorner);
         mRowsAdapter = new ArrayObjectAdapter(listRowPresenter);
         HashMap<String, List<VideoInfo>> data = VideoProvider.buildMedia(categoryCount,
                 entriesPerCat, cardWidth, cardHeight, getActivity(), useSingleBitmap);
diff --git a/v17/leanback/res/values-az/strings.xml b/v17/leanback/res/values-az/strings.xml
index 31d4304..7d5aa7b 100644
--- a/v17/leanback/res/values-az/strings.xml
+++ b/v17/leanback/res/values-az/strings.xml
@@ -27,7 +27,7 @@
     <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
     <string name="lb_playback_controls_play" msgid="731953341987346903">"Oyun"</string>
     <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Pauza"</string>
-    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"İrəli Ötürmə"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"İrəli ötürmə"</string>
     <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"İrəli sarı %1$dX"</string>
     <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Geri ötürmə"</string>
     <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Geri sarı %1$dX"</string>
diff --git a/v17/leanback/res/values-en-rXC/strings.xml b/v17/leanback/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..92f9b9a
--- /dev/null
+++ b/v17/leanback/res/values-en-rXC/strings.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="lb_navigation_menu_contentDescription" msgid="6215811486591629025">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‎‎‏‎Navigation menu‎‏‎‎‏‎"</string>
+    <string name="orb_search_action" msgid="5651268540267663887">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎Search Action‎‏‎‎‏‎"</string>
+    <string name="lb_search_bar_hint" msgid="8325490927970116252">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‎Search‎‏‎‎‏‎"</string>
+    <string name="lb_search_bar_hint_speech" msgid="5511270823320183816">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‏‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‎‎‎‎‎‏‎‎‎‎Speak to search‎‏‎‎‏‎"</string>
+    <string name="lb_search_bar_hint_with_title" msgid="1627103380996590035">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎Search ‎‏‎‎‏‏‎<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="lb_search_bar_hint_with_title_speech" msgid="2712734639766312034">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‎‎‏‎‏‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‎‏‏‎‎‎‏‎‎Speak to search ‎‏‎‎‏‏‎<xliff:g id="SEARCH_CONTEXT">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="lb_control_display_fast_forward_multiplier" msgid="4541442045214207774">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎%1$dX‎‏‎‎‏‎"</string>
+    <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎%1$dX‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_play" msgid="731953341987346903">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‏‎Play‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_pause" msgid="6189521112079849518">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎Pause‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎Fast Forward‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‏‎‎Fast Forward %1$dX‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‎Rewind‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‏‎‎‏‎‏‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‎‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‎‏‎‏‏‎‎Rewind %1$dX‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‎‎‏‎‎‎‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‎‏‏‏‎‎‎Skip Next‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‎Skip Previous‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎More Actions‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‎‎‏‎Deselect Thumb Up‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎‎Select Thumb Up‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‏‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‎‏‏‎‏‏‏‏‎‏‎Deselect Thumb Down‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎Select Thumb Down‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎Repeat None‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_repeat_all" msgid="6730354406289599000">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‎‎‎‏‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‏‎‏‎‎‎‎‏‏‎‎‎‎Repeat All‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_repeat_one" msgid="3285202316452203619">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‎‎‏‏‎‎‎‏‏‎Repeat One‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_shuffle_enable" msgid="1099874107835264529">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‎‏‎Enable Shuffle‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_shuffle_disable" msgid="8388150597335115226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‎‏‎‎Disable Shuffle‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_high_quality_enable" msgid="202415780019335254">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‎‏‏‎‎Enable High Quality‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_high_quality_disable" msgid="8637371582779057866">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‎‎‏‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎Disable High Quality‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_closed_captioning_enable" msgid="2429655367176440226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‏‎‏‎‎‎‏‎‎Enable Closed Captioning‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_closed_captioning_disable" msgid="6133362019475930048">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‎‎‎‎Disable Closed Captioning‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_picture_in_picture" msgid="3040035547765350690">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‎‎‏‏‏‎‏‎‎‏‎‎‎‎‏‎‎‏‎‎‎‏‎‎Enter Picture In Picture Mode‎‏‎‎‏‎"</string>
+    <string name="lb_playback_time_separator" msgid="3208380806582304911">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‏‎‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‎‎‎‏‏‏‏‎/‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_shown" msgid="6382160135512023238">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‎Media controls shown‎‏‎‎‏‎"</string>
+    <string name="lb_playback_controls_hidden" msgid="8940984081242033574">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎‎‎‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‏‎‎‏‏‎‎Media controls hidden, press d-pad to show‎‏‎‎‏‎"</string>
+    <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‎‎‏‎‏‎Finish‎‏‎‎‏‎"</string>
+    <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‎Continue‎‏‎‎‏‎"</string>
+    <string name="lb_media_player_error" msgid="3650250994187305396">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‎‎‏‏‎‏‏‎‏‎‎‎MediaPlayer error code %1$d extra %2$d‎‏‎‎‏‎"</string>
+    <string name="lb_onboarding_get_started" msgid="6961440391306351139">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‎‎‏‎‎‏‎‎‏‏‏‎‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎GET STARTED‎‏‎‎‏‎"</string>
+    <string name="lb_onboarding_accessibility_next" msgid="2918313444257732434">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‎‏‎‏‎‎‏‎‎Next‎‏‎‎‏‎"</string>
+</resources>
diff --git a/v17/leanback/res/values-ka/strings.xml b/v17/leanback/res/values-ka/strings.xml
index c561923..7ca9ff8 100644
--- a/v17/leanback/res/values-ka/strings.xml
+++ b/v17/leanback/res/values-ka/strings.xml
@@ -28,13 +28,9 @@
     <string name="lb_playback_controls_play" msgid="731953341987346903">"დაკვრა"</string>
     <string name="lb_playback_controls_pause" msgid="6189521112079849518">"პაუზა"</string>
     <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"წინ გადახვევა"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for lb_playback_controls_fast_forward_multiplier (1058753672110224526) -->
-    <skip />
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"სწრაფი გადამისამართება %1$dX"</string>
     <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"უკან გადახვევა"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for lb_playback_controls_rewind_multiplier (1640629531440849942) -->
-    <skip />
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"გადახვევა %1$dX"</string>
     <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"შემდეგის გამოტოვება"</string>
     <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"წინას გამოტოვება"</string>
     <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"დამატებითი ქმედებები"</string>
diff --git a/v17/leanback/res/values-ky/strings.xml b/v17/leanback/res/values-ky/strings.xml
index 574adae..e368e06 100644
--- a/v17/leanback/res/values-ky/strings.xml
+++ b/v17/leanback/res/values-ky/strings.xml
@@ -34,8 +34,8 @@
     <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"Кийинкини өткөрүп жиберүү"</string>
     <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"Мурункуну өткөрүп жиберүү"</string>
     <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"Дагы көнүгүүлөр"</string>
-    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"Жактырууну тандоодон чыгаруу"</string>
-    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Жактырууну тандоо"</string>
+    <string name="lb_playback_controls_thumb_up" msgid="6530420347129222601">"\"Жакты\" белгисин өчүрүү"</string>
+    <string name="lb_playback_controls_thumb_up_outline" msgid="1577637924003500946">"Жакты деп белгилөө"</string>
     <string name="lb_playback_controls_thumb_down" msgid="4498041193172964797">"Жактырбоону тандоодон чыгаруу"</string>
     <string name="lb_playback_controls_thumb_down_outline" msgid="2936020280629424365">"Жактырбоону тандоо"</string>
     <string name="lb_playback_controls_repeat_none" msgid="87476947476529036">"Эч бирин кайталабоо"</string>
diff --git a/v17/leanback/res/values-mk/strings.xml b/v17/leanback/res/values-mk/strings.xml
index 5284f64..8d6b89e 100644
--- a/v17/leanback/res/values-mk/strings.xml
+++ b/v17/leanback/res/values-mk/strings.xml
@@ -27,7 +27,7 @@
     <string name="lb_control_display_rewind_multiplier" msgid="3097220783222910245">"%1$dX"</string>
     <string name="lb_playback_controls_play" msgid="731953341987346903">"Пушти"</string>
     <string name="lb_playback_controls_pause" msgid="6189521112079849518">"Пауза"</string>
-    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Брзо премотај напред"</string>
+    <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"Премотај напред"</string>
     <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"Премотај напред %1$dX"</string>
     <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"Премотај назад"</string>
     <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"Премотај назад %1$dX"</string>
diff --git a/v17/leanback/res/values-ne/strings.xml b/v17/leanback/res/values-ne/strings.xml
index 0f1b784..fb071a7 100644
--- a/v17/leanback/res/values-ne/strings.xml
+++ b/v17/leanback/res/values-ne/strings.xml
@@ -28,11 +28,9 @@
     <string name="lb_playback_controls_play" msgid="731953341987346903">"प्ले गर्नुहोस्"</string>
     <string name="lb_playback_controls_pause" msgid="6189521112079849518">"रोक्नुहोस्"</string>
     <string name="lb_playback_controls_fast_forward" msgid="8569951318244687220">"फास्ट फर्वार्ड"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for lb_playback_controls_fast_forward_multiplier (1058753672110224526) -->
-    <skip />
-    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"दोहोर्याउनुहोस्"</string>
-    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"पुन: वाइन्ड गर्नुहोस् %1$dX"</string>
+    <string name="lb_playback_controls_fast_forward_multiplier" msgid="1058753672110224526">"द्रूत फर्वार्ड %1$dX"</string>
+    <string name="lb_playback_controls_rewind" msgid="2227196334132350684">"रिवाइन्ड गर्नुहोस्"</string>
+    <string name="lb_playback_controls_rewind_multiplier" msgid="1640629531440849942">"रिवाइन्ड गर्नुहोस् %1$dX"</string>
     <string name="lb_playback_controls_skip_next" msgid="2946499493161095772">"अर्को छोड्नुहोस्"</string>
     <string name="lb_playback_controls_skip_previous" msgid="2326801832933178348">"अघिल्लो छोड्नुहोस्"</string>
     <string name="lb_playback_controls_more_actions" msgid="2330770008796987655">"थप कार्यहरू"</string>
diff --git a/v17/leanback/res/values-uz/strings.xml b/v17/leanback/res/values-uz/strings.xml
index ac9adaa..ab6542d 100644
--- a/v17/leanback/res/values-uz/strings.xml
+++ b/v17/leanback/res/values-uz/strings.xml
@@ -53,7 +53,7 @@
     <string name="lb_playback_controls_hidden" msgid="8940984081242033574">"Boshqaruv elementlari berkitilgan, ochish uchun D-pad tugmasini bosing"</string>
     <string name="lb_guidedaction_finish_title" msgid="4015190340667946245">"Tugatish"</string>
     <string name="lb_guidedaction_continue_title" msgid="8842094924543063706">"Davom etish"</string>
-    <string name="lb_media_player_error" msgid="3650250994187305396">"MediaPlayer xatosi kodi: %1$d, %2$d"</string>
+    <string name="lb_media_player_error" msgid="3650250994187305396">"Media pleyer xatoligi kodi: %1$d (yana: %2$d)"</string>
     <string name="lb_onboarding_get_started" msgid="6961440391306351139">"BOSHLADIK"</string>
     <string name="lb_onboarding_accessibility_next" msgid="2918313444257732434">"Keyingisi"</string>
 </resources>
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java b/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
index 8f0c66e..53b27c6 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ImageCardView.java
@@ -13,6 +13,7 @@
  */
 package android.support.v17.leanback.widget;
 
+import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
@@ -122,12 +123,15 @@
     public static final int CARD_TYPE_FLAG_ICON_RIGHT = 4;
     public static final int CARD_TYPE_FLAG_ICON_LEFT = 8;
 
+    private static final String ALPHA = "alpha";
+
     private ImageView mImageView;
     private ViewGroup mInfoArea;
     private TextView mTitleView;
     private TextView mContentView;
     private ImageView mBadgeImage;
     private boolean mAttachedToWindow;
+    ObjectAnimator mFadeInAnimator;
 
     /**
      * Create an ImageCardView using a given theme for customization.
@@ -179,6 +183,10 @@
         if (mImageView.getDrawable() == null) {
             mImageView.setVisibility(View.INVISIBLE);
         }
+        // Set Object Animator for image view.
+        mFadeInAnimator = ObjectAnimator.ofFloat(mImageView, ALPHA, 1f);
+        mFadeInAnimator.setDuration(
+                mImageView.getResources().getInteger(android.R.integer.config_shortAnimTime));
 
         mInfoArea = findViewById(R.id.info_field);
         if (hasImageOnly) {
@@ -324,7 +332,7 @@
 
         mImageView.setImageDrawable(drawable);
         if (drawable == null) {
-            mImageView.animate().cancel();
+            mFadeInAnimator.cancel();
             mImageView.setAlpha(1f);
             mImageView.setVisibility(View.INVISIBLE);
         } else {
@@ -332,7 +340,7 @@
             if (fade) {
                 fadeIn();
             } else {
-                mImageView.animate().cancel();
+                mFadeInAnimator.cancel();
                 mImageView.setAlpha(1f);
             }
         }
@@ -458,8 +466,7 @@
     private void fadeIn() {
         mImageView.setAlpha(0f);
         if (mAttachedToWindow) {
-            mImageView.animate().alpha(1f).setDuration(
-                    mImageView.getResources().getInteger(android.R.integer.config_shortAnimTime));
+            mFadeInAnimator.start();
         }
     }
 
@@ -480,9 +487,8 @@
     @Override
     protected void onDetachedFromWindow() {
         mAttachedToWindow = false;
-        mImageView.animate().cancel();
+        mFadeInAnimator.cancel();
         mImageView.setAlpha(1f);
         super.onDetachedFromWindow();
     }
-
 }
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
index 06288dc..b1187be 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayContainer.java
@@ -296,7 +296,7 @@
         } else {
             addView(view);
         }
-        if (mRoundedCorners && mShadowType == SHADOW_STATIC) {
+        if (mRoundedCorners && mShadowType != SHADOW_DYNAMIC) {
             RoundedRectHelper.getInstance().setClipToRoundedOutline(view, true);
         }
         mWrappedView = view;
diff --git a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java
index 8ac584d..6458cb4 100644
--- a/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java
+++ b/v17/leanback/src/android/support/v17/leanback/widget/ShadowOverlayHelper.java
@@ -394,6 +394,9 @@
                     Object tag = ShadowHelper.getInstance().addDynamicShadow(
                             view, mUnfocusedZ, mFocusedZ, mRoundedCornerRadius);
                     view.setTag(R.id.lb_shadow_impl, tag);
+                } else if (mNeedsRoundedCorner) {
+                    RoundedRectHelper.getInstance().setClipToRoundedOutline(view,
+                            true, mRoundedCornerRadius);
                 }
             }
         }
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/ImageCardViewTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/ImageCardViewTest.java
new file mode 100644
index 0000000..a407e28
--- /dev/null
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/ImageCardViewTest.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright (C) 2017 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.support.v17.leanback.widget;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.v17.leanback.R;
+import android.support.v17.leanback.app.TestActivity;
+import android.support.v17.leanback.testutils.PollingCheck;
+import android.view.View;
+import android.widget.ImageView;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ImageCardViewTest {
+
+    private static final String IMAGE_CARD_VIEW_ACTIVITY = "ImageCardViewActivity";
+    private static final float FINAL_ALPHA_STATE = 1.0f;
+    private static final float INITIAL_ALPHA_STATE = 0.0f;
+    private static final float DELTA = 0.0f;
+    private static final long ANIMATION_DURATION = 5000;
+    private static final int RANDOM_COLOR_ONE = 0xffffffff;
+    private static final int RANDOM_COLOR_TWO = 0x00000000;
+
+    @Rule
+    public TestName mUnitTestName = new TestName();
+
+    // Enable lifecycle based testing
+    private TestActivity.TestActivityTestRule mRule;
+
+    // Only support alpha animation
+    private static final String ALPHA = "alpha";
+
+    // Flag to represent if the callback has been called or not
+    private boolean mOnAnimationStartCalled;
+    private boolean mOnAnimationPauseCalled;
+    private boolean mOnAnimationResumeCalled;
+    private boolean mOnAnimationCancelCalled;
+    private boolean mOnAnimationEndCalled;
+    private boolean mOnAnimationRepeatCalled;
+
+    // ImageCardView for testing.
+    private ImageCardView mImageCardView;
+
+    // Animator for testing.
+    private ObjectAnimator mFadeInAnimator;
+
+    // ImageView on ImageCardView;
+    private ImageView mImageView;
+
+    // Sample Drawable which will be used as the parameter for some methods.
+    private Drawable mSampleDrawable;
+
+    // Another Sample Drawable.
+    private Drawable mSampleDrawable2;
+
+    // Generated Image View Id.
+    private int mImageCardViewId;
+
+    // Listener to capture animator's state
+    private AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationStart(Animator animation) {
+            super.onAnimationStart(animation);
+            mOnAnimationStartCalled = true;
+        }
+
+        @Override
+        public void onAnimationPause(Animator animation) {
+            super.onAnimationPause(animation);
+            mOnAnimationPauseCalled = true;
+        }
+
+        @Override
+        public void onAnimationResume(Animator animation) {
+            super.onAnimationResume(animation);
+            mOnAnimationResumeCalled = true; }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            super.onAnimationCancel(animation);
+            mOnAnimationCancelCalled = true;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            super.onAnimationEnd(animation);
+            mOnAnimationEndCalled = true;
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+            super.onAnimationRepeat(animation);
+            mOnAnimationRepeatCalled = true;
+        }
+    };
+
+    // Set up before executing test cases.
+    @Before
+    public void setUp() throws Exception {
+        // The following provider will create an Activity which can inflate the ImageCardView
+        // And the ImageCardView can be fetched through ID for future testing.
+        TestActivity.Provider imageCardViewProvider = new TestActivity.Provider() {
+            @Override
+            public void onCreate(TestActivity activity, Bundle savedInstanceState) {
+                super.onCreate(activity, savedInstanceState);
+
+                // The theme must be set to make sure imageCardView can be populated correctly.
+                activity.setTheme(R.style.Widget_Leanback_ImageCardView_BadgeStyle);
+
+                // Create Drawable using random color for test purpose.
+                mSampleDrawable = new ColorDrawable(RANDOM_COLOR_ONE);
+
+                // Create Drawable using random color for test purpose.
+                mSampleDrawable2 = new ColorDrawable(RANDOM_COLOR_TWO);
+
+                // Create imageCardView and save system generated ID.
+                ImageCardView imageCardView = new ImageCardView(activity);
+                mImageCardViewId = imageCardView.generateViewId();
+                imageCardView.setId(mImageCardViewId);
+
+                // Set up imageCardView with activity programmatically.
+                activity.setContentView(imageCardView);
+            }
+        };
+
+        // Initialize testing rule and testing activity
+        mRule = new TestActivity.TestActivityTestRule(imageCardViewProvider, generateProviderName(
+                IMAGE_CARD_VIEW_ACTIVITY));
+        final TestActivity imageCardViewTestActivity = mRule.launchActivity();
+
+        // Create card view and image view
+        mImageCardView = (ImageCardView) imageCardViewTestActivity.findViewById(mImageCardViewId);
+        mImageView = mImageCardView.getMainImageView();
+
+        // Create animator.
+        mFadeInAnimator = mImageCardView.mFadeInAnimator;
+        mFadeInAnimator.addListener(mAnimatorListener);
+
+        // Set animation duration with longer period of time for robust testing.
+        mFadeInAnimator.setDuration(ANIMATION_DURATION);
+    }
+
+    /**
+     * Test SetMainImage method when the parameters are null and false
+     *
+     * @throws Throwable
+     */
+    @Test
+    public void testSetMainImageTest0() throws Throwable {
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+
+                // set random alpha value initially
+                mImageView.setAlpha(generateInitialialAlphaValue());
+                mImageCardView.setMainImage(null, false);
+
+                // Currently, the animation hasn't started yet, the cancel event will not be
+                // triggered
+                assertFalse(mOnAnimationCancelCalled);
+
+                // The animation will not be started, check status immediately.
+                assertEquals(mImageCardView.getMainImage(), null);
+                assertEquals(mImageView.getAlpha(), FINAL_ALPHA_STATE, DELTA);
+                assertEquals(mImageView.getVisibility(), View.INVISIBLE);
+            }
+        });
+    }
+
+    /**
+     * Test SetMainImage method when the parameters are mSampleDrawable and false
+     *
+     * @throws Throwable
+     */
+    @Test
+    public void testSetMainImageTest1() throws Throwable {
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+
+                // set random alpha value initially
+                mImageView.setAlpha(generateInitialialAlphaValue());
+                mImageCardView.setMainImage(mSampleDrawable, false);
+
+                // Currently, the animation hasn't started yet, the cancel event will not be
+                // triggered
+                assertFalse(mOnAnimationCancelCalled);
+
+                // The animation will not be started, check status immediately.
+                assertEquals(mImageCardView.getMainImage(), mSampleDrawable);
+                assertEquals(mImageView.getAlpha(), FINAL_ALPHA_STATE, DELTA);
+                assertEquals(mImageView.getVisibility(), View.VISIBLE);
+            }
+        });
+    }
+
+    /**
+     * Test SetMainImage method when the parameters are null and true
+     *
+     * @throws Throwable
+     */
+    @Test
+    public void testSetMainImageTest2() throws Throwable {
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+
+                // set random alpha value initially
+                mImageView.setAlpha(generateInitialialAlphaValue());
+                mImageCardView.setMainImage(null, true);
+
+                // Currently, the animation hasn't started yet, the cancel event will not be
+                // triggered
+                assertFalse(mOnAnimationCancelCalled);
+
+                // The animation will not be started, check status immediately.
+                assertEquals(mImageCardView.getMainImage(), null);
+                assertEquals(mImageView.getAlpha(), FINAL_ALPHA_STATE, DELTA);
+                assertEquals(mImageView.getVisibility(), View.INVISIBLE);
+            }
+        });
+    }
+
+    /**
+     * Test SetMainImage method with sample drawable object and true parameter
+     *
+     * @throws Throwable
+     */
+    @Test
+    public void testSetMainImageTest3() throws Throwable {
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+
+                // set random alpha value initially
+                mImageView.setAlpha(generateInitialialAlphaValue());
+                mImageCardView.setMainImage(mSampleDrawable, true);
+
+                // The fadeIn method should be triggered in this scenario
+                assertTrue(mOnAnimationStartCalled);
+
+                assertEquals(mImageCardView.getMainImage(), mSampleDrawable);
+                assertEquals(mImageView.getVisibility(), View.VISIBLE);
+            }
+        });
+
+        // Set time out limitation to be 2 * ANIMATION_DURATION.
+        PollingCheck.waitFor(2 * ANIMATION_DURATION, new PollingCheck.PollingCheckCondition() {
+            @Override
+            public boolean canProceed() {
+                return mOnAnimationEndCalled;
+            }
+        });
+
+        // Test if animation ended successfully through alpha value.
+        assertTrue(mOnAnimationEndCalled);
+        assertEquals(mImageView.getAlpha(), FINAL_ALPHA_STATE, DELTA);
+    }
+
+    /**
+     * Test SetMainImage method's behavior when the animation is already started
+     * In this test case, the parameters are set to null and false to interrupt existed animation
+     *
+     * @throws Throwable
+     */
+    @Test
+    public void testSetMainImageInTransitionTest0() throws Throwable {
+        // The transition duration before the interruption happens.
+        long durationBeforeInterruption = (long) (0.5 * ANIMATION_DURATION);
+
+        // Perform an animation firstly
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+
+                // set random alpha value initially
+                mImageView.setAlpha(generateInitialialAlphaValue());
+                mImageCardView.setMainImage(mSampleDrawable, true);
+
+                // The fadeIn method should be triggered in this scenario
+                assertTrue(mOnAnimationStartCalled);
+
+                assertEquals(mImageCardView.getMainImage(), mSampleDrawable);
+                assertEquals(mImageView.getVisibility(), View.VISIBLE);
+            }
+        });
+
+        // simulate the duration of animation
+        SystemClock.sleep(durationBeforeInterruption);
+
+        // Interrupt current animation using setMainImage(Drawable, boolean) method
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+
+                // Interrupt existed animation
+                mImageCardView.setMainImage(null, false);
+
+                // Existed animation will be cancelled immediately.
+                assertTrue(mOnAnimationCancelCalled);
+
+                // New animation will not be triggered, check the status immediately
+                assertEquals(mImageCardView.getMainImage(), null);
+                assertEquals(mImageCardView.getAlpha(), FINAL_ALPHA_STATE, DELTA);
+                assertEquals(mImageView.getVisibility(), View.INVISIBLE);
+            }
+        });
+    }
+
+    /**
+     * Test SetMainImage method's behavior when the animation is already started
+     * In this test case, the parameters are set to mSampleDrawable2 and false to interrupt
+     * existed animation
+     *
+     * @throws Throwable
+     */
+    @Test
+    public void testSetMainImageInTransitionTest1() throws Throwable {
+        // The transition duration before the interruption happens.
+        long durationBeforeInterruption = (long) (0.5 * ANIMATION_DURATION);
+
+        // Perform an animation firstly
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // set random alpha value initially
+                mImageView.setAlpha(generateInitialialAlphaValue());
+                mImageCardView.setMainImage(mSampleDrawable, true);
+
+                // The fadeIn method should be triggered in this scenario
+                assertTrue(mOnAnimationStartCalled);
+
+                assertEquals(mImageCardView.getMainImage(), mSampleDrawable);
+                assertEquals(mImageView.getVisibility(), View.VISIBLE);
+            }
+        });
+
+        // simulate the duration of animation
+        SystemClock.sleep(durationBeforeInterruption);
+
+        // Interrupt current animation using setMainImage(Drawable, boolean) method
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+
+                // Interrupt existed animation
+                mImageCardView.setMainImage(mSampleDrawable2, false);
+
+                // Existed animation will be cancelled immediately.
+                assertTrue(mOnAnimationCancelCalled);
+
+                // New animation will not be triggered, check the status immediately
+                assertEquals(mImageCardView.getMainImage(), mSampleDrawable2);
+                assertEquals(mImageCardView.getAlpha(), FINAL_ALPHA_STATE, DELTA);
+                assertEquals(mImageView.getVisibility(), View.VISIBLE);
+            }
+        });
+    }
+
+    /**
+     * Test SetMainImage method's behavior when the animation is already started
+     * In this test case, the parameters are set to null and true to interrupt existed animation
+     *
+     * @throws Throwable
+     */
+    @Test
+    public void testSetMainImageInTransitionTest2() throws Throwable {
+        // The transition duration before the interruption happens.
+        long durationBeforeInterruption = (long) (0.5 * ANIMATION_DURATION);
+
+        // Perform an animation firstly
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // set random alpha value initially
+                mImageView.setAlpha(generateInitialialAlphaValue());
+                mImageCardView.setMainImage(mSampleDrawable, true);
+
+                // The fadeIn method should be triggered in this scenario
+                assertTrue(mOnAnimationStartCalled);
+
+                assertEquals(mImageCardView.getMainImage(), mSampleDrawable);
+                assertEquals(mImageView.getVisibility(), View.VISIBLE);
+            }
+        });
+
+        // simulate the duration of animation
+        SystemClock.sleep(durationBeforeInterruption);
+
+        // Interrupt current animation using setMainImage(Drawable, boolean) method
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+
+                // Interrupt existed animation
+                mImageCardView.setMainImage(null, true);
+
+                // Existed animation will be cancelled immediately.
+                assertTrue(mOnAnimationCancelCalled);
+
+                // New animation will not be triggered, check the status immediately
+                assertEquals(mImageCardView.getMainImage(), null);
+                assertEquals(mImageCardView.getAlpha(), FINAL_ALPHA_STATE, DELTA);
+                assertEquals(mImageView.getVisibility(), View.INVISIBLE);
+            }
+        });
+    }
+
+    /**
+     * Test SetMainImage method's behavior when the animation is already started
+     * In this test case, the parameters are set to mSampleDrawable2 and true to interrupt
+     * existed animation
+     *
+     * @throws Throwable
+     */
+    @Test
+    public void testSetMainImageInTransitionTest3() throws Throwable {
+        // The transition duration before the interruption happens.
+        long durationBeforeInterruption = (long) (0.5 * ANIMATION_DURATION);
+
+        // Perform an animation firstly
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // set random alpha value initially
+                mImageView.setAlpha(generateInitialialAlphaValue());
+                mImageCardView.setMainImage(mSampleDrawable, true);
+
+                // The fadeIn method should be triggered in this scenario
+                assertTrue(mOnAnimationStartCalled);
+
+                assertEquals(mImageCardView.getMainImage(), mSampleDrawable);
+                assertEquals(mImageView.getVisibility(), View.VISIBLE);
+            }
+        });
+
+        // Simulate the duration of animation
+        SystemClock.sleep(durationBeforeInterruption);
+
+        // Interrupt current animation using setMainImage(Drawable, boolean) method
+        mRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+
+                // Interrupt existed animation
+                mImageCardView.setMainImage(mSampleDrawable2, true);
+
+                // Existed animation will not be cancelled immediately.
+                assertFalse(mOnAnimationCancelCalled);
+
+                // New animation will not be triggered, check the status immediately
+                assertEquals(mImageCardView.getMainImage(), mSampleDrawable2);
+                assertEquals(mImageView.getVisibility(), View.VISIBLE);
+            }
+        });
+
+        // Set time out limitation to be 2 * ANIMATION_DURATION.
+        PollingCheck.waitFor(2 * ANIMATION_DURATION, new PollingCheck.PollingCheckCondition() {
+            @Override
+            public boolean canProceed() {
+                return mOnAnimationEndCalled;
+            }
+        });
+
+        // Test if animation ended successfully through alpha value.
+        assertEquals(mImageView.getAlpha(), FINAL_ALPHA_STATE, DELTA);
+    }
+
+
+    // Helper function to register provider's name
+    private String generateProviderName(String name) {
+        return mUnitTestName.getMethodName() + "_" + name;
+    }
+
+    // generate random number as the initial alpha value
+    private float generateInitialialAlphaValue() {
+        Random generator = new Random();
+        return generator.nextFloat();
+    }
+}
+
+
diff --git a/v17/leanback/tests/java/android/support/v17/leanback/widget/ListRowPresenterTest.java b/v17/leanback/tests/java/android/support/v17/leanback/widget/ListRowPresenterTest.java
index 5e605d7..4919efe 100644
--- a/v17/leanback/tests/java/android/support/v17/leanback/widget/ListRowPresenterTest.java
+++ b/v17/leanback/tests/java/android/support/v17/leanback/widget/ListRowPresenterTest.java
@@ -268,12 +268,16 @@
         int mShadowOverlayContainerOverlayColor;
         float mShadowOverlayContainerOverlayZ;
         boolean mShadowOverlayContainerOpticalBounds;
+        boolean mShadowOverlayContainerClipToOutline;
         int mViewOverlayColor;
         float mViewZ;
         boolean mViewOpticalBounds;
+        boolean mViewClipToOutline;
         void expect(boolean shadowOverlayContainer, int shadowOverlayContainerOverlayColor,
                 float shadowOverlayContainerOverlayZ, boolean shadowOverlayContainerOpticalBounds,
-                int viewOverlayColor, float viewZ, boolean viewOpticalBounds) {
+                boolean shadowOverlayContainerClipToOutline,
+                int viewOverlayColor, float viewZ, boolean viewOpticalBounds,
+                boolean viewClipToOutline) {
             assertEquals(this.mShadowOverlayContainer, shadowOverlayContainer);
             assertEquals(this.mShadowOverlayContainerOverlayColor,
                     shadowOverlayContainerOverlayColor);
@@ -281,9 +285,12 @@
                     DELTA);
             assertEquals(this.mShadowOverlayContainerOpticalBounds,
                     shadowOverlayContainerOpticalBounds);
+            assertEquals(this.mShadowOverlayContainerClipToOutline,
+                    shadowOverlayContainerClipToOutline);
             assertEquals(this.mViewOverlayColor, viewOverlayColor);
             assertEquals(this.mViewZ, viewZ, DELTA);
             assertEquals(this.mViewOpticalBounds, viewOpticalBounds);
+            assertEquals(this.mViewClipToOutline, viewClipToOutline);
         }
     }
 
@@ -332,6 +339,8 @@
                     .mOverlayColor;
             result.mShadowOverlayContainerOverlayZ = ViewCompat.getZ(view);
             result.mShadowOverlayContainerOpticalBounds = view.getWidth() > 100;
+            result.mShadowOverlayContainerClipToOutline = Build.VERSION.SDK_INT >= 21
+                    ? view.getClipToOutline() : false;
         } else {
             result.mShadowOverlayContainer = false;
         }
@@ -341,6 +350,7 @@
                 : Color.TRANSPARENT;
         result.mViewZ = ViewCompat.getZ(view);
         result.mViewOpticalBounds = view.getWidth() > 100;
+        result.mViewClipToOutline = Build.VERSION.SDK_INT >= 21 ? view.getClipToOutline() : false;
         return result;
     }
 
@@ -356,16 +366,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, false);
         }
     }
 
@@ -381,16 +391,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         }
     }
 
@@ -406,16 +416,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, false);
         }
     }
 
@@ -431,16 +441,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         }
     }
 
@@ -456,16 +466,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, true);
         }
     }
 
@@ -481,16 +491,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         }
     }
 
@@ -506,16 +516,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, true);
         }
     }
 
@@ -531,16 +541,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         }
     }
 
@@ -556,16 +566,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, false);
         }
     }
 
@@ -581,16 +591,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         }
     }
 
@@ -606,16 +616,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, true,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, true, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, true,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, true, false,
+                    0, 0, false, false);
         }
     }
 
@@ -631,16 +641,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, true,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, true, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, true,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, true, false,
+                    0, 0, false, false);
         }
     }
 
@@ -656,16 +666,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, true);
         }
     }
 
@@ -681,16 +691,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         }
     }
 
@@ -706,16 +716,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, true,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, true, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, true,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, true, false,
+                    0, 0, false, true);
         }
     }
 
@@ -731,16 +741,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, true,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, true, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, true,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, true, false,
+                    0, 0, false, true);
         }
     }
 
@@ -756,16 +766,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, false);
         }
     }
 
@@ -781,16 +791,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         }
     }
 
@@ -806,16 +816,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, false);
         }
     }
 
@@ -831,16 +841,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         }
     }
 
@@ -856,16 +866,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, true);
         }
     }
 
@@ -881,16 +891,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         }
     }
 
@@ -906,16 +916,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, true);
         }
     }
 
@@ -931,16 +941,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         }
     }
 
@@ -956,16 +966,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, false);
         }
     }
 
@@ -981,16 +991,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         }
     }
 
@@ -1006,16 +1016,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, sFocusedZ, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, sFocusedZ, false, false);
         }
     }
 
@@ -1031,16 +1041,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false, false,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false, false,
+                    0, 0, false, false);
         }
     }
 
@@ -1056,16 +1066,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, 0, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, 0, false, true);
         }
     }
 
@@ -1081,16 +1091,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, true);
         }
     }
 
@@ -1106,16 +1116,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false, true,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(false, 0, 0, false,
-                    HALF_OVERLAY_COLOR, sFocusedZ, false);
+            result.expect(false, 0, 0, false, false,
+                    HALF_OVERLAY_COLOR, sFocusedZ, false, true);
         }
     }
 
@@ -1131,16 +1141,16 @@
         final int version = Build.VERSION.SDK_INT;
         if (version < 21) {
             // nothing supported
-            result.expect(true, HALF_OVERLAY_COLOR, 0, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, 0, false, false,
+                    0, 0, false, false);
         } else if (version < 23) {
             // supports static/dynamic shadow, supports rounded corner
-            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false, true,
+                    0, 0, false, false);
         } else {
             // supports foreground
-            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false,
-                    0, 0, false);
+            result.expect(true, HALF_OVERLAY_COLOR, sFocusedZ, false, true,
+                    0, 0, false, false);
         }
     }
 
diff --git a/v7/appcompat/res/values-en-rXC/strings.xml b/v7/appcompat/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..b1d5f93
--- /dev/null
+++ b/v7/appcompat/res/values-en-rXC/strings.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2012 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="abc_action_mode_done" msgid="4076576682505996667">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎Done‎‏‎‎‏‎"</string>
+    <string name="abc_action_bar_home_description" msgid="4600421777120114993">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‏‎Navigate home‎‏‎‎‏‎"</string>
+    <string name="abc_action_bar_up_description" msgid="1594238315039666878">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‏‏‎‎Navigate up‎‏‎‎‏‎"</string>
+    <string name="abc_action_menu_overflow_description" msgid="3588849162933574182">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‏‏‏‎‏‎‎‎‏‏‎‏‎‎‎‏‎‎‏‏‎‎More options‎‏‎‎‏‎"</string>
+    <string name="abc_toolbar_collapse_description" msgid="1603543279005712093">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎Collapse‎‏‎‎‏‎"</string>
+    <string name="abc_searchview_description_search" msgid="8264924765203268293">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‏‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‏‎‏‎Search‎‏‎‎‏‎"</string>
+    <string name="abc_search_hint" msgid="7723749260725869598">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎Search…‎‏‎‎‏‎"</string>
+    <string name="abc_searchview_description_query" msgid="2550479030709304392">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‎‎‎‎‏‎‏‎‏‏‏‏‎‎‎‏‎‎‏‎‎‎‎Search query‎‏‎‎‏‎"</string>
+    <string name="abc_searchview_description_clear" msgid="3691816814315814921">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‎‎‏‎Clear query‎‏‎‎‏‎"</string>
+    <string name="abc_searchview_description_submit" msgid="8928215447528550784">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‎‎‎‎‎‎‎Submit query‎‏‎‎‏‎"</string>
+    <string name="abc_searchview_description_voice" msgid="893419373245838918">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‎Voice search‎‏‎‎‏‎"</string>
+    <string name="abc_activitychooserview_choose_application" msgid="2031811694353399454">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‏‏‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‏‏‏‎‏‎‎‏‏‏‏‎‎Choose an app‎‏‎‎‏‎"</string>
+    <string name="abc_activity_chooser_view_see_all" msgid="7468859129482906941">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‎See all‎‏‎‎‏‎"</string>
+    <string name="abc_shareactionprovider_share_with_application" msgid="3300176832234831527">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎Share with ‎‏‎‎‏‏‎<xliff:g id="APPLICATION_NAME">%s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="abc_shareactionprovider_share_with" msgid="3421042268587513524">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎‏‏‎‏‎‎‎Share with‎‏‎‎‏‎"</string>
+    <string name="abc_capital_on" msgid="3405795526292276155">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎‏‏‎ON‎‏‎‎‏‎"</string>
+    <string name="abc_capital_off" msgid="121134116657445385">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‎‏‎‎‏‎OFF‎‏‎‎‏‎"</string>
+    <string name="search_menu_title" msgid="146198913615257606">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‎‎‎‎‎‎‏‏‎‎Search‎‏‎‎‏‎"</string>
+</resources>
diff --git a/v7/appcompat/src/android/support/v7/app/AlertController.java b/v7/appcompat/src/android/support/v7/app/AlertController.java
index 986baf3..5ff4537 100644
--- a/v7/appcompat/src/android/support/v7/app/AlertController.java
+++ b/v7/appcompat/src/android/support/v7/app/AlertController.java
@@ -501,10 +501,8 @@
 
             // Only show the divider if we have a title.
             View divider = null;
-            if (mMessage != null || mListView != null || hasCustomPanel) {
-                if (!hasCustomPanel) {
-                    divider = topPanel.findViewById(R.id.titleDividerNoCustom);
-                }
+            if (mMessage != null || mListView != null) {
+                divider = topPanel.findViewById(R.id.titleDividerNoCustom);
             }
 
             if (divider != null) {
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatButton.java b/v7/appcompat/src/android/support/v7/widget/AppCompatButton.java
index 2156dce..478d42d 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatButton.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatButton.java
@@ -22,7 +22,6 @@
 import android.content.res.ColorStateList;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
@@ -192,7 +191,7 @@
 
     @Override
     public void setTextSize(int unit, float size) {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             super.setTextSize(unit, size);
         } else {
             if (mTextHelper != null) {
@@ -204,7 +203,7 @@
     @Override
     protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
         super.onTextChanged(text, start, lengthBefore, lengthAfter);
-        if (mTextHelper != null && Build.VERSION.SDK_INT < 26 && mTextHelper.isAutoSizeEnabled()) {
+        if (mTextHelper != null && !PLATFORM_SUPPORTS_AUTOSIZE && mTextHelper.isAutoSizeEnabled()) {
             mTextHelper.autoSizeText();
         }
     }
@@ -216,7 +215,7 @@
     @Override
     public void setAutoSizeTextTypeWithDefaults(
             @TextViewCompat.AutoSizeTextType int autoSizeTextType) {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             super.setAutoSizeTextTypeWithDefaults(autoSizeTextType);
         } else {
             if (mTextHelper != null) {
@@ -235,7 +234,7 @@
             int autoSizeMaxTextSize,
             int autoSizeStepGranularity,
             int unit) throws IllegalArgumentException {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             super.setAutoSizeTextTypeUniformWithConfiguration(
                     autoSizeMinTextSize, autoSizeMaxTextSize, autoSizeStepGranularity, unit);
         } else {
@@ -253,7 +252,7 @@
     @Override
     public void setAutoSizeTextTypeUniformWithPresetSizes(@NonNull int[] presetSizes, int unit)
             throws IllegalArgumentException {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             super.setAutoSizeTextTypeUniformWithPresetSizes(presetSizes, unit);
         } else {
             if (mTextHelper != null) {
@@ -269,7 +268,7 @@
     @Override
     @TextViewCompat.AutoSizeTextType
     public int getAutoSizeTextType() {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             return super.getAutoSizeTextType() == TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM
                     ? TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM
                     : TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE;
@@ -287,7 +286,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int getAutoSizeStepGranularity() {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             return super.getAutoSizeStepGranularity();
         } else {
             if (mTextHelper != null) {
@@ -303,7 +302,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int getAutoSizeMinTextSize() {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             return super.getAutoSizeMinTextSize();
         } else {
             if (mTextHelper != null) {
@@ -319,7 +318,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int getAutoSizeMaxTextSize() {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             return super.getAutoSizeMaxTextSize();
         } else {
             if (mTextHelper != null) {
@@ -335,7 +334,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int[] getAutoSizeTextAvailableSizes() {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             return super.getAutoSizeTextAvailableSizes();
         } else {
             if (mTextHelper != null) {
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java b/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
index afd59bd..45b3e95 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatTextHelper.java
@@ -17,7 +17,9 @@
 package android.support.v7.widget;
 
 import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
+import static android.support.v4.widget.AutoSizeableTextView.PLATFORM_SUPPORTS_AUTOSIZE;
 
+import android.annotation.SuppressLint;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
@@ -61,6 +63,7 @@
         mAutoSizeTextHelper = new AppCompatTextViewAutoSizeHelper(mView);
     }
 
+    @SuppressLint("NewApi")
     void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
         final Context context = mView.getContext();
         final AppCompatDrawableManager drawableManager = AppCompatDrawableManager.get();
@@ -170,7 +173,7 @@
 
         mAutoSizeTextHelper.loadFromAttributes(attrs, defStyleAttr);
 
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             // Delegate auto-size functionality to the framework implementation.
             if (mAutoSizeTextHelper.getAutoSizeTextType()
                     != TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE) {
@@ -282,8 +285,7 @@
     /** @hide */
     @RestrictTo(LIBRARY_GROUP)
     void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        // Auto-size is supported by the framework starting from Android O.
-        if (!(Build.VERSION.SDK_INT >= 26)) {
+        if (!PLATFORM_SUPPORTS_AUTOSIZE) {
             autoSizeText();
         }
     }
@@ -291,7 +293,7 @@
     /** @hide */
     @RestrictTo(LIBRARY_GROUP)
     void setTextSize(int unit, float size) {
-        if (!(Build.VERSION.SDK_INT >= 26)) {
+        if (!PLATFORM_SUPPORTS_AUTOSIZE) {
             if (!isAutoSizeEnabled()) {
                 setTextSizeInternal(unit, size);
             }
diff --git a/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java b/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
index 12d0ff9..cfa6a2a 100644
--- a/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
+++ b/v7/appcompat/src/android/support/v7/widget/AppCompatTextView.java
@@ -22,7 +22,6 @@
 import android.content.res.ColorStateList;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
 import android.support.annotation.DrawableRes;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
@@ -183,7 +182,7 @@
 
     @Override
     public void setTextSize(int unit, float size) {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             super.setTextSize(unit, size);
         } else {
             if (mTextHelper != null) {
@@ -195,7 +194,7 @@
     @Override
     protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
         super.onTextChanged(text, start, lengthBefore, lengthAfter);
-        if (mTextHelper != null && Build.VERSION.SDK_INT < 26 && mTextHelper.isAutoSizeEnabled()) {
+        if (mTextHelper != null && !PLATFORM_SUPPORTS_AUTOSIZE && mTextHelper.isAutoSizeEnabled()) {
             mTextHelper.autoSizeText();
         }
     }
@@ -211,7 +210,7 @@
     @Override
     public void setAutoSizeTextTypeWithDefaults(
             @TextViewCompat.AutoSizeTextType int autoSizeTextType) {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             super.setAutoSizeTextTypeWithDefaults(autoSizeTextType);
         } else {
             if (mTextHelper != null) {
@@ -234,7 +233,7 @@
             int autoSizeMaxTextSize,
             int autoSizeStepGranularity,
             int unit) throws IllegalArgumentException {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             super.setAutoSizeTextTypeUniformWithConfiguration(
                     autoSizeMinTextSize, autoSizeMaxTextSize, autoSizeStepGranularity, unit);
         } else {
@@ -256,7 +255,7 @@
     @Override
     public void setAutoSizeTextTypeUniformWithPresetSizes(@NonNull int[] presetSizes, int unit)
             throws IllegalArgumentException {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             super.setAutoSizeTextTypeUniformWithPresetSizes(presetSizes, unit);
         } else {
             if (mTextHelper != null) {
@@ -275,7 +274,7 @@
     @Override
     @TextViewCompat.AutoSizeTextType
     public int getAutoSizeTextType() {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             return super.getAutoSizeTextType() == TextView.AUTO_SIZE_TEXT_TYPE_UNIFORM
                     ? TextViewCompat.AUTO_SIZE_TEXT_TYPE_UNIFORM
                     : TextViewCompat.AUTO_SIZE_TEXT_TYPE_NONE;
@@ -296,7 +295,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int getAutoSizeStepGranularity() {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             return super.getAutoSizeStepGranularity();
         } else {
             if (mTextHelper != null) {
@@ -315,7 +314,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int getAutoSizeMinTextSize() {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             return super.getAutoSizeMinTextSize();
         } else {
             if (mTextHelper != null) {
@@ -334,7 +333,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int getAutoSizeMaxTextSize() {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             return super.getAutoSizeMaxTextSize();
         } else {
             if (mTextHelper != null) {
@@ -353,7 +352,7 @@
     @RestrictTo(LIBRARY_GROUP)
     @Override
     public int[] getAutoSizeTextAvailableSizes() {
-        if (Build.VERSION.SDK_INT >= 26) {
+        if (PLATFORM_SUPPORTS_AUTOSIZE) {
             return super.getAutoSizeTextAvailableSizes();
         } else {
             if (mTextHelper != null) {
diff --git a/v7/mediarouter/res/values-en-rXC/strings.xml b/v7/mediarouter/res/values-en-rXC/strings.xml
new file mode 100644
index 0000000..8ed9aab
--- /dev/null
+++ b/v7/mediarouter/res/values-en-rXC/strings.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--  Copyright (C) 2013 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.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="mr_system_route_name" msgid="5441529851481176817">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‎‏‎System‎‏‎‎‏‎"</string>
+    <string name="mr_user_route_category_name" msgid="7498112907524977311">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‏‏‏‎Devices‎‏‎‎‏‎"</string>
+    <string name="mr_button_content_description" msgid="3698378085901466129">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‏‎‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎Cast button‎‏‎‎‏‎"</string>
+    <string name="mr_cast_button_disconnected" msgid="816305490427819240">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‎‏‏‎‏‎‎‏‏‏‎‏‎‎‎‎Cast button. Disconnected‎‏‎‎‏‎"</string>
+    <string name="mr_cast_button_connecting" msgid="2187642765091873834">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‎Cast button. Connecting‎‏‎‎‏‎"</string>
+    <string name="mr_cast_button_connected" msgid="5088427771788648085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‎‎‏‎‏‎‏‎Cast button. Connected‎‏‎‎‏‎"</string>
+    <string name="mr_chooser_title" msgid="414301941546135990">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎Cast to‎‏‎‎‏‎"</string>
+    <string name="mr_chooser_searching" msgid="6349900579507521956">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎Finding devices‎‏‎‎‏‎"</string>
+    <string name="mr_controller_disconnect" msgid="1227264889412989580">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‏‎‎‎‏‎‎‎‏‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‎Disconnect‎‏‎‎‏‎"</string>
+    <string name="mr_controller_stop_casting" msgid="8857886794086583226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‏‎‏‏‏‎‏‎‎Stop casting‎‏‎‎‏‎"</string>
+    <string name="mr_controller_close_description" msgid="7333862312480583260">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‏‏‎‎‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‎‎Close‎‏‎‎‏‎"</string>
+    <string name="mr_controller_play" msgid="683634565969987458">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‎‏‏‎‏‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‎Play‎‏‎‎‏‎"</string>
+    <string name="mr_controller_pause" msgid="5451884435510905406">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎Pause‎‏‎‎‏‎"</string>
+    <string name="mr_controller_stop" msgid="735874641921425123">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎Stop‎‏‎‎‏‎"</string>
+    <string name="mr_controller_expand_group" msgid="8062427022744266907">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‏‏‏‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‏‎Expand‎‏‎‎‏‎"</string>
+    <string name="mr_controller_collapse_group" msgid="7924809056904240926">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‏‏‎‎Collapse‎‏‎‎‏‎"</string>
+    <string name="mr_controller_album_art" msgid="6422801843540543585">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎Album art‎‏‎‎‏‎"</string>
+    <string name="mr_controller_volume_slider" msgid="2361785992211841709">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‎‏‎Volume slider‎‏‎‎‏‎"</string>
+    <string name="mr_controller_no_media_selected" msgid="6547130360349182381">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‏‎‎‎‎‎‏‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‎‏‎No media selected‎‏‎‎‏‎"</string>
+    <string name="mr_controller_no_info_available" msgid="5585418471741142924">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‏‎‎‎No info available‎‏‎‎‏‎"</string>
+    <string name="mr_controller_casting_screen" msgid="4868457957151124867">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎Casting screen‎‏‎‎‏‎"</string>
+</resources>
diff --git a/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java b/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
index 07eaa87..dc7a942 100644
--- a/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
+++ b/wear/tests/src/android/support/wear/widget/drawer/WearableDrawerLayoutEspressoTest.java
@@ -23,7 +23,6 @@
 import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withParent;
 import static android.support.test.espresso.matcher.ViewMatchers.withText;
 import static android.support.wear.widget.util.AsyncViewActions.waitForMatchingView;
 
@@ -337,10 +336,12 @@
         OnMenuItemClickListener mockClickListener = mock(OnMenuItemClickListener.class);
         actionDrawer.setOnMenuItemClickListener(mockClickListener);
         // WHEN the action drawer peek view is tapped
-        onView(
-                allOf(
-                        withParent(withId(R.id.action_drawer)),
-                        withId(R.id.ws_drawer_view_peek_container)))
+        onView(withId(R.id.ws_drawer_view_peek_container))
+                .perform(waitForMatchingView(
+                        allOf(
+                                withId(R.id.ws_drawer_view_peek_container),
+                                isCompletelyDisplayed()),
+                        MAX_WAIT_MS))
                 .perform(click());
         // THEN its click listener should be notified
         verify(mockClickListener).onMenuItemClick(any(MenuItem.class));