Merge "Fix issue #15195464: battery history says wakelock held when it's not" into lmp-preview-dev
diff --git a/Android.mk b/Android.mk
index de93ca2..9c41f9f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -276,6 +276,7 @@
core/java/com/android/internal/view/IInputMethodSession.aidl \
core/java/com/android/internal/view/IInputSessionCallback.aidl \
core/java/com/android/internal/widget/ILockSettings.aidl \
+ core/java/com/android/internal/widget/ILockSettingsObserver.aidl \
core/java/com/android/internal/widget/IRemoteViewsFactory.aidl \
core/java/com/android/internal/widget/IRemoteViewsAdapterConnection.aidl \
keystore/java/android/security/IKeyChainAliasCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index a021d59..a829bdf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5106,6 +5106,7 @@
method public void clearForwardingIntentFilters(android.content.ComponentName);
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
+ method public android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
method public void enableSystemApp(android.content.ComponentName, java.lang.String);
method public int enableSystemApp(android.content.ComponentName, android.content.Intent);
method public java.lang.String[] getAccountTypesWithManagementDisabled();
@@ -5139,6 +5140,7 @@
method public boolean isProfileOwnerApp(java.lang.String);
method public void lockNow();
method public void removeActiveAdmin(android.content.ComponentName);
+ method public boolean removeUser(android.content.ComponentName, android.os.UserHandle);
method public boolean resetPassword(java.lang.String, int);
method public void setAccountManagementDisabled(android.content.ComponentName, java.lang.String, boolean);
method public boolean setApplicationBlocked(android.content.ComponentName, java.lang.String, boolean);
@@ -12164,69 +12166,75 @@
}
public final class CameraCharacteristics extends android.hardware.camera2.CameraMetadata {
- method public T get(android.hardware.camera2.CameraMetadata.Key<T>);
- method public java.util.List<android.hardware.camera2.CameraMetadata.Key<?>> getAvailableCaptureRequestKeys();
- method public java.util.List<android.hardware.camera2.CameraMetadata.Key<?>> getAvailableCaptureResultKeys();
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_AVAILABLE_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_COMPENSATION_RANGE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_COMPENSATION_STEP;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_AVAILABLE_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AVAILABLE_EFFECTS;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AVAILABLE_SCENE_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_AVAILABLE_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_MAX_REGIONS;
- field public static final android.hardware.camera2.CameraMetadata.Key EDGE_AVAILABLE_EDGE_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key FLASH_INFO_AVAILABLE;
- field public static final android.hardware.camera2.CameraMetadata.Key HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key INFO_SUPPORTED_HARDWARE_LEVEL;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_AVAILABLE_THUMBNAIL_SIZES;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_FACING;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_INFO_AVAILABLE_APERTURES;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_INFO_AVAILABLE_FILTER_DENSITIES;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_INFO_AVAILABLE_FOCAL_LENGTHS;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_INFO_FOCUS_DISTANCE_CALIBRATION;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_INFO_HYPERFOCAL_DISTANCE;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_INFO_MINIMUM_FOCUS_DISTANCE;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_INFO_SHADING_MAP_SIZE;
- field public static final android.hardware.camera2.CameraMetadata.Key NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key REQUEST_AVAILABLE_CAPABILITIES;
- field public static final android.hardware.camera2.CameraMetadata.Key REQUEST_MAX_NUM_INPUT_STREAMS;
- field public static final android.hardware.camera2.CameraMetadata.Key REQUEST_MAX_NUM_OUTPUT_STREAMS;
- field public static final android.hardware.camera2.CameraMetadata.Key REQUEST_PARTIAL_RESULT_COUNT;
- field public static final android.hardware.camera2.CameraMetadata.Key REQUEST_PIPELINE_MAX_DEPTH;
- field public static final android.hardware.camera2.CameraMetadata.Key SCALER_AVAILABLE_MAX_DIGITAL_ZOOM;
- field public static final android.hardware.camera2.CameraMetadata.Key SCALER_STREAM_CONFIGURATION_MAP;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_AVAILABLE_TEST_PATTERN_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_BASE_GAIN_FACTOR;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_BLACK_LEVEL_PATTERN;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_CALIBRATION_TRANSFORM1;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_CALIBRATION_TRANSFORM2;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_COLOR_TRANSFORM1;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_COLOR_TRANSFORM2;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FORWARD_MATRIX1;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FORWARD_MATRIX2;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_ACTIVE_ARRAY_SIZE;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_COLOR_FILTER_ARRANGEMENT;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_EXPOSURE_TIME_RANGE;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_MAX_FRAME_DURATION;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_PHYSICAL_SIZE;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_PIXEL_ARRAY_SIZE;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_SENSITIVITY_RANGE;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_WHITE_LEVEL;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_MAX_ANALOG_SENSITIVITY;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_ORIENTATION;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_REFERENCE_ILLUMINANT1;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_REFERENCE_ILLUMINANT2;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_MAX_FACE_COUNT;
- field public static final android.hardware.camera2.CameraMetadata.Key SYNC_MAX_LATENCY;
- field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_AVAILABLE_TONE_MAP_MODES;
- field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_MAX_CURVE_POINTS;
+ method public T get(android.hardware.camera2.CameraCharacteristics.Key<T>);
+ method public java.util.List<android.hardware.camera2.CaptureRequest.Key<?>> getAvailableCaptureRequestKeys();
+ method public java.util.List<android.hardware.camera2.CaptureResult.Key<?>> getAvailableCaptureResultKeys();
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_AVAILABLE_ANTIBANDING_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_AVAILABLE_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_COMPENSATION_RANGE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AE_COMPENSATION_STEP;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AF_AVAILABLE_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AVAILABLE_EFFECTS;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AVAILABLE_SCENE_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_AWB_AVAILABLE_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key CONTROL_MAX_REGIONS;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key EDGE_AVAILABLE_EDGE_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key FLASH_INFO_AVAILABLE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key INFO_SUPPORTED_HARDWARE_LEVEL;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key JPEG_AVAILABLE_THUMBNAIL_SIZES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_FACING;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_AVAILABLE_APERTURES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_AVAILABLE_FILTER_DENSITIES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_AVAILABLE_FOCAL_LENGTHS;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_FOCUS_DISTANCE_CALIBRATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_HYPERFOCAL_DISTANCE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_MINIMUM_FOCUS_DISTANCE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key LENS_INFO_SHADING_MAP_SIZE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_AVAILABLE_CAPABILITIES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_MAX_NUM_INPUT_STREAMS;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_MAX_NUM_OUTPUT_STREAMS;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_PARTIAL_RESULT_COUNT;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key REQUEST_PIPELINE_MAX_DEPTH;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_AVAILABLE_MAX_DIGITAL_ZOOM;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_CROPPING_TYPE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SCALER_STREAM_CONFIGURATION_MAP;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_AVAILABLE_TEST_PATTERN_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_BLACK_LEVEL_PATTERN;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_CALIBRATION_TRANSFORM1;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_CALIBRATION_TRANSFORM2;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_COLOR_TRANSFORM1;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_COLOR_TRANSFORM2;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_FORWARD_MATRIX1;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_FORWARD_MATRIX2;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_ACTIVE_ARRAY_SIZE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_COLOR_FILTER_ARRANGEMENT;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_EXPOSURE_TIME_RANGE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_MAX_FRAME_DURATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_PHYSICAL_SIZE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_PIXEL_ARRAY_SIZE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_SENSITIVITY_RANGE;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_INFO_WHITE_LEVEL;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_MAX_ANALOG_SENSITIVITY;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_ORIENTATION;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_REFERENCE_ILLUMINANT1;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SENSOR_REFERENCE_ILLUMINANT2;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key STATISTICS_INFO_MAX_FACE_COUNT;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key SYNC_MAX_LATENCY;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key TONEMAP_AVAILABLE_TONE_MAP_MODES;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key TONEMAP_MAX_CURVE_POINTS;
+ }
+
+ public static final class CameraCharacteristics.Key {
+ method public final boolean equals(java.lang.Object);
+ method public java.lang.String getName();
+ method public final int hashCode();
}
public abstract interface CameraDevice implements java.lang.AutoCloseable {
@@ -12289,8 +12297,7 @@
}
public abstract class CameraMetadata {
- method public abstract T get(android.hardware.camera2.CameraMetadata.Key<T>);
- method public java.util.List<android.hardware.camera2.CameraMetadata.Key<?>> getKeys();
+ method public java.util.List<TKey> getKeys();
field public static final int COLOR_CORRECTION_MODE_FAST = 1; // 0x1
field public static final int COLOR_CORRECTION_MODE_HIGH_QUALITY = 2; // 0x2
field public static final int COLOR_CORRECTION_MODE_TRANSFORM_MATRIX = 0; // 0x0
@@ -12410,6 +12417,8 @@
field public static final int REQUEST_AVAILABLE_CAPABILITIES_DNG = 5; // 0x5
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 2; // 0x2
field public static final int REQUEST_AVAILABLE_CAPABILITIES_ZSL = 4; // 0x4
+ field public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0; // 0x0
+ field public static final int SCALER_CROPPING_TYPE_FREEFORM = 1; // 0x1
field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR = 3; // 0x3
field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG = 2; // 0x2
field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG = 1; // 0x1
@@ -12458,12 +12467,6 @@
field public static final int TONEMAP_MODE_HIGH_QUALITY = 2; // 0x2
}
- public static class CameraMetadata.Key {
- method public final boolean equals(java.lang.Object);
- method public final java.lang.String getName();
- method public final int hashCode();
- }
-
public class CaptureFailure {
method public int getFrameNumber();
method public int getReason();
@@ -12476,146 +12479,170 @@
public final class CaptureRequest extends android.hardware.camera2.CameraMetadata implements android.os.Parcelable {
method public int describeContents();
- method public T get(android.hardware.camera2.CameraMetadata.Key<T>);
+ method public T get(android.hardware.camera2.CaptureRequest.Key<T>);
method public java.lang.Object getTag();
method public void writeToParcel(android.os.Parcel, int);
- field public static final android.hardware.camera2.CameraMetadata.Key BLACK_LEVEL_LOCK;
- field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_GAINS;
- field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_TRANSFORM;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_ANTIBANDING_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_EXPOSURE_COMPENSATION;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_LOCK;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_PRECAPTURE_TRIGGER;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_REGIONS;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_TARGET_FPS_RANGE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_REGIONS;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_TRIGGER;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_LOCK;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_REGIONS;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_CAPTURE_INTENT;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_EFFECT_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_SCENE_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_VIDEO_STABILIZATION_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key BLACK_LEVEL_LOCK;
+ field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_GAINS;
+ field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key COLOR_CORRECTION_TRANSFORM;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_ANTIBANDING_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_EXPOSURE_COMPENSATION;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_LOCK;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_PRECAPTURE_TRIGGER;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_REGIONS;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AE_TARGET_FPS_RANGE;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AF_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AF_REGIONS;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AF_TRIGGER;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AWB_LOCK;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AWB_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_AWB_REGIONS;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_CAPTURE_INTENT;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_EFFECT_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_SCENE_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key CONTROL_VIDEO_STABILIZATION_MODE;
field public static final android.os.Parcelable.Creator CREATOR;
- field public static final android.hardware.camera2.CameraMetadata.Key EDGE_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key FLASH_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key HOT_PIXEL_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_GPS_COORDINATES;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_GPS_PROCESSING_METHOD;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_GPS_TIMESTAMP;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_ORIENTATION;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_QUALITY;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_THUMBNAIL_QUALITY;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_THUMBNAIL_SIZE;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_APERTURE;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_FILTER_DENSITY;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_FOCAL_LENGTH;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_FOCUS_DISTANCE;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_OPTICAL_STABILIZATION_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key NOISE_REDUCTION_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key SCALER_CROP_REGION;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_EXPOSURE_TIME;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FRAME_DURATION;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_SENSITIVITY;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_DATA;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key SHADING_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACE_DETECT_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_BLUE;
- field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_GREEN;
- field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_RED;
- field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key EDGE_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key FLASH_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key HOT_PIXEL_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key JPEG_GPS_COORDINATES;
+ field public static final android.hardware.camera2.CaptureRequest.Key JPEG_GPS_PROCESSING_METHOD;
+ field public static final android.hardware.camera2.CaptureRequest.Key JPEG_GPS_TIMESTAMP;
+ field public static final android.hardware.camera2.CaptureRequest.Key JPEG_ORIENTATION;
+ field public static final android.hardware.camera2.CaptureRequest.Key JPEG_QUALITY;
+ field public static final android.hardware.camera2.CaptureRequest.Key JPEG_THUMBNAIL_QUALITY;
+ field public static final android.hardware.camera2.CaptureRequest.Key JPEG_THUMBNAIL_SIZE;
+ field public static final android.hardware.camera2.CaptureRequest.Key LENS_APERTURE;
+ field public static final android.hardware.camera2.CaptureRequest.Key LENS_FILTER_DENSITY;
+ field public static final android.hardware.camera2.CaptureRequest.Key LENS_FOCAL_LENGTH;
+ field public static final android.hardware.camera2.CaptureRequest.Key LENS_FOCUS_DISTANCE;
+ field public static final android.hardware.camera2.CaptureRequest.Key LENS_OPTICAL_STABILIZATION_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key NOISE_REDUCTION_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key SCALER_CROP_REGION;
+ field public static final android.hardware.camera2.CaptureRequest.Key SENSOR_EXPOSURE_TIME;
+ field public static final android.hardware.camera2.CaptureRequest.Key SENSOR_FRAME_DURATION;
+ field public static final android.hardware.camera2.CaptureRequest.Key SENSOR_SENSITIVITY;
+ field public static final android.hardware.camera2.CaptureRequest.Key SENSOR_TEST_PATTERN_DATA;
+ field public static final android.hardware.camera2.CaptureRequest.Key SENSOR_TEST_PATTERN_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key SHADING_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key STATISTICS_FACE_DETECT_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key STATISTICS_HOT_PIXEL_MAP_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key STATISTICS_LENS_SHADING_MAP_MODE;
+ field public static final android.hardware.camera2.CaptureRequest.Key TONEMAP_CURVE_BLUE;
+ field public static final android.hardware.camera2.CaptureRequest.Key TONEMAP_CURVE_GREEN;
+ field public static final android.hardware.camera2.CaptureRequest.Key TONEMAP_CURVE_RED;
+ field public static final android.hardware.camera2.CaptureRequest.Key TONEMAP_MODE;
}
public static final class CaptureRequest.Builder {
method public void addTarget(android.view.Surface);
method public android.hardware.camera2.CaptureRequest build();
- method public T get(android.hardware.camera2.CameraMetadata.Key<T>);
+ method public T get(android.hardware.camera2.CaptureRequest.Key<T>);
method public void removeTarget(android.view.Surface);
- method public void set(android.hardware.camera2.CameraMetadata.Key<T>, T);
+ method public void set(android.hardware.camera2.CaptureRequest.Key<T>, T);
method public void setTag(java.lang.Object);
}
+ public static final class CaptureRequest.Key {
+ method public final boolean equals(java.lang.Object);
+ method public java.lang.String getName();
+ method public final int hashCode();
+ }
+
public final class CaptureResult extends android.hardware.camera2.CameraMetadata {
- method public T get(android.hardware.camera2.CameraMetadata.Key<T>);
+ method public T get(android.hardware.camera2.CaptureResult.Key<T>);
method public int getFrameNumber();
method public android.hardware.camera2.CaptureRequest getRequest();
method public int getSequenceId();
- field public static final android.hardware.camera2.CameraMetadata.Key BLACK_LEVEL_LOCK;
- field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_GAINS;
- field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key COLOR_CORRECTION_TRANSFORM;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_ANTIBANDING_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_EXPOSURE_COMPENSATION;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_LOCK;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_PRECAPTURE_TRIGGER;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_REGIONS;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_STATE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AE_TARGET_FPS_RANGE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_REGIONS;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_STATE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AF_TRIGGER;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_LOCK;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_REGIONS;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_AWB_STATE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_CAPTURE_INTENT;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_EFFECT_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_SCENE_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key CONTROL_VIDEO_STABILIZATION_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key EDGE_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key FLASH_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key FLASH_STATE;
- field public static final android.hardware.camera2.CameraMetadata.Key HOT_PIXEL_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_GPS_COORDINATES;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_GPS_PROCESSING_METHOD;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_GPS_TIMESTAMP;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_ORIENTATION;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_QUALITY;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_THUMBNAIL_QUALITY;
- field public static final android.hardware.camera2.CameraMetadata.Key JPEG_THUMBNAIL_SIZE;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_APERTURE;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_FILTER_DENSITY;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_FOCAL_LENGTH;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_FOCUS_DISTANCE;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_FOCUS_RANGE;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_OPTICAL_STABILIZATION_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key LENS_STATE;
- field public static final android.hardware.camera2.CameraMetadata.Key NOISE_REDUCTION_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key REQUEST_FRAME_COUNT;
- field public static final android.hardware.camera2.CameraMetadata.Key REQUEST_PIPELINE_DEPTH;
- field public static final android.hardware.camera2.CameraMetadata.Key SCALER_CROP_REGION;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_EXPOSURE_TIME;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FRAME_DURATION;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_GREEN_SPLIT;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_NEUTRAL_COLOR_POINT;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_SENSITIVITY;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEMPERATURE;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_DATA;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TIMESTAMP;
- field public static final android.hardware.camera2.CameraMetadata.Key SHADING_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACES;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_FACE_DETECT_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_HOT_PIXEL_MAP_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_LENS_SHADING_MAP_MODE;
- field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_SCENE_FLICKER;
- field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_BLUE;
- field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_GREEN;
- field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_CURVE_RED;
- field public static final android.hardware.camera2.CameraMetadata.Key TONEMAP_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key BLACK_LEVEL_LOCK;
+ field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_GAINS;
+ field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key COLOR_CORRECTION_TRANSFORM;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_ANTIBANDING_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_EXPOSURE_COMPENSATION;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_LOCK;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_PRECAPTURE_TRIGGER;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_REGIONS;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_STATE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AE_TARGET_FPS_RANGE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AF_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AF_REGIONS;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AF_STATE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AF_TRIGGER;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AWB_LOCK;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AWB_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AWB_REGIONS;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_AWB_STATE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_CAPTURE_INTENT;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_EFFECT_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_SCENE_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key CONTROL_VIDEO_STABILIZATION_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key EDGE_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key FLASH_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key FLASH_STATE;
+ field public static final android.hardware.camera2.CaptureResult.Key HOT_PIXEL_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key JPEG_GPS_COORDINATES;
+ field public static final android.hardware.camera2.CaptureResult.Key JPEG_GPS_PROCESSING_METHOD;
+ field public static final android.hardware.camera2.CaptureResult.Key JPEG_GPS_TIMESTAMP;
+ field public static final android.hardware.camera2.CaptureResult.Key JPEG_ORIENTATION;
+ field public static final android.hardware.camera2.CaptureResult.Key JPEG_QUALITY;
+ field public static final android.hardware.camera2.CaptureResult.Key JPEG_THUMBNAIL_QUALITY;
+ field public static final android.hardware.camera2.CaptureResult.Key JPEG_THUMBNAIL_SIZE;
+ field public static final android.hardware.camera2.CaptureResult.Key LENS_APERTURE;
+ field public static final android.hardware.camera2.CaptureResult.Key LENS_FILTER_DENSITY;
+ field public static final android.hardware.camera2.CaptureResult.Key LENS_FOCAL_LENGTH;
+ field public static final android.hardware.camera2.CaptureResult.Key LENS_FOCUS_DISTANCE;
+ field public static final android.hardware.camera2.CaptureResult.Key LENS_FOCUS_RANGE;
+ field public static final android.hardware.camera2.CaptureResult.Key LENS_OPTICAL_STABILIZATION_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key LENS_STATE;
+ field public static final android.hardware.camera2.CaptureResult.Key NOISE_REDUCTION_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key REQUEST_FRAME_COUNT;
+ field public static final android.hardware.camera2.CaptureResult.Key REQUEST_PIPELINE_DEPTH;
+ field public static final android.hardware.camera2.CaptureResult.Key SCALER_CROP_REGION;
+ field public static final android.hardware.camera2.CaptureResult.Key SENSOR_EXPOSURE_TIME;
+ field public static final android.hardware.camera2.CaptureResult.Key SENSOR_FRAME_DURATION;
+ field public static final android.hardware.camera2.CaptureResult.Key SENSOR_GREEN_SPLIT;
+ field public static final android.hardware.camera2.CaptureResult.Key SENSOR_NEUTRAL_COLOR_POINT;
+ field public static final android.hardware.camera2.CaptureResult.Key SENSOR_SENSITIVITY;
+ field public static final android.hardware.camera2.CaptureResult.Key SENSOR_TEST_PATTERN_DATA;
+ field public static final android.hardware.camera2.CaptureResult.Key SENSOR_TEST_PATTERN_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key SENSOR_TIMESTAMP;
+ field public static final android.hardware.camera2.CaptureResult.Key SHADING_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_FACES;
+ field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_FACE_DETECT_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_HOT_PIXEL_MAP;
+ field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_HOT_PIXEL_MAP_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_LENS_SHADING_MAP;
+ field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_LENS_SHADING_MAP_MODE;
+ field public static final android.hardware.camera2.CaptureResult.Key STATISTICS_SCENE_FLICKER;
+ field public static final android.hardware.camera2.CaptureResult.Key TONEMAP_CURVE_BLUE;
+ field public static final android.hardware.camera2.CaptureResult.Key TONEMAP_CURVE_GREEN;
+ field public static final android.hardware.camera2.CaptureResult.Key TONEMAP_CURVE_RED;
+ field public static final android.hardware.camera2.CaptureResult.Key TONEMAP_MODE;
+ }
+
+ public static final class CaptureResult.Key {
+ method public final boolean equals(java.lang.Object);
+ method public java.lang.String getName();
+ method public final int hashCode();
+ }
+
+ public final class DngCreator implements java.lang.AutoCloseable {
+ ctor public DngCreator(android.hardware.camera2.CameraCharacteristics, android.hardware.camera2.CaptureResult);
+ method public void close();
+ method public android.hardware.camera2.DngCreator setDescription(java.lang.String);
+ method public android.hardware.camera2.DngCreator setLocation(android.location.Location);
+ method public android.hardware.camera2.DngCreator setOrientation(int);
+ method public android.hardware.camera2.DngCreator setThumbnail(android.graphics.Bitmap);
+ method public android.hardware.camera2.DngCreator setThumbnail(android.media.Image);
+ method public void writeByteBuffer(java.io.OutputStream, android.util.Size, java.nio.ByteBuffer, long) throws java.io.IOException;
+ method public void writeImage(java.io.OutputStream, android.media.Image) throws java.io.IOException;
+ method public void writeInputStream(java.io.OutputStream, android.util.Size, java.io.InputStream, long) throws java.io.IOException;
}
}
@@ -14086,19 +14113,6 @@
ctor public DeniedByServerException(java.lang.String);
}
- public final class DngCreator implements java.lang.AutoCloseable {
- ctor public DngCreator(android.hardware.camera2.CameraCharacteristics, android.hardware.camera2.CaptureResult);
- method public void close();
- method public android.media.DngCreator setDescription(java.lang.String);
- method public android.media.DngCreator setLocation(android.location.Location);
- method public android.media.DngCreator setOrientation(int);
- method public android.media.DngCreator setThumbnail(android.graphics.Bitmap);
- method public android.media.DngCreator setThumbnail(android.media.Image);
- method public void writeByteBuffer(java.io.OutputStream, android.util.Size, java.nio.ByteBuffer, long) throws java.io.IOException;
- method public void writeImage(java.io.OutputStream, android.media.Image) throws java.io.IOException;
- method public void writeInputStream(java.io.OutputStream, android.util.Size, java.io.InputStream, long) throws java.io.IOException;
- }
-
public class ExifInterface {
ctor public ExifInterface(java.lang.String) throws java.io.IOException;
method public double getAltitude(double);
@@ -25056,7 +25070,9 @@
field public static final java.lang.String COLUMN_DESCRIPTION = "description";
field public static final java.lang.String COLUMN_DISPLAY_NAME = "display_name";
field public static final java.lang.String COLUMN_DISPLAY_NUMBER = "display_number";
+ field public static final java.lang.String COLUMN_LOCKED = "locked";
field public static final java.lang.String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
field public static final java.lang.String COLUMN_SERVICE_ID = "service_id";
field public static final java.lang.String COLUMN_SERVICE_NAME = "service_name";
field public static final java.lang.String COLUMN_SERVICE_TYPE = "service_type";
@@ -25094,10 +25110,12 @@
}
public static final class TvContract.Programs implements android.provider.TvContract.BaseTvColumns {
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
field public static final java.lang.String COLUMN_DATA = "data";
field public static final java.lang.String COLUMN_DESCRIPTION = "description";
field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+ field public static final java.lang.String COLUMN_GENRE = "genre";
field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
field public static final java.lang.String COLUMN_TITLE = "title";
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 18e2a95..77b1acf 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -32,6 +32,7 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.service.trust.TrustAgentService;
import android.util.Log;
@@ -1983,6 +1984,43 @@
}
/**
+ * Called by a device owner to create a user with the specified name. The UserHandle returned
+ * by this method should not be persisted as user handles are recycled as users are removed and
+ * created. If you need to persist an identifier for this user, use
+ * {@link UserManager#getSerialNumberForUser}.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param name the user's name
+ * @see UserHandle
+ * @return the UserHandle object for the created user, or null if the user could not be created.
+ */
+ public UserHandle createUser(ComponentName admin, String name) {
+ try {
+ return mService.createUser(admin, name);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not create a user", re);
+ }
+ return null;
+ }
+
+ /**
+ * Called by a device owner to remove a user and all associated data. The primary user can
+ * not be removed.
+ *
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param userHandle the user to remove.
+ * @return {@code true} if the user was removed, {@code false} otherwise.
+ */
+ public boolean removeUser(ComponentName admin, UserHandle userHandle) {
+ try {
+ return mService.removeUser(admin, userHandle);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not remove user ", re);
+ return false;
+ }
+ }
+
+ /**
* Called by a profile or device owner to get the application restrictions for a given target
* application running in the managed profile.
*
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7257158..3c08c14 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -22,6 +22,7 @@
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.RemoteCallback;
+import android.os.UserHandle;
/**
* Internal IPC interface to the device policy service.
@@ -128,6 +129,9 @@
int setApplicationsBlocked(in ComponentName admin, in Intent intent, boolean blocked);
boolean isApplicationBlocked(in ComponentName admin, in String packageName);
+ UserHandle createUser(in ComponentName who, in String name);
+ boolean removeUser(in ComponentName who, in UserHandle userHandle);
+
void enableSystemApp(in ComponentName admin, in String packageName);
int enableSystemAppWithIntent(in ComponentName admin, in Intent intent);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index d0ac9c9..6ae006c 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1994,6 +1994,7 @@
WIFI_PASSPOINT_SERVICE,
WIFI_P2P_SERVICE,
WIFI_SCANNING_SERVICE,
+ //@hide: ETHERNET_SERVICE,
NSD_SERVICE,
AUDIO_SERVICE,
MEDIA_ROUTER_SERVICE,
@@ -2069,9 +2070,6 @@
* <dt> {@link #WIFI_P2P_SERVICE} ("wifip2p")
* <dd> A {@link android.net.wifi.p2p.WifiP2pManager WifiP2pManager} for management of
* Wi-Fi Direct connectivity.
- * <dt> {@link #ETHERNET_SERVICE} ("ethernet")
- * <dd> A {@link android.net.ethernet.EthernetManager EthernetManager} for
- * management of Ethernet connectivity.
* <dt> {@link #INPUT_METHOD_SERVICE} ("input_method")
* <dd> An {@link android.view.inputmethod.InputMethodManager InputMethodManager}
* for management of input methods.
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index a78f8e2..3737638 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -31,11 +31,11 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.Trace;
+import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
-import android.util.SparseArray;
import android.util.TypedValue;
import android.util.LongSparseArray;
@@ -104,10 +104,10 @@
// These are protected by mAccessLock.
private final Object mAccessLock = new Object();
private final Configuration mTmpConfig = new Configuration();
- private final ThemedCaches<ConstantState> mDrawableCache =
- new ThemedCaches<ConstantState>();
- private final ThemedCaches<ConstantState> mColorDrawableCache =
- new ThemedCaches<ConstantState>();
+ private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> mDrawableCache =
+ new ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>>();
+ private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> mColorDrawableCache =
+ new ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>>();
private final LongSparseArray<WeakReference<ColorStateList>> mColorStateListCache =
new LongSparseArray<WeakReference<ColorStateList>>();
@@ -1261,18 +1261,17 @@
* any of the style's attributes are already defined in the theme, the
* current values in the theme will be overwritten.
*
- * @param resid The resource ID of a style resource from which to
+ * @param resId The resource ID of a style resource from which to
* obtain attribute values.
* @param force If true, values in the style resource will always be
* used in the theme; otherwise, they will only be used
* if not already defined in the theme.
*/
- public void applyStyle(int resid, boolean force) {
- AssetManager.applyThemeStyle(mTheme, resid, force);
+ public void applyStyle(int resId, boolean force) {
+ AssetManager.applyThemeStyle(mTheme, resId, force);
- // TODO: In very rare cases, we may end up with a hybrid theme
- // that can't map to a single theme ID.
- mThemeResId = resid;
+ mThemeResId = resId;
+ mKey += Integer.toHexString(resId) + (force ? "! " : " ");
}
/**
@@ -1288,6 +1287,7 @@
AssetManager.copyTheme(mTheme, other.mTheme);
mThemeResId = other.mThemeResId;
+ mKey = other.mKey;
}
/**
@@ -1577,6 +1577,9 @@
/** Resource identifier for the theme. */
private int mThemeResId = 0;
+ /** Unique key for the series of styles applied to this theme. */
+ private String mKey = "";
+
// Needed by layoutlib.
/*package*/ long getNativeTheme() {
return mTheme;
@@ -1585,6 +1588,10 @@
/*package*/ int getAppliedStyleResId() {
return mThemeResId;
}
+
+ /*package*/ String getKey() {
+ return mKey;
+ }
}
/**
@@ -1740,7 +1747,8 @@
}
private void clearDrawableCachesLocked(
- ThemedCaches<ConstantState> caches, int configChanges) {
+ ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
+ int configChanges) {
final int N = caches.size();
for (int i = 0; i < N; i++) {
clearDrawableCacheLocked(caches.valueAt(i), configChanges);
@@ -1763,7 +1771,7 @@
configChanges, cs.getChangingConfigurations())) {
if (DEBUG_CONFIG) {
Log.d(TAG, "FLUSHING #0x"
- + Long.toHexString(mDrawableCache.keyAt(i))
+ + Long.toHexString(cache.keyAt(i))
+ " / " + cs + " with changes: 0x"
+ Integer.toHexString(cs.getChangingConfigurations()));
}
@@ -2205,7 +2213,7 @@
}
final boolean isColorDrawable;
- final ThemedCaches<ConstantState> caches;
+ final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches;
final long key;
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
&& value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
@@ -2258,7 +2266,8 @@
}
private void cacheDrawable(TypedValue value, Theme theme, boolean isColorDrawable,
- ThemedCaches<ConstantState> caches, long key, Drawable dr) {
+ ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
+ long key, Drawable dr) {
final ConstantState cs = dr.getConstantState();
if (cs == null) {
return;
@@ -2287,8 +2296,12 @@
}
} else {
synchronized (mAccessLock) {
- final LongSparseArray<WeakReference<ConstantState>> themedCache;
- themedCache = caches.getOrCreate(theme == null ? 0 : theme.mThemeResId);
+ final String themeKey = theme == null ? "" : theme.mKey;
+ LongSparseArray<WeakReference<ConstantState>> themedCache = caches.get(themeKey);
+ if (themedCache == null) {
+ themedCache = new LongSparseArray<WeakReference<ConstantState>>(1);
+ caches.put(themeKey, themedCache);
+ }
themedCache.put(key, new WeakReference<ConstantState>(cs));
}
}
@@ -2347,7 +2360,9 @@
return dr;
}
- private Drawable getCachedDrawable(ThemedCaches<ConstantState> caches, long key, Theme theme) {
+ private Drawable getCachedDrawable(
+ ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
+ long key, Theme theme) {
synchronized (mAccessLock) {
final int themeKey = theme != null ? theme.mThemeResId : 0;
final LongSparseArray<WeakReference<ConstantState>> themedCache = caches.get(themeKey);
@@ -2584,21 +2599,4 @@
updateConfiguration(null, null);
mAssets.ensureStringBlocks();
}
-
- static class ThemedCaches<T> extends SparseArray<LongSparseArray<WeakReference<T>>> {
- /**
- * Returns the cache of drawables styled for the specified theme.
- * <p>
- * Drawables that have themeable attributes but were loaded without
- * specifying a theme are cached at themeResId = 0.
- */
- public LongSparseArray<WeakReference<T>> getOrCreate(int themeResId) {
- LongSparseArray<WeakReference<T>> result = get(themeResId);
- if (result == null) {
- result = new LongSparseArray<WeakReference<T>>(1);
- put(themeResId, result);
- }
- return result;
- }
- }
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 7cc6d1d..c08424a 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -16,7 +16,9 @@
package android.hardware.camera2;
+import android.hardware.camera2.CaptureResult.Key;
import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.utils.TypeReference;
import android.util.Rational;
import java.util.Collections;
@@ -35,18 +37,109 @@
* @see CameraDevice
* @see CameraManager
*/
-public final class CameraCharacteristics extends CameraMetadata {
+public final class CameraCharacteristics extends CameraMetadata<CameraCharacteristics.Key<?>> {
+
+ /**
+ * A {@code Key} is used to do camera characteristics field lookups with
+ * {@link CameraCharacteristics#get}.
+ *
+ * <p>For example, to get the stream configuration map:
+ * <code><pre>
+ * StreamConfigurationMap map = cameraCharacteristics.get(
+ * CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ * </pre></code>
+ * </p>
+ *
+ * <p>To enumerate over all possible keys for {@link CameraCharacteristics}, see
+ * {@link CameraCharacteristics#getKeys()}.</p>
+ *
+ * @see CameraCharacteristics#get
+ * @see CameraCharacteristics#getKeys()
+ */
+ public static final class Key<T> {
+ private final CameraMetadataNative.Key<T> mKey;
+
+ /**
+ * Visible for testing and vendor extensions only.
+ *
+ * @hide
+ */
+ public Key(String name, Class<T> type) {
+ mKey = new CameraMetadataNative.Key<T>(name, type);
+ }
+
+ /**
+ * Visible for testing and vendor extensions only.
+ *
+ * @hide
+ */
+ public Key(String name, TypeReference<T> typeReference) {
+ mKey = new CameraMetadataNative.Key<T>(name, typeReference);
+ }
+
+ /**
+ * Return a camelCase, period separated name formatted like:
+ * {@code "root.section[.subsections].name"}.
+ *
+ * <p>Built-in keys exposed by the Android SDK are always prefixed with {@code "android."};
+ * keys that are device/platform-specific are prefixed with {@code "com."}.</p>
+ *
+ * <p>For example, {@code CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP} would
+ * have a name of {@code "android.scaler.streamConfigurationMap"}; whereas a device
+ * specific key might look like {@code "com.google.nexus.data.private"}.</p>
+ *
+ * @return String representation of the key name
+ */
+ public String getName() {
+ return mKey.getName();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int hashCode() {
+ return mKey.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public final boolean equals(Object o) {
+ return o instanceof Key && ((Key<T>)o).mKey.equals(mKey);
+ }
+
+ /**
+ * Visible for CameraMetadataNative implementation only; do not use.
+ *
+ * TODO: Make this private or remove it altogether.
+ *
+ * @hide
+ */
+ public CameraMetadataNative.Key<T> getNativeKey() {
+ return mKey;
+ }
+
+ @SuppressWarnings({
+ "unused", "unchecked"
+ })
+ private Key(CameraMetadataNative.Key<?> nativeKey) {
+ mKey = (CameraMetadataNative.Key<T>) nativeKey;
+ }
+ }
private final CameraMetadataNative mProperties;
- private List<Key<?>> mAvailableRequestKeys;
- private List<Key<?>> mAvailableResultKeys;
+ private List<CaptureRequest.Key<?>> mAvailableRequestKeys;
+ private List<CaptureResult.Key<?>> mAvailableResultKeys;
/**
* Takes ownership of the passed-in properties object
* @hide
*/
public CameraCharacteristics(CameraMetadataNative properties) {
- mProperties = properties;
+ mProperties = CameraMetadataNative.move(properties);
}
/**
@@ -57,12 +150,55 @@
return new CameraMetadataNative(mProperties);
}
- @Override
+ /**
+ * Get a camera characteristics field value.
+ *
+ * <p>The field definitions can be
+ * found in {@link CameraCharacteristics}.</p>
+ *
+ * <p>Querying the value for the same key more than once will return a value
+ * which is equal to the previous queried value.</p>
+ *
+ * @throws IllegalArgumentException if the key was not valid
+ *
+ * @param key The characteristics field to read.
+ * @return The value of that key, or {@code null} if the field is not set.
+ */
public <T> T get(Key<T> key) {
return mProperties.get(key);
}
/**
+ * {@inheritDoc}
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected <T> T getProtected(Key<?> key) {
+ return (T) mProperties.get(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Class<Key<?>> getKeyClass() {
+ Object thisClass = Key.class;
+ return (Class<Key<?>>)thisClass;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Key<?>> getKeys() {
+ // Force the javadoc for this function to show up on the CameraCharacteristics page
+ return super.getKeys();
+ }
+
+ /**
* Returns the list of keys supported by this {@link CameraDevice} for querying
* with a {@link CaptureRequest}.
*
@@ -76,9 +212,14 @@
*
* @return List of keys supported by this CameraDevice for CaptureRequests.
*/
- public List<Key<?>> getAvailableCaptureRequestKeys() {
+ @SuppressWarnings({"unchecked"})
+ public List<CaptureRequest.Key<?>> getAvailableCaptureRequestKeys() {
if (mAvailableRequestKeys == null) {
- mAvailableRequestKeys = getAvailableKeyList(CaptureRequest.class);
+ Object crKey = CaptureRequest.Key.class;
+ Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>)crKey;
+
+ mAvailableRequestKeys = Collections.unmodifiableList(
+ getAvailableKeyList(CaptureRequest.class, crKeyTyped));
}
return mAvailableRequestKeys;
}
@@ -97,9 +238,14 @@
*
* @return List of keys supported by this CameraDevice for CaptureResults.
*/
- public List<Key<?>> getAvailableCaptureResultKeys() {
+ @SuppressWarnings({"unchecked"})
+ public List<CaptureResult.Key<?>> getAvailableCaptureResultKeys() {
if (mAvailableResultKeys == null) {
- mAvailableResultKeys = getAvailableKeyList(CaptureResult.class);
+ Object crKey = CaptureResult.Key.class;
+ Class<CaptureResult.Key<?>> crKeyTyped = (Class<CaptureResult.Key<?>>)crKey;
+
+ mAvailableResultKeys = Collections.unmodifiableList(
+ getAvailableKeyList(CaptureResult.class, crKeyTyped));
}
return mAvailableResultKeys;
}
@@ -113,12 +259,14 @@
* <p>Each key is only listed once in the list. The order of the keys is undefined.</p>
*
* @param metadataClass The subclass of CameraMetadata that you want to get the keys for.
+ * @param keyClass The class of the metadata key, e.g. CaptureRequest.Key.class
*
* @return List of keys supported by this CameraDevice for metadataClass.
*
* @throws IllegalArgumentException if metadataClass is not a subclass of CameraMetadata
*/
- private <T extends CameraMetadata> List<Key<?>> getAvailableKeyList(Class<T> metadataClass) {
+ private <TKey> List<TKey>
+ getAvailableKeyList(Class<?> metadataClass, Class<TKey> keyClass) {
if (metadataClass.equals(CameraMetadata.class)) {
throw new AssertionError(
@@ -128,7 +276,9 @@
"metadataClass must be a subclass of CameraMetadata");
}
- return Collections.unmodifiableList(getKeysStatic(metadataClass, /*instance*/null));
+ List<TKey> staticKeyList = CameraCharacteristics.<TKey>getKeysStatic(
+ metadataClass, keyClass, /*instance*/null);
+ return Collections.unmodifiableList(staticKeyList);
}
/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
@@ -1046,6 +1196,28 @@
new Key<android.hardware.camera2.params.StreamConfigurationMap>("android.scaler.streamConfigurationMap", android.hardware.camera2.params.StreamConfigurationMap.class);
/**
+ * <p>The crop type that this camera device supports.</p>
+ * <p>When passing a non-centered crop region ({@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}) to a camera
+ * device that only supports CENTER_ONLY cropping, the camera device will move the
+ * crop region to the center of the sensor active array ({@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize})
+ * and keep the crop region width and height unchanged. The camera device will return the
+ * final used crop region in metadata result {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}.</p>
+ * <p>Camera devices that support FREEFORM cropping will support any crop region that
+ * is inside of the active array. The camera device will apply the same crop region and
+ * return the final used crop region in capture result metadata {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}.</p>
+ * <p>FULL capability devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} <code>==</code> FULL) will support
+ * FREEFORM cropping.</p>
+ *
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ * @see CaptureRequest#SCALER_CROP_REGION
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
+ * @see #SCALER_CROPPING_TYPE_CENTER_ONLY
+ * @see #SCALER_CROPPING_TYPE_FREEFORM
+ */
+ public static final Key<Integer> SCALER_CROPPING_TYPE =
+ new Key<Integer>("android.scaler.croppingType", int.class);
+
+ /**
* <p>Area of raw data which corresponds to only
* active pixels.</p>
* <p>It is smaller or equal to
@@ -1324,19 +1496,6 @@
new Key<Rational[]>("android.sensor.forwardMatrix2", Rational[].class);
/**
- * <p>Gain factor from electrons to raw units when
- * ISO=100</p>
- * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
- * <p><b>Full capability</b> -
- * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
- * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
- *
- * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
- */
- public static final Key<Rational> SENSOR_BASE_GAIN_FACTOR =
- new Key<Rational>("android.sensor.baseGainFactor", Rational.class);
-
- /**
* <p>A fixed black level offset for each of the color filter arrangement
* (CFA) mosaic channels.</p>
* <p>This tag specifies the zero light value for each of the CFA mosaic
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index a11390d..4cde601 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -16,8 +16,7 @@
package android.hardware.camera2;
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.utils.TypeReference;
+import android.util.Log;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -36,7 +35,7 @@
*
* <p>
* All instances of CameraMetadata are immutable. The list of keys with {@link #getKeys()}
- * never changes, nor do the values returned by any key with {@link #get} throughout
+ * never changes, nor do the values returned by any key with {@code #get} throughout
* the lifetime of the object.
* </p>
*
@@ -44,7 +43,10 @@
* @see CameraManager
* @see CameraCharacteristics
**/
-public abstract class CameraMetadata {
+public abstract class CameraMetadata<TKey> {
+
+ private static final String TAG = "CameraMetadataAb";
+ private static final boolean VERBOSE = false;
/**
* Set a camera metadata field to a value. The field definitions can be
@@ -74,8 +76,15 @@
*
* @param key The metadata field to read.
* @return The value of that key, or {@code null} if the field is not set.
+ *
+ * @hide
*/
- public abstract <T> T get(Key<T> key);
+ protected abstract <T> T getProtected(TKey key);
+
+ /**
+ * @hide
+ */
+ protected abstract Class<TKey> getKeyClass();
/**
* Returns a list of the keys contained in this map.
@@ -83,14 +92,16 @@
* <p>The list returned is not modifiable, so any attempts to modify it will throw
* a {@code UnsupportedOperationException}.</p>
*
- * <p>All values retrieved by a key from this list with {@link #get} are guaranteed to be
+ * <p>All values retrieved by a key from this list with {@code #get} are guaranteed to be
* non-{@code null}. Each key is only listed once in the list. The order of the keys
* is undefined.</p>
*
* @return List of the keys contained in this map.
*/
- public List<Key<?>> getKeys() {
- return Collections.unmodifiableList(getKeysStatic(this.getClass(), this));
+ @SuppressWarnings("unchecked")
+ public List<TKey> getKeys() {
+ Class<CameraMetadata<TKey>> thisClass = (Class<CameraMetadata<TKey>>) getClass();
+ return Collections.unmodifiableList(getKeysStatic(thisClass, getKeyClass(), this));
}
/**
@@ -101,24 +112,31 @@
* Optionally, if {@code instance} is not null, then filter out any keys with null values.
* </p>
*/
- /*package*/ static ArrayList<Key<?>> getKeysStatic(Class<? extends CameraMetadata> type,
- CameraMetadata instance) {
- ArrayList<Key<?>> keyList = new ArrayList<Key<?>>();
+ /*package*/ @SuppressWarnings("unchecked")
+ static <TKey> ArrayList<TKey> getKeysStatic(
+ Class<?> type, Class<TKey> keyClass,
+ CameraMetadata<TKey> instance) {
+
+ if (VERBOSE) Log.v(TAG, "getKeysStatic for " + type);
+
+ ArrayList<TKey> keyList = new ArrayList<TKey>();
Field[] fields = type.getDeclaredFields();
for (Field field : fields) {
// Filter for Keys that are public
- if (field.getType().isAssignableFrom(Key.class) &&
+ if (field.getType().isAssignableFrom(keyClass) &&
(field.getModifiers() & Modifier.PUBLIC) != 0) {
- Key<?> key;
+
+ TKey key;
try {
- key = (Key<?>) field.get(instance);
+ key = (TKey) field.get(instance);
} catch (IllegalAccessException e) {
throw new AssertionError("Can't get IllegalAccessException", e);
} catch (IllegalArgumentException e) {
throw new AssertionError("Can't get IllegalArgumentException", e);
}
- if (instance == null || instance.get(key) != null) {
+
+ if (instance == null || instance.getProtected(key) != null) {
keyList.add(key);
}
}
@@ -127,113 +145,6 @@
return keyList;
}
- // TODO: make final or abstract
- public static class Key<T> {
-
- private boolean mHasTag;
- private int mTag;
- private final Class<T> mType;
- private final TypeReference<T> mTypeReference;
- private final String mName;
-
- /**
- * @hide
- */
- public Key(String name, Class<T> type) {
- if (name == null) {
- throw new NullPointerException("Key needs a valid name");
- } else if (type == null) {
- throw new NullPointerException("Type needs to be non-null");
- }
- mName = name;
- mType = type;
- mTypeReference = TypeReference.createSpecializedTypeReference(type);
- }
-
- /**
- * @hide
- */
- @SuppressWarnings("unchecked")
- public Key(String name, TypeReference<T> typeReference) {
- if (name == null) {
- throw new NullPointerException("Key needs a valid name");
- } else if (typeReference == null) {
- throw new NullPointerException("TypeReference needs to be non-null");
- }
- mName = name;
- mType = (Class<T>)typeReference.getRawType();
- mTypeReference = typeReference;
- }
-
- public final String getName() {
- return mName;
- }
-
- @Override
- public final int hashCode() {
- return mName.hashCode() ^ mTypeReference.hashCode();
- }
-
- @Override
- public final boolean equals(Object o) {
- if (this == o) {
- return true;
- }
-
- if (!(o instanceof Key)) {
- return false;
- }
-
- Key<?> lhs = (Key<?>)o;
- return mName.equals(lhs.mName) && mTypeReference.equals(lhs.mTypeReference);
- }
-
- /**
- * <p>
- * Get the tag corresponding to this key. This enables insertion into the
- * native metadata.
- * </p>
- *
- * <p>This value is looked up the first time, and cached subsequently.</p>
- *
- * @return The tag numeric value corresponding to the string
- *
- * @hide
- */
- public final int getTag() {
- if (!mHasTag) {
- mTag = CameraMetadataNative.getTag(mName);
- mHasTag = true;
- }
- return mTag;
- }
-
- /**
- * Get the raw class backing the type {@code T} for this key.
- *
- * <p>The distinction is only important if {@code T} is a generic, e.g.
- * {@code Range<Integer>} since the nested type will be erased.</p>
- *
- * @hide
- */
- public final Class<T> getType() {
- // TODO: remove this; other places should use #getTypeReference() instead
- return mType;
- }
-
- /**
- * Get the type reference backing the type {@code T} for this key.
- *
- * <p>The distinction is only important if {@code T} is a generic, e.g.
- * {@code Range<Integer>} since the nested type will be retained.</p>
- *
- * @hide
- */
- public final TypeReference<T> getTypeReference() {
- return mTypeReference;
- }
- }
-
/*@O~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* The enum values below this point are generated from metadata
* definitions in /system/media/camera/docs. Do not modify by hand or
@@ -336,7 +247,6 @@
* <li>Manual sensitivity control<ul>
* <li>{@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity}</li>
* <li>{@link CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE android.sensor.info.sensitivityRange}</li>
- * <li>{@link CameraCharacteristics#SENSOR_BASE_GAIN_FACTOR android.sensor.baseGainFactor}</li>
* </ul>
* </li>
* <li>Manual lens control<ul>
@@ -357,7 +267,6 @@
* result.</p>
*
* @see CaptureRequest#BLACK_LEVEL_LOCK
- * @see CameraCharacteristics#SENSOR_BASE_GAIN_FACTOR
* @see CaptureRequest#SENSOR_EXPOSURE_TIME
* @see CameraCharacteristics#SENSOR_INFO_EXPOSURE_TIME_RANGE
* @see CameraCharacteristics#SENSOR_INFO_SENSITIVITY_RANGE
@@ -446,6 +355,22 @@
public static final int REQUEST_AVAILABLE_CAPABILITIES_DNG = 5;
//
+ // Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE
+ //
+
+ /**
+ * <p>The camera device will only support centered crop regions.</p>
+ * @see CameraCharacteristics#SCALER_CROPPING_TYPE
+ */
+ public static final int SCALER_CROPPING_TYPE_CENTER_ONLY = 0;
+
+ /**
+ * <p>The camera device will support arbitrarily chosen crop regions.</p>
+ * @see CameraCharacteristics#SCALER_CROPPING_TYPE
+ */
+ public static final int SCALER_CROPPING_TYPE_FREEFORM = 1;
+
+ //
// Enumeration values for CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
//
@@ -1365,8 +1290,7 @@
/**
* <p>If the flash is available and charged, fire flash
- * for this capture based on android.flash.firingPower and
- * android.flash.firingTime.</p>
+ * for this capture.</p>
* @see CaptureRequest#FLASH_MODE
*/
public static final int FLASH_MODE_SINGLE = 1;
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 54ffd6b..a4aa296 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -16,7 +16,9 @@
package android.hardware.camera2;
+import android.hardware.camera2.CameraCharacteristics.Key;
import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.utils.TypeReference;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Rational;
@@ -25,6 +27,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Objects;
@@ -58,7 +61,98 @@
* @see CameraDevice#setRepeatingRequest
* @see CameraDevice#createCaptureRequest
*/
-public final class CaptureRequest extends CameraMetadata implements Parcelable {
+public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
+ implements Parcelable {
+
+ /**
+ * A {@code Key} is used to do capture request field lookups with
+ * {@link CaptureResult#get} or to set fields with
+ * {@link CaptureRequest.Builder#set(Key, Object)}.
+ *
+ * <p>For example, to set the crop rectangle for the next capture:
+ * <code><pre>
+ * Rect cropRectangle = new Rect(0, 0, 640, 480);
+ * captureRequestBuilder.set(SCALER_CROP_REGION, cropRectangle);
+ * </pre></code>
+ * </p>
+ *
+ * <p>To enumerate over all possible keys for {@link CaptureResult}, see
+ * {@link CameraCharacteristics#getAvailableCaptureResultKeys}.</p>
+ *
+ * @see CaptureResult#get
+ * @see CameraCharacteristics#getAvailableCaptureResultKeys
+ */
+ public final static class Key<T> {
+ private final CameraMetadataNative.Key<T> mKey;
+
+ /**
+ * Visible for testing and vendor extensions only.
+ *
+ * @hide
+ */
+ public Key(String name, Class<T> type) {
+ mKey = new CameraMetadataNative.Key<T>(name, type);
+ }
+
+ /**
+ * Visible for testing and vendor extensions only.
+ *
+ * @hide
+ */
+ public Key(String name, TypeReference<T> typeReference) {
+ mKey = new CameraMetadataNative.Key<T>(name, typeReference);
+ }
+
+ /**
+ * Return a camelCase, period separated name formatted like:
+ * {@code "root.section[.subsections].name"}.
+ *
+ * <p>Built-in keys exposed by the Android SDK are always prefixed with {@code "android."};
+ * keys that are device/platform-specific are prefixed with {@code "com."}.</p>
+ *
+ * <p>For example, {@code CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP} would
+ * have a name of {@code "android.scaler.streamConfigurationMap"}; whereas a device
+ * specific key might look like {@code "com.google.nexus.data.private"}.</p>
+ *
+ * @return String representation of the key name
+ */
+ public String getName() {
+ return mKey.getName();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int hashCode() {
+ return mKey.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public final boolean equals(Object o) {
+ return o instanceof Key && ((Key<T>)o).mKey.equals(mKey);
+ }
+
+ /**
+ * Visible for CameraMetadataNative implementation only; do not use.
+ *
+ * TODO: Make this private or remove it altogether.
+ *
+ * @hide
+ */
+ public CameraMetadataNative.Key<T> getNativeKey() {
+ return mKey;
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ /*package*/ Key(CameraMetadataNative.Key<?> nativeKey) {
+ mKey = (CameraMetadataNative.Key<T>) nativeKey;
+ }
+ }
private final HashSet<Surface> mSurfaceSet;
private final CameraMetadataNative mSettings;
@@ -93,17 +187,58 @@
* Used by the Builder to create a mutable CaptureRequest.
*/
private CaptureRequest(CameraMetadataNative settings) {
- mSettings = settings;
+ mSettings = CameraMetadataNative.move(settings);
mSurfaceSet = new HashSet<Surface>();
}
- @SuppressWarnings("unchecked")
- @Override
+ /**
+ * Get a capture request field value.
+ *
+ * <p>The field definitions can be found in {@link CaptureRequest}.</p>
+ *
+ * <p>Querying the value for the same key more than once will return a value
+ * which is equal to the previous queried value.</p>
+ *
+ * @throws IllegalArgumentException if the key was not valid
+ *
+ * @param key The result field to read.
+ * @return The value of that key, or {@code null} if the field is not set.
+ */
public <T> T get(Key<T> key) {
return mSettings.get(key);
}
/**
+ * {@inheritDoc}
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected <T> T getProtected(Key<?> key) {
+ return (T) mSettings.get(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Class<Key<?>> getKeyClass() {
+ Object thisClass = Key.class;
+ return (Class<Key<?>>)thisClass;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Key<?>> getKeys() {
+ // Force the javadoc for this function to show up on the CaptureRequest page
+ return super.getKeys();
+ }
+
+ /**
* Retrieve the tag for this request, if any.
*
* <p>This tag is not used for anything by the camera device, but can be
@@ -569,9 +704,9 @@
* should be nonnegative.</p>
* <p>If all regions have 0 weight, then no specific metering area
* needs to be used by the camera device. If the metering region is
- * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
- * will ignore the sections outside the region and output the
- * used sections in the frame metadata.</p>
+ * outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
+ * the camera device will ignore the sections outside the region and output the
+ * used sections in the result metadata.</p>
*
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -644,9 +779,9 @@
* should be nonnegative.</p>
* <p>If all regions have 0 weight, then no specific focus area
* needs to be used by the camera device. If the focusing region is
- * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
- * will ignore the sections outside the region and output the
- * used sections in the frame metadata.</p>
+ * outside the the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture
+ * result metadata, the camera device will ignore the sections outside
+ * the region and output the used sections in the result metadata.</p>
*
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -731,9 +866,9 @@
* should be nonnegative.</p>
* <p>If all regions have 0 weight, then no specific auto-white balance (AWB) area
* needs to be used by the camera device. If the AWB region is
- * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
- * will ignore the sections outside the region and output the
- * used sections in the frame metadata.</p>
+ * outside the the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
+ * the camera device will ignore the sections outside the region and output the
+ * used sections in the result metadata.</p>
*
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -1126,8 +1261,11 @@
* output, cropping to a smaller region if necessary to
* maintain the stream's aspect ratio.</p>
* <p>HAL2.x uses only (x, y, width)</p>
- * <p>Any additional per-stream cropping must be done to
- * maximize the final pixel area of the stream.</p>
+ * <p>The crop region is applied after the RAW to other color space (e.g. YUV)
+ * conversion. Since raw streams (e.g. RAW16) don't have the conversion stage,
+ * it is not croppable. The crop region will be ignored by raw streams.</p>
+ * <p>For non-raw streams, any additional per-stream cropping will
+ * be done to maximize the final pixel area of the stream.</p>
* <p>For example, if the crop region is set to a 4:3 aspect
* ratio, then 4:3 streams should use the exact crop
* region. 16:9 streams should further crop vertically
@@ -1308,8 +1446,16 @@
* camera device. Applications can request lens shading map data by setting
* {@link CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE android.statistics.lensShadingMapMode} to ON, and then the camera device will provide
* lens shading map data in {@link CaptureResult#STATISTICS_LENS_SHADING_MAP android.statistics.lensShadingMap}, with size specified
- * by {@link CameraCharacteristics#LENS_INFO_SHADING_MAP_SIZE android.lens.info.shadingMapSize}.</p>
+ * by {@link CameraCharacteristics#LENS_INFO_SHADING_MAP_SIZE android.lens.info.shadingMapSize}; the returned shading map data will be the one
+ * applied by the camera device for this capture request.</p>
+ * <p>The shading map data may depend on the AE and AWB statistics, therefore the reliability
+ * of the map data may be affected by the AE and AWB algorithms. When AE and AWB are in
+ * AUTO modes({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF and {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} <code>!=</code> OFF),
+ * to get best results, it is recommended that the applications wait for the AE and AWB to
+ * be converged before using the returned shading map data.</p>
*
+ * @see CaptureRequest#CONTROL_AE_MODE
+ * @see CaptureRequest#CONTROL_AWB_MODE
* @see CameraCharacteristics#LENS_INFO_SHADING_MAP_SIZE
* @see CaptureResult#STATISTICS_LENS_SHADING_MAP
* @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
@@ -1458,7 +1604,7 @@
* {@link CaptureRequest#TONEMAP_CURVE_GREEN android.tonemap.curveGreen}, and {@link CaptureRequest#TONEMAP_CURVE_BLUE android.tonemap.curveBlue}.
* These values are always available, and as close as possible to the
* actually used nonlinear/nonglobal transforms.</p>
- * <p>If a request is sent with TRANSFORM_MATRIX with the camera device's
+ * <p>If a request is sent with CONTRAST_CURVE with the camera device's
* provided curve in FAST or HIGH_QUALITY, the image's tonemap will be
* roughly the same.</p>
*
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index f91fcb9..61d491b 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -17,9 +17,12 @@
package android.hardware.camera2;
import android.hardware.camera2.impl.CameraMetadataNative;
-import android.hardware.camera2.params.Face;
+import android.hardware.camera2.utils.TypeReference;
+import android.util.Log;
import android.util.Rational;
+import java.util.List;
+
/**
* <p>The results of a single image capture from the image sensor.</p>
*
@@ -36,7 +39,98 @@
* <p>{@link CameraCharacteristics} objects are immutable.</p>
*
*/
-public final class CaptureResult extends CameraMetadata {
+public final class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> {
+
+ private static final String TAG = "CaptureResult";
+ private static final boolean VERBOSE = false;
+
+ /**
+ * A {@code Key} is used to do capture result field lookups with
+ * {@link CaptureResult#get}.
+ *
+ * <p>For example, to get the timestamp corresponding to the exposure of the first row:
+ * <code><pre>
+ * long timestamp = captureResult.get(CaptureResult.SENSOR_TIMESTAMP);
+ * </pre></code>
+ * </p>
+ *
+ * <p>To enumerate over all possible keys for {@link CaptureResult}, see
+ * {@link CameraCharacteristics#getAvailableCaptureResultKeys}.</p>
+ *
+ * @see CaptureResult#get
+ * @see CameraCharacteristics#getAvailableCaptureResultKeys
+ */
+ public final static class Key<T> {
+ private final CameraMetadataNative.Key<T> mKey;
+
+ /**
+ * Visible for testing and vendor extensions only.
+ *
+ * @hide
+ */
+ public Key(String name, Class<T> type) {
+ mKey = new CameraMetadataNative.Key<T>(name, type);
+ }
+
+ /**
+ * Visible for testing and vendor extensions only.
+ *
+ * @hide
+ */
+ public Key(String name, TypeReference<T> typeReference) {
+ mKey = new CameraMetadataNative.Key<T>(name, typeReference);
+ }
+
+ /**
+ * Return a camelCase, period separated name formatted like:
+ * {@code "root.section[.subsections].name"}.
+ *
+ * <p>Built-in keys exposed by the Android SDK are always prefixed with {@code "android."};
+ * keys that are device/platform-specific are prefixed with {@code "com."}.</p>
+ *
+ * <p>For example, {@code CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP} would
+ * have a name of {@code "android.scaler.streamConfigurationMap"}; whereas a device
+ * specific key might look like {@code "com.google.nexus.data.private"}.</p>
+ *
+ * @return String representation of the key name
+ */
+ public String getName() {
+ return mKey.getName();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int hashCode() {
+ return mKey.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public final boolean equals(Object o) {
+ return o instanceof Key && ((Key<T>)o).mKey.equals(mKey);
+ }
+
+ /**
+ * Visible for CameraMetadataNative implementation only; do not use.
+ *
+ * TODO: Make this private or remove it altogether.
+ *
+ * @hide
+ */
+ public CameraMetadataNative.Key<T> getNativeKey() {
+ return mKey;
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ /*package*/ Key(CameraMetadataNative.Key<?> nativeKey) {
+ mKey = (CameraMetadataNative.Key<T>) nativeKey;
+ }
+ }
private final CameraMetadataNative mResults;
private final CaptureRequest mRequest;
@@ -55,7 +149,10 @@
throw new IllegalArgumentException("parent was null");
}
- mResults = results;
+ mResults = CameraMetadataNative.move(results);
+ if (mResults.isEmpty()) {
+ throw new AssertionError("Results must not be empty");
+ }
mRequest = parent;
mSequenceId = sequenceId;
}
@@ -68,9 +165,85 @@
return new CameraMetadataNative(mResults);
}
- @Override
+ /**
+ * Creates a request-less result.
+ *
+ * <p><strong>For testing only.</strong></p>
+ * @hide
+ */
+ public CaptureResult(CameraMetadataNative results, int sequenceId) {
+ if (results == null) {
+ throw new IllegalArgumentException("results was null");
+ }
+
+ mResults = CameraMetadataNative.move(results);
+ if (mResults.isEmpty()) {
+ throw new AssertionError("Results must not be empty");
+ }
+
+ mRequest = null;
+ mSequenceId = sequenceId;
+ }
+
+ /**
+ * Get a capture result field value.
+ *
+ * <p>The field definitions can be found in {@link CaptureResult}.</p>
+ *
+ * <p>Querying the value for the same key more than once will return a value
+ * which is equal to the previous queried value.</p>
+ *
+ * @throws IllegalArgumentException if the key was not valid
+ *
+ * @param key The result field to read.
+ * @return The value of that key, or {@code null} if the field is not set.
+ */
public <T> T get(Key<T> key) {
- return mResults.get(key);
+ T value = mResults.get(key);
+ if (VERBOSE) Log.v(TAG, "#get for Key = " + key.getName() + ", returned value = " + value);
+ return value;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected <T> T getProtected(Key<?> key) {
+ return (T) mResults.get(key);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ protected Class<Key<?>> getKeyClass() {
+ Object thisClass = Key.class;
+ return (Class<Key<?>>)thisClass;
+ }
+
+ /**
+ * Dumps the native metadata contents to logcat.
+ *
+ * <p>Visibility for testing/debugging only. The results will not
+ * include any synthesized keys, as they are invisible to the native layer.</p>
+ *
+ * @hide
+ */
+ public void dumpToLog() {
+ mResults.dumpToLog();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Key<?>> getKeys() {
+ // Force the javadoc for this function to show up on the CaptureResult page
+ return super.getKeys();
}
/**
@@ -110,6 +283,7 @@
* @return int frame number
*/
public int getFrameNumber() {
+ // TODO: @hide REQUEST_FRAME_COUNT
return get(REQUEST_FRAME_COUNT);
}
@@ -369,9 +543,9 @@
* should be nonnegative.</p>
* <p>If all regions have 0 weight, then no specific metering area
* needs to be used by the camera device. If the metering region is
- * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
- * will ignore the sections outside the region and output the
- * used sections in the frame metadata.</p>
+ * outside the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
+ * the camera device will ignore the sections outside the region and output the
+ * used sections in the result metadata.</p>
*
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -642,9 +816,9 @@
* should be nonnegative.</p>
* <p>If all regions have 0 weight, then no specific focus area
* needs to be used by the camera device. If the focusing region is
- * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
- * will ignore the sections outside the region and output the
- * used sections in the frame metadata.</p>
+ * outside the the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture
+ * result metadata, the camera device will ignore the sections outside
+ * the region and output the used sections in the result metadata.</p>
*
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -1126,9 +1300,9 @@
* should be nonnegative.</p>
* <p>If all regions have 0 weight, then no specific auto-white balance (AWB) area
* needs to be used by the camera device. If the AWB region is
- * outside the current {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion}, the camera device
- * will ignore the sections outside the region and output the
- * used sections in the frame metadata.</p>
+ * outside the the used {@link CaptureRequest#SCALER_CROP_REGION android.scaler.cropRegion} returned in capture result metadata,
+ * the camera device will ignore the sections outside the region and output the
+ * used sections in the result metadata.</p>
*
* @see CaptureRequest#SCALER_CROP_REGION
* @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
@@ -1749,8 +1923,11 @@
* output, cropping to a smaller region if necessary to
* maintain the stream's aspect ratio.</p>
* <p>HAL2.x uses only (x, y, width)</p>
- * <p>Any additional per-stream cropping must be done to
- * maximize the final pixel area of the stream.</p>
+ * <p>The crop region is applied after the RAW to other color space (e.g. YUV)
+ * conversion. Since raw streams (e.g. RAW16) don't have the conversion stage,
+ * it is not croppable. The crop region will be ignored by raw streams.</p>
+ * <p>For non-raw streams, any additional per-stream cropping will
+ * be done to maximize the final pixel area of the stream.</p>
* <p>For example, if the crop region is set to a 4:3 aspect
* ratio, then 4:3 streams should use the exact crop
* region. 16:9 streams should further crop vertically
@@ -1885,21 +2062,6 @@
new Key<Long>("android.sensor.timestamp", long.class);
/**
- * <p>The temperature of the sensor, sampled at the time
- * exposure began for this frame.</p>
- * <p>The thermal diode being queried should be inside the sensor PCB, or
- * somewhere close to it.</p>
- * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
- * <p><b>Full capability</b> -
- * Present on all camera devices that report being {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_FULL HARDWARE_LEVEL_FULL} devices in the
- * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
- *
- * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
- */
- public static final Key<Float> SENSOR_TEMPERATURE =
- new Key<Float>("android.sensor.temperature", float.class);
-
- /**
* <p>The estimated camera neutral color in the native sensor colorspace at
* the time of capture.</p>
* <p>This value gives the neutral color point encoded as an RGB value in the
@@ -2006,8 +2168,16 @@
* camera device. Applications can request lens shading map data by setting
* {@link CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE android.statistics.lensShadingMapMode} to ON, and then the camera device will provide
* lens shading map data in {@link CaptureResult#STATISTICS_LENS_SHADING_MAP android.statistics.lensShadingMap}, with size specified
- * by {@link CameraCharacteristics#LENS_INFO_SHADING_MAP_SIZE android.lens.info.shadingMapSize}.</p>
+ * by {@link CameraCharacteristics#LENS_INFO_SHADING_MAP_SIZE android.lens.info.shadingMapSize}; the returned shading map data will be the one
+ * applied by the camera device for this capture request.</p>
+ * <p>The shading map data may depend on the AE and AWB statistics, therefore the reliability
+ * of the map data may be affected by the AE and AWB algorithms. When AE and AWB are in
+ * AUTO modes({@link CaptureRequest#CONTROL_AE_MODE android.control.aeMode} <code>!=</code> OFF and {@link CaptureRequest#CONTROL_AWB_MODE android.control.awbMode} <code>!=</code> OFF),
+ * to get best results, it is recommended that the applications wait for the AE and AWB to
+ * be converged before using the returned shading map data.</p>
*
+ * @see CaptureRequest#CONTROL_AE_MODE
+ * @see CaptureRequest#CONTROL_AWB_MODE
* @see CameraCharacteristics#LENS_INFO_SHADING_MAP_SIZE
* @see CaptureResult#STATISTICS_LENS_SHADING_MAP
* @see CaptureRequest#STATISTICS_LENS_SHADING_MAP_MODE
@@ -2338,7 +2508,7 @@
* {@link CaptureRequest#TONEMAP_CURVE_GREEN android.tonemap.curveGreen}, and {@link CaptureRequest#TONEMAP_CURVE_BLUE android.tonemap.curveBlue}.
* These values are always available, and as close as possible to the
* actually used nonlinear/nonglobal transforms.</p>
- * <p>If a request is sent with TRANSFORM_MATRIX with the camera device's
+ * <p>If a request is sent with CONTRAST_CURVE with the camera device's
* provided curve in FAST or HIGH_QUALITY, the image's tonemap will be
* roughly the same.</p>
*
diff --git a/core/java/android/hardware/camera2/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java
new file mode 100644
index 0000000..54568ed
--- /dev/null
+++ b/core/java/android/hardware/camera2/DngCreator.java
@@ -0,0 +1,368 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2;
+
+import android.graphics.Bitmap;
+import android.graphics.ImageFormat;
+import android.hardware.camera2.impl.CameraMetadataNative;
+import android.location.Location;
+import android.media.ExifInterface;
+import android.media.Image;
+import android.util.Size;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * The {@link DngCreator} class provides functions to write raw pixel data as a DNG file.
+ *
+ * <p>
+ * This class is designed to be used with the {@link android.graphics.ImageFormat#RAW_SENSOR}
+ * buffers available from {@link android.hardware.camera2.CameraDevice}, or with Bayer-type raw
+ * pixel data that is otherwise generated by an application. The DNG metadata tags will be
+ * generated from a {@link android.hardware.camera2.CaptureResult} object or set directly.
+ * </p>
+ *
+ * <p>
+ * The DNG file format is a cross-platform file format that is used to store pixel data from
+ * camera sensors with minimal pre-processing applied. DNG files allow for pixel data to be
+ * defined in a user-defined colorspace, and have associated metadata that allow for this
+ * pixel data to be converted to the standard CIE XYZ colorspace during post-processing.
+ * </p>
+ *
+ * <p>
+ * For more information on the DNG file format and associated metadata, please refer to the
+ * <a href=
+ * "https://wwwimages2.adobe.com/content/dam/Adobe/en/products/photoshop/pdfs/dng_spec_1.4.0.0.pdf">
+ * Adobe DNG 1.4.0.0 specification</a>.
+ * </p>
+ */
+public final class DngCreator implements AutoCloseable {
+
+ /**
+ * Create a new DNG object.
+ *
+ * <p>
+ * It is not necessary to call any set methods to write a well-formatted DNG file.
+ * </p>
+ * <p>
+ * DNG metadata tags will be generated from the corresponding parameters in the
+ * {@link android.hardware.camera2.CaptureResult} object. This removes or overrides
+ * all previous tags set.
+ * </p>
+ *
+ * @param characteristics an object containing the static
+ * {@link android.hardware.camera2.CameraCharacteristics}.
+ * @param metadata a metadata object to generate tags from.
+ */
+ public DngCreator(CameraCharacteristics characteristics, CaptureResult metadata) {
+ if (characteristics == null || metadata == null) {
+ throw new NullPointerException("Null argument to DngCreator constructor");
+ }
+ nativeInit(characteristics.getNativeCopy(), metadata.getNativeCopy());
+ }
+
+ /**
+ * Set the orientation value to write.
+ *
+ * <p>
+ * This will be written as the TIFF "Orientation" tag {@code (0x0112)}.
+ * Calling this will override any prior settings for this tag.
+ * </p>
+ *
+ * @param orientation the orientation value to set, one of:
+ * <ul>
+ * <li>{@link android.media.ExifInterface#ORIENTATION_NORMAL}</li>
+ * <li>{@link android.media.ExifInterface#ORIENTATION_FLIP_HORIZONTAL}</li>
+ * <li>{@link android.media.ExifInterface#ORIENTATION_ROTATE_180}</li>
+ * <li>{@link android.media.ExifInterface#ORIENTATION_FLIP_VERTICAL}</li>
+ * <li>{@link android.media.ExifInterface#ORIENTATION_TRANSPOSE}</li>
+ * <li>{@link android.media.ExifInterface#ORIENTATION_ROTATE_90}</li>
+ * <li>{@link android.media.ExifInterface#ORIENTATION_TRANSVERSE}</li>
+ * <li>{@link android.media.ExifInterface#ORIENTATION_ROTATE_270}</li>
+ * </ul>
+ * @return this {@link #DngCreator} object.
+ */
+ public DngCreator setOrientation(int orientation) {
+
+ if (orientation < ExifInterface.ORIENTATION_UNDEFINED ||
+ orientation > ExifInterface.ORIENTATION_ROTATE_270) {
+ throw new IllegalArgumentException("Orientation " + orientation +
+ " is not a valid EXIF orientation value");
+ }
+ nativeSetOrientation(orientation);
+ return this;
+ }
+
+ /**
+ * Set the thumbnail image.
+ *
+ * <p>
+ * Pixel data will be converted to a Baseline TIFF RGB image, with 8 bits per color channel.
+ * The alpha channel will be discarded.
+ * </p>
+ *
+ * <p>
+ * The given bitmap should not be altered while this object is in use.
+ * </p>
+ *
+ * @param pixels a {@link android.graphics.Bitmap} of pixel data.
+ * @return this {@link #DngCreator} object.
+ */
+ public DngCreator setThumbnail(Bitmap pixels) {
+ if (pixels == null) {
+ throw new NullPointerException("Null argument to setThumbnail");
+ }
+
+ Bitmap.Config config = pixels.getConfig();
+
+ if (config != Bitmap.Config.ARGB_8888) {
+ pixels = pixels.copy(Bitmap.Config.ARGB_8888, false);
+ if (pixels == null) {
+ throw new IllegalArgumentException("Unsupported Bitmap format " + config);
+ }
+ nativeSetThumbnailBitmap(pixels);
+ }
+
+ return this;
+ }
+
+ /**
+ * Set the thumbnail image.
+ *
+ * <p>
+ * Pixel data is interpreted as a {@link android.graphics.ImageFormat#YUV_420_888} image.
+ * </p>
+ *
+ * <p>
+ * The given image should not be altered while this object is in use.
+ * </p>
+ *
+ * @param pixels an {@link android.media.Image} object with the format
+ * {@link android.graphics.ImageFormat#YUV_420_888}.
+ * @return this {@link #DngCreator} object.
+ */
+ public DngCreator setThumbnail(Image pixels) {
+ if (pixels == null) {
+ throw new NullPointerException("Null argument to setThumbnail");
+ }
+
+ int format = pixels.getFormat();
+ if (format != ImageFormat.YUV_420_888) {
+ throw new IllegalArgumentException("Unsupported image format " + format);
+ }
+
+ Image.Plane[] planes = pixels.getPlanes();
+ nativeSetThumbnailImage(pixels.getWidth(), pixels.getHeight(), planes[0].getBuffer(),
+ planes[0].getRowStride(), planes[0].getPixelStride(), planes[1].getBuffer(),
+ planes[1].getRowStride(), planes[1].getPixelStride(), planes[1].getBuffer(),
+ planes[1].getRowStride(), planes[1].getPixelStride());
+
+ return this;
+ }
+
+
+ /**
+ * Set image location metadata.
+ *
+ * <p>
+ * The given location object must contain at least a valid time, latitude, and longitude
+ * (equivalent to the values returned by {@link android.location.Location#getTime()},
+ * {@link android.location.Location#getLatitude()}, and
+ * {@link android.location.Location#getLongitude()} methods).
+ * </p>
+ *
+ * @param location an {@link android.location.Location} object to set.
+ * @return this {@link #DngCreator} object.
+ *
+ * @throws java.lang.IllegalArgumentException if the given location object doesn't
+ * contain enough information to set location metadata.
+ */
+ public DngCreator setLocation(Location location) {
+ /*TODO*/
+ return this;
+ }
+
+ /**
+ * Set the user description string to write.
+ *
+ * <p>
+ * This is equivalent to setting the TIFF "ImageDescription" tag {@code (0x010E)}.
+ * </p>
+ *
+ * @param description the user description string.
+ * @return this {@link #DngCreator} object.
+ */
+ public DngCreator setDescription(String description) {
+ /*TODO*/
+ return this;
+ }
+
+ /**
+ * Write the {@link android.graphics.ImageFormat#RAW_SENSOR} pixel data to a DNG file with
+ * the currently configured metadata.
+ *
+ * <p>
+ * Raw pixel data must have 16 bits per pixel, and the input must contain at least
+ * {@code offset + 2 * width * height)} bytes. The width and height of
+ * the input are taken from the width and height set in the {@link DngCreator} metadata tags,
+ * and will typically be equal to the width and height of
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
+ * The pixel layout in the input is determined from the reported color filter arrangement (CFA)
+ * set in {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}. If insufficient
+ * metadata is available to write a well-formatted DNG file, an
+ * {@link java.lang.IllegalStateException} will be thrown.
+ * </p>
+ *
+ * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
+ * @param size the {@link Size} of the image to write, in pixels.
+ * @param pixels an {@link java.io.InputStream} of pixel data to write.
+ * @param offset the offset of the raw image in bytes. This indicates how many bytes will
+ * be skipped in the input before any pixel data is read.
+ *
+ * @throws IOException if an error was encountered in the input or output stream.
+ * @throws java.lang.IllegalStateException if not enough metadata information has been
+ * set to write a well-formatted DNG file.
+ * @throws java.lang.IllegalArgumentException if the size passed in does not match the
+ */
+ public void writeInputStream(OutputStream dngOutput, Size size, InputStream pixels, long offset)
+ throws IOException {
+ if (dngOutput == null || pixels == null) {
+ throw new NullPointerException("Null argument to writeImage");
+ }
+ nativeWriteInputStream(dngOutput, pixels, offset);
+ }
+
+ /**
+ * Write the {@link android.graphics.ImageFormat#RAW_SENSOR} pixel data to a DNG file with
+ * the currently configured metadata.
+ *
+ * <p>
+ * Raw pixel data must have 16 bits per pixel, and the input must contain at least
+ * {@code offset + 2 * width * height)} bytes. The width and height of
+ * the input are taken from the width and height set in the {@link DngCreator} metadata tags,
+ * and will typically be equal to the width and height of
+ * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
+ * The pixel layout in the input is determined from the reported color filter arrangement (CFA)
+ * set in {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}. If insufficient
+ * metadata is available to write a well-formatted DNG file, an
+ * {@link java.lang.IllegalStateException} will be thrown.
+ * </p>
+ *
+ * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
+ * @param size the {@link Size} of the image to write, in pixels.
+ * @param pixels an {@link java.nio.ByteBuffer} of pixel data to write.
+ * @param offset the offset of the raw image in bytes. This indicates how many bytes will
+ * be skipped in the input before any pixel data is read.
+ *
+ * @throws IOException if an error was encountered in the input or output stream.
+ * @throws java.lang.IllegalStateException if not enough metadata information has been
+ * set to write a well-formatted DNG file.
+ */
+ public void writeByteBuffer(OutputStream dngOutput, Size size, ByteBuffer pixels, long offset)
+ throws IOException {
+ if (dngOutput == null || pixels == null) {
+ throw new NullPointerException("Null argument to writeImage");
+ }
+ nativeWriteByteBuffer(dngOutput, pixels, offset);
+ }
+
+ /**
+ * Write the pixel data to a DNG file with the currently configured metadata.
+ *
+ * <p>
+ * For this method to succeed, the {@link android.media.Image} input must contain
+ * {@link android.graphics.ImageFormat#RAW_SENSOR} pixel data, otherwise an
+ * {@link java.lang.IllegalArgumentException} will be thrown.
+ * </p>
+ *
+ * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
+ * @param pixels an {@link android.media.Image} to write.
+ *
+ * @throws java.io.IOException if an error was encountered in the output stream.
+ * @throws java.lang.IllegalArgumentException if an image with an unsupported format was used.
+ * @throws java.lang.IllegalStateException if not enough metadata information has been
+ * set to write a well-formatted DNG file.
+ */
+ public void writeImage(OutputStream dngOutput, Image pixels) throws IOException {
+ if (dngOutput == null || pixels == null) {
+ throw new NullPointerException("Null argument to writeImage");
+ }
+
+ int format = pixels.getFormat();
+ if (format != ImageFormat.RAW_SENSOR) {
+ throw new IllegalArgumentException("Unsupported image format " + format);
+ }
+
+ Image.Plane[] planes = pixels.getPlanes();
+ nativeWriteImage(dngOutput, pixels.getWidth(), pixels.getHeight(), planes[0].getBuffer(),
+ planes[0].getRowStride(), planes[0].getPixelStride());
+ }
+
+ @Override
+ public void close() {
+ nativeDestroy();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * This field is used by native code, do not access or modify.
+ */
+ private long mNativeContext;
+
+ private static native void nativeClassInit();
+
+ private synchronized native void nativeInit(CameraMetadataNative nativeCharacteristics,
+ CameraMetadataNative nativeResult);
+
+ private synchronized native void nativeDestroy();
+
+ private synchronized native void nativeSetOrientation(int orientation);
+
+ private synchronized native void nativeSetThumbnailBitmap(Bitmap bitmap);
+
+ private synchronized native void nativeSetThumbnailImage(int width, int height,
+ ByteBuffer yBuffer, int yRowStride,
+ int yPixStride, ByteBuffer uBuffer,
+ int uRowStride, int uPixStride,
+ ByteBuffer vBuffer, int vRowStride,
+ int vPixStride);
+
+ private synchronized native void nativeWriteImage(OutputStream out, int width, int height,
+ ByteBuffer rawBuffer, int rowStride,
+ int pixStride) throws IOException;
+
+ private synchronized native void nativeWriteByteBuffer(OutputStream out, ByteBuffer rawBuffer,
+ long offset) throws IOException;
+
+ private synchronized native void nativeWriteInputStream(OutputStream out, InputStream rawStream,
+ long offset) throws IOException;
+
+ static {
+ nativeClassInit();
+ }
+}
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index 27cfd38..ab2c49a 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -20,7 +20,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.marshal.Marshaler;
import android.hardware.camera2.marshal.MarshalQueryable;
@@ -46,10 +46,14 @@
import android.hardware.camera2.params.StreamConfiguration;
import android.hardware.camera2.params.StreamConfigurationDuration;
import android.hardware.camera2.params.StreamConfigurationMap;
+import android.hardware.camera2.utils.TypeReference;
import android.os.Parcelable;
import android.os.Parcel;
import android.util.Log;
+import com.android.internal.util.Preconditions;
+
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
@@ -58,7 +62,147 @@
* Implementation of camera metadata marshal/unmarshal across Binder to
* the camera service
*/
-public class CameraMetadataNative extends CameraMetadata implements Parcelable {
+public class CameraMetadataNative implements Parcelable {
+
+ public static class Key<T> {
+ private boolean mHasTag;
+ private int mTag;
+ private final Class<T> mType;
+ private final TypeReference<T> mTypeReference;
+ private final String mName;
+
+ /**
+ * Visible for testing only.
+ *
+ * <p>Use the CameraCharacteristics.Key, CaptureResult.Key, or CaptureRequest.Key
+ * for application code or vendor-extended keys.</p>
+ */
+ public Key(String name, Class<T> type) {
+ if (name == null) {
+ throw new NullPointerException("Key needs a valid name");
+ } else if (type == null) {
+ throw new NullPointerException("Type needs to be non-null");
+ }
+ mName = name;
+ mType = type;
+ mTypeReference = TypeReference.createSpecializedTypeReference(type);
+ }
+
+ /**
+ * Visible for testing only.
+ *
+ * <p>Use the CameraCharacteristics.Key, CaptureResult.Key, or CaptureRequest.Key
+ * for application code or vendor-extended keys.</p>
+ */
+ @SuppressWarnings("unchecked")
+ public Key(String name, TypeReference<T> typeReference) {
+ if (name == null) {
+ throw new NullPointerException("Key needs a valid name");
+ } else if (typeReference == null) {
+ throw new NullPointerException("TypeReference needs to be non-null");
+ }
+ mName = name;
+ mType = (Class<T>)typeReference.getRawType();
+ mTypeReference = typeReference;
+ }
+
+ /**
+ * Return a camelCase, period separated name formatted like:
+ * {@code "root.section[.subsections].name"}.
+ *
+ * <p>Built-in keys exposed by the Android SDK are always prefixed with {@code "android."};
+ * keys that are device/platform-specific are prefixed with {@code "com."}.</p>
+ *
+ * <p>For example, {@code CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP} would
+ * have a name of {@code "android.scaler.streamConfigurationMap"}; whereas a device
+ * specific key might look like {@code "com.google.nexus.data.private"}.</p>
+ *
+ * @return String representation of the key name
+ */
+ public final String getName() {
+ return mName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public final int hashCode() {
+ return mName.hashCode() ^ mTypeReference.hashCode();
+ }
+
+ /**
+ * Compare this key against other native keys, request keys, result keys, and
+ * characteristics keys.
+ *
+ * <p>Two keys are considered equal if their name and type reference are equal.</p>
+ *
+ * <p>Note that the equality against non-native keys is one-way. A native key may be equal
+ * to a result key; but that same result key will not be equal to a native key.</p>
+ */
+ @SuppressWarnings("rawtypes")
+ @Override
+ public final boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ Key<?> lhs;
+
+ if (o instanceof CaptureResult.Key) {
+ lhs = ((CaptureResult.Key)o).getNativeKey();
+ } else if (o instanceof CaptureRequest.Key) {
+ lhs = ((CaptureRequest.Key)o).getNativeKey();
+ } else if (o instanceof CameraCharacteristics.Key) {
+ lhs = ((CameraCharacteristics.Key)o).getNativeKey();
+ } else if ((o instanceof Key)) {
+ lhs = (Key<?>)o;
+ } else {
+ return false;
+ }
+
+ return mName.equals(lhs.mName) && mTypeReference.equals(lhs.mTypeReference);
+ }
+
+ /**
+ * <p>
+ * Get the tag corresponding to this key. This enables insertion into the
+ * native metadata.
+ * </p>
+ *
+ * <p>This value is looked up the first time, and cached subsequently.</p>
+ *
+ * @return The tag numeric value corresponding to the string
+ */
+ public final int getTag() {
+ if (!mHasTag) {
+ mTag = CameraMetadataNative.getTag(mName);
+ mHasTag = true;
+ }
+ return mTag;
+ }
+
+ /**
+ * Get the raw class backing the type {@code T} for this key.
+ *
+ * <p>The distinction is only important if {@code T} is a generic, e.g.
+ * {@code Range<Integer>} since the nested type will be erased.</p>
+ */
+ public final Class<T> getType() {
+ // TODO: remove this; other places should use #getTypeReference() instead
+ return mType;
+ }
+
+ /**
+ * Get the type reference backing the type {@code T} for this key.
+ *
+ * <p>The distinction is only important if {@code T} is a generic, e.g.
+ * {@code Range<Integer>} since the nested type will be retained.</p>
+ */
+ public final TypeReference<T> getTypeReference() {
+ return mTypeReference;
+ }
+ }
private static final String TAG = "CameraMetadataJV";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
@@ -84,6 +228,20 @@
}
}
+ /**
+ * Move the contents from {@code other} into a new camera metadata instance.</p>
+ *
+ * <p>After this call, {@code other} will become empty.</p>
+ *
+ * @param other the previous metadata instance which will get pilfered
+ * @return a new metadata instance with the values from {@code other} moved into it
+ */
+ public static CameraMetadataNative move(CameraMetadataNative other) {
+ CameraMetadataNative newObject = new CameraMetadataNative();
+ newObject.swap(other);
+ return newObject;
+ }
+
public static final Parcelable.Creator<CameraMetadataNative> CREATOR =
new Parcelable.Creator<CameraMetadataNative>() {
@Override
@@ -109,8 +267,36 @@
nativeWriteToParcel(dest);
}
- @Override
+ /**
+ * @hide
+ */
+ public <T> T get(CameraCharacteristics.Key<T> key) {
+ return get(key.getNativeKey());
+ }
+
+ /**
+ * @hide
+ */
+ public <T> T get(CaptureResult.Key<T> key) {
+ return get(key.getNativeKey());
+ }
+
+ /**
+ * @hide
+ */
+ public <T> T get(CaptureRequest.Key<T> key) {
+ return get(key.getNativeKey());
+ }
+
+ /**
+ * Look-up a metadata field value by its key.
+ *
+ * @param key a non-{@code null} key instance
+ * @return the field corresponding to the {@code key}, or {@code null} if no value was set
+ */
public <T> T get(Key<T> key) {
+ Preconditions.checkNotNull(key, "key must not be null");
+
T value = getOverride(key);
if (value != null) {
return value;
@@ -152,6 +338,18 @@
setBase(key, value);
}
+ public <T> void set(CaptureRequest.Key<T> key, T value) {
+ set(key.getNativeKey(), value);
+ }
+
+ public <T> void set(CaptureResult.Key<T> key, T value) {
+ set(key.getNativeKey(), value);
+ }
+
+ public <T> void set(CameraCharacteristics.Key<T> key, T value) {
+ set(key.getNativeKey(), value);
+ }
+
// Keep up-to-date with camera_metadata.h
/**
* @hide
@@ -188,6 +386,18 @@
mMetadataPtr = 0; // set it to 0 again to prevent eclipse from making this field final
}
+ private <T> T getBase(CameraCharacteristics.Key<T> key) {
+ return getBase(key.getNativeKey());
+ }
+
+ private <T> T getBase(CaptureResult.Key<T> key) {
+ return getBase(key.getNativeKey());
+ }
+
+ private <T> T getBase(CaptureRequest.Key<T> key) {
+ return getBase(key.getNativeKey());
+ }
+
private <T> T getBase(Key<T> key) {
int tag = key.getTag();
byte[] values = readValues(tag);
@@ -342,6 +552,18 @@
return new StreamConfigurationMap(configurations, minFrameDurations, stallDurations);
}
+ private <T> void setBase(CameraCharacteristics.Key<T> key, T value) {
+ setBase(key.getNativeKey(), value);
+ }
+
+ private <T> void setBase(CaptureResult.Key<T> key, T value) {
+ setBase(key.getNativeKey(), value);
+ }
+
+ private <T> void setBase(CaptureRequest.Key<T> key, T value) {
+ setBase(key.getNativeKey(), value);
+ }
+
private <T> void setBase(Key<T> key, T value) {
int tag = key.getTag();
@@ -440,6 +662,7 @@
private native synchronized byte[] nativeReadValues(int tag);
private native synchronized void nativeWriteValues(int tag, byte[] src);
+ private native synchronized void nativeDump() throws IOException; // dump to ALOGD
private static native int nativeGetTagFromKey(String keyName)
throws IllegalArgumentException;
@@ -531,6 +754,22 @@
return nativeReadValues(tag);
}
+ /**
+ * Dumps the native metadata contents to logcat.
+ *
+ * <p>Visibility for testing/debugging only. The results will not
+ * include any synthesized keys, as they are invisible to the native layer.</p>
+ *
+ * @hide
+ */
+ public void dumpToLog() {
+ try {
+ nativeDump();
+ } catch (IOException e) {
+ Log.wtf(TAG, "Dump logging failed", e);
+ }
+ }
+
@Override
protected void finalize() throws Throwable {
try {
@@ -599,5 +838,4 @@
nativeClassInit();
registerAllMarshalers();
}
-
}
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
index 71adf8b..22ff9c6 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceState.java
@@ -93,7 +93,7 @@
* {@link CameraDeviceStateListener#onConfiguring()} will be called.
* </p>
*
- * @returns {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+ * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
*/
public synchronized int setConfiguring() {
doStateTransition(STATE_CONFIGURING);
@@ -108,7 +108,7 @@
* {@link CameraDeviceStateListener#onIdle()} will be called.
* </p>
*
- * @returns {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+ * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
*/
public synchronized int setIdle() {
doStateTransition(STATE_IDLE);
@@ -124,7 +124,7 @@
* </p>
*
* @param request A {@link RequestHolder} containing the request for the current capture.
- * @returns {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+ * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
*/
public synchronized int setCaptureStart(final RequestHolder request) {
mCurrentRequest = request;
@@ -144,7 +144,7 @@
*
* @param request the {@link RequestHolder} request that created this result.
* @param result the {@link CameraMetadataNative} result to set.
- * @returns {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
+ * @return {@link CameraBinderDecorator#NO_ERROR}, or an error if one has occurred.
*/
public synchronized int setCaptureResult(final RequestHolder request,
final CameraMetadataNative result) {
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index 70cc708..5df4baf 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -47,7 +47,7 @@
}
/**
- * Get Ethernet configuration
+ * Get Ethernet configuration.
* @return the Ethernet Configuration, contained in {@link IpConfiguration}.
*/
public IpConfiguration getConfiguration() {
@@ -61,8 +61,7 @@
}
/**
- * Set Ethernet configuration
- * @return true if setting success
+ * Set Ethernet configuration.
*/
public void setConfiguration(IpConfiguration config) {
try {
diff --git a/core/java/android/provider/TvContract.java b/core/java/android/provider/TvContract.java
index 5ffffb5..e4f93a8 100644
--- a/core/java/android/provider/TvContract.java
+++ b/core/java/android/provider/TvContract.java
@@ -462,7 +462,7 @@
* <p>
* A value of 1 indicates the channel is included in the channel list that applications use
* to browse channels, a value of 0 indicates the channel is not included in the list. If
- * not specified, this value is set to 1 by default.
+ * not specified, this value is set to 1 (browsable) by default.
* </p><p>
* Type: INTEGER (boolean)
* </p>
@@ -470,6 +470,36 @@
public static final String COLUMN_BROWSABLE = "browsable";
/**
+ * The flag indicating whether this TV channel is searchable or not.
+ * <p>
+ * In some regions, it is not allowed to surface search results for a given channel without
+ * broadcaster's consent. This is used to impose such restriction. A value of 1 indicates
+ * the channel is searchable and can be included in search results, a value of 0 indicates
+ * the channel and its TV programs are hidden from search. If not specified, this value is
+ * set to 1 (searchable) by default.
+ * </p>
+ * <p>
+ * Type: INTEGER (boolean)
+ * </p>
+ */
+ public static final String COLUMN_SEARCHABLE = "searchable";
+
+ /**
+ * The flag indicating whether this TV channel is locked or not.
+ * <p>
+ * This is primarily used for alternative parental control to prevent unauthorized users
+ * from watching the current channel regardless of the content rating. A value of 1
+ * indicates the channel is locked and the user is required to enter passcode to unlock it
+ * in order to watch the current program from the channel, a value of 0 indicates the
+ * channel is not locked thus the user is not prompted to enter passcode If not specified,
+ * this value is set to 0 (not locked) by default.
+ * </p><p>
+ * Type: INTEGER (boolean)
+ * </p>
+ */
+ public static final String COLUMN_LOCKED = "locked";
+
+ /**
* Generic data used by individual TV input services.
* <p>
* Type: BLOB
@@ -544,6 +574,33 @@
public static final String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
/**
+ * The comma-separated genre string of this TV program.
+ * <p>
+ * Use the same language appeared in the underlying broadcast standard, if applicable. (For
+ * example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
+ * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, use one of the
+ * following genres:
+ * <ul>
+ * <li>Family/Kids</li>
+ * <li>Sports</li>
+ * <li>Shopping</li>
+ * <li>Movies</li>
+ * <li>Comedy</li>
+ * <li>Travel</li>
+ * <li>Drama</li>
+ * <li>Education</li>
+ * <li>Animal/Wildlife</li>
+ * <li>News</li>
+ * <li>Gaming</li>
+ * <li>Others</li>
+ * </ul>
+ * </p><p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String COLUMN_GENRE = "genre";
+
+ /**
* The description of this TV program that is displayed to the user by default.
* <p>
* The maximum length of this field is 256 characters.
@@ -566,6 +623,17 @@
public static final String COLUMN_LONG_DESCRIPTION = "long_description";
/**
+ * The comma-separated audio languages of this TV program.
+ * <p>
+ * This is used to describe available audio languages included in the program. Use
+ * 3-character language code as specified by ISO 639-2.
+ * </p><p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String COLUMN_AUDIO_LANGUAGE = "audio_language";
+
+ /**
* Generic data used by TV input services.
* <p>
* Type: BLOB
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index a272296..424d860 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -41,10 +41,6 @@
* An implementation of Canvas on top of OpenGL ES 2.0.
*/
class GLES20Canvas extends HardwareCanvas {
- // Must match modifiers used in the JNI layer
- private static final int MODIFIER_NONE = 0;
- private static final int MODIFIER_SHADER = 2;
-
private final boolean mOpaque;
protected long mRenderer;
@@ -650,13 +646,8 @@
@Override
public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,
Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom,
- startAngle, sweepAngle, useCenter, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawArc(mRenderer, oval.left, oval.top, oval.right, oval.bottom,
+ startAngle, sweepAngle, useCenter, paint.mNativePaint);
}
private static native void nDrawArc(long renderer, float left, float top,
@@ -672,7 +663,6 @@
public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing patches
final long nativePaint = paint == null ? 0 : paint.mNativePaint;
nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
@@ -682,7 +672,6 @@
public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing patches
final long nativePaint = paint == null ? 0 : paint.mNativePaint;
nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
@@ -694,14 +683,8 @@
@Override
public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing bitmaps
- int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
}
private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
@@ -710,15 +693,9 @@
@Override
public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing bitmaps
- int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
- matrix.native_instance, nativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
+ matrix.native_instance, nativePaint);
}
private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
@@ -727,55 +704,43 @@
@Override
public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing bitmaps
- int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- int left, top, right, bottom;
- if (src == null) {
- left = top = 0;
- right = bitmap.getWidth();
- bottom = bitmap.getHeight();
- } else {
- left = src.left;
- right = src.right;
- top = src.top;
- bottom = src.bottom;
- }
-
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
+ int left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
}
+
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint);
}
@Override
public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
throwIfCannotDraw(bitmap);
- // Shaders are ignored when drawing bitmaps
- int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
-
- float left, top, right, bottom;
- if (src == null) {
- left = top = 0;
- right = bitmap.getWidth();
- bottom = bitmap.getHeight();
- } else {
- left = src.left;
- right = src.right;
- top = src.top;
- bottom = src.bottom;
- }
-
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+
+ float left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
}
+
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint);
}
private static native void nDrawBitmap(long renderer, long bitmap, byte[] buffer,
@@ -805,7 +770,6 @@
throw new ArrayIndexOutOfBoundsException();
}
- // Shaders are ignored when drawing bitmaps
final long nativePaint = paint == null ? 0 : paint.mNativePaint;
nDrawBitmap(mRenderer, colors, offset, stride, x, y,
width, height, hasAlpha, nativePaint);
@@ -817,7 +781,6 @@
@Override
public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
int width, int height, boolean hasAlpha, Paint paint) {
- // Shaders are ignored when drawing bitmaps
drawBitmap(colors, offset, stride, (float) x, (float) y, width, height, hasAlpha, paint);
}
@@ -840,14 +803,9 @@
checkRange(colors.length, colorOffset, count);
}
- int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
- try {
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
- verts, vertOffset, colors, colorOffset, nativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+ nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
+ verts, vertOffset, colors, colorOffset, nativePaint);
}
private static native void nDrawBitmapMesh(long renderer, long bitmap, byte[] buffer,
@@ -856,12 +814,7 @@
@Override
public void drawCircle(float cx, float cy, float radius, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
}
private static native void nDrawCircle(long renderer, float cx, float cy,
@@ -906,12 +859,7 @@
if ((offset | count) < 0 || offset + count > pts.length) {
throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
}
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
}
private static native void nDrawLines(long renderer, float[] points,
@@ -924,12 +872,7 @@
@Override
public void drawOval(RectF oval, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawOval(mRenderer, oval.left, oval.top, oval.right, oval.bottom, paint.mNativePaint);
}
private static native void nDrawOval(long renderer, float left, float top,
@@ -944,17 +887,12 @@
@Override
public void drawPath(Path path, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- if (path.isSimplePath) {
- if (path.rects != null) {
- nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
- }
- } else {
- nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
+ if (path.isSimplePath) {
+ if (path.rects != null) {
+ nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
}
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
+ } else {
+ nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
}
}
@@ -962,12 +900,7 @@
private static native void nDrawRects(long renderer, long region, long paint);
void drawRects(float[] rects, int count, Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawRects(mRenderer, rects, count, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawRects(mRenderer, rects, count, paint.mNativePaint);
}
private static native void nDrawRects(long renderer, float[] rects, int count, long paint);
@@ -1029,12 +962,7 @@
public void drawPoints(float[] pts, int offset, int count, Paint paint) {
if (count < 2) return;
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
}
private static native void nDrawPoints(long renderer, float[] points,
@@ -1047,12 +975,7 @@
throw new IndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawPosText(mRenderer, text, index, count, pos, paint.mNativePaint);
}
private static native void nDrawPosText(long renderer, char[] text, int index, int count,
@@ -1065,12 +988,7 @@
throw new ArrayIndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawPosText(mRenderer, text, 0, text.length(), pos, paint.mNativePaint);
}
private static native void nDrawPosText(long renderer, String text, int start, int end,
@@ -1079,12 +997,7 @@
@Override
public void drawRect(float left, float top, float right, float bottom, Paint paint) {
if (left == right || top == bottom) return;
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
}
private static native void nDrawRect(long renderer, float left, float top,
@@ -1108,12 +1021,7 @@
@Override
public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
Paint paint) {
- int modifiers = setupModifiers(paint, MODIFIER_SHADER);
- try {
- nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.mNativePaint);
}
private static native void nDrawRoundRect(long renderer, float left, float top,
@@ -1125,13 +1033,8 @@
throw new IndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawText(mRenderer, text, index, count, x, y, paint.mBidiFlags, paint.mNativePaint,
- paint.mNativeTypeface);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawText(mRenderer, text, index, count, x, y,
+ paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
}
private static native void nDrawText(long renderer, char[] text, int index, int count,
@@ -1139,24 +1042,18 @@
@Override
public void drawText(CharSequence text, int start, int end, float x, float y, Paint paint) {
- int modifiers = setupModifiers(paint);
- try {
- if (text instanceof String || text instanceof SpannedString ||
- text instanceof SpannableString) {
- nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
- paint.mNativePaint, paint.mNativeTypeface);
- } else if (text instanceof GraphicsOperations) {
- ((GraphicsOperations) text).drawText(this, start, end, x, y,
- paint);
- } else {
- char[] buf = TemporaryBuffer.obtain(end - start);
- TextUtils.getChars(text, start, end, buf, 0);
- nDrawText(mRenderer, buf, 0, end - start, x, y,
- paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
- TemporaryBuffer.recycle(buf);
- }
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
+ if (text instanceof String || text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
+ paint.mNativePaint, paint.mNativeTypeface);
+ } else if (text instanceof GraphicsOperations) {
+ ((GraphicsOperations) text).drawText(this, start, end, x, y, paint);
+ } else {
+ char[] buf = TemporaryBuffer.obtain(end - start);
+ TextUtils.getChars(text, start, end, buf, 0);
+ nDrawText(mRenderer, buf, 0, end - start, x, y,
+ paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+ TemporaryBuffer.recycle(buf);
}
}
@@ -1166,13 +1063,8 @@
throw new IndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawText(mRenderer, text, start, end, x, y, paint.mBidiFlags, paint.mNativePaint,
- paint.mNativeTypeface);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawText(mRenderer, text, start, end, x, y,
+ paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
}
private static native void nDrawText(long renderer, String text, int start, int end,
@@ -1180,13 +1072,8 @@
@Override
public void drawText(String text, float x, float y, Paint paint) {
- int modifiers = setupModifiers(paint);
- try {
- nDrawText(mRenderer, text, 0, text.length(), x, y, paint.mBidiFlags,
- paint.mNativePaint, paint.mNativeTypeface);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawText(mRenderer, text, 0, text.length(), x, y,
+ paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
}
@Override
@@ -1196,13 +1083,8 @@
throw new ArrayIndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
- paint.mBidiFlags, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
+ paint.mBidiFlags, paint.mNativePaint);
}
private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count,
@@ -1212,13 +1094,8 @@
public void drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) {
if (text.length() == 0) return;
- int modifiers = setupModifiers(paint);
- try {
- nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
- paint.mBidiFlags, paint.mNativePaint);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
+ paint.mBidiFlags, paint.mNativePaint);
}
private static native void nDrawTextOnPath(long renderer, String text, int start, int end,
@@ -1234,13 +1111,8 @@
throw new IllegalArgumentException("Unknown direction: " + dir);
}
- int modifiers = setupModifiers(paint);
- try {
- nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
- paint.mNativePaint, paint.mNativeTypeface);
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
- }
+ nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, dir,
+ paint.mNativePaint, paint.mNativeTypeface);
}
private static native void nDrawTextRun(long renderer, char[] text, int index, int count,
@@ -1253,27 +1125,22 @@
throw new IndexOutOfBoundsException();
}
- int modifiers = setupModifiers(paint);
- try {
- int flags = dir == 0 ? 0 : 1;
- if (text instanceof String || text instanceof SpannedString ||
- text instanceof SpannableString) {
- nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
- contextEnd, x, y, flags, paint.mNativePaint, paint.mNativeTypeface);
- } else if (text instanceof GraphicsOperations) {
- ((GraphicsOperations) text).drawTextRun(this, start, end,
- contextStart, contextEnd, x, y, flags, paint);
- } else {
- int contextLen = contextEnd - contextStart;
- int len = end - start;
- char[] buf = TemporaryBuffer.obtain(contextLen);
- TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
- nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
- x, y, flags, paint.mNativePaint, paint.mNativeTypeface);
- TemporaryBuffer.recycle(buf);
- }
- } finally {
- if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
+ int flags = dir == 0 ? 0 : 1;
+ if (text instanceof String || text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
+ contextEnd, x, y, flags, paint.mNativePaint, paint.mNativeTypeface);
+ } else if (text instanceof GraphicsOperations) {
+ ((GraphicsOperations) text).drawTextRun(this, start, end,
+ contextStart, contextEnd, x, y, flags, paint);
+ } else {
+ int contextLen = contextEnd - contextStart;
+ int len = end - start;
+ char[] buf = TemporaryBuffer.obtain(contextLen);
+ TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
+ nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
+ x, y, flags, paint.mNativePaint, paint.mNativeTypeface);
+ TemporaryBuffer.recycle(buf);
}
}
@@ -1286,40 +1153,4 @@
int indexOffset, int indexCount, Paint paint) {
// TODO: Implement
}
-
- private int setupModifiers(Bitmap b, Paint paint) {
- if (b.getConfig() != Bitmap.Config.ALPHA_8) {
- return MODIFIER_NONE;
- } else {
- return setupModifiers(paint);
- }
- }
-
- private int setupModifiers(Paint paint) {
- int modifiers = MODIFIER_NONE;
-
- final Shader shader = paint.getShader();
- if (shader != null) {
- nSetupShader(mRenderer, shader.native_shader);
- modifiers |= MODIFIER_SHADER;
- }
-
- return modifiers;
- }
-
- private int setupModifiers(Paint paint, int flags) {
- int modifiers = MODIFIER_NONE;
-
- final Shader shader = paint.getShader();
- if (shader != null && (flags & MODIFIER_SHADER) != 0) {
- nSetupShader(mRenderer, shader.native_shader);
- modifiers |= MODIFIER_SHADER;
- }
-
- return modifiers;
- }
-
- private static native void nSetupShader(long renderer, long shader);
-
- private static native void nResetModifiers(long renderer, int modifiers);
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index a902ce7..3c4d83f 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -579,6 +579,12 @@
abstract void fence();
/**
+ * Called by {@link ViewRootImpl} when a new performTraverals is scheduled.
+ */
+ public void notifyFramePending() {
+ }
+
+ /**
* Describes a series of frames that should be drawn on screen as a graph.
* Each frame is composed of 1 or more elements.
*/
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 704d516..8417887 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -291,6 +291,11 @@
}
@Override
+ public void notifyFramePending() {
+ nNotifyFramePending(mNativeProxy);
+ }
+
+ @Override
protected void finalize() throws Throwable {
try {
nDeleteProxy(mNativeProxy);
@@ -364,4 +369,5 @@
private static native void nDestroyLayer(long nativeProxy, long layer);
private static native void nFence(long nativeProxy);
+ private static native void nNotifyFramePending(long nativeProxy);
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 799a406..fc7bf0e 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -999,6 +999,17 @@
}
}
+ /**
+ * Notifies the HardwareRenderer that a new frame will be coming soon.
+ * Currently only {@link ThreadedRenderer} cares about this, and uses
+ * this knowledge to adjust the scheduling of off-thread animations
+ */
+ void notifyRendererOfFramePending() {
+ if (mAttachInfo.mHardwareRenderer != null) {
+ mAttachInfo.mHardwareRenderer.notifyFramePending();
+ }
+ }
+
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
@@ -1006,6 +1017,7 @@
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
scheduleConsumeBatchedInput();
+ notifyRendererOfFramePending();
}
}
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 1152e17..43f623b 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -256,6 +256,16 @@
}
@Override
+ public void invalidateDrawable(Drawable dr) {
+ super.invalidateDrawable(dr);
+
+ if (dr == mThumb) {
+ // Handle changes to thumb width and height.
+ requestLayout();
+ }
+ }
+
+ @Override
void onProgressRefresh(float scale, boolean fromUser) {
super.onProgressRefresh(scale, fromUser);
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index 1533510..3ae9508 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -24,6 +24,7 @@
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.Gravity;
+import android.view.RemotableViewMethod;
import android.view.ViewDebug;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -156,10 +157,36 @@
mCheckMarkWidth = 0;
}
mCheckMarkDrawable = d;
- // Do padding resolution. This will call internalSetPadding() and do a requestLayout() if needed.
+
+ // Do padding resolution. This will call internalSetPadding() and do a
+ // requestLayout() if needed.
resolvePadding();
}
+ @RemotableViewMethod
+ @Override
+ public void setVisibility(int visibility) {
+ super.setVisibility(visibility);
+
+ if (mCheckMarkDrawable != null) {
+ mCheckMarkDrawable.setVisible(visibility == VISIBLE, false);
+ }
+ }
+
+ @Override
+ public void jumpDrawablesToCurrentState() {
+ super.jumpDrawablesToCurrentState();
+
+ if (mCheckMarkDrawable != null) {
+ mCheckMarkDrawable.jumpToCurrentState();
+ }
+ }
+
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ return who == mCheckMarkDrawable || super.verifyDrawable(who);
+ }
+
/**
* Gets the checkmark drawable
*
@@ -249,6 +276,11 @@
}
checkMarkDrawable.setBounds(mScrollX + left, top, mScrollX + right, bottom);
checkMarkDrawable.draw(canvas);
+
+ final Drawable background = getBackground();
+ if (background != null) {
+ background.setHotspotBounds(mScrollX + left, top, mScrollX + right, bottom);
+ }
}
}
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index ad1a023..c5c6e64 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -951,9 +951,8 @@
final int[] myDrawableState = getDrawableState();
- if (mThumbDrawable != null && mThumbDrawable.setState(myDrawableState)) {
- // Handle changes to thumb width and height.
- requestLayout();
+ if (mThumbDrawable != null) {
+ mThumbDrawable.setState(myDrawableState);
}
if (mTrackDrawable != null) {
@@ -964,6 +963,16 @@
}
@Override
+ public void invalidateDrawable(Drawable drawable) {
+ super.invalidateDrawable(drawable);
+
+ if (drawable == mThumbDrawable) {
+ // Handle changes to thumb width and height.
+ requestLayout();
+ }
+ }
+
+ @Override
protected boolean verifyDrawable(Drawable who) {
return super.verifyDrawable(who) || who == mThumbDrawable || who == mTrackDrawable;
}
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 664f9db..5547a10 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -1026,7 +1026,7 @@
? dialog.mSingleChoiceItemLayout : dialog.mListItemLayout;
if (mCursor == null) {
adapter = (mAdapter != null) ? mAdapter
- : new ArrayAdapter<CharSequence>(mContext, layout, R.id.text1, mItems);
+ : new CheckedItemAdapter(mContext, layout, R.id.text1, mItems);
} else {
adapter = new SimpleCursorAdapter(mContext, layout,
mCursor, new String[]{mLabelColumn}, new int[]{R.id.text1});
@@ -1081,4 +1081,20 @@
}
}
+ private static class CheckedItemAdapter extends ArrayAdapter<CharSequence> {
+ public CheckedItemAdapter(Context context, int resource, int textViewResourceId,
+ CharSequence[] objects) {
+ super(context, resource, textViewResourceId, objects);
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+ }
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 1366499..a01e9b7 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -24,9 +24,9 @@
{
void setIcon(int index, in StatusBarIcon icon);
void removeIcon(int index);
- void addNotification(IBinder key, in StatusBarNotification notification);
- void updateNotification(IBinder key, in StatusBarNotification notification);
- void removeNotification(IBinder key);
+ void addNotification(in StatusBarNotification notification);
+ void updateNotification(in StatusBarNotification notification);
+ void removeNotification(String key);
void disable(int state);
void animateExpandNotificationsPanel();
void animateExpandSettingsPanel();
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 2d6cf2e..a3b417f 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -39,8 +39,8 @@
// ---- Methods below are for use by the status bar policy services ----
// You need the STATUS_BAR_SERVICE permission
void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList,
- out List<IBinder> notificationKeys, out List<StatusBarNotification> notifications,
- out int[] switches, out List<IBinder> binders);
+ out List<StatusBarNotification> notifications, out int[] switches,
+ out List<IBinder> binders);
void onPanelRevealed();
void onPanelHidden();
void onNotificationClick(String key);
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index 9501f92..c70841b 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -16,6 +16,8 @@
package com.android.internal.widget;
+import com.android.internal.widget.ILockSettingsObserver;
+
/** {@hide} */
interface ILockSettings {
void setBoolean(in String key, in boolean value, in int userId);
@@ -32,4 +34,6 @@
boolean havePattern(int userId);
boolean havePassword(int userId);
void removeUser(int userId);
+ void registerObserver(in ILockSettingsObserver observer);
+ void unregisterObserver(in ILockSettingsObserver observer);
}
diff --git a/core/java/com/android/internal/widget/ILockSettingsObserver.aidl b/core/java/com/android/internal/widget/ILockSettingsObserver.aidl
new file mode 100644
index 0000000..6c354d8
--- /dev/null
+++ b/core/java/com/android/internal/widget/ILockSettingsObserver.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+/** {@hide} */
+oneway interface ILockSettingsObserver {
+ void onLockSettingChanged(in String key, in int userId);
+}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 2882b54..25e3463 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -199,8 +199,8 @@
private ILockSettings getLockSettings() {
if (mLockSettingsService == null) {
- mLockSettingsService = ILockSettings.Stub.asInterface(
- (IBinder) ServiceManager.getService("lock_settings"));
+ mLockSettingsService = LockPatternUtilsCache.getInstance(
+ ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings")));
}
return mLockSettingsService;
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtilsCache.java b/core/java/com/android/internal/widget/LockPatternUtilsCache.java
new file mode 100644
index 0000000..550aa6d
--- /dev/null
+++ b/core/java/com/android/internal/widget/LockPatternUtilsCache.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.widget;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+
+/**
+ * A decorator for {@link ILockSettings} that caches the key-value responses in memory.
+ *
+ * Specifically, the return values of {@link #getString(String, String, int)},
+ * {@link #getLong(String, long, int)} and {@link #getBoolean(String, boolean, int)} are cached.
+ */
+public class LockPatternUtilsCache implements ILockSettings {
+
+ private static LockPatternUtilsCache sInstance;
+
+ private final ILockSettings mService;
+
+ /** Only access when holding {@code mCache} lock. */
+ private final ArrayMap<CacheKey, Object> mCache = new ArrayMap<>();
+
+ /** Only access when holding {@link #mCache} lock. */
+ private final CacheKey mCacheKey = new CacheKey();
+
+
+ public static synchronized LockPatternUtilsCache getInstance(ILockSettings service) {
+ if (sInstance == null) {
+ sInstance = new LockPatternUtilsCache(service);
+ }
+ return sInstance;
+ }
+
+ // ILockSettings
+
+ private LockPatternUtilsCache(ILockSettings service) {
+ mService = service;
+ try {
+ service.registerObserver(mObserver);
+ } catch (RemoteException e) {
+ // Not safe to do caching without the observer. System process has probably died
+ // anyway, so crashing here is fine.
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void setBoolean(String key, boolean value, int userId) throws RemoteException {
+ invalidateCache(key, userId);
+ mService.setBoolean(key, value, userId);
+ putCache(key, userId, value);
+ }
+
+ public void setLong(String key, long value, int userId) throws RemoteException {
+ invalidateCache(key, userId);
+ mService.setLong(key, value, userId);
+ putCache(key, userId, value);
+ }
+
+ public void setString(String key, String value, int userId) throws RemoteException {
+ invalidateCache(key, userId);
+ mService.setString(key, value, userId);
+ putCache(key, userId, value);
+ }
+
+ public long getLong(String key, long defaultValue, int userId) throws RemoteException {
+ Object value = peekCache(key, userId);
+ if (value instanceof Long) {
+ return (long) value;
+ }
+ long result = mService.getLong(key, defaultValue, userId);
+ putCache(key, userId, result);
+ return result;
+ }
+
+ public String getString(String key, String defaultValue, int userId) throws RemoteException {
+ Object value = peekCache(key, userId);
+ if (value instanceof String) {
+ return (String) value;
+ }
+ String result = mService.getString(key, defaultValue, userId);
+ putCache(key, userId, result);
+ return result;
+ }
+
+ public boolean getBoolean(String key, boolean defaultValue, int userId) throws RemoteException {
+ Object value = peekCache(key, userId);
+ if (value instanceof Boolean) {
+ return (boolean) value;
+ }
+ boolean result = mService.getBoolean(key, defaultValue, userId);
+ putCache(key, userId, result);
+ return result;
+ }
+
+ @Override
+ public void setLockPattern(String pattern, int userId) throws RemoteException {
+ mService.setLockPattern(pattern, userId);
+ }
+
+ @Override
+ public boolean checkPattern(String pattern, int userId) throws RemoteException {
+ return mService.checkPattern(pattern, userId);
+ }
+
+ @Override
+ public void setLockPassword(String password, int userId) throws RemoteException {
+ mService.setLockPassword(password, userId);
+ }
+
+ @Override
+ public boolean checkPassword(String password, int userId) throws RemoteException {
+ return mService.checkPassword(password, userId);
+ }
+
+ @Override
+ public boolean checkVoldPassword(int userId) throws RemoteException {
+ return mService.checkVoldPassword(userId);
+ }
+
+ @Override
+ public boolean havePattern(int userId) throws RemoteException {
+ return mService.havePattern(userId);
+ }
+
+ @Override
+ public boolean havePassword(int userId) throws RemoteException {
+ return mService.havePassword(userId);
+ }
+
+ @Override
+ public void removeUser(int userId) throws RemoteException {
+ mService.removeUser(userId);
+ }
+
+ @Override
+ public void registerObserver(ILockSettingsObserver observer) throws RemoteException {
+ mService.registerObserver(observer);
+ }
+
+ @Override
+ public void unregisterObserver(ILockSettingsObserver observer) throws RemoteException {
+ mService.unregisterObserver(observer);
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return mService.asBinder();
+ }
+
+ // Caching
+
+ private Object peekCache(String key, int userId) {
+ synchronized (mCache) {
+ // Safe to reuse mCacheKey, because it is not stored in the map.
+ return mCache.get(mCacheKey.set(key, userId));
+ }
+ }
+
+ private void putCache(String key, int userId, Object value) {
+ synchronized (mCache) {
+ // Create a new key, because this will be stored in the map.
+ mCache.put(new CacheKey().set(key, userId), value);
+ }
+ }
+
+ private void invalidateCache(String key, int userId) {
+ synchronized (mCache) {
+ // Safe to reuse mCacheKey, because it is not stored in the map.
+ mCache.remove(mCacheKey.set(key, userId));
+ }
+ }
+
+ private final ILockSettingsObserver mObserver = new ILockSettingsObserver.Stub() {
+ @Override
+ public void onLockSettingChanged(String key, int userId) throws RemoteException {
+ invalidateCache(key, userId);
+ }
+ };
+
+ private static final class CacheKey {
+ String key;
+ int userId;
+
+ public CacheKey set(String key, int userId) {
+ this.key = key;
+ this.userId = userId;
+ return this;
+ }
+
+ public CacheKey copy() {
+ return new CacheKey().set(key, userId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof CacheKey))
+ return false;
+ CacheKey o = (CacheKey) obj;
+ return userId == o.userId && key.equals(o.key);
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode() ^ userId;
+ }
+ }
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 835a648..a159715 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -138,6 +138,7 @@
android_hardware_Camera.cpp \
android_hardware_camera2_CameraMetadata.cpp \
android_hardware_camera2_legacy_LegacyCameraDevice.cpp \
+ android_hardware_camera2_DngCreator.cpp \
android_hardware_SensorManager.cpp \
android_hardware_SerialPort.cpp \
android_hardware_UsbDevice.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 2d350e0..0c7eefa 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -80,6 +80,7 @@
extern int register_android_hardware_Camera(JNIEnv *env);
extern int register_android_hardware_camera2_CameraMetadata(JNIEnv *env);
extern int register_android_hardware_camera2_legacy_LegacyCameraDevice(JNIEnv *env);
+extern int register_android_hardware_camera2_DngCreator(JNIEnv *env);
extern int register_android_hardware_SensorManager(JNIEnv *env);
extern int register_android_hardware_SerialPort(JNIEnv *env);
extern int register_android_hardware_UsbDevice(JNIEnv *env);
@@ -1286,6 +1287,7 @@
REG_JNI(register_android_hardware_Camera),
REG_JNI(register_android_hardware_camera2_CameraMetadata),
REG_JNI(register_android_hardware_camera2_legacy_LegacyCameraDevice),
+ REG_JNI(register_android_hardware_camera2_DngCreator),
REG_JNI(register_android_hardware_SensorManager),
REG_JNI(register_android_hardware_SerialPort),
REG_JNI(register_android_hardware_UsbDevice),
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index b389d9e..0cfcaef 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -50,26 +50,16 @@
///////////////////////////////////////////////////////////////////////////////////////////////
-static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle, jlong skiaShaderHandle)
+static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle)
{
SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- SkiaShader* skiaShader = reinterpret_cast<SkiaShader*>(skiaShaderHandle);
SkSafeUnref(shader);
- // skiaShader == NULL when not !USE_OPENGL_RENDERER, so no need to delete it outside the ifdef
-#ifdef USE_OPENGL_RENDERER
- if (android::uirenderer::Caches::hasInstance()) {
- android::uirenderer::Caches::getInstance().resourceCache.destructor(skiaShader);
- } else {
- delete skiaShader;
- }
-#endif
}
static void Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle,
- jlong skiaShaderHandle, jlong matrixHandle)
+ jlong matrixHandle)
{
SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- SkiaShader* skiaShader = reinterpret_cast<SkiaShader*>(skiaShaderHandle);
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
if (shader) {
if (NULL == matrix) {
@@ -78,9 +68,6 @@
else {
shader->setLocalMatrix(*matrix);
}
-#ifdef USE_OPENGL_RENDERER
- skiaShader->setMatrix(const_cast<SkMatrix*>(matrix));
-#endif
}
}
@@ -98,20 +85,6 @@
return reinterpret_cast<jlong>(s);
}
-static jlong BitmapShader_postConstructor(JNIEnv* env, jobject o, jlong shaderHandle,
- jlong bitmapHandle, jint tileModeX, jint tileModeY) {
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
-#ifdef USE_OPENGL_RENDERER
- SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader,
- static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY),
- NULL, !shader->isOpaque());
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////
static jlong LinearGradient_create1(JNIEnv* env, jobject o,
@@ -141,105 +114,6 @@
return reinterpret_cast<jlong>(shader);
}
-static jlong LinearGradient_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x0, jfloat y0, jfloat x1, jfloat y1, jintArray colorArray,
- jfloatArray posArray, jint tileMode) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- size_t count = env->GetArrayLength(colorArray);
- const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
-
- jfloat* storedBounds = new jfloat[4];
- storedBounds[0] = x0; storedBounds[1] = y0;
- storedBounds[2] = x1; storedBounds[3] = y1;
-
- bool missFirst = false;
- bool missLast = false;
- size_t stopCount = count;
-
- jfloat* storedPositions = NULL;
- if (posArray) {
- AutoJavaFloatArray autoPos(env, posArray, count);
- const float* posValues = autoPos.ptr();
-
- missFirst = posValues[0] != 0.0f;
- missLast = posValues[count - 1] != 1.0f;
-
- stopCount += missFirst + missLast;
- storedPositions = new jfloat[stopCount];
-
- if (missFirst) {
- storedPositions[0] = 0.0f;
- }
-
- for (size_t i = missFirst; i < count + missFirst; i++) {
- storedPositions[i] = posValues[i - missFirst];
- }
-
- if (missLast) {
- storedPositions[stopCount - 1] = 1.0f;
- }
- } else {
- storedPositions = new jfloat[count];
- storedPositions[0] = 0.0f;
- const jfloat step = 1.0f / (count - 1);
- for (size_t i = 1; i < count - 1; i++) {
- storedPositions[i] = step * i;
- }
- storedPositions[count - 1] = 1.0f;
- }
-
- uint32_t* storedColors = new uint32_t[stopCount];
-
- if (missFirst) {
- storedColors[0] = static_cast<uint32_t>(colorValues[0]);
- }
-
- for (size_t i = missFirst; i < count + missFirst; i++) {
- storedColors[i] = static_cast<uint32_t>(colorValues[i - missFirst]);
- }
-
- if (missLast) {
- storedColors[stopCount - 1] = static_cast<uint32_t>(colorValues[count - 1]);
- }
-
- SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
- storedPositions, stopCount, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
- !shader->isOpaque());
-
- env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
-static jlong LinearGradient_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x0, jfloat y0, jfloat x1, jfloat y1, jint color0, jint color1, jint tileMode) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- float* storedBounds = new float[4];
- storedBounds[0] = x0; storedBounds[1] = y0;
- storedBounds[2] = x1; storedBounds[3] = y1;
-
- float* storedPositions = new float[2];
- storedPositions[0] = 0.0f;
- storedPositions[1] = 1.0f;
-
- uint32_t* storedColors = new uint32_t[2];
- storedColors[0] = static_cast<uint32_t>(color0);
- storedColors[1] = static_cast<uint32_t>(color1);
-
- SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
- storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
- !shader->isOpaque());
-
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
static jlong LinearGradient_create2(JNIEnv* env, jobject o,
jfloat x0, jfloat y0, jfloat x1, jfloat y1,
jint color0, jint color1, jint tileMode)
@@ -300,67 +174,6 @@
return reinterpret_cast<jlong>(s);
}
-static jlong RadialGradient_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x, jfloat y, jfloat radius, jintArray colorArray, jfloatArray posArray, jint tileMode) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- size_t count = env->GetArrayLength(colorArray);
- const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
-
- jfloat* storedPositions = new jfloat[count];
- uint32_t* storedColors = new uint32_t[count];
- for (size_t i = 0; i < count; i++) {
- storedColors[i] = static_cast<uint32_t>(colorValues[i]);
- }
-
- if (posArray) {
- AutoJavaFloatArray autoPos(env, posArray, count);
- const float* posValues = autoPos.ptr();
- for (size_t i = 0; i < count; i++) {
- storedPositions[i] = posValues[i];
- }
- } else {
- storedPositions[0] = 0.0f;
- const jfloat step = 1.0f / (count - 1);
- for (size_t i = 1; i < count - 1; i++) {
- storedPositions[i] = step * i;
- }
- storedPositions[count - 1] = 1.0f;
- }
-
- SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
- storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL,
- !shader->isOpaque());
-
- env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
-static jlong RadialGradient_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x, jfloat y, jfloat radius, jint color0, jint color1, jint tileMode) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- float* storedPositions = new float[2];
- storedPositions[0] = 0.0f;
- storedPositions[1] = 1.0f;
-
- uint32_t* storedColors = new uint32_t[2];
- storedColors[0] = static_cast<uint32_t>(color0);
- storedColors[1] = static_cast<uint32_t>(color1);
-
- SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
- storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL,
- !shader->isOpaque());
-
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
///////////////////////////////////////////////////////////////////////////////
static jlong SweepGradient_create1(JNIEnv* env, jobject, jfloat x, jfloat y,
@@ -393,65 +206,6 @@
return reinterpret_cast<jlong>(s);
}
-static jlong SweepGradient_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x, jfloat y, jintArray colorArray, jfloatArray posArray) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- size_t count = env->GetArrayLength(colorArray);
- const jint* colorValues = env->GetIntArrayElements(colorArray, NULL);
-
- jfloat* storedPositions = new jfloat[count];
- uint32_t* storedColors = new uint32_t[count];
- for (size_t i = 0; i < count; i++) {
- storedColors[i] = static_cast<uint32_t>(colorValues[i]);
- }
-
- if (posArray) {
- AutoJavaFloatArray autoPos(env, posArray, count);
- const float* posValues = autoPos.ptr();
- for (size_t i = 0; i < count; i++) {
- storedPositions[i] = posValues[i];
- }
- } else {
- storedPositions[0] = 0.0f;
- const jfloat step = 1.0f / (count - 1);
- for (size_t i = 1; i < count - 1; i++) {
- storedPositions[i] = step * i;
- }
- storedPositions[count - 1] = 1.0f;
- }
-
- SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count,
- shader, NULL, !shader->isOpaque());
-
- env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
-static jlong SweepGradient_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
- jfloat x, jfloat y, jint color0, jint color1) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle);
- float* storedPositions = new float[2];
- storedPositions[0] = 0.0f;
- storedPositions[1] = 1.0f;
-
- uint32_t* storedColors = new uint32_t[2];
- storedColors[0] = static_cast<uint32_t>(color0);
- storedColors[1] = static_cast<uint32_t>(color1);
-
- SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2,
- shader, NULL, !shader->isOpaque());
-
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////
static jlong ComposeShader_create1(JNIEnv* env, jobject o,
@@ -476,40 +230,6 @@
return reinterpret_cast<jlong>(shader);
}
-static jlong ComposeShader_postCreate2(JNIEnv* env, jobject o, jlong shaderHandle,
- jlong shaderAHandle, jlong shaderBHandle, jint porterDuffModeHandle) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader *>(shaderHandle);
- SkiaShader* shaderA = reinterpret_cast<SkiaShader *>(shaderAHandle);
- SkiaShader* shaderB = reinterpret_cast<SkiaShader *>(shaderBHandle);
- SkPorterDuff::Mode porterDuffMode = static_cast<SkPorterDuff::Mode>(porterDuffModeHandle);
- SkXfermode::Mode mode = SkPorterDuff::ToXfermodeMode(porterDuffMode);
- SkiaShader* skiaShader = new SkiaComposeShader(shaderA, shaderB, mode, shader);
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
-static jlong ComposeShader_postCreate1(JNIEnv* env, jobject o, jlong shaderHandle,
- jlong shaderAHandle, jlong shaderBHandle, jlong modeHandle) {
-#ifdef USE_OPENGL_RENDERER
- SkShader* shader = reinterpret_cast<SkShader *>(shaderHandle);
- SkiaShader* shaderA = reinterpret_cast<SkiaShader *>(shaderAHandle);
- SkiaShader* shaderB = reinterpret_cast<SkiaShader *>(shaderBHandle);
- SkXfermode* mode = reinterpret_cast<SkXfermode *>(modeHandle);
- SkXfermode::Mode skiaMode;
- if (!SkXfermode::AsMode(mode, &skiaMode)) {
- // TODO: Support other modes
- skiaMode = SkXfermode::kSrcOver_Mode;
- }
- SkiaShader* skiaShader = new SkiaComposeShader(shaderA, shaderB, skiaMode, shader);
- return reinterpret_cast<jlong>(skiaShader);
-#else
- return NULL;
-#endif
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////
static JNINativeMethod gColorMethods[] = {
@@ -518,41 +238,32 @@
};
static JNINativeMethod gShaderMethods[] = {
- { "nativeDestructor", "(JJ)V", (void*)Shader_destructor },
- { "nativeSetLocalMatrix", "(JJJ)V", (void*)Shader_setLocalMatrix }
+ { "nativeDestructor", "(J)V", (void*)Shader_destructor },
+ { "nativeSetLocalMatrix", "(JJ)V", (void*)Shader_setLocalMatrix }
};
static JNINativeMethod gBitmapShaderMethods[] = {
{ "nativeCreate", "(JII)J", (void*)BitmapShader_constructor },
- { "nativePostCreate", "(JJII)J", (void*)BitmapShader_postConstructor }
};
static JNINativeMethod gLinearGradientMethods[] = {
{ "nativeCreate1", "(FFFF[I[FI)J", (void*)LinearGradient_create1 },
{ "nativeCreate2", "(FFFFIII)J", (void*)LinearGradient_create2 },
- { "nativePostCreate1", "(JFFFF[I[FI)J", (void*)LinearGradient_postCreate1 },
- { "nativePostCreate2", "(JFFFFIII)J", (void*)LinearGradient_postCreate2 }
};
static JNINativeMethod gRadialGradientMethods[] = {
{ "nativeCreate1", "(FFF[I[FI)J", (void*)RadialGradient_create1 },
{ "nativeCreate2", "(FFFIII)J", (void*)RadialGradient_create2 },
- { "nativePostCreate1", "(JFFF[I[FI)J", (void*)RadialGradient_postCreate1 },
- { "nativePostCreate2", "(JFFFIII)J", (void*)RadialGradient_postCreate2 }
};
static JNINativeMethod gSweepGradientMethods[] = {
{ "nativeCreate1", "(FF[I[F)J", (void*)SweepGradient_create1 },
{ "nativeCreate2", "(FFII)J", (void*)SweepGradient_create2 },
- { "nativePostCreate1", "(JFF[I[F)J", (void*)SweepGradient_postCreate1 },
- { "nativePostCreate2", "(JFFII)J", (void*)SweepGradient_postCreate2 }
};
static JNINativeMethod gComposeShaderMethods[] = {
{ "nativeCreate1", "(JJJ)J", (void*)ComposeShader_create1 },
{ "nativeCreate2", "(JJI)J", (void*)ComposeShader_create2 },
- { "nativePostCreate1", "(JJJJ)J", (void*)ComposeShader_postCreate1 },
- { "nativePostCreate2", "(JJJI)J", (void*)ComposeShader_postCreate2 }
};
#include <android_runtime/AndroidRuntime.h>
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 0d2df80..79353299 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -39,6 +39,9 @@
#include <nativehelper/ScopedUtfChars.h>
#include <nativehelper/ScopedPrimitiveArray.h>
+#include <sys/types.h> // for socketpair
+#include <sys/socket.h> // for socketpair
+
#if defined(LOG_NNDEBUG)
#if !LOG_NNDEBUG
#define ALOGVV ALOGV
@@ -351,6 +354,119 @@
}
}
+struct DumpMetadataParams {
+ int writeFd;
+ const CameraMetadata* metadata;
+};
+
+static void* CameraMetadata_writeMetadataThread(void* arg) {
+ DumpMetadataParams* p = static_cast<DumpMetadataParams*>(arg);
+
+ /*
+ * Write the dumped data, and close the writing side FD.
+ */
+ p->metadata->dump(p->writeFd, /*verbosity*/2);
+
+ if (close(p->writeFd) < 0) {
+ ALOGE("%s: Failed to close writeFd (errno = %#x, message = '%s')",
+ __FUNCTION__, errno, strerror(errno));
+ }
+
+ return NULL;
+}
+
+static void CameraMetadata_dump(JNIEnv *env, jobject thiz) {
+ ALOGV("%s", __FUNCTION__);
+ CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
+ if (metadata == NULL) {
+ return;
+ }
+
+ /*
+ * Create a socket pair for local streaming read/writes.
+ *
+ * The metadata will be dumped into the write side,
+ * and then read back out (and logged) via the read side.
+ */
+
+ int writeFd, readFd;
+ {
+
+ int sv[2];
+ if (socketpair(AF_LOCAL, SOCK_STREAM, /*protocol*/0, &sv[0]) < 0) {
+ jniThrowExceptionFmt(env, "java/io/IOException",
+ "Failed to create socketpair (errno = %#x, message = '%s')",
+ errno, strerror(errno));
+ return;
+ }
+ writeFd = sv[0];
+ readFd = sv[1];
+ }
+
+ /*
+ * Create a thread for doing the writing.
+ *
+ * The reading and writing must be concurrent, otherwise
+ * the write will block forever once it exhausts the capped
+ * buffer size (from getsockopt).
+ */
+ pthread_t writeThread;
+ DumpMetadataParams params = {
+ writeFd,
+ metadata
+ };
+
+ {
+ int threadRet = pthread_create(&writeThread, /*attr*/NULL,
+ CameraMetadata_writeMetadataThread, (void*)¶ms);
+
+ if (threadRet != 0) {
+ close(writeFd);
+
+ jniThrowExceptionFmt(env, "java/io/IOException",
+ "Failed to create thread for writing (errno = %#x, message = '%s')",
+ threadRet, strerror(threadRet));
+ }
+ }
+
+ /*
+ * Read out a byte until stream is complete. Write completed lines
+ * to ALOG.
+ */
+ {
+ char out[] = {'\0', '\0'}; // large enough to append as a string
+ String8 logLine;
+
+ // Read one byte at a time! Very slow but avoids complicated \n scanning.
+ ssize_t res;
+ while ((res = TEMP_FAILURE_RETRY(read(readFd, &out[0], /*count*/1))) > 0) {
+ if (out[0] == '\n') {
+ ALOGD("%s", logLine.string());
+ logLine.clear();
+ } else {
+ logLine.append(out);
+ }
+ }
+
+ if (res < 0) {
+ jniThrowExceptionFmt(env, "java/io/IOException",
+ "Failed to read from fd (errno = %#x, message = '%s')",
+ errno, strerror(errno));
+ //return;
+ } else if (!logLine.isEmpty()) {
+ ALOGD("%s", logLine.string());
+ }
+ }
+
+ int res;
+
+ // Join until thread finishes. Ensures params/metadata is valid until then.
+ if ((res = pthread_join(writeThread, /*retval*/NULL)) != 0) {
+ ALOGE("%s: Failed to join thread (errno = %#x, message = '%s')",
+ __FUNCTION__, res, strerror(res));
+ }
+}
+
static void CameraMetadata_readFromParcel(JNIEnv *env, jobject thiz, jobject parcel) {
ALOGV("%s", __FUNCTION__);
CameraMetadata* metadata = CameraMetadata_getPointerThrow(env, thiz);
@@ -436,6 +552,9 @@
{ "nativeWriteValues",
"(I[B)V",
(void *)CameraMetadata_writeValues },
+ { "nativeDump",
+ "()V",
+ (void *)CameraMetadata_dump },
// Parcelable interface
{ "nativeReadFromParcel",
"(Landroid/os/Parcel;)V",
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
new file mode 100644
index 0000000..7b686e7
--- /dev/null
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -0,0 +1,774 @@
+/*
+ * Copyright 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "DngCreator_JNI"
+
+#include <system/camera_metadata.h>
+#include <camera/CameraMetadata.h>
+#include <img_utils/DngUtils.h>
+#include <img_utils/TagDefinitions.h>
+#include <img_utils/TiffIfd.h>
+#include <img_utils/TiffWriter.h>
+#include <img_utils/Output.h>
+
+#include <utils/Log.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+#include <utils/RefBase.h>
+#include <cutils/properties.h>
+
+#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/android_hardware_camera2_CameraMetadata.h"
+
+#include <jni.h>
+#include <JNIHelp.h>
+
+using namespace android;
+using namespace img_utils;
+
+#define BAIL_IF_INVALID(expr, jnienv, tagId) \
+ if ((expr) != OK) { \
+ jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
+ "Invalid metadata for tag %x", tagId); \
+ return; \
+ }
+
+#define BAIL_IF_EMPTY(entry, jnienv, tagId) \
+ if (entry.count == 0) { \
+ jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
+ "Missing metadata fields for tag %x", tagId); \
+ return; \
+ }
+
+#define ANDROID_DNGCREATOR_CTX_JNI_ID "mNativeContext"
+
+static struct {
+ jfieldID mNativeContext;
+} gDngCreatorClassInfo;
+
+static struct {
+ jmethodID mWriteMethod;
+} gOutputStreamClassInfo;
+
+enum {
+ BITS_PER_SAMPLE = 16,
+ BYTES_PER_SAMPLE = 2,
+ TIFF_IFD_0 = 0
+};
+
+// ----------------------------------------------------------------------------
+
+// This class is not intended to be used across JNI calls.
+class JniOutputStream : public Output, public LightRefBase<JniOutputStream> {
+public:
+ JniOutputStream(JNIEnv* env, jobject outStream);
+
+ virtual ~JniOutputStream();
+
+ status_t open();
+ status_t write(const uint8_t* buf, size_t offset, size_t count);
+ status_t close();
+private:
+ enum {
+ BYTE_ARRAY_LENGTH = 1024
+ };
+ jobject mOutputStream;
+ JNIEnv* mEnv;
+ jbyteArray mByteArray;
+};
+
+JniOutputStream::JniOutputStream(JNIEnv* env, jobject outStream) : mOutputStream(outStream),
+ mEnv(env) {
+ mByteArray = env->NewByteArray(BYTE_ARRAY_LENGTH);
+ if (mByteArray == NULL) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", "Could not allocate byte array.");
+ }
+}
+
+JniOutputStream::~JniOutputStream() {
+ mEnv->DeleteLocalRef(mByteArray);
+}
+
+status_t JniOutputStream::open() {
+ // Do nothing
+ return OK;
+}
+
+status_t JniOutputStream::write(const uint8_t* buf, size_t offset, size_t count) {
+ while(count > 0) {
+ size_t len = BYTE_ARRAY_LENGTH;
+ len = (count > len) ? len : count;
+ mEnv->SetByteArrayRegion(mByteArray, 0, len, reinterpret_cast<const jbyte*>(buf + offset));
+
+ if (mEnv->ExceptionCheck()) {
+ return BAD_VALUE;
+ }
+
+ mEnv->CallVoidMethod(mOutputStream, gOutputStreamClassInfo.mWriteMethod, mByteArray,
+ 0, len);
+
+ if (mEnv->ExceptionCheck()) {
+ return BAD_VALUE;
+ }
+
+ count -= len;
+ offset += len;
+ }
+ return OK;
+}
+
+status_t JniOutputStream::close() {
+ // Do nothing
+ return OK;
+}
+
+// ----------------------------------------------------------------------------
+
+extern "C" {
+
+static TiffWriter* DngCreator_getCreator(JNIEnv* env, jobject thiz) {
+ ALOGV("%s:", __FUNCTION__);
+ return reinterpret_cast<TiffWriter*>(env->GetLongField(thiz,
+ gDngCreatorClassInfo.mNativeContext));
+}
+
+static void DngCreator_setCreator(JNIEnv* env, jobject thiz, sp<TiffWriter> writer) {
+ ALOGV("%s:", __FUNCTION__);
+ TiffWriter* current = DngCreator_getCreator(env, thiz);
+ if (writer != NULL) {
+ writer->incStrong((void*) DngCreator_setCreator);
+ }
+ if (current) {
+ current->decStrong((void*) DngCreator_setCreator);
+ }
+ env->SetLongField(thiz, gDngCreatorClassInfo.mNativeContext,
+ reinterpret_cast<jlong>(writer.get()));
+}
+
+static void DngCreator_nativeClassInit(JNIEnv* env, jclass clazz) {
+ ALOGV("%s:", __FUNCTION__);
+
+ gDngCreatorClassInfo.mNativeContext = env->GetFieldID(clazz,
+ ANDROID_DNGCREATOR_CTX_JNI_ID, "J");
+ LOG_ALWAYS_FATAL_IF(gDngCreatorClassInfo.mNativeContext == NULL,
+ "can't find android/hardware/camera2/DngCreator.%s",
+ ANDROID_DNGCREATOR_CTX_JNI_ID);
+
+ jclass outputStreamClazz = env->FindClass("java/io/OutputStream");
+ LOG_ALWAYS_FATAL_IF(outputStreamClazz == NULL, "Can't find java/io/OutputStream class");
+ gOutputStreamClassInfo.mWriteMethod = env->GetMethodID(outputStreamClazz, "write", "([BII)V");
+ LOG_ALWAYS_FATAL_IF(gOutputStreamClassInfo.mWriteMethod == NULL, "Can't find write method");
+}
+
+static void DngCreator_init(JNIEnv* env, jobject thiz, jobject characteristicsPtr,
+ jobject resultsPtr) {
+ ALOGV("%s:", __FUNCTION__);
+ CameraMetadata characteristics;
+ CameraMetadata results;
+ if (CameraMetadata_getNativeMetadata(env, characteristicsPtr, &characteristics) != OK) {
+ jniThrowException(env, "java/lang/AssertionError",
+ "No native metadata defined for camera characteristics.");
+ return;
+ }
+ if (CameraMetadata_getNativeMetadata(env, resultsPtr, &results) != OK) {
+ jniThrowException(env, "java/lang/AssertionError",
+ "No native metadata defined for capture results.");
+ return;
+ }
+
+ sp<TiffWriter> writer = new TiffWriter();
+
+ writer->addIfd(TIFF_IFD_0);
+
+ status_t err = OK;
+
+ const uint32_t samplesPerPixel = 1;
+ const uint32_t bitsPerSample = BITS_PER_SAMPLE;
+ const uint32_t bitsPerByte = BITS_PER_SAMPLE / BYTES_PER_SAMPLE;
+ uint32_t imageWidth = 0;
+ uint32_t imageHeight = 0;
+
+ OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
+
+ // TODO: Greensplit.
+ // TODO: UniqueCameraModel
+ // TODO: Add remaining non-essential tags
+ {
+ // Set orientation
+ uint16_t orientation = 1; // Normal
+ BAIL_IF_INVALID(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_0), env,
+ TAG_ORIENTATION);
+ }
+
+ {
+ // Set subfiletype
+ uint32_t subfileType = 0; // Main image
+ BAIL_IF_INVALID(writer->addEntry(TAG_NEWSUBFILETYPE, 1, &subfileType, TIFF_IFD_0), env,
+ TAG_NEWSUBFILETYPE);
+ }
+
+ {
+ // Set bits per sample
+ uint16_t bits = static_cast<uint16_t>(bitsPerSample);
+ BAIL_IF_INVALID(writer->addEntry(TAG_BITSPERSAMPLE, 1, &bits, TIFF_IFD_0), env,
+ TAG_BITSPERSAMPLE);
+ }
+
+ {
+ // Set compression
+ uint16_t compression = 1; // None
+ BAIL_IF_INVALID(writer->addEntry(TAG_COMPRESSION, 1, &compression, TIFF_IFD_0), env,
+ TAG_COMPRESSION);
+ }
+
+ {
+ // Set dimensions
+ camera_metadata_entry entry =
+ characteristics.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+ BAIL_IF_EMPTY(entry, env, TAG_IMAGEWIDTH);
+ uint32_t width = static_cast<uint32_t>(entry.data.i32[2]);
+ uint32_t height = static_cast<uint32_t>(entry.data.i32[3]);
+ BAIL_IF_INVALID(writer->addEntry(TAG_IMAGEWIDTH, 1, &width, TIFF_IFD_0), env,
+ TAG_IMAGEWIDTH);
+ BAIL_IF_INVALID(writer->addEntry(TAG_IMAGELENGTH, 1, &height, TIFF_IFD_0), env,
+ TAG_IMAGELENGTH);
+ imageWidth = width;
+ imageHeight = height;
+ }
+
+ {
+ // Set photometric interpretation
+ uint16_t interpretation = 32803;
+ BAIL_IF_INVALID(writer->addEntry(TAG_PHOTOMETRICINTERPRETATION, 1, &interpretation,
+ TIFF_IFD_0), env, TAG_PHOTOMETRICINTERPRETATION);
+ }
+
+ {
+ // Set blacklevel tags
+ camera_metadata_entry entry =
+ characteristics.find(ANDROID_SENSOR_BLACK_LEVEL_PATTERN);
+ BAIL_IF_EMPTY(entry, env, TAG_BLACKLEVEL);
+ const uint32_t* blackLevel = reinterpret_cast<const uint32_t*>(entry.data.i32);
+ BAIL_IF_INVALID(writer->addEntry(TAG_BLACKLEVEL, entry.count, blackLevel, TIFF_IFD_0), env,
+ TAG_BLACKLEVEL);
+
+ uint16_t repeatDim[2] = {2, 2};
+ BAIL_IF_INVALID(writer->addEntry(TAG_BLACKLEVELREPEATDIM, 2, repeatDim, TIFF_IFD_0), env,
+ TAG_BLACKLEVELREPEATDIM);
+ }
+
+ {
+ // Set samples per pixel
+ uint16_t samples = static_cast<uint16_t>(samplesPerPixel);
+ BAIL_IF_INVALID(writer->addEntry(TAG_SAMPLESPERPIXEL, 1, &samples, TIFF_IFD_0),
+ env, TAG_SAMPLESPERPIXEL);
+ }
+
+ {
+ // Set planar configuration
+ uint16_t config = 1; // Chunky
+ BAIL_IF_INVALID(writer->addEntry(TAG_PLANARCONFIGURATION, 1, &config, TIFF_IFD_0),
+ env, TAG_PLANARCONFIGURATION);
+ }
+
+ {
+ // Set CFA pattern dimensions
+ uint16_t repeatDim[2] = {2, 2};
+ BAIL_IF_INVALID(writer->addEntry(TAG_CFAREPEATPATTERNDIM, 2, repeatDim, TIFF_IFD_0),
+ env, TAG_CFAREPEATPATTERNDIM);
+ }
+
+ {
+ // Set CFA pattern
+ camera_metadata_entry entry =
+ characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
+ BAIL_IF_EMPTY(entry, env, TAG_CFAPATTERN);
+ camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa =
+ static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>(
+ entry.data.u8[0]);
+ switch(cfa) {
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: {
+ uint8_t cfa[4] = {0, 1, 1, 2};
+ BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
+ env, TAG_CFAPATTERN);
+ opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
+ break;
+ }
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: {
+ uint8_t cfa[4] = {1, 0, 2, 1};
+ BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
+ env, TAG_CFAPATTERN);
+ opcodeCfaLayout = OpcodeListBuilder::CFA_GRBG;
+ break;
+ }
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: {
+ uint8_t cfa[4] = {1, 2, 0, 1};
+ BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
+ env, TAG_CFAPATTERN);
+ opcodeCfaLayout = OpcodeListBuilder::CFA_GBRG;
+ break;
+ }
+ case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: {
+ uint8_t cfa[4] = {2, 1, 1, 0};
+ BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
+ env, TAG_CFAPATTERN);
+ opcodeCfaLayout = OpcodeListBuilder::CFA_BGGR;
+ break;
+ }
+ default: {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Invalid metadata for tag %d", TAG_CFAPATTERN);
+ return;
+ }
+ }
+ }
+
+ {
+ // Set CFA plane color
+ uint8_t cfaPlaneColor[3] = {0, 1, 2};
+ BAIL_IF_INVALID(writer->addEntry(TAG_CFAPLANECOLOR, 3, cfaPlaneColor, TIFF_IFD_0),
+ env, TAG_CFAPLANECOLOR);
+ }
+
+ {
+ // Set CFA layout
+ uint16_t cfaLayout = 1;
+ BAIL_IF_INVALID(writer->addEntry(TAG_CFALAYOUT, 1, &cfaLayout, TIFF_IFD_0),
+ env, TAG_CFALAYOUT);
+ }
+
+ {
+ // Set DNG version information
+ uint8_t version[4] = {1, 4, 0, 0};
+ BAIL_IF_INVALID(writer->addEntry(TAG_DNGVERSION, 4, version, TIFF_IFD_0),
+ env, TAG_DNGVERSION);
+
+ uint8_t backwardVersion[4] = {1, 1, 0, 0};
+ BAIL_IF_INVALID(writer->addEntry(TAG_DNGBACKWARDVERSION, 4, backwardVersion, TIFF_IFD_0),
+ env, TAG_DNGBACKWARDVERSION);
+ }
+
+ {
+ // Set whitelevel
+ camera_metadata_entry entry =
+ characteristics.find(ANDROID_SENSOR_INFO_WHITE_LEVEL);
+ BAIL_IF_EMPTY(entry, env, TAG_WHITELEVEL);
+ uint32_t whiteLevel = static_cast<uint32_t>(entry.data.i32[0]);
+ BAIL_IF_INVALID(writer->addEntry(TAG_WHITELEVEL, 1, &whiteLevel, TIFF_IFD_0), env,
+ TAG_WHITELEVEL);
+ }
+
+ {
+ // Set default scale
+ uint32_t defaultScale[4] = {1, 1, 1, 1};
+ BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTSCALE, 2, defaultScale, TIFF_IFD_0),
+ env, TAG_DEFAULTSCALE);
+ }
+
+ bool singleIlluminant = false;
+ {
+ // Set calibration illuminants
+ camera_metadata_entry entry1 =
+ characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT1);
+ BAIL_IF_EMPTY(entry1, env, TAG_CALIBRATIONILLUMINANT1);
+ camera_metadata_entry entry2 =
+ characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT2);
+ if (entry2.count == 0) {
+ singleIlluminant = true;
+ }
+ uint16_t ref1 = entry1.data.u8[0];
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_CALIBRATIONILLUMINANT1, 1, &ref1,
+ TIFF_IFD_0), env, TAG_CALIBRATIONILLUMINANT1);
+
+ if (!singleIlluminant) {
+ uint16_t ref2 = entry2.data.u8[0];
+ BAIL_IF_INVALID(writer->addEntry(TAG_CALIBRATIONILLUMINANT2, 1, &ref2,
+ TIFF_IFD_0), env, TAG_CALIBRATIONILLUMINANT2);
+ }
+ }
+
+ {
+ // Set color transforms
+ camera_metadata_entry entry1 =
+ characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM1);
+ BAIL_IF_EMPTY(entry1, env, TAG_COLORMATRIX1);
+
+ int32_t colorTransform1[entry1.count * 2];
+
+ size_t ctr = 0;
+ for(size_t i = 0; i < entry1.count; ++i) {
+ colorTransform1[ctr++] = entry1.data.r[i].numerator;
+ colorTransform1[ctr++] = entry1.data.r[i].denominator;
+ }
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_COLORMATRIX1, entry1.count, colorTransform1, TIFF_IFD_0),
+ env, TAG_COLORMATRIX1);
+
+ if (!singleIlluminant) {
+ camera_metadata_entry entry2 = characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM2);
+ BAIL_IF_EMPTY(entry2, env, TAG_COLORMATRIX2);
+ int32_t colorTransform2[entry2.count * 2];
+
+ ctr = 0;
+ for(size_t i = 0; i < entry2.count; ++i) {
+ colorTransform2[ctr++] = entry2.data.r[i].numerator;
+ colorTransform2[ctr++] = entry2.data.r[i].denominator;
+ }
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_COLORMATRIX2, entry2.count, colorTransform2, TIFF_IFD_0),
+ env, TAG_COLORMATRIX2);
+ }
+ }
+
+ {
+ // Set calibration transforms
+ camera_metadata_entry entry1 =
+ characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM1);
+ BAIL_IF_EMPTY(entry1, env, TAG_CAMERACALIBRATION1);
+
+ int32_t calibrationTransform1[entry1.count * 2];
+
+ size_t ctr = 0;
+ for(size_t i = 0; i < entry1.count; ++i) {
+ calibrationTransform1[ctr++] = entry1.data.r[i].numerator;
+ calibrationTransform1[ctr++] = entry1.data.r[i].denominator;
+ }
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_CAMERACALIBRATION1, entry1.count, calibrationTransform1,
+ TIFF_IFD_0), env, TAG_CAMERACALIBRATION1);
+
+ if (!singleIlluminant) {
+ camera_metadata_entry entry2 =
+ characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM2);
+ BAIL_IF_EMPTY(entry2, env, TAG_CAMERACALIBRATION2);
+ int32_t calibrationTransform2[entry2.count * 2];
+
+ ctr = 0;
+ for(size_t i = 0; i < entry2.count; ++i) {
+ calibrationTransform2[ctr++] = entry2.data.r[i].numerator;
+ calibrationTransform2[ctr++] = entry2.data.r[i].denominator;
+ }
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_CAMERACALIBRATION2, entry2.count, calibrationTransform1,
+ TIFF_IFD_0), env, TAG_CAMERACALIBRATION2);
+ }
+ }
+
+ {
+ // Set forward transforms
+ camera_metadata_entry entry1 =
+ characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX1);
+ BAIL_IF_EMPTY(entry1, env, TAG_FORWARDMATRIX1);
+
+ int32_t forwardTransform1[entry1.count * 2];
+
+ size_t ctr = 0;
+ for(size_t i = 0; i < entry1.count; ++i) {
+ forwardTransform1[ctr++] = entry1.data.r[i].numerator;
+ forwardTransform1[ctr++] = entry1.data.r[i].denominator;
+ }
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_FORWARDMATRIX1, entry1.count, forwardTransform1,
+ TIFF_IFD_0), env, TAG_FORWARDMATRIX1);
+
+ if (!singleIlluminant) {
+ camera_metadata_entry entry2 =
+ characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX2);
+ BAIL_IF_EMPTY(entry2, env, TAG_FORWARDMATRIX2);
+ int32_t forwardTransform2[entry2.count * 2];
+
+ ctr = 0;
+ for(size_t i = 0; i < entry2.count; ++i) {
+ forwardTransform2[ctr++] = entry2.data.r[i].numerator;
+ forwardTransform2[ctr++] = entry2.data.r[i].denominator;
+ }
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_FORWARDMATRIX2, entry2.count, forwardTransform2,
+ TIFF_IFD_0), env, TAG_FORWARDMATRIX2);
+ }
+ }
+
+ {
+ // Set camera neutral
+ camera_metadata_entry entry =
+ results.find(ANDROID_SENSOR_NEUTRAL_COLOR_POINT);
+ BAIL_IF_EMPTY(entry, env, TAG_ASSHOTNEUTRAL);
+ uint32_t cameraNeutral[entry.count * 2];
+
+ size_t ctr = 0;
+ for(size_t i = 0; i < entry.count; ++i) {
+ cameraNeutral[ctr++] =
+ static_cast<uint32_t>(entry.data.r[i].numerator);
+ cameraNeutral[ctr++] =
+ static_cast<uint32_t>(entry.data.r[i].denominator);
+ }
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_ASSHOTNEUTRAL, entry.count, cameraNeutral,
+ TIFF_IFD_0), env, TAG_ASSHOTNEUTRAL);
+ }
+
+ {
+ // Setup data strips
+ // TODO: Switch to tiled implementation.
+ uint32_t offset = 0;
+ BAIL_IF_INVALID(writer->addEntry(TAG_STRIPOFFSETS, 1, &offset, TIFF_IFD_0), env,
+ TAG_STRIPOFFSETS);
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_ROWSPERSTRIP, 1, &imageHeight, TIFF_IFD_0), env,
+ TAG_ROWSPERSTRIP);
+
+ uint32_t byteCount = imageWidth * imageHeight * bitsPerSample * samplesPerPixel /
+ bitsPerByte;
+ BAIL_IF_INVALID(writer->addEntry(TAG_STRIPBYTECOUNTS, 1, &byteCount, TIFF_IFD_0), env,
+ TAG_STRIPBYTECOUNTS);
+ }
+
+ {
+ // Setup default crop + crop origin tags
+ uint32_t margin = 8; // Default margin recommended by Adobe for interpolation.
+ uint32_t dimensionLimit = 128; // Smallest image dimension crop margin from.
+ if (imageWidth >= dimensionLimit && imageHeight >= dimensionLimit) {
+ uint32_t defaultCropOrigin[] = {margin, margin};
+ uint32_t defaultCropSize[] = {imageWidth - margin, imageHeight - margin};
+ BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTCROPORIGIN, 2, defaultCropOrigin,
+ TIFF_IFD_0), env, TAG_DEFAULTCROPORIGIN);
+ BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTCROPSIZE, 2, defaultCropSize,
+ TIFF_IFD_0), env, TAG_DEFAULTCROPSIZE);
+ }
+ }
+
+ {
+ // Setup unique camera model tag
+ char model[PROPERTY_VALUE_MAX];
+ property_get("ro.product.model", model, "");
+
+ char manufacturer[PROPERTY_VALUE_MAX];
+ property_get("ro.product.manufacturer", manufacturer, "");
+
+ char brand[PROPERTY_VALUE_MAX];
+ property_get("ro.product.brand", brand, "");
+
+ String8 cameraModel(model);
+ cameraModel += "-";
+ cameraModel += manufacturer;
+ cameraModel += "-";
+ cameraModel += brand;
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_UNIQUECAMERAMODEL, cameraModel.size() + 1,
+ reinterpret_cast<const uint8_t*>(cameraModel.string()), TIFF_IFD_0), env,
+ TAG_UNIQUECAMERAMODEL);
+ }
+
+ {
+ // Setup opcode List 2
+ camera_metadata_entry entry1 =
+ characteristics.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
+ BAIL_IF_EMPTY(entry1, env, TAG_OPCODELIST2);
+ uint32_t lsmWidth = static_cast<uint32_t>(entry1.data.i32[0]);
+ uint32_t lsmHeight = static_cast<uint32_t>(entry1.data.i32[1]);
+
+ camera_metadata_entry entry2 =
+ results.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
+ BAIL_IF_EMPTY(entry2, env, TAG_OPCODELIST2);
+ if (entry2.count == lsmWidth * lsmHeight * 4) {
+
+ OpcodeListBuilder builder;
+ status_t err = builder.addGainMapsForMetadata(lsmWidth,
+ lsmHeight,
+ 0,
+ 0,
+ imageHeight,
+ imageWidth,
+ opcodeCfaLayout,
+ entry2.data.f);
+ if (err == OK) {
+ size_t listSize = builder.getSize();
+ uint8_t opcodeListBuf[listSize];
+ err = builder.buildOpList(opcodeListBuf);
+ if (err == OK) {
+ BAIL_IF_INVALID(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf,
+ TIFF_IFD_0), env, TAG_OPCODELIST2);
+ } else {
+ ALOGE("%s: Could not build Lens shading map opcode.", __FUNCTION__);
+ jniThrowRuntimeException(env, "failed to construct lens shading map opcode.");
+ }
+ } else {
+ ALOGE("%s: Could not add Lens shading map.", __FUNCTION__);
+ jniThrowRuntimeException(env, "failed to add lens shading map.");
+ }
+ } else {
+ ALOGW("%s: Lens shading map not present in results, skipping...", __FUNCTION__);
+ }
+ }
+
+ DngCreator_setCreator(env, thiz, writer);
+}
+
+static void DngCreator_destroy(JNIEnv* env, jobject thiz) {
+ ALOGV("%s:", __FUNCTION__);
+ DngCreator_setCreator(env, thiz, NULL);
+}
+
+static void DngCreator_nativeSetOrientation(JNIEnv* env, jobject thiz) {
+ ALOGV("%s:", __FUNCTION__);
+ jniThrowRuntimeException(env, "nativeSetOrientation is not implemented");
+}
+
+static void DngCreator_nativeSetThumbnailBitmap(JNIEnv* env, jobject thiz, jobject bitmap) {
+ ALOGV("%s:", __FUNCTION__);
+ jniThrowRuntimeException(env, "nativeSetThumbnailBitmap is not implemented");
+}
+
+static void DngCreator_nativeSetThumbnailImage(JNIEnv* env, jobject thiz, jint width, jint height,
+ jobject yBuffer, jint yRowStride, jint yPixStride, jobject uBuffer, jint uRowStride,
+ jint uPixStride, jobject vBuffer, jint vRowStride, jint vPixStride) {
+ ALOGV("%s:", __FUNCTION__);
+ jniThrowRuntimeException(env, "nativeSetThumbnailImage is not implemented");
+}
+
+static void DngCreator_nativeWriteImage(JNIEnv* env, jobject thiz, jobject outStream, jint width,
+ jint height, jobject inBuffer, jint rowStride, jint pixStride) {
+ ALOGV("%s:", __FUNCTION__);
+
+ sp<JniOutputStream> out = new JniOutputStream(env, outStream);
+ if(env->ExceptionCheck()) {
+ ALOGE("%s: Could not allocate buffers for output stream", __FUNCTION__);
+ return;
+ }
+
+ uint8_t* pixelBytes = reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(inBuffer));
+ if (pixelBytes == NULL) {
+ ALOGE("%s: Could not get native byte buffer", __FUNCTION__);
+ jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid bytebuffer");
+ return;
+ }
+
+ TiffWriter* writer = DngCreator_getCreator(env, thiz);
+ if (writer == NULL) {
+ ALOGE("%s: Failed to initialize DngCreator", __FUNCTION__);
+ jniThrowException(env, "java/lang/AssertionError",
+ "Write called with uninitialized DngCreator");
+ return;
+ }
+ // TODO: handle lens shading map, etc. conversions for other raw buffer sizes.
+ uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, TIFF_IFD_0)->getData<uint32_t>());
+ uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, TIFF_IFD_0)->getData<uint32_t>());
+ if (metadataWidth != width) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException", \
+ "Metadata width %d doesn't match image width %d", metadataWidth, width);
+ return;
+ }
+
+ if (metadataHeight != height) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException", \
+ "Metadata height %d doesn't match image height %d", metadataHeight, height);
+ return;
+ }
+
+ uint32_t stripOffset = writer->getTotalSize();
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_STRIPOFFSETS, 1, &stripOffset, TIFF_IFD_0), env,
+ TAG_STRIPOFFSETS);
+
+ if (writer->write(out.get()) != OK) {
+ if (!env->ExceptionCheck()) {
+ jniThrowException(env, "java/io/IOException", "Failed to write metadata");
+ }
+ return;
+ }
+
+ size_t fullSize = rowStride * height;
+ jlong capacity = env->GetDirectBufferCapacity(inBuffer);
+ if (capacity < 0 || fullSize > capacity) {
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Invalid size %d for Image, size given in metadata is %d at current stride",
+ capacity, fullSize);
+ return;
+ }
+
+ if (pixStride == BYTES_PER_SAMPLE && rowStride == width * BYTES_PER_SAMPLE) {
+ if (out->write(pixelBytes, 0, fullSize) != OK || env->ExceptionCheck()) {
+ if (!env->ExceptionCheck()) {
+ jniThrowException(env, "java/io/IOException", "Failed to write pixel data");
+ }
+ return;
+ }
+ } else if (pixStride == BYTES_PER_SAMPLE) {
+ for (size_t i = 0; i < height; ++i) {
+ if (out->write(pixelBytes, i * rowStride, pixStride * width) != OK ||
+ env->ExceptionCheck()) {
+ if (!env->ExceptionCheck()) {
+ jniThrowException(env, "java/io/IOException", "Failed to write pixel data");
+ }
+ return;
+ }
+ }
+ } else {
+ for (size_t i = 0; i < height; ++i) {
+ for (size_t j = 0; j < width; ++j) {
+ if (out->write(pixelBytes, i * rowStride + j * pixStride,
+ BYTES_PER_SAMPLE) != OK || !env->ExceptionCheck()) {
+ if (env->ExceptionCheck()) {
+ jniThrowException(env, "java/io/IOException", "Failed to write pixel data");
+ }
+ return;
+ }
+ }
+ }
+ }
+
+}
+
+static void DngCreator_nativeWriteByteBuffer(JNIEnv* env, jobject thiz, jobject outStream,
+ jobject rawBuffer, jlong offset) {
+ ALOGV("%s:", __FUNCTION__);
+ jniThrowRuntimeException(env, "nativeWriteByteBuffer is not implemented.");
+}
+
+static void DngCreator_nativeWriteInputStream(JNIEnv* env, jobject thiz, jobject outStream,
+ jobject inStream, jlong offset) {
+ ALOGV("%s:", __FUNCTION__);
+ jniThrowRuntimeException(env, "nativeWriteInputStream is not implemented.");
+}
+
+} /*extern "C" */
+
+static JNINativeMethod gDngCreatorMethods[] = {
+ {"nativeClassInit", "()V", (void*) DngCreator_nativeClassInit},
+ {"nativeInit", "(Landroid/hardware/camera2/impl/CameraMetadataNative;"
+ "Landroid/hardware/camera2/impl/CameraMetadataNative;)V", (void*) DngCreator_init},
+ {"nativeDestroy", "()V", (void*) DngCreator_destroy},
+ {"nativeSetOrientation", "(I)V", (void*) DngCreator_nativeSetOrientation},
+ {"nativeSetThumbnailBitmap","(Landroid/graphics/Bitmap;)V",
+ (void*) DngCreator_nativeSetThumbnailBitmap},
+ {"nativeSetThumbnailImage",
+ "(IILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;II)V",
+ (void*) DngCreator_nativeSetThumbnailImage},
+ {"nativeWriteImage", "(Ljava/io/OutputStream;IILjava/nio/ByteBuffer;II)V",
+ (void*) DngCreator_nativeWriteImage},
+ {"nativeWriteByteBuffer", "(Ljava/io/OutputStream;Ljava/nio/ByteBuffer;J)V",
+ (void*) DngCreator_nativeWriteByteBuffer},
+ {"nativeWriteInputStream", "(Ljava/io/OutputStream;Ljava/io/InputStream;J)V",
+ (void*) DngCreator_nativeWriteInputStream},
+};
+
+int register_android_hardware_camera2_DngCreator(JNIEnv *env) {
+ return AndroidRuntime::registerNativeMethods(env,
+ "android/hardware/camera2/DngCreator", gDngCreatorMethods,
+ NELEM(gDngCreatorMethods));
+}
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 27d3f39..c5dd06f 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -45,7 +45,6 @@
#include <DisplayListRenderer.h>
#include <LayerRenderer.h>
#include <OpenGLRenderer.h>
-#include <SkiaShader.h>
#include <Stencil.h>
#include <Rect.h>
#include <RenderNode.h>
@@ -85,8 +84,6 @@
#define RENDERER_LOGD(...)
#endif
-#define MODIFIER_SHADER 2
-
// ----------------------------------------------------------------------------
static struct {
@@ -616,24 +613,6 @@
}
// ----------------------------------------------------------------------------
-// Shaders and color filters
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_resetModifiers(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jint modifiers) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- if (modifiers & MODIFIER_SHADER) renderer->resetShader();
-}
-
-static void android_view_GLES20Canvas_setupShader(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong shaderPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- SkiaShader* shader = reinterpret_cast<SkiaShader*>(shaderPtr);
- renderer->setupShader(shader);
-}
-
-
-// ----------------------------------------------------------------------------
// Draw filters
// ----------------------------------------------------------------------------
@@ -1091,9 +1070,6 @@
{ "nDrawPath", "(JJJ)V", (void*) android_view_GLES20Canvas_drawPath },
{ "nDrawLines", "(J[FIIJ)V", (void*) android_view_GLES20Canvas_drawLines },
- { "nResetModifiers", "(JI)V", (void*) android_view_GLES20Canvas_resetModifiers },
- { "nSetupShader", "(JJ)V", (void*) android_view_GLES20Canvas_setupShader },
-
{ "nSetupPaintFilter", "(JII)V", (void*) android_view_GLES20Canvas_setupPaintFilter },
{ "nResetPaintFilter", "(J)V", (void*) android_view_GLES20Canvas_resetPaintFilter },
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 48fb729..5bc0f62 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -299,6 +299,12 @@
proxy->fence();
}
+static void android_view_ThreadedRenderer_notifyFramePending(JNIEnv* env, jobject clazz,
+ jlong proxyPtr) {
+ RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+ proxy->notifyFramePending();
+}
+
#endif
// ----------------------------------------------------------------------------
@@ -329,6 +335,7 @@
{ "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
{ "nDestroyLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_destroyLayer },
{ "nFence", "(J)V", (void*) android_view_ThreadedRenderer_fence },
+ { "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
#endif
};
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00000_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00000_qntm_alpha.png
deleted file mode 100644
index 1880a15..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00000_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00001_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00001_qntm_alpha.png
deleted file mode 100644
index aecb4d2..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00001_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00002_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00002_qntm_alpha.png
deleted file mode 100644
index 8401f91..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00002_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00003_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00003_qntm_alpha.png
deleted file mode 100644
index 5832865..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00003_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00004_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00004_qntm_alpha.png
deleted file mode 100644
index 6d14962..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00004_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00005_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00005_qntm_alpha.png
deleted file mode 100644
index aee057c..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00005_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00006_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00006_qntm_alpha.png
deleted file mode 100644
index fb5801e..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00006_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00007_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00007_qntm_alpha.png
deleted file mode 100644
index fdb5271..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00007_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00008_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00008_qntm_alpha.png
deleted file mode 100644
index b8c7397..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00008_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00009_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00009_qntm_alpha.png
deleted file mode 100644
index d0395a8..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00009_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00010_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00010_qntm_alpha.png
deleted file mode 100644
index 59bb437..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00010_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00011_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00011_qntm_alpha.png
deleted file mode 100644
index c053b90..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00011_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00012_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00012_qntm_alpha.png
deleted file mode 100644
index eb30a79..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00012_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00013_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00013_qntm_alpha.png
deleted file mode 100644
index 1af0bff..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00013_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00014_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00014_qntm_alpha.png
deleted file mode 100644
index 3b36e7d..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00014_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_anim_00015_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_anim_00015_qntm_alpha.png
deleted file mode 100644
index c12d20a..0000000
--- a/core/res/res/drawable-hdpi/btn_check_anim_00015_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_off_qntm_alpha.png
deleted file mode 100644
index 5bc1d90..0000000
--- a/core/res/res/drawable-hdpi/btn_check_off_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_check_on_qntm_alpha.png
deleted file mode 100644
index e5de2c1..0000000
--- a/core/res/res/drawable-hdpi/btn_check_on_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_000.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_000.png
new file mode 100644
index 0000000..3cb4073
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_001.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_001.png
new file mode 100644
index 0000000..8fd1480
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_002.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_002.png
new file mode 100644
index 0000000..d35b579
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_003.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_003.png
new file mode 100644
index 0000000..543c6bc
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_004.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_004.png
new file mode 100644
index 0000000..4fc3c40
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_005.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_005.png
new file mode 100644
index 0000000..c184535
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_006.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_006.png
new file mode 100644
index 0000000..9f9dd43
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_007.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_007.png
new file mode 100644
index 0000000..8c629ce
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_008.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_008.png
new file mode 100644
index 0000000..81134b5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_009.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_009.png
new file mode 100644
index 0000000..baa5860
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_010.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_010.png
new file mode 100644
index 0000000..d7e28366
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_011.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_011.png
new file mode 100644
index 0000000..6f24795
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_012.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_012.png
new file mode 100644
index 0000000..22f997d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_013.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_013.png
new file mode 100644
index 0000000..85f4471
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_014.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_014.png
new file mode 100644
index 0000000..ad483c9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_off_qntm_015.png b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_015.png
new file mode 100644
index 0000000..f24c2fb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_off_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_000.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_000.png
new file mode 100644
index 0000000..7a9e9bd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_001.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_001.png
new file mode 100644
index 0000000..af04902
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_002.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_002.png
new file mode 100644
index 0000000..32a6e94
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_003.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_003.png
new file mode 100644
index 0000000..c1b4b37
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_004.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_004.png
new file mode 100644
index 0000000..34d3ade
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_005.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_005.png
new file mode 100644
index 0000000..3d5db53
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_006.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_006.png
new file mode 100644
index 0000000..ea35437
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_007.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_007.png
new file mode 100644
index 0000000..48744f8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_008.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_008.png
new file mode 100644
index 0000000..f654517
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_009.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_009.png
new file mode 100644
index 0000000..16f959a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_010.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_010.png
new file mode 100644
index 0000000..98c754b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_011.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_011.png
new file mode 100644
index 0000000..5827dc2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_012.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_012.png
new file mode 100644
index 0000000..9850d74
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_013.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_013.png
new file mode 100644
index 0000000..03ab06b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_014.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_014.png
new file mode 100644
index 0000000..11cdd88
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_to_on_qntm_015.png b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_015.png
new file mode 100644
index 0000000..874edbf
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_check_to_on_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00000_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00000_qntm_alpha.png
deleted file mode 100644
index 882365b..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00000_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00001_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00001_qntm_alpha.png
deleted file mode 100644
index f6c7094..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00001_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00002_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00002_qntm_alpha.png
deleted file mode 100644
index 0e326c9..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00002_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00003_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00003_qntm_alpha.png
deleted file mode 100644
index 8bf1170..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00003_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00004_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00004_qntm_alpha.png
deleted file mode 100644
index cedb66e..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00004_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00005_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00005_qntm_alpha.png
deleted file mode 100644
index 257d7ba..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00005_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00006_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00006_qntm_alpha.png
deleted file mode 100644
index e07b36e..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00006_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00007_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00007_qntm_alpha.png
deleted file mode 100644
index ef94200..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00007_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00008_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00008_qntm_alpha.png
deleted file mode 100644
index ad67004..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00008_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00009_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00009_qntm_alpha.png
deleted file mode 100644
index 50796e2..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00009_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00010_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00010_qntm_alpha.png
deleted file mode 100644
index ba7be9e..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00010_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00011_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00011_qntm_alpha.png
deleted file mode 100644
index bdbfe78..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00011_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00012_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00012_qntm_alpha.png
deleted file mode 100644
index fe89951..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00012_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00013_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00013_qntm_alpha.png
deleted file mode 100644
index 840c88f..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00013_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00014_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00014_qntm_alpha.png
deleted file mode 100644
index 621d1d2..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00014_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_anim_00015_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_anim_00015_qntm_alpha.png
deleted file mode 100644
index fd8be89..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_anim_00015_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed_qntm_alpha.png
deleted file mode 100644
index 7bef530..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_off_pressed_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_off_qntm_alpha.png
deleted file mode 100644
index ae50dd5..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_off_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed_qntm_alpha.png
deleted file mode 100644
index 0678dbb..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_on_pressed_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_qntm_alpha.png b/core/res/res/drawable-hdpi/btn_radio_on_qntm_alpha.png
deleted file mode 100644
index f332925..0000000
--- a/core/res/res/drawable-hdpi/btn_radio_on_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_000.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_000.png
new file mode 100644
index 0000000..da88e98
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_001.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_001.png
new file mode 100644
index 0000000..907d92d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_002.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_002.png
new file mode 100644
index 0000000..9d24dc1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_003.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_003.png
new file mode 100644
index 0000000..8aa2605
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_004.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_004.png
new file mode 100644
index 0000000..b4cdf02
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_005.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_005.png
new file mode 100644
index 0000000..0724ed7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_006.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_006.png
new file mode 100644
index 0000000..c9bd4e3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_007.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_007.png
new file mode 100644
index 0000000..5630ec3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_008.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_008.png
new file mode 100644
index 0000000..4bf666c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_009.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_009.png
new file mode 100644
index 0000000..dffaa07
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_010.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_010.png
new file mode 100644
index 0000000..5f86e18
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_011.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_011.png
new file mode 100644
index 0000000..9b50aef
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_012.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_012.png
new file mode 100644
index 0000000..1cf5e7f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_013.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_013.png
new file mode 100644
index 0000000..2bb641a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_014.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_014.png
new file mode 100644
index 0000000..08e7485
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_015.png b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_015.png
new file mode 100644
index 0000000..519b5a3
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_off_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_000.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_000.png
new file mode 100644
index 0000000..0d3e1e7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_001.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_001.png
new file mode 100644
index 0000000..88c4a9e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_002.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_002.png
new file mode 100644
index 0000000..8fa2e88
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_003.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_003.png
new file mode 100644
index 0000000..53dd9d7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_004.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_004.png
new file mode 100644
index 0000000..e235195
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_005.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_005.png
new file mode 100644
index 0000000..1721284
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_006.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_006.png
new file mode 100644
index 0000000..31819fa
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_007.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_007.png
new file mode 100644
index 0000000..5de44b9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_008.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_008.png
new file mode 100644
index 0000000..aa20f65
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_009.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_009.png
new file mode 100644
index 0000000..c379ba7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_010.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_010.png
new file mode 100644
index 0000000..e23b410
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_011.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_011.png
new file mode 100644
index 0000000..a9543dc
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_012.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_012.png
new file mode 100644
index 0000000..2473b78
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_013.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_013.png
new file mode 100644
index 0000000..b4acc9c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_014.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_014.png
new file mode 100644
index 0000000..c9cf344
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_015.png b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_015.png
new file mode 100644
index 0000000..a8c390e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_to_on_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_000.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_000.png
new file mode 100644
index 0000000..c54f8d7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_001.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_001.png
new file mode 100644
index 0000000..e062f61
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_002.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_002.png
new file mode 100644
index 0000000..7737646
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_003.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_003.png
new file mode 100644
index 0000000..65ff45e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_004.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_004.png
new file mode 100644
index 0000000..11aaec0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_005.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_005.png
new file mode 100644
index 0000000..9e1b60f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_006.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_006.png
new file mode 100644
index 0000000..1e45687
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_007.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_007.png
new file mode 100644
index 0000000..1e45687
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_008.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_008.png
new file mode 100644
index 0000000..6c48456
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_009.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_009.png
new file mode 100644
index 0000000..a4d084b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_010.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_010.png
new file mode 100644
index 0000000..1e1a1b0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_011.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_011.png
new file mode 100644
index 0000000..1e1a1b0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_012.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_012.png
new file mode 100644
index 0000000..1e1a1b0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_013.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_013.png
new file mode 100644
index 0000000..1e1a1b0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_014.png b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_014.png
new file mode 100644
index 0000000..1e1a1b0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_000.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_000.png
new file mode 100644
index 0000000..cf09f97
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_001.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_001.png
new file mode 100644
index 0000000..3218e66
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_002.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_002.png
new file mode 100644
index 0000000..0acff03
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_003.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_003.png
new file mode 100644
index 0000000..c93adf4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_004.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_004.png
new file mode 100644
index 0000000..5d8ddc96
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_005.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_005.png
new file mode 100644
index 0000000..47206a4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_006.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_006.png
new file mode 100644
index 0000000..7d6a91f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_007.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_007.png
new file mode 100644
index 0000000..e062f61
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_008.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_008.png
new file mode 100644
index 0000000..b0f0dde
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_009.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_009.png
new file mode 100644
index 0000000..c54f8d7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_010.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_010.png
new file mode 100644
index 0000000..c54f8d7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_011.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_011.png
new file mode 100644
index 0000000..c54f8d7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_012.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_012.png
new file mode 100644
index 0000000..c54f8d7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_013.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_013.png
new file mode 100644
index 0000000..c54f8d7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_014.png b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_014.png
new file mode 100644
index 0000000..c54f8d7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_switch_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_indicator_qntm_alpha.9.png b/core/res/res/drawable-hdpi/btn_toggle_indicator_qntm_alpha.9.png
new file mode 100644
index 0000000..68e17ad
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_indicator_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_qntm_alpha.9.png b/core/res/res/drawable-hdpi/btn_toggle_qntm_alpha.9.png
new file mode 100644
index 0000000..879d9c2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_000.png b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_000.png
new file mode 100644
index 0000000..281923e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_001.png b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_001.png
new file mode 100644
index 0000000..e91d4fb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_002.png b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_002.png
new file mode 100644
index 0000000..15baded
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_003.png b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_003.png
new file mode 100644
index 0000000..3d5899f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_004.png b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_004.png
new file mode 100644
index 0000000..e2277bd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_005.png b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_005.png
new file mode 100644
index 0000000..b502e22
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_from_pressed_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_000.png b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_000.png
new file mode 100644
index 0000000..a70be2c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_001.png b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_001.png
new file mode 100644
index 0000000..9442316
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_002.png b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_002.png
new file mode 100644
index 0000000..33db4a88
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_003.png b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_003.png
new file mode 100644
index 0000000..4e1cd16
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_004.png b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_004.png
new file mode 100644
index 0000000..d5254f4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_005.png b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_005.png
new file mode 100644
index 0000000..7aa0a3e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_control_to_pressed_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.png
deleted file mode 100644
index 73e8f1c..0000000
--- a/core/res/res/drawable-hdpi/switch_off_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.png
deleted file mode 100644
index ff6affe..0000000
--- a/core/res/res/drawable-hdpi/switch_on_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/switch_track_qntm_alpha.9.png b/core/res/res/drawable-hdpi/switch_track_qntm_alpha.9.png
index b11de9e..ac1fc23 100644
--- a/core/res/res/drawable-hdpi/switch_track_qntm_alpha.9.png
+++ b/core/res/res/drawable-hdpi/switch_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png
index 598b98c..9cdc25b 100644
--- a/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png
index 79fe7c5..276d480 100644
--- a/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png
+++ b/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00000_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00000_qntm_alpha.png
deleted file mode 100644
index 0f44ff9..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00000_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00001_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00001_qntm_alpha.png
deleted file mode 100644
index 9d5dda0..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00001_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00002_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00002_qntm_alpha.png
deleted file mode 100644
index e4ce802..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00002_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00003_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00003_qntm_alpha.png
deleted file mode 100644
index d1806ac..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00003_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00004_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00004_qntm_alpha.png
deleted file mode 100644
index ab9315b..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00004_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00005_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00005_qntm_alpha.png
deleted file mode 100644
index 46e90e6..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00005_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00006_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00006_qntm_alpha.png
deleted file mode 100644
index e8c56ff..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00006_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00007_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00007_qntm_alpha.png
deleted file mode 100644
index 59dcb7e..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00007_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00008_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00008_qntm_alpha.png
deleted file mode 100644
index e9bd4a2..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00008_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00009_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00009_qntm_alpha.png
deleted file mode 100644
index 1d05037..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00009_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00010_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00010_qntm_alpha.png
deleted file mode 100644
index 91b40de..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00010_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00011_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00011_qntm_alpha.png
deleted file mode 100644
index c531cab..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00011_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00012_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00012_qntm_alpha.png
deleted file mode 100644
index 11bb387..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00012_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00013_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00013_qntm_alpha.png
deleted file mode 100644
index 8843210..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00013_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00014_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00014_qntm_alpha.png
deleted file mode 100644
index 6ff2f3d..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00014_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_anim_00015_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_anim_00015_qntm_alpha.png
deleted file mode 100644
index a03c1e2..0000000
--- a/core/res/res/drawable-mdpi/btn_check_anim_00015_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_off_qntm_alpha.png
deleted file mode 100644
index 2ab6b7f..0000000
--- a/core/res/res/drawable-mdpi/btn_check_off_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_check_on_qntm_alpha.png
deleted file mode 100644
index 2211d83..0000000
--- a/core/res/res/drawable-mdpi/btn_check_on_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_000.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_000.png
new file mode 100644
index 0000000..9759818
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_001.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_001.png
new file mode 100644
index 0000000..4eb2c4f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_002.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_002.png
new file mode 100644
index 0000000..e6d6b42
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_003.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_003.png
new file mode 100644
index 0000000..03cb23a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_004.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_004.png
new file mode 100644
index 0000000..bfe3c3d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_005.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_005.png
new file mode 100644
index 0000000..65bdf42
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_006.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_006.png
new file mode 100644
index 0000000..44f9614b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_007.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_007.png
new file mode 100644
index 0000000..cf8ec38
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_008.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_008.png
new file mode 100644
index 0000000..4d624b3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_009.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_009.png
new file mode 100644
index 0000000..7c4eb7f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_010.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_010.png
new file mode 100644
index 0000000..e90dd31
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_011.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_011.png
new file mode 100644
index 0000000..831c0e8
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_012.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_012.png
new file mode 100644
index 0000000..7355dfd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_013.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_013.png
new file mode 100644
index 0000000..be71a69
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_014.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_014.png
new file mode 100644
index 0000000..a4a185b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_off_qntm_015.png b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_015.png
new file mode 100644
index 0000000..8d0386f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_off_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_000.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_000.png
new file mode 100644
index 0000000..70793c4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_001.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_001.png
new file mode 100644
index 0000000..632082b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_002.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_002.png
new file mode 100644
index 0000000..e7fc5fb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_003.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_003.png
new file mode 100644
index 0000000..91a0a33
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_004.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_004.png
new file mode 100644
index 0000000..3bd90d6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_005.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_005.png
new file mode 100644
index 0000000..5ac39ec
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_006.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_006.png
new file mode 100644
index 0000000..4181983
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_007.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_007.png
new file mode 100644
index 0000000..c8b04df
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_008.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_008.png
new file mode 100644
index 0000000..b7b3a9f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_009.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_009.png
new file mode 100644
index 0000000..62bc4ed
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_010.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_010.png
new file mode 100644
index 0000000..ac463ad
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_011.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_011.png
new file mode 100644
index 0000000..12b605d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_012.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_012.png
new file mode 100644
index 0000000..63a3c6a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_013.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_013.png
new file mode 100644
index 0000000..17660c4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_014.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_014.png
new file mode 100644
index 0000000..7d9de3d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_to_on_qntm_015.png b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_015.png
new file mode 100644
index 0000000..8aa1be2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_check_to_on_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00000_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00000_qntm_alpha.png
deleted file mode 100644
index 0a22e1a..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00000_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00001_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00001_qntm_alpha.png
deleted file mode 100644
index 2e2469c..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00001_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00002_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00002_qntm_alpha.png
deleted file mode 100644
index c1054d9..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00002_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00003_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00003_qntm_alpha.png
deleted file mode 100644
index cf8d80a..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00003_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00004_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00004_qntm_alpha.png
deleted file mode 100644
index 9d9e870..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00004_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00005_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00005_qntm_alpha.png
deleted file mode 100644
index 1bad701..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00005_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00006_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00006_qntm_alpha.png
deleted file mode 100644
index a84a54f..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00006_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00007_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00007_qntm_alpha.png
deleted file mode 100644
index 4d8050b..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00007_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00008_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00008_qntm_alpha.png
deleted file mode 100644
index 374172c..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00008_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00009_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00009_qntm_alpha.png
deleted file mode 100644
index 233036e..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00009_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00010_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00010_qntm_alpha.png
deleted file mode 100644
index 61d9b58..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00010_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00011_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00011_qntm_alpha.png
deleted file mode 100644
index 274e983..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00011_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00012_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00012_qntm_alpha.png
deleted file mode 100644
index acf16e5..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00012_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00013_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00013_qntm_alpha.png
deleted file mode 100644
index ee48241..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00013_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00014_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00014_qntm_alpha.png
deleted file mode 100644
index dbbb736..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00014_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_anim_00015_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_anim_00015_qntm_alpha.png
deleted file mode 100644
index bcabd0d..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_anim_00015_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed_qntm_alpha.png
deleted file mode 100644
index 713fee8..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_off_pressed_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_qntm_alpha.png b/core/res/res/drawable-mdpi/btn_radio_off_qntm_alpha.png
deleted file mode 100644
index dcb90d0..0000000
--- a/core/res/res/drawable-mdpi/btn_radio_off_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_000.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_000.png
new file mode 100644
index 0000000..a2b7fce
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_001.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_001.png
new file mode 100644
index 0000000..fe0d3b1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_002.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_002.png
new file mode 100644
index 0000000..d66d00d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_003.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_003.png
new file mode 100644
index 0000000..2f2f5cd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_004.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_004.png
new file mode 100644
index 0000000..72c9495
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_005.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_005.png
new file mode 100644
index 0000000..7d9090f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_006.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_006.png
new file mode 100644
index 0000000..c5442e8
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_007.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_007.png
new file mode 100644
index 0000000..ca80cdb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_008.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_008.png
new file mode 100644
index 0000000..d41a10b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_009.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_009.png
new file mode 100644
index 0000000..262c838
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_010.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_010.png
new file mode 100644
index 0000000..7f6ea8ba
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_011.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_011.png
new file mode 100644
index 0000000..8d50a81
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_012.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_012.png
new file mode 100644
index 0000000..0725a68
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_013.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_013.png
new file mode 100644
index 0000000..6191a4b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_014.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_014.png
new file mode 100644
index 0000000..1904d74
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_015.png b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_015.png
new file mode 100644
index 0000000..bec8dda
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_off_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_000.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_000.png
new file mode 100644
index 0000000..54ef480
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_001.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_001.png
new file mode 100644
index 0000000..55c5163
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_002.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_002.png
new file mode 100644
index 0000000..0fe2a897
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_003.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_003.png
new file mode 100644
index 0000000..86efab7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_004.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_004.png
new file mode 100644
index 0000000..c0a5ca5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_005.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_005.png
new file mode 100644
index 0000000..ec55175
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_006.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_006.png
new file mode 100644
index 0000000..3e4a690
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_007.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_007.png
new file mode 100644
index 0000000..da49734
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_008.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_008.png
new file mode 100644
index 0000000..471cda1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_009.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_009.png
new file mode 100644
index 0000000..d560262
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_010.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_010.png
new file mode 100644
index 0000000..f6096b4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_011.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_011.png
new file mode 100644
index 0000000..9e2500b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_012.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_012.png
new file mode 100644
index 0000000..efbac99
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_013.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_013.png
new file mode 100644
index 0000000..676f0ca
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_014.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_014.png
new file mode 100644
index 0000000..4803157
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_015.png b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_015.png
new file mode 100644
index 0000000..4f8a162
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_to_on_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_000.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_000.png
new file mode 100644
index 0000000..8c3f26c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_001.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_001.png
new file mode 100644
index 0000000..3617168
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_002.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_002.png
new file mode 100644
index 0000000..e4366f4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_003.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_003.png
new file mode 100644
index 0000000..ea4533b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_004.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_004.png
new file mode 100644
index 0000000..94aedbb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_005.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_005.png
new file mode 100644
index 0000000..ef84578
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_006.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_006.png
new file mode 100644
index 0000000..4de2321
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_007.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_007.png
new file mode 100644
index 0000000..4de2321
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_008.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_008.png
new file mode 100644
index 0000000..d62fbd5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_009.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_009.png
new file mode 100644
index 0000000..3d87c4e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_010.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_010.png
new file mode 100644
index 0000000..536ed46
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_011.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_011.png
new file mode 100644
index 0000000..536ed46
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_012.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_012.png
new file mode 100644
index 0000000..536ed46
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_013.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_013.png
new file mode 100644
index 0000000..536ed46
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_014.png b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_014.png
new file mode 100644
index 0000000..536ed46
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_000.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_000.png
new file mode 100644
index 0000000..f5b660d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_001.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_001.png
new file mode 100644
index 0000000..9e4db6c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_002.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_002.png
new file mode 100644
index 0000000..7de2128
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_003.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_003.png
new file mode 100644
index 0000000..1980c2c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_004.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_004.png
new file mode 100644
index 0000000..6e73ef0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_005.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_005.png
new file mode 100644
index 0000000..f897392
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_006.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_006.png
new file mode 100644
index 0000000..74a6ebd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_007.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_007.png
new file mode 100644
index 0000000..3617168
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_008.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_008.png
new file mode 100644
index 0000000..884eb66
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_009.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_009.png
new file mode 100644
index 0000000..8c3f26c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_010.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_010.png
new file mode 100644
index 0000000..8c3f26c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_011.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_011.png
new file mode 100644
index 0000000..8c3f26c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_012.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_012.png
new file mode 100644
index 0000000..8c3f26c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_013.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_013.png
new file mode 100644
index 0000000..8c3f26c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_014.png b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_014.png
new file mode 100644
index 0000000..8c3f26c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_switch_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_indicator_qntm_alpha.9.png b/core/res/res/drawable-mdpi/btn_toggle_indicator_qntm_alpha.9.png
new file mode 100644
index 0000000..e5bface
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_indicator_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_qntm_alpha.9.png b/core/res/res/drawable-mdpi/btn_toggle_qntm_alpha.9.png
new file mode 100644
index 0000000..dca86ea
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_000.png b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_000.png
new file mode 100644
index 0000000..377a6b4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_001.png b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_001.png
new file mode 100644
index 0000000..0859f62
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_002.png b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_002.png
new file mode 100644
index 0000000..bf5cdcd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_003.png b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_003.png
new file mode 100644
index 0000000..4cd177d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_004.png b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_004.png
new file mode 100644
index 0000000..dfe39ca
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_005.png b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_005.png
new file mode 100644
index 0000000..5d3ab99
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_from_pressed_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_000.png b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_000.png
new file mode 100644
index 0000000..80922eb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_001.png b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_001.png
new file mode 100644
index 0000000..aa77044
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_002.png b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_002.png
new file mode 100644
index 0000000..7b099db
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_003.png b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_003.png
new file mode 100644
index 0000000..088c86a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_004.png b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_004.png
new file mode 100644
index 0000000..3c6b9bc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_005.png b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_005.png
new file mode 100644
index 0000000..adf5100
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_control_to_pressed_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.png
deleted file mode 100644
index 8949b52..0000000
--- a/core/res/res/drawable-mdpi/switch_off_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.png
deleted file mode 100644
index d727683..0000000
--- a/core/res/res/drawable-mdpi/switch_on_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/switch_track_qntm_alpha.9.png b/core/res/res/drawable-mdpi/switch_track_qntm_alpha.9.png
index 8991421..b6538e4 100644
--- a/core/res/res/drawable-mdpi/switch_track_qntm_alpha.9.png
+++ b/core/res/res/drawable-mdpi/switch_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png
index 506a186..95c0168 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png
index fb0e926..569332a 100644
--- a/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png
+++ b/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00000_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00000_qntm_alpha.png
deleted file mode 100644
index 25500e8..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00000_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00001_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00001_qntm_alpha.png
deleted file mode 100644
index b136e25..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00001_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00002_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00002_qntm_alpha.png
deleted file mode 100644
index 6a94e30..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00002_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00003_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00003_qntm_alpha.png
deleted file mode 100644
index d386421..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00003_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00004_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00004_qntm_alpha.png
deleted file mode 100644
index c811385..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00004_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00005_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00005_qntm_alpha.png
deleted file mode 100644
index 58b3267..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00005_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00006_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00006_qntm_alpha.png
deleted file mode 100644
index 0659e72..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00006_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00007_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00007_qntm_alpha.png
deleted file mode 100644
index b4227d1..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00007_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00008_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00008_qntm_alpha.png
deleted file mode 100644
index 714ef00..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00008_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00009_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00009_qntm_alpha.png
deleted file mode 100644
index 139595b..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00009_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00010_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00010_qntm_alpha.png
deleted file mode 100644
index 4491107..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00010_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00011_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00011_qntm_alpha.png
deleted file mode 100644
index 20eb752..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00011_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00012_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00012_qntm_alpha.png
deleted file mode 100644
index 532c9f2..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00012_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00013_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00013_qntm_alpha.png
deleted file mode 100644
index 0d78a32..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00013_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00014_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00014_qntm_alpha.png
deleted file mode 100644
index af29678..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00014_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_anim_00015_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_anim_00015_qntm_alpha.png
deleted file mode 100644
index 23eb9e3..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_anim_00015_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_off_qntm_alpha.png
deleted file mode 100644
index 5d820ae..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_off_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_on_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_check_on_qntm_alpha.png
deleted file mode 100644
index 019c92e..0000000
--- a/core/res/res/drawable-xhdpi/btn_check_on_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_000.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_000.png
new file mode 100644
index 0000000..2347643
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_001.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_001.png
new file mode 100644
index 0000000..70aaa01
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_002.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_002.png
new file mode 100644
index 0000000..01e498a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_003.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_003.png
new file mode 100644
index 0000000..71d1cf7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_004.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_004.png
new file mode 100644
index 0000000..d1e7b1d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_005.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_005.png
new file mode 100644
index 0000000..7db7d06
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_006.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_006.png
new file mode 100644
index 0000000..dadb62e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_007.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_007.png
new file mode 100644
index 0000000..f87f744
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_008.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_008.png
new file mode 100644
index 0000000..be99d87
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_009.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_009.png
new file mode 100644
index 0000000..f83bc05
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_010.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_010.png
new file mode 100644
index 0000000..870071d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_011.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_011.png
new file mode 100644
index 0000000..3a18414
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_012.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_012.png
new file mode 100644
index 0000000..f3d1187
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_013.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_013.png
new file mode 100644
index 0000000..4078cca
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_014.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_014.png
new file mode 100644
index 0000000..d4849b5
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_015.png b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_015.png
new file mode 100644
index 0000000..6e2af72
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_off_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_000.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_000.png
new file mode 100644
index 0000000..9244174
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_001.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_001.png
new file mode 100644
index 0000000..8c7fe95
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_002.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_002.png
new file mode 100644
index 0000000..71eb1d0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_003.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_003.png
new file mode 100644
index 0000000..613f38a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_004.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_004.png
new file mode 100644
index 0000000..2d20ccc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_005.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_005.png
new file mode 100644
index 0000000..407f78d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_006.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_006.png
new file mode 100644
index 0000000..1bf24b0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_007.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_007.png
new file mode 100644
index 0000000..a450bd0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_008.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_008.png
new file mode 100644
index 0000000..63ba593
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_009.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_009.png
new file mode 100644
index 0000000..6d05e5a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_010.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_010.png
new file mode 100644
index 0000000..1c8cd8f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_011.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_011.png
new file mode 100644
index 0000000..b8bc564
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_012.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_012.png
new file mode 100644
index 0000000..3d80128
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_013.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_013.png
new file mode 100644
index 0000000..c21dfba
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_014.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_014.png
new file mode 100644
index 0000000..2dfe90d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_015.png b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_015.png
new file mode 100644
index 0000000..5f40d73
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_check_to_on_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00000_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00000_qntm_alpha.png
deleted file mode 100644
index cd11e14..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00000_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00001_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00001_qntm_alpha.png
deleted file mode 100644
index b10db83..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00001_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00002_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00002_qntm_alpha.png
deleted file mode 100644
index efeb6fb..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00002_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00003_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00003_qntm_alpha.png
deleted file mode 100644
index 83080af..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00003_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00004_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00004_qntm_alpha.png
deleted file mode 100644
index b9cc322..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00004_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00005_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00005_qntm_alpha.png
deleted file mode 100644
index 3b5f9c4..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00005_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00006_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00006_qntm_alpha.png
deleted file mode 100644
index 58c93db..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00006_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00007_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00007_qntm_alpha.png
deleted file mode 100644
index 0f1d010..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00007_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00008_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00008_qntm_alpha.png
deleted file mode 100644
index 05a7a0f..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00008_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00009_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00009_qntm_alpha.png
deleted file mode 100644
index 9345035..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00009_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00010_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00010_qntm_alpha.png
deleted file mode 100644
index 5f149b7..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00010_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00011_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00011_qntm_alpha.png
deleted file mode 100644
index 191f369..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00011_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00012_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00012_qntm_alpha.png
deleted file mode 100644
index 44e08e6..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00012_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00013_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00013_qntm_alpha.png
deleted file mode 100644
index 5a9dfa0..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00013_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00014_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00014_qntm_alpha.png
deleted file mode 100644
index ee921c6..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00014_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_anim_00015_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_anim_00015_qntm_alpha.png
deleted file mode 100644
index 567bb0c..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_anim_00015_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_pressed_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_off_pressed_qntm_alpha.png
deleted file mode 100644
index 2fd964e..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_off_pressed_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_off_qntm_alpha.png b/core/res/res/drawable-xhdpi/btn_radio_off_qntm_alpha.png
deleted file mode 100644
index 8873cd6..0000000
--- a/core/res/res/drawable-xhdpi/btn_radio_off_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_000.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_000.png
new file mode 100644
index 0000000..b54c6ff
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_001.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_001.png
new file mode 100644
index 0000000..fff7056
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_002.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_002.png
new file mode 100644
index 0000000..026462d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_003.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_003.png
new file mode 100644
index 0000000..26cc8de
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_004.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_004.png
new file mode 100644
index 0000000..c055fff
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_005.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_005.png
new file mode 100644
index 0000000..a22e780
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_006.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_006.png
new file mode 100644
index 0000000..357374c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_007.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_007.png
new file mode 100644
index 0000000..71d4667
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_008.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_008.png
new file mode 100644
index 0000000..2ed175e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_009.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_009.png
new file mode 100644
index 0000000..e0f7d8e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_010.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_010.png
new file mode 100644
index 0000000..62b0578
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_011.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_011.png
new file mode 100644
index 0000000..4d6ef4a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_012.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_012.png
new file mode 100644
index 0000000..37cee2d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_013.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_013.png
new file mode 100644
index 0000000..a8bc25f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_014.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_014.png
new file mode 100644
index 0000000..cf68d93
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_015.png b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_015.png
new file mode 100644
index 0000000..96834bc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_off_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_000.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_000.png
new file mode 100644
index 0000000..d068dbe
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_001.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_001.png
new file mode 100644
index 0000000..4aabb1e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_002.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_002.png
new file mode 100644
index 0000000..bbac8e4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_003.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_003.png
new file mode 100644
index 0000000..2fc7459
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_004.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_004.png
new file mode 100644
index 0000000..83c6d0e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_005.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_005.png
new file mode 100644
index 0000000..45c08d7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_006.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_006.png
new file mode 100644
index 0000000..05b7dfb
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_007.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_007.png
new file mode 100644
index 0000000..baf9964
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_008.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_008.png
new file mode 100644
index 0000000..d6e0369
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_009.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_009.png
new file mode 100644
index 0000000..3f35270
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_010.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_010.png
new file mode 100644
index 0000000..a5b34dc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_011.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_011.png
new file mode 100644
index 0000000..361967b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_012.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_012.png
new file mode 100644
index 0000000..c478bb7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_013.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_013.png
new file mode 100644
index 0000000..075fa0c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_014.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_014.png
new file mode 100644
index 0000000..d9e364b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_015.png b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_015.png
new file mode 100644
index 0000000..9924496
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_radio_to_on_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_000.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_000.png
new file mode 100644
index 0000000..2494fd4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_001.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_001.png
new file mode 100644
index 0000000..7bd99fe
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_002.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_002.png
new file mode 100644
index 0000000..2ef623b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_003.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_003.png
new file mode 100644
index 0000000..19db3e0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_004.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_004.png
new file mode 100644
index 0000000..984c3c5
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_005.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_005.png
new file mode 100644
index 0000000..6454190
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_006.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_006.png
new file mode 100644
index 0000000..cee9393
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_007.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_007.png
new file mode 100644
index 0000000..cee9393
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_008.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_008.png
new file mode 100644
index 0000000..437ffdd
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_009.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_009.png
new file mode 100644
index 0000000..d2e14ad
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_010.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_010.png
new file mode 100644
index 0000000..4e2f5bc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_011.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_011.png
new file mode 100644
index 0000000..4e2f5bc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_012.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_012.png
new file mode 100644
index 0000000..4e2f5bc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_013.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_013.png
new file mode 100644
index 0000000..4e2f5bc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_014.png b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_014.png
new file mode 100644
index 0000000..4e2f5bc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_000.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_000.png
new file mode 100644
index 0000000..f1bcfa3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_001.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_001.png
new file mode 100644
index 0000000..ede2fec
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_002.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_002.png
new file mode 100644
index 0000000..94ce017
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_003.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_003.png
new file mode 100644
index 0000000..647cfe3
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_004.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_004.png
new file mode 100644
index 0000000..b3bf923
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_005.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_005.png
new file mode 100644
index 0000000..ae95b2b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_006.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_006.png
new file mode 100644
index 0000000..b8e4bd6
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_007.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_007.png
new file mode 100644
index 0000000..ec6d6d7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_008.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_008.png
new file mode 100644
index 0000000..c0e493f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_009.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_009.png
new file mode 100644
index 0000000..2494fd4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_010.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_010.png
new file mode 100644
index 0000000..2494fd4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_011.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_011.png
new file mode 100644
index 0000000..2494fd4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_012.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_012.png
new file mode 100644
index 0000000..2494fd4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_013.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_013.png
new file mode 100644
index 0000000..2494fd4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_014.png b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_014.png
new file mode 100644
index 0000000..2494fd4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_switch_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_indicator_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/btn_toggle_indicator_qntm_alpha.9.png
new file mode 100644
index 0000000..dff391f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_toggle_indicator_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/btn_toggle_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/btn_toggle_qntm_alpha.9.png
new file mode 100644
index 0000000..b135338
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/btn_toggle_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_000.png b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_000.png
new file mode 100644
index 0000000..ea09a31
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_001.png b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_001.png
new file mode 100644
index 0000000..f9a4391
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_002.png b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_002.png
new file mode 100644
index 0000000..d9606e1
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_003.png b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_003.png
new file mode 100644
index 0000000..df2d9d0
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_004.png b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_004.png
new file mode 100644
index 0000000..625a322
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_005.png b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_005.png
new file mode 100644
index 0000000..79e8dde
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_from_pressed_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_000.png b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_000.png
new file mode 100644
index 0000000..e99c266
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_001.png b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_001.png
new file mode 100644
index 0000000..f0329a4
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_002.png b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_002.png
new file mode 100644
index 0000000..42c40b7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_003.png b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_003.png
new file mode 100644
index 0000000..807491f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_004.png b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_004.png
new file mode 100644
index 0000000..dfec9cc
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_005.png b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_005.png
new file mode 100644
index 0000000..0ed59ea
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_control_to_pressed_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.png
deleted file mode 100644
index a7a972c..0000000
--- a/core/res/res/drawable-xhdpi/switch_off_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.png
deleted file mode 100644
index dd8910b..0000000
--- a/core/res/res/drawable-xhdpi/switch_on_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/switch_track_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/switch_track_qntm_alpha.9.png
index 4970f56..d6a0ab2 100644
--- a/core/res/res/drawable-xhdpi/switch_track_qntm_alpha.9.png
+++ b/core/res/res/drawable-xhdpi/switch_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png
index 38b8e8b..a01ac10 100644
--- a/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png
+++ b/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png
index d6002a7..d3602d9 100644
--- a/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png
+++ b/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00000_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00000_qntm_alpha.png
deleted file mode 100644
index 1881f54..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00000_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00001_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00001_qntm_alpha.png
deleted file mode 100644
index 6f8ec2d..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00001_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00002_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00002_qntm_alpha.png
deleted file mode 100644
index c954ed9..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00002_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00003_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00003_qntm_alpha.png
deleted file mode 100644
index 9d1a47e..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00003_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00004_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00004_qntm_alpha.png
deleted file mode 100644
index ce63631..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00004_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00005_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00005_qntm_alpha.png
deleted file mode 100644
index 430c134..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00005_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00006_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00006_qntm_alpha.png
deleted file mode 100644
index cdebf83..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00006_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00007_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00007_qntm_alpha.png
deleted file mode 100644
index 40ceadb..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00007_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00008_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00008_qntm_alpha.png
deleted file mode 100644
index fb13eb2..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00008_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00009_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00009_qntm_alpha.png
deleted file mode 100644
index d716fba..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00009_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00010_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00010_qntm_alpha.png
deleted file mode 100644
index b8be041..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00010_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00011_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00011_qntm_alpha.png
deleted file mode 100644
index bad0c3c..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00011_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00012_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00012_qntm_alpha.png
deleted file mode 100644
index a6368fb..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00012_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00013_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00013_qntm_alpha.png
deleted file mode 100644
index 234e5d1..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00013_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00014_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00014_qntm_alpha.png
deleted file mode 100644
index 3e7796d..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00014_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_anim_00015_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_anim_00015_qntm_alpha.png
deleted file mode 100644
index 0673999..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_anim_00015_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_off_qntm_alpha.png
deleted file mode 100644
index 2a17861..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_off_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_check_on_qntm_alpha.png
deleted file mode 100644
index 61067ac..0000000
--- a/core/res/res/drawable-xxhdpi/btn_check_on_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_000.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_000.png
new file mode 100644
index 0000000..b754381
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_001.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_001.png
new file mode 100644
index 0000000..517d7a7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_002.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_002.png
new file mode 100644
index 0000000..2c1d5b6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_003.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_003.png
new file mode 100644
index 0000000..0c6ff7e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_004.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_004.png
new file mode 100644
index 0000000..0796601
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_005.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_005.png
new file mode 100644
index 0000000..9b4e0f8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_006.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_006.png
new file mode 100644
index 0000000..25767eb
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_007.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_007.png
new file mode 100644
index 0000000..cd0951f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_008.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_008.png
new file mode 100644
index 0000000..9ae8165
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_009.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_009.png
new file mode 100644
index 0000000..efd9bc6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_010.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_010.png
new file mode 100644
index 0000000..fccbc9d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_011.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_011.png
new file mode 100644
index 0000000..dddafca
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_012.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_012.png
new file mode 100644
index 0000000..7e37433
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_013.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_013.png
new file mode 100644
index 0000000..9bc22de
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_014.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_014.png
new file mode 100644
index 0000000..507ed10
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_015.png b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_015.png
new file mode 100644
index 0000000..6a21c7f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_off_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_000.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_000.png
new file mode 100644
index 0000000..0d544d9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_001.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_001.png
new file mode 100644
index 0000000..39da0ac
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_002.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_002.png
new file mode 100644
index 0000000..d5ada12
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_003.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_003.png
new file mode 100644
index 0000000..d4e096c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_004.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_004.png
new file mode 100644
index 0000000..468a9b4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_005.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_005.png
new file mode 100644
index 0000000..ea3cd2e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_006.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_006.png
new file mode 100644
index 0000000..0652cb0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_007.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_007.png
new file mode 100644
index 0000000..768d2b0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_008.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_008.png
new file mode 100644
index 0000000..1d06a90
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_009.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_009.png
new file mode 100644
index 0000000..8a70a80
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_010.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_010.png
new file mode 100644
index 0000000..bf9ec7f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_011.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_011.png
new file mode 100644
index 0000000..cff07b9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_012.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_012.png
new file mode 100644
index 0000000..40f997e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_013.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_013.png
new file mode 100644
index 0000000..6ba84ec
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_014.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_014.png
new file mode 100644
index 0000000..766610e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_015.png b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_015.png
new file mode 100644
index 0000000..810a029
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_check_to_on_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_qntm_alpha.png
deleted file mode 100644
index fdbbbce..0000000
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_pressed_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_off_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_off_qntm_alpha.png
deleted file mode 100644
index 0ec2ee6..0000000
--- a/core/res/res/drawable-xxhdpi/btn_radio_off_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_qntm_alpha.png
deleted file mode 100644
index b46ee1c..0000000
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_pressed_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_on_qntm_alpha.png b/core/res/res/drawable-xxhdpi/btn_radio_on_qntm_alpha.png
deleted file mode 100644
index 8737156..0000000
--- a/core/res/res/drawable-xxhdpi/btn_radio_on_qntm_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_000.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_000.png
new file mode 100644
index 0000000..cbc3833
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_001.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_001.png
new file mode 100644
index 0000000..4243895
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_002.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_002.png
new file mode 100644
index 0000000..b522d37
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_003.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_003.png
new file mode 100644
index 0000000..647b965
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_004.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_004.png
new file mode 100644
index 0000000..a317497
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_005.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_005.png
new file mode 100644
index 0000000..0e4b25f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_006.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_006.png
new file mode 100644
index 0000000..6e279d9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_007.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_007.png
new file mode 100644
index 0000000..f0840cc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_008.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_008.png
new file mode 100644
index 0000000..140e9e8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_009.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_009.png
new file mode 100644
index 0000000..5cf8ec5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_010.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_010.png
new file mode 100644
index 0000000..f9624d8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_011.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_011.png
new file mode 100644
index 0000000..899df8c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_012.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_012.png
new file mode 100644
index 0000000..6543e1c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_013.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_013.png
new file mode 100644
index 0000000..cd758dd
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_014.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_014.png
new file mode 100644
index 0000000..72d950c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_015.png b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_015.png
new file mode 100644
index 0000000..07bdbc9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_off_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_000.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_000.png
new file mode 100644
index 0000000..c9af24b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_001.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_001.png
new file mode 100644
index 0000000..01de3f5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_002.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_002.png
new file mode 100644
index 0000000..f428bc5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_003.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_003.png
new file mode 100644
index 0000000..ab5c008
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_004.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_004.png
new file mode 100644
index 0000000..5b157cf
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_005.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_005.png
new file mode 100644
index 0000000..1210be2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_006.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_006.png
new file mode 100644
index 0000000..e6b4140
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_007.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_007.png
new file mode 100644
index 0000000..b678e08
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_008.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_008.png
new file mode 100644
index 0000000..6ca2a69
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_009.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_009.png
new file mode 100644
index 0000000..7de608e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_010.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_010.png
new file mode 100644
index 0000000..b2bbcce
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_011.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_011.png
new file mode 100644
index 0000000..6950db3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_012.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_012.png
new file mode 100644
index 0000000..c790756
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_013.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_013.png
new file mode 100644
index 0000000..ed5d888
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_014.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_014.png
new file mode 100644
index 0000000..81a4a63
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_015.png b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_015.png
new file mode 100644
index 0000000..db1d93a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_radio_to_on_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_000.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_000.png
new file mode 100644
index 0000000..198ac07
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_001.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_001.png
new file mode 100644
index 0000000..eff3dd0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_002.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_002.png
new file mode 100644
index 0000000..000a23a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_003.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_003.png
new file mode 100644
index 0000000..394d661
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_004.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_004.png
new file mode 100644
index 0000000..4e7311d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_005.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_005.png
new file mode 100644
index 0000000..d9dcf91
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_006.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_006.png
new file mode 100644
index 0000000..674142e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_007.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_007.png
new file mode 100644
index 0000000..674142e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_008.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_008.png
new file mode 100644
index 0000000..9d4026a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_009.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_009.png
new file mode 100644
index 0000000..bb4b426
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_010.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_010.png
new file mode 100644
index 0000000..a37076d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_011.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_011.png
new file mode 100644
index 0000000..a37076d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_012.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_012.png
new file mode 100644
index 0000000..a37076d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_013.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_013.png
new file mode 100644
index 0000000..a37076d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_014.png b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_014.png
new file mode 100644
index 0000000..a37076d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_000.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_000.png
new file mode 100644
index 0000000..22e9951
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_001.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_001.png
new file mode 100644
index 0000000..14e6b39
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_002.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_002.png
new file mode 100644
index 0000000..86b2c01
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_003.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_003.png
new file mode 100644
index 0000000..1c565df
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_004.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_004.png
new file mode 100644
index 0000000..b825449
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_005.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_005.png
new file mode 100644
index 0000000..170c234
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_006.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_006.png
new file mode 100644
index 0000000..5477007
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_007.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_007.png
new file mode 100644
index 0000000..eff3dd0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_008.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_008.png
new file mode 100644
index 0000000..e3fd96a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_009.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_009.png
new file mode 100644
index 0000000..198ac07
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_010.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_010.png
new file mode 100644
index 0000000..198ac07
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_011.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_011.png
new file mode 100644
index 0000000..198ac07
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_012.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_012.png
new file mode 100644
index 0000000..198ac07
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_013.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_013.png
new file mode 100644
index 0000000..198ac07
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_014.png b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_014.png
new file mode 100644
index 0000000..198ac07
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_switch_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_indicator_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_indicator_qntm_alpha.9.png
new file mode 100644
index 0000000..0d6a39a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_indicator_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/btn_toggle_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/btn_toggle_qntm_alpha.9.png
new file mode 100644
index 0000000..f235aed
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/btn_toggle_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_000.png b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_000.png
new file mode 100644
index 0000000..46aa533
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_001.png b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_001.png
new file mode 100644
index 0000000..a749469
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_002.png b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_002.png
new file mode 100644
index 0000000..ef43f00
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_003.png b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_003.png
new file mode 100644
index 0000000..eebddc3
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_004.png b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_004.png
new file mode 100644
index 0000000..44b654d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_005.png b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_005.png
new file mode 100644
index 0000000..6e768c1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_from_pressed_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_000.png b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_000.png
new file mode 100644
index 0000000..2ac6dae
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_001.png b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_001.png
new file mode 100644
index 0000000..91c49ce
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_002.png b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_002.png
new file mode 100644
index 0000000..4b4bd1f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_003.png b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_003.png
new file mode 100644
index 0000000..637e596
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_004.png b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_004.png
new file mode 100644
index 0000000..42d4d2a
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_005.png b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_005.png
new file mode 100644
index 0000000..995d1b2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_control_to_pressed_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.png
deleted file mode 100644
index 8d79a13..0000000
--- a/core/res/res/drawable-xxhdpi/switch_off_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.png
deleted file mode 100644
index e0e4ef9..0000000
--- a/core/res/res/drawable-xxhdpi/switch_on_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/switch_track_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/switch_track_qntm_alpha.9.png
index 74a259b..a8067cb 100644
--- a/core/res/res/drawable-xxhdpi/switch_track_qntm_alpha.9.png
+++ b/core/res/res/drawable-xxhdpi/switch_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png
index 93469a2..75085ce 100644
--- a/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png
index b3493e7..e2eb5be 100644
--- a/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_000.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_000.png
new file mode 100644
index 0000000..f0ff1a7
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_001.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_001.png
new file mode 100644
index 0000000..b382df3
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_002.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_002.png
new file mode 100644
index 0000000..8cb4ce2
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_003.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_003.png
new file mode 100644
index 0000000..4db2b01
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_004.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_004.png
new file mode 100644
index 0000000..8c4709b
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_005.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_005.png
new file mode 100644
index 0000000..1ad960a
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_006.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_006.png
new file mode 100644
index 0000000..e47cc20
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_007.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_007.png
new file mode 100644
index 0000000..c4d0d51
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_008.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_008.png
new file mode 100644
index 0000000..915d56a
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_009.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_009.png
new file mode 100644
index 0000000..85795cb
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_010.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_010.png
new file mode 100644
index 0000000..157fd91
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_011.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_011.png
new file mode 100644
index 0000000..9d446de
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_012.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_012.png
new file mode 100644
index 0000000..dfac1f0
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_013.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_013.png
new file mode 100644
index 0000000..aed6c08
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_014.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_014.png
new file mode 100644
index 0000000..1b8bd6b
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_015.png b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_015.png
new file mode 100644
index 0000000..5dd0e5b
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_off_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_000.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_000.png
new file mode 100644
index 0000000..5dd0e5b
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_001.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_001.png
new file mode 100644
index 0000000..1a31ad9
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_002.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_002.png
new file mode 100644
index 0000000..63c7f12
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_003.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_003.png
new file mode 100644
index 0000000..847dd08
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_004.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_004.png
new file mode 100644
index 0000000..b93f3cc
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_005.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_005.png
new file mode 100644
index 0000000..1e3dea7
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_006.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_006.png
new file mode 100644
index 0000000..5a85238
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_007.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_007.png
new file mode 100644
index 0000000..35960ca
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_008.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_008.png
new file mode 100644
index 0000000..6db5555
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_009.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_009.png
new file mode 100644
index 0000000..a9c5851
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_010.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_010.png
new file mode 100644
index 0000000..38465bd
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_011.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_011.png
new file mode 100644
index 0000000..15942dc
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_012.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_012.png
new file mode 100644
index 0000000..67d0d64
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_013.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_013.png
new file mode 100644
index 0000000..69b5c1b
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_014.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_014.png
new file mode 100644
index 0000000..0e5d331
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_015.png b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_015.png
new file mode 100644
index 0000000..f0ff1a7
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_check_to_on_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_qntm_alpha.9.png b/core/res/res/drawable-xxxhdpi/btn_qntm_alpha.9.png
new file mode 100644
index 0000000..01eeefe
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_000.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_000.png
new file mode 100644
index 0000000..44028af
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_001.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_001.png
new file mode 100644
index 0000000..ec13a86
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_002.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_002.png
new file mode 100644
index 0000000..43754eb
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_003.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_003.png
new file mode 100644
index 0000000..39d1d64
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_004.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_004.png
new file mode 100644
index 0000000..f36f883
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_005.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_005.png
new file mode 100644
index 0000000..7a4cc5c
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_006.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_006.png
new file mode 100644
index 0000000..80a21ec
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_007.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_007.png
new file mode 100644
index 0000000..2141104
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_008.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_008.png
new file mode 100644
index 0000000..203bd51
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_009.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_009.png
new file mode 100644
index 0000000..5df6fc5
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_010.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_010.png
new file mode 100644
index 0000000..6d0fced
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_011.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_011.png
new file mode 100644
index 0000000..8c0c372
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_012.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_012.png
new file mode 100644
index 0000000..4fa6f53
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_013.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_013.png
new file mode 100644
index 0000000..d3dbf7d
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_014.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_014.png
new file mode 100644
index 0000000..4ccf8de
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_015.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_015.png
new file mode 100644
index 0000000..adef871
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_off_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_000.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_000.png
new file mode 100644
index 0000000..adef871
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_001.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_001.png
new file mode 100644
index 0000000..9fc3556
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_002.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_002.png
new file mode 100644
index 0000000..7f00609
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_003.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_003.png
new file mode 100644
index 0000000..e4aa58d
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_004.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_004.png
new file mode 100644
index 0000000..fe4e4b7
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_005.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_005.png
new file mode 100644
index 0000000..86666ca
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_006.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_006.png
new file mode 100644
index 0000000..608faaf
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_007.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_007.png
new file mode 100644
index 0000000..ec95422
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_008.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_008.png
new file mode 100644
index 0000000..76e2754
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_009.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_009.png
new file mode 100644
index 0000000..3853eac
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_010.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_010.png
new file mode 100644
index 0000000..621aff1
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_011.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_011.png
new file mode 100644
index 0000000..d24be2a
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_012.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_012.png
new file mode 100644
index 0000000..df33892
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_013.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_013.png
new file mode 100644
index 0000000..ff4b818
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_014.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_014.png
new file mode 100644
index 0000000..d9793ae
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_015.png b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_015.png
new file mode 100644
index 0000000..44028af
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_radio_to_on_qntm_015.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_000.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_000.png
new file mode 100644
index 0000000..8b202c6
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_001.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_001.png
new file mode 100644
index 0000000..3b497f3
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_002.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_002.png
new file mode 100644
index 0000000..532b6de
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_003.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_003.png
new file mode 100644
index 0000000..403b2fe
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_004.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_004.png
new file mode 100644
index 0000000..8c5086c
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_005.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_005.png
new file mode 100644
index 0000000..d4870f8
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_006.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_006.png
new file mode 100644
index 0000000..c05adf5
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_007.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_007.png
new file mode 100644
index 0000000..99b2056
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_008.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_008.png
new file mode 100644
index 0000000..d839358
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_009.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_009.png
new file mode 100644
index 0000000..913f94d
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_010.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_010.png
new file mode 100644
index 0000000..7f325b3
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_011.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_011.png
new file mode 100644
index 0000000..149a9aa
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_012.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_012.png
new file mode 100644
index 0000000..95c219e
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_013.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_013.png
new file mode 100644
index 0000000..462a128d
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_014.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_014.png
new file mode 100644
index 0000000..5911d16
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_off_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_000.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_000.png
new file mode 100644
index 0000000..e0c6d85
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_001.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_001.png
new file mode 100644
index 0000000..5679943
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_002.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_002.png
new file mode 100644
index 0000000..54b636d
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_003.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_003.png
new file mode 100644
index 0000000..bf9fac0
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_004.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_004.png
new file mode 100644
index 0000000..25d5319
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_005.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_005.png
new file mode 100644
index 0000000..d2df595
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_006.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_006.png
new file mode 100644
index 0000000..7700bde
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_006.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_007.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_007.png
new file mode 100644
index 0000000..883f98b
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_007.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_008.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_008.png
new file mode 100644
index 0000000..b3b2108
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_008.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_009.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_009.png
new file mode 100644
index 0000000..3aad596
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_009.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_010.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_010.png
new file mode 100644
index 0000000..2017e17
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_010.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_011.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_011.png
new file mode 100644
index 0000000..1fc2700
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_011.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_012.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_012.png
new file mode 100644
index 0000000..bb8b0f2
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_012.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_013.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_013.png
new file mode 100644
index 0000000..66ab8f6
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_013.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_014.png b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_014.png
new file mode 100644
index 0000000..e3424db
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_switch_to_on_qntm_014.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_toggle_indicator_qntm_alpha.9.png b/core/res/res/drawable-xxxhdpi/btn_toggle_indicator_qntm_alpha.9.png
new file mode 100755
index 0000000..c06740b
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_toggle_indicator_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/btn_toggle_qntm_alpha.9.png b/core/res/res/drawable-xxxhdpi/btn_toggle_qntm_alpha.9.png
new file mode 100755
index 0000000..7556167
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/btn_toggle_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_000.png b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_000.png
new file mode 100644
index 0000000..0c8f746
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_001.png b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_001.png
new file mode 100644
index 0000000..5db9deb
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_002.png b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_002.png
new file mode 100644
index 0000000..3aca6d3
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_003.png b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_003.png
new file mode 100644
index 0000000..746c74f
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_004.png b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_004.png
new file mode 100644
index 0000000..454a5b2
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_005.png b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_005.png
new file mode 100644
index 0000000..80ad8cc
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_from_pressed_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_000.png b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_000.png
new file mode 100644
index 0000000..cfd0db4
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_000.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_001.png b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_001.png
new file mode 100644
index 0000000..845092f
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_001.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_002.png b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_002.png
new file mode 100644
index 0000000..0042db4
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_002.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_003.png b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_003.png
new file mode 100644
index 0000000..77b2901
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_003.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_004.png b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_004.png
new file mode 100644
index 0000000..fb3c238
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_004.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_005.png b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_005.png
new file mode 100644
index 0000000..0d28c45
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/scrubber_control_to_pressed_qntm_005.png
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/switch_track_qntm_alpha.9.png b/core/res/res/drawable-xxxhdpi/switch_track_qntm_alpha.9.png
new file mode 100644
index 0000000..fb07f2a
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/switch_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_borderless_quantum.xml b/core/res/res/drawable/btn_borderless_quantum.xml
index a8def44..2cd7ed6 100644
--- a/core/res/res/drawable/btn_borderless_quantum.xml
+++ b/core/res/res/drawable/btn_borderless_quantum.xml
@@ -16,21 +16,6 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:tint="?attr/colorControlHighlight">
- <item android:id="@id/mask">
- <inset
- android:insetLeft="4dp"
- android:insetTop="4dp"
- android:insetBottom="4dp"
- android:insetRight="4dp">
- <shape android:shape="rectangle">
- <solid android:color="@color/white" />
- <corners android:radius="2dp" />
- <padding
- android:left="4dp"
- android:top="4dp"
- android:bottom="4dp"
- android:right="4dp" />
- </shape>
- </inset>
- </item>
+ <item android:id="@id/mask"
+ android:drawable="@drawable/btn_qntm_alpha" />
</ripple>
diff --git a/core/res/res/drawable/btn_check_quantum.xml b/core/res/res/drawable/btn_check_quantum.xml
deleted file mode 100644
index 6ceba60..0000000
--- a/core/res/res/drawable/btn_check_quantum.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_checked="true" android:state_pressed="true">
- <bitmap android:src="@drawable/btn_check_on_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item android:state_checked="true">
- <bitmap android:src="@drawable/btn_check_on_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item android:state_pressed="true">
- <bitmap android:src="@drawable/btn_check_off_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item>
- <bitmap android:src="@drawable/btn_check_off_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/btn_check_quantum_anim.xml b/core/res/res/drawable/btn_check_quantum_anim.xml
index 96715a4..b16875e 100644
--- a/core/res/res/drawable/btn_check_quantum_anim.xml
+++ b/core/res/res/drawable/btn_check_quantum_anim.xml
@@ -16,88 +16,118 @@
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:state_checked="true">
- <bitmap android:src="@drawable/btn_check_anim_00015_qntm_alpha"
- android:tint="?attr/colorControlActivated"
- android:alpha="?attr/disabledAlpha" />
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_015" android:tint="?attr/colorControlActivated" android:alpha="?attr/disabledAlpha" />
</item>
<item android:state_enabled="false">
- <bitmap android:src="@drawable/btn_check_anim_00000_qntm_alpha"
- android:tint="?attr/colorControlNormal"
- android:alpha="?attr/disabledAlpha" />
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_000" android:tint="?attr/colorControlNormal" android:alpha="?attr/disabledAlpha" />
</item>
<item android:state_checked="true" android:id="@+id/on">
- <bitmap android:src="@drawable/btn_check_anim_00015_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_015" android:tint="?attr/colorControlActivated" />
</item>
<item android:id="@+id/off">
- <bitmap android:src="@drawable/btn_check_anim_00000_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_000" android:tint="?attr/colorControlNormal" />
</item>
- <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="true">
+ <transition android:fromId="@+id/off" android:toId="@+id/on">
<animation-list>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00000_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_000" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00001_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_001" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00002_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_002" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00003_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_003" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00004_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_004" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00005_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_005" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00006_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_006" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00007_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_007" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00008_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_008" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00009_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_009" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00010_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_010" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00011_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_011" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00012_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_012" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00013_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_013" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00014_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_014" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_check_anim_00015_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_on_qntm_015" android:tint="?attr/colorControlActivated" />
+ </item>
+ </animation-list>
+ </transition>
+ <transition android:fromId="@+id/on" android:toId="@+id/off">
+ <animation-list>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_000" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_001" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_002" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_003" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_004" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_005" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_006" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_007" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_008" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_009" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_010" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_011" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_012" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_013" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_014" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_check_to_off_qntm_015" android:tint="?attr/colorControlActivated" />
</item>
</animation-list>
</transition>
diff --git a/core/res/res/drawable/btn_default_quantum.xml b/core/res/res/drawable/btn_default_quantum.xml
index 63473a4..61193fe 100644
--- a/core/res/res/drawable/btn_default_quantum.xml
+++ b/core/res/res/drawable/btn_default_quantum.xml
@@ -17,20 +17,7 @@
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:tint="?attr/colorControlHighlight">
<item>
- <inset
- android:insetLeft="4dp"
- android:insetTop="4dp"
- android:insetBottom="4dp"
- android:insetRight="4dp">
- <shape android:shape="rectangle">
- <solid android:color="?attr/colorButtonNormal" />
- <corners android:radius="2dp" />
- <padding
- android:left="4dp"
- android:top="4dp"
- android:bottom="4dp"
- android:right="4dp" />
- </shape>
- </inset>
+ <nine-patch android:src="@drawable/btn_qntm_alpha"
+ android:tint="?attr/colorButtonNormal" />
</item>
</ripple>
diff --git a/core/res/res/drawable/btn_radio_quantum.xml b/core/res/res/drawable/btn_radio_quantum.xml
deleted file mode 100644
index 0f9ebce..0000000
--- a/core/res/res/drawable/btn_radio_quantum.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="false" android:state_checked="true">
- <bitmap android:src="@drawable/btn_radio_on_qntm_alpha"
- android:tint="?attr/colorControlNormal"
- android:alpha="?attr/disabledAlpha" />
- </item>
- <item android:state_enabled="false">
- <bitmap android:src="@drawable/btn_radio_off_qntm_alpha"
- android:tint="?attr/colorControlNormal"
- android:alpha="?attr/disabledAlpha" />
- </item>
- <item android:state_checked="true">
- <bitmap android:src="@drawable/btn_radio_on_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item>
- <bitmap android:src="@drawable/btn_radio_off_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/btn_radio_quantum_anim.xml b/core/res/res/drawable/btn_radio_quantum_anim.xml
index 5068b7a..cd9b518 100644
--- a/core/res/res/drawable/btn_radio_quantum_anim.xml
+++ b/core/res/res/drawable/btn_radio_quantum_anim.xml
@@ -16,88 +16,118 @@
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:state_checked="true">
- <bitmap android:src="@drawable/btn_radio_anim_00015_qntm_alpha"
- android:tint="?attr/colorControlActivated"
- android:alpha="?attr/disabledAlpha" />
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_015" android:tint="?attr/colorControlActivated" android:alpha="?attr/disabledAlpha" />
</item>
<item android:state_enabled="false">
- <bitmap android:src="@drawable/btn_radio_anim_00000_qntm_alpha"
- android:tint="?attr/colorControlNormal"
- android:alpha="?attr/disabledAlpha" />
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_000" android:tint="?attr/colorControlNormal" android:alpha="?attr/disabledAlpha" />
</item>
<item android:state_checked="true" android:id="@+id/on">
- <bitmap android:src="@drawable/btn_radio_anim_00015_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_015" android:tint="?attr/colorControlActivated" />
</item>
<item android:id="@+id/off">
- <bitmap android:src="@drawable/btn_radio_anim_00000_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_000" android:tint="?attr/colorControlNormal" />
</item>
- <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="true">
+ <transition android:fromId="@+id/off" android:toId="@+id/on">
<animation-list>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00000_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_000" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00001_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_001" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00002_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_002" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00003_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_003" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00004_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_004" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00005_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_005" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00006_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_006" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00007_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_007" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00008_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_008" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00009_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_009" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00010_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_010" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00011_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_011" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00012_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_012" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00013_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_013" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00014_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_014" android:tint="?attr/colorControlActivated" />
</item>
- <item android:duration="33">
- <bitmap android:src="@drawable/btn_radio_anim_00015_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_on_qntm_015" android:tint="?attr/colorControlActivated" />
+ </item>
+ </animation-list>
+ </transition>
+ <transition android:fromId="@+id/on" android:toId="@+id/off">
+ <animation-list>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_000" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_001" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_002" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_003" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_004" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_005" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_006" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_007" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_008" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_009" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_010" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_011" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_012" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_013" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_014" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_radio_to_off_qntm_015" android:tint="?attr/colorControlActivated" />
</item>
</animation-list>
</transition>
diff --git a/core/res/res/drawable/btn_toggle_quantum.xml b/core/res/res/drawable/btn_toggle_quantum.xml
new file mode 100644
index 0000000..e235598
--- /dev/null
+++ b/core/res/res/drawable/btn_toggle_quantum.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetLeft="4dp"
+ android:insetTop="4dp"
+ android:insetBottom="4dp"
+ android:insetRight="4dp">
+ <layer-list android:paddingMode="stack">
+ <item>
+ <ripple android:tint="?attr/colorControlHighlight">
+ <item>
+ <nine-patch android:src="@drawable/btn_toggle_qntm_alpha"
+ android:tint="?attr/colorButtonNormal" />
+ </item>
+ </ripple>
+ </item>
+ <item>
+ <selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_checked="false">
+ <nine-patch android:src="@drawable/btn_toggle_indicator_qntm_alpha"
+ android:tint="?attr/colorControlNormal" />
+ </item>
+ <item android:state_checked="true">
+ <nine-patch android:src="@drawable/btn_toggle_indicator_qntm_alpha"
+ android:tint="?attr/colorControlActivated" />
+ </item>
+ </selector>
+ </item>
+ </layer-list>
+</inset>
diff --git a/core/res/res/drawable/scrubber_control_quantum_anim.xml b/core/res/res/drawable/scrubber_control_quantum_anim.xml
new file mode 100644
index 0000000..87d3ae9
--- /dev/null
+++ b/core/res/res/drawable/scrubber_control_quantum_anim.xml
@@ -0,0 +1,74 @@
+<?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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android" android:constantSize="true">
+ <item android:state_enabled="false" android:state_pressed="true">
+ <bitmap android:src="@drawable/scrubber_control_off_qntm_alpha" android:gravity="center" android:tint="?attr/colorControlActivated" android:alpha="?attr/disabledAlpha" />
+ </item>
+ <item android:state_enabled="false">
+ <bitmap android:src="@drawable/scrubber_control_off_qntm_alpha" android:gravity="center" android:tint="?attr/colorControlNormal" android:alpha="?attr/disabledAlpha" />
+ </item>
+ <item android:state_pressed="true" android:id="@+id/pressed">
+ <bitmap android:src="@drawable/scrubber_control_to_pressed_qntm_005" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:id="@+id/not_pressed">
+ <bitmap android:src="@drawable/scrubber_control_to_pressed_qntm_000" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <transition android:fromId="@+id/not_pressed" android:toId="@+id/pressed">
+ <animation-list>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_to_pressed_qntm_000" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_to_pressed_qntm_001" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_to_pressed_qntm_002" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_to_pressed_qntm_003" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_to_pressed_qntm_004" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_to_pressed_qntm_005" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ </animation-list>
+ </transition>
+ <transition android:fromId="@+id/pressed" android:toId="@+id/not_pressed">
+ <animation-list>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_from_pressed_qntm_000" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_from_pressed_qntm_001" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_from_pressed_qntm_002" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_from_pressed_qntm_003" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_from_pressed_qntm_004" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/scrubber_control_from_pressed_qntm_005" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ </animation-list>
+ </transition>
+</animated-selector>
diff --git a/core/res/res/drawable/switch_inner_quantum.xml b/core/res/res/drawable/switch_inner_quantum.xml
deleted file mode 100644
index 856895e..0000000
--- a/core/res/res/drawable/switch_inner_quantum.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="false" android:state_checked="true">
- <nine-patch android:src="@drawable/switch_on_qntm_alpha"
- android:tint="?attr/colorControlNormal"
- android:alpha="?attr/disabledAlpha" />
- </item>
- <item android:state_enabled="false">
- <nine-patch android:src="@drawable/switch_off_qntm_alpha"
- android:tint="?attr/colorControlNormal"
- android:alpha="?attr/disabledAlpha" />
- </item>
- <item android:state_checked="true">
- <nine-patch android:src="@drawable/switch_on_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item>
- <nine-patch android:src="@drawable/switch_off_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
-</selector>
diff --git a/core/res/res/drawable/switch_thumb_quantum_anim.xml b/core/res/res/drawable/switch_thumb_quantum_anim.xml
new file mode 100644
index 0000000..1984d47
--- /dev/null
+++ b/core/res/res/drawable/switch_thumb_quantum_anim.xml
@@ -0,0 +1,128 @@
+<?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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android" android:constantSize="true">
+ <item android:state_enabled="false" android:state_checked="true">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_014" android:gravity="center" android:tint="?attr/colorControlActivated" android:alpha="?attr/disabledAlpha" />
+ </item>
+ <item android:state_enabled="false">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_000" android:gravity="center" android:tint="?attr/colorControlNormal" android:alpha="?attr/disabledAlpha" />
+ </item>
+ <item android:state_checked="true" android:id="@+id/on">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_014" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:id="@+id/off">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_000" android:gravity="center" android:tint="?attr/colorControlNormal" />
+ </item>
+ <transition android:fromId="@+id/off" android:toId="@+id/on">
+ <animation-list>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_000" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_001" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_002" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_003" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_004" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_005" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_006" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_007" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_008" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_009" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_010" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_011" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_012" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_013" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_on_qntm_014" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ </animation-list>
+ </transition>
+ <transition android:fromId="@+id/on" android:toId="@+id/off">
+ <animation-list>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_000" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_001" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_002" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_003" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_004" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_005" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_006" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_007" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_008" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_009" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_010" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_011" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_012" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_013" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ <item android:duration="15">
+ <bitmap android:src="@drawable/btn_switch_to_off_qntm_014" android:gravity="center" android:tint="?attr/colorControlActivated" />
+ </item>
+ </animation-list>
+ </transition>
+</animated-selector>
diff --git a/core/res/res/drawable/switch_track_quantum.xml b/core/res/res/drawable/switch_track_quantum.xml
index 8c4e6b71..3651a0a 100644
--- a/core/res/res/drawable/switch_track_quantum.xml
+++ b/core/res/res/drawable/switch_track_quantum.xml
@@ -15,6 +15,16 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:state_checked="true">
+ <nine-patch android:src="@drawable/switch_track_qntm_alpha"
+ android:tint="?attr/colorControlActivated"
+ android:alpha="?attr/disabledAlpha" />
+ </item>
+ <item android:state_enabled="false">
+ <nine-patch android:src="@drawable/switch_track_qntm_alpha"
+ android:tint="?attr/colorControlNormal"
+ android:alpha="?attr/disabledAlpha" />
+ </item>
<item android:state_checked="true">
<nine-patch android:src="@drawable/switch_track_qntm_alpha"
android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/values/dimens_quantum.xml b/core/res/res/values/dimens_quantum.xml
index 53e97fd..2defee2 100644
--- a/core/res/res/values/dimens_quantum.xml
+++ b/core/res/res/values/dimens_quantum.xml
@@ -47,6 +47,10 @@
<dimen name="text_size_menu_quantum">14sp</dimen>
<dimen name="text_size_button_quantum">14sp</dimen>
+ <dimen name="text_size_large_quantum">22sp</dimen>
+ <dimen name="text_size_medium_quantum">18sp</dimen>
+ <dimen name="text_size_small_quantum">14sp</dimen>
+
<dimen name="floating_window_z">16dp</dimen>
<dimen name="floating_window_margin">32dp</dimen>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 4a27ebe..f6cd9e8 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -277,37 +277,6 @@
<item name="android:textColor">#CCCCCC</item>
</style>
- <style name="TextAppearance.StatusBar.Quantum">
- </style>
- <style name="TextAppearance.StatusBar.Quantum.EventContent">
- <item name="android:textColor">#90000000</item>
- <item name="android:textSize">@dimen/notification_text_size</item>
- </style>
- <style name="TextAppearance.StatusBar.Quantum.EventContent.Title">
- <item name="android:textColor">#DD000000</item>
- <item name="android:textSize">@dimen/notification_title_text_size</item>
- </style>
- <style name="TextAppearance.StatusBar.Quantum.EventContent.Line2">
- <item name="android:textSize">@dimen/notification_subtext_size</item>
- </style>
- <style name="TextAppearance.StatusBar.Quantum.EventContent.Info">
- <item name="android:textSize">@dimen/notification_subtext_size</item>
- </style>
- <style name="TextAppearance.StatusBar.Quantum.EventContent.Time">
- <item name="android:textSize">@dimen/notification_subtext_size</item>
- </style>
- <style name="TextAppearance.StatusBar.Quantum.EventContent.Emphasis">
- <item name="android:textColor">#66000000</item>
- </style>
- <style name="Widget.StatusBar.Quantum.ProgressBar"
- parent="Widget.Quantum.Light.ProgressBar.Horizontal">
- <item name="android:progressDrawable">@drawable/notification_quantum_media_progress</item>
- </style>
-
- <style name="Widget.StatusBar.Quantum.ProgressBar"
- parent="Widget.Quantum.Light.ProgressBar.Horizontal">
- </style>
-
<style name="TextAppearance.Small.CalendarViewWeekDayView">
<item name="android:textStyle">bold</item>
</style>
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index e528278..2e7a5b1 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -182,7 +182,10 @@
<item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
- <style name="TextAppearance.Quantum.Large" parent="TextAppearance.Quantum.Headline" />
+ <style name="TextAppearance.Quantum.Large">
+ <item name="textSize">@dimen/text_size_large_quantum</item>
+ <item name="textColor">?attr/textColorPrimary</item>
+ </style>
<style name="TextAppearance.Quantum.Large.Inverse">
<item name="textColor">?attr/textColorPrimaryInverse</item>
@@ -191,7 +194,10 @@
<item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
- <style name="TextAppearance.Quantum.Medium" parent="TextAppearance.Quantum.Body1" />
+ <style name="TextAppearance.Quantum.Medium">
+ <item name="textSize">@dimen/text_size_medium_quantum</item>
+ <item name="textColor">?attr/textColorSecondary</item>
+ </style>
<style name="TextAppearance.Quantum.Medium.Inverse">
<item name="textColor">?attr/textColorSecondaryInverse</item>
@@ -200,7 +206,10 @@
<item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
- <style name="TextAppearance.Quantum.Small" parent="TextAppearance.Quantum.Caption" />
+ <style name="TextAppearance.Quantum.Small">
+ <item name="textSize">@dimen/text_size_small_quantum</item>
+ <item name="textColor">?attr/textColorTertiary</item>
+ </style>
<style name="TextAppearance.Quantum.Small.Inverse">
<item name="textColor">?attr/textColorTertiaryInverse</item>
@@ -351,6 +360,38 @@
<item name="textStyle">bold</item>
</style>
+ <style name="TextAppearance.StatusBar.Quantum" />
+
+ <style name="TextAppearance.StatusBar.Quantum.EventContent">
+ <item name="android:textColor">#90000000</item>
+ <item name="android:textSize">@dimen/notification_text_size</item>
+ </style>
+
+ <style name="TextAppearance.StatusBar.Quantum.EventContent.Title">
+ <item name="android:textColor">#DD000000</item>
+ <item name="android:textSize">@dimen/notification_title_text_size</item>
+ </style>
+
+ <style name="TextAppearance.StatusBar.Quantum.EventContent.Line2">
+ <item name="android:textSize">@dimen/notification_subtext_size</item>
+ </style>
+
+ <style name="TextAppearance.StatusBar.Quantum.EventContent.Info">
+ <item name="android:textSize">@dimen/notification_subtext_size</item>
+ </style>
+
+ <style name="TextAppearance.StatusBar.Quantum.EventContent.Time">
+ <item name="android:textSize">@dimen/notification_subtext_size</item>
+ </style>
+
+ <style name="TextAppearance.StatusBar.Quantum.EventContent.Emphasis">
+ <item name="android:textColor">#66000000</item>
+ </style>
+
+ <style name="Widget.StatusBar.Quantum.ProgressBar" parent="Widget.Quantum.Light.ProgressBar.Horizontal">
+ <item name="android:progressDrawable">@drawable/notification_quantum_media_progress</item>
+ </style>
+
<!-- Widget Styles -->
<style name="Quantum"/>
@@ -390,7 +431,7 @@
</style>
<style name="Widget.Quantum.Button.Toggle">
- <item name="background">@drawable/btn_toggle_holo_dark</item>
+ <item name="background">@drawable/btn_toggle_quantum</item>
<item name="textOn">@string/capital_on</item>
<item name="textOff">@string/capital_off</item>
<item name="textAppearance">?attr/textAppearanceSmall</item>
@@ -459,13 +500,13 @@
<style name="Widget.Quantum.CompoundButton.Switch">
<item name="track">@drawable/switch_track_quantum</item>
- <item name="thumb">@drawable/switch_inner_quantum</item>
+ <item name="thumb">@drawable/switch_thumb_quantum_anim</item>
<item name="splitTrack">true</item>
<item name="switchTextAppearance">@style/TextAppearance.Quantum.Widget.Switch</item>
<item name="textOn"></item>
<item name="textOff"></item>
- <item name="switchMinWidth">72dip</item>
- <item name="switchPadding">16dip</item>
+ <item name="switchMinWidth">4dip</item>
+ <item name="switchPadding">4dip</item>
<item name="background">?attr/selectableItemBackground</item>
</style>
@@ -579,7 +620,7 @@
<item name="indeterminateOnly">false</item>
<item name="progressDrawable">@drawable/scrubber_progress_horizontal_quantum</item>
<item name="indeterminateDrawable">@drawable/scrubber_progress_horizontal_quantum</item>
- <item name="thumb">@drawable/scrubber_control_selector_quantum</item>
+ <item name="thumb">@drawable/scrubber_control_quantum_anim</item>
<item name="splitTrack">true</item>
<item name="focusable">true</item>
<item name="paddingStart">16dip</item>
@@ -784,15 +825,7 @@
<style name="Widget.Quantum.Light.Button.Borderless" parent="Widget.Quantum.Button.Borderless"/>
<style name="Widget.Quantum.Light.Button.Borderless.Small" parent="Widget.Quantum.Button.Borderless.Small"/>
<style name="Widget.Quantum.Light.Button.Inset" parent="Widget.Quantum.Button.Inset"/>
-
- <style name="Widget.Quantum.Light.Button.Toggle">
- <item name="background">@drawable/btn_toggle_holo_light</item>
- <item name="textOn">@string/capital_on</item>
- <item name="textOff">@string/capital_off</item>
- <item name="textAppearance">?attr/textAppearanceSmall</item>
- <item name="minHeight">48dip</item>
- </style>
-
+ <style name="Widget.Quantum.Light.Button.Toggle" parent="Widget.Quantum.Button.Toggle" />
<style name="Widget.Quantum.Light.ButtonBar" parent="Widget.Quantum.ButtonBar"/>
<style name="Widget.Quantum.Light.ButtonBar.AlertDialog" parent="Widget.Quantum.ButtonBar.AlertDialog"/>
diff --git a/data/fonts/Android.mk b/data/fonts/Android.mk
index 452c575..c6bccfe 100644
--- a/data/fonts/Android.mk
+++ b/data/fonts/Android.mk
@@ -105,8 +105,11 @@
ifeq ($(MINIMAL_FONT_FOOTPRINT),true)
+$(eval $(call create-font-symlink,Roboto-Black.ttf,Roboto-Bold.ttf))
$(eval $(call create-font-symlink,Roboto-Light.ttf,Roboto-Regular.ttf))
$(eval $(call create-font-symlink,Roboto-LightItalic.ttf,Roboto-Italic.ttf))
+$(eval $(call create-font-symlink,Roboto-Medium.ttf,Roboto-Regular.ttf))
+$(eval $(call create-font-symlink,Roboto-MediumItalic.ttf,Roboto-Italic.ttf))
$(eval $(call create-font-symlink,Roboto-Thin.ttf,Roboto-Regular.ttf))
$(eval $(call create-font-symlink,Roboto-ThinItalic.ttf,Roboto-Italic.ttf))
$(eval $(call create-font-symlink,RobotoCondensed-Regular.ttf,Roboto-Regular.ttf))
@@ -116,8 +119,11 @@
else # !MINIMAL_FONT
font_src_files += \
+ Roboto-Black.ttf \
Roboto-Light.ttf \
Roboto-LightItalic.ttf \
+ Roboto-Medium.ttf \
+ Roboto-MediumItalic.ttf \
Roboto-Thin.ttf \
Roboto-ThinItalic.ttf \
RobotoCondensed-Regular.ttf \
diff --git a/data/fonts/Roboto-Black.ttf b/data/fonts/Roboto-Black.ttf
new file mode 100644
index 0000000..2cdbe43
--- /dev/null
+++ b/data/fonts/Roboto-Black.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Bold.ttf b/data/fonts/Roboto-Bold.ttf
index c5b9c67..15c9b4e 100644
--- a/data/fonts/Roboto-Bold.ttf
+++ b/data/fonts/Roboto-Bold.ttf
Binary files differ
diff --git a/data/fonts/Roboto-BoldItalic.ttf b/data/fonts/Roboto-BoldItalic.ttf
index 0320214..a0abf30 100644
--- a/data/fonts/Roboto-BoldItalic.ttf
+++ b/data/fonts/Roboto-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Italic.ttf b/data/fonts/Roboto-Italic.ttf
index 38ba570..67b5394 100644
--- a/data/fonts/Roboto-Italic.ttf
+++ b/data/fonts/Roboto-Italic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Light.ttf b/data/fonts/Roboto-Light.ttf
index 271606b..d9fb64a 100644
--- a/data/fonts/Roboto-Light.ttf
+++ b/data/fonts/Roboto-Light.ttf
Binary files differ
diff --git a/data/fonts/Roboto-LightItalic.ttf b/data/fonts/Roboto-LightItalic.ttf
index 17ef355..1fd1d31 100644
--- a/data/fonts/Roboto-LightItalic.ttf
+++ b/data/fonts/Roboto-LightItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Medium.ttf b/data/fonts/Roboto-Medium.ttf
new file mode 100644
index 0000000..c63c115
--- /dev/null
+++ b/data/fonts/Roboto-Medium.ttf
Binary files differ
diff --git a/data/fonts/Roboto-MediumItalic.ttf b/data/fonts/Roboto-MediumItalic.ttf
new file mode 100644
index 0000000..cd7c835
--- /dev/null
+++ b/data/fonts/Roboto-MediumItalic.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Regular.ttf b/data/fonts/Roboto-Regular.ttf
index 7469063..9cb4a5a 100644
--- a/data/fonts/Roboto-Regular.ttf
+++ b/data/fonts/Roboto-Regular.ttf
Binary files differ
diff --git a/data/fonts/Roboto-Thin.ttf b/data/fonts/Roboto-Thin.ttf
index 74efe4d..f02f100 100644
--- a/data/fonts/Roboto-Thin.ttf
+++ b/data/fonts/Roboto-Thin.ttf
Binary files differ
diff --git a/data/fonts/Roboto-ThinItalic.ttf b/data/fonts/Roboto-ThinItalic.ttf
index f08ea51..12a2ce0 100644
--- a/data/fonts/Roboto-ThinItalic.ttf
+++ b/data/fonts/Roboto-ThinItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Bold.ttf b/data/fonts/RobotoCondensed-Bold.ttf
index 1252d00..1079af6 100644
--- a/data/fonts/RobotoCondensed-Bold.ttf
+++ b/data/fonts/RobotoCondensed-Bold.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-BoldItalic.ttf b/data/fonts/RobotoCondensed-BoldItalic.ttf
index e914a07..e7f13c2 100644
--- a/data/fonts/RobotoCondensed-BoldItalic.ttf
+++ b/data/fonts/RobotoCondensed-BoldItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Italic.ttf b/data/fonts/RobotoCondensed-Italic.ttf
index 8a570cf..7fa04481 100644
--- a/data/fonts/RobotoCondensed-Italic.ttf
+++ b/data/fonts/RobotoCondensed-Italic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Light.ttf b/data/fonts/RobotoCondensed-Light.ttf
index 41d212a..96b75dd 100644
--- a/data/fonts/RobotoCondensed-Light.ttf
+++ b/data/fonts/RobotoCondensed-Light.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-LightItalic.ttf b/data/fonts/RobotoCondensed-LightItalic.ttf
old mode 100755
new mode 100644
index dd54971..7a2c164
--- a/data/fonts/RobotoCondensed-LightItalic.ttf
+++ b/data/fonts/RobotoCondensed-LightItalic.ttf
Binary files differ
diff --git a/data/fonts/RobotoCondensed-Regular.ttf b/data/fonts/RobotoCondensed-Regular.ttf
index a16b9cb..734cc40 100644
--- a/data/fonts/RobotoCondensed-Regular.ttf
+++ b/data/fonts/RobotoCondensed-Regular.ttf
Binary files differ
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 2312a04..e5573bb 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -24,8 +24,11 @@
Roboto-Bold.ttf \
Roboto-Italic.ttf \
Roboto-BoldItalic.ttf \
+ Roboto-Black.ttf \
Roboto-Light.ttf \
Roboto-LightItalic.ttf \
+ Roboto-Medium.ttf \
+ Roboto-MediumItalic.ttf \
Roboto-Thin.ttf \
Roboto-ThinItalic.ttf \
RobotoCondensed-Regular.ttf \
diff --git a/data/fonts/system_fonts.xml b/data/fonts/system_fonts.xml
index 97b7fd8..646b33b 100644
--- a/data/fonts/system_fonts.xml
+++ b/data/fonts/system_fonts.xml
@@ -68,6 +68,25 @@
<family>
<nameset>
+ <name>sans-serif-medium</name>
+ </nameset>
+ <fileset>
+ <file>Roboto-Medium.ttf</file>
+ <file>Roboto-MediumItalic.ttf</file>
+ </fileset>
+ </family>
+
+ <family>
+ <nameset>
+ <name>sans-serif-black</name>
+ </nameset>
+ <fileset>
+ <file>Roboto-Black.ttf</file>
+ </fileset>
+ </family>
+
+ <family>
+ <nameset>
<name>sans-serif-condensed-light</name>
</nameset>
<fileset>
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index b7673d8..3ab57c1 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -44,7 +44,6 @@
mTileY = tileY;
final long b = bitmap.ni();
native_instance = nativeCreate(b, tileX.nativeInt, tileY.nativeInt);
- native_shader = nativePostCreate(native_instance, b, tileX.nativeInt, tileY.nativeInt);
}
/**
@@ -59,6 +58,4 @@
private static native long nativeCreate(long native_bitmap, int shaderTileModeX,
int shaderTileModeY);
- private static native long nativePostCreate(long native_shader, long native_bitmap,
- int shaderTileModeX, int shaderTileModeY);
}
diff --git a/graphics/java/android/graphics/ComposeShader.java b/graphics/java/android/graphics/ComposeShader.java
index 5109ffd..d7b2071 100644
--- a/graphics/java/android/graphics/ComposeShader.java
+++ b/graphics/java/android/graphics/ComposeShader.java
@@ -55,14 +55,6 @@
mXferMode = mode;
native_instance = nativeCreate1(shaderA.native_instance, shaderB.native_instance,
(mode != null) ? mode.native_instance : 0);
- if (mode instanceof PorterDuffXfermode) {
- PorterDuff.Mode pdMode = ((PorterDuffXfermode) mode).mode;
- native_shader = nativePostCreate2(native_instance, shaderA.native_shader,
- shaderB.native_shader, pdMode != null ? pdMode.nativeInt : 0);
- } else {
- native_shader = nativePostCreate1(native_instance, shaderA.native_shader,
- shaderB.native_shader, mode != null ? mode.native_instance : 0);
- }
}
/** Create a new compose shader, given shaders A, B, and a combining PorterDuff mode.
@@ -79,8 +71,6 @@
mPorterDuffMode = mode;
native_instance = nativeCreate2(shaderA.native_instance, shaderB.native_instance,
mode.nativeInt);
- native_shader = nativePostCreate2(native_instance, shaderA.native_shader,
- shaderB.native_shader, mode.nativeInt);
}
/**
@@ -108,8 +98,4 @@
long native_mode);
private static native long nativeCreate2(long native_shaderA, long native_shaderB,
int porterDuffMode);
- private static native long nativePostCreate1(long native_shader, long native_skiaShaderA,
- long native_skiaShaderB, long native_mode);
- private static native long nativePostCreate2(long native_shader, long native_skiaShaderA,
- long native_skiaShaderB, int porterDuffMode);
}
diff --git a/graphics/java/android/graphics/LinearGradient.java b/graphics/java/android/graphics/LinearGradient.java
index 0eae67c..90cb217 100644
--- a/graphics/java/android/graphics/LinearGradient.java
+++ b/graphics/java/android/graphics/LinearGradient.java
@@ -66,8 +66,6 @@
mPositions = positions;
mTileMode = tile;
native_instance = nativeCreate1(x0, y0, x1, y1, colors, positions, tile.nativeInt);
- native_shader = nativePostCreate1(native_instance, x0, y0, x1, y1, colors, positions,
- tile.nativeInt);
}
/** Create a shader that draws a linear gradient along a line.
@@ -90,8 +88,6 @@
mColor1 = color1;
mTileMode = tile;
native_instance = nativeCreate2(x0, y0, x1, y1, color0, color1, tile.nativeInt);
- native_shader = nativePostCreate2(native_instance, x0, y0, x1, y1, color0, color1,
- tile.nativeInt);
}
/**
@@ -120,8 +116,4 @@
int colors[], float positions[], int tileMode);
private native long nativeCreate2(float x0, float y0, float x1, float y1,
int color0, int color1, int tileMode);
- private native long nativePostCreate1(long native_shader, float x0, float y0, float x1, float y1,
- int colors[], float positions[], int tileMode);
- private native long nativePostCreate2(long native_shader, float x0, float y0, float x1, float y1,
- int color0, int color1, int tileMode);
}
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index c00c612..75c951a 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -66,8 +66,6 @@
mPositions = positions;
mTileMode = tile;
native_instance = nativeCreate1(x, y, radius, colors, positions, tile.nativeInt);
- native_shader = nativePostCreate1(native_instance, x, y, radius, colors, positions,
- tile.nativeInt);
}
/** Create a shader that draws a radial gradient given the center and radius.
@@ -91,8 +89,6 @@
mColor1 = color1;
mTileMode = tile;
native_instance = nativeCreate2(x, y, radius, color0, color1, tile.nativeInt);
- native_shader = nativePostCreate2(native_instance, x, y, radius, color0, color1,
- tile.nativeInt);
}
/**
@@ -121,10 +117,5 @@
int colors[], float positions[], int tileMode);
private static native long nativeCreate2(float x, float y, float radius,
int color0, int color1, int tileMode);
-
- private static native long nativePostCreate1(long native_shader, float x, float y, float radius,
- int colors[], float positions[], int tileMode);
- private static native long nativePostCreate2(long native_shader, float x, float y, float radius,
- int color0, int color1, int tileMode);
}
diff --git a/graphics/java/android/graphics/Shader.java b/graphics/java/android/graphics/Shader.java
index 94b4c4a..6870ab4 100644
--- a/graphics/java/android/graphics/Shader.java
+++ b/graphics/java/android/graphics/Shader.java
@@ -29,10 +29,6 @@
* @hide
*/
public long native_instance;
- /**
- * @hide
- */
- public long native_shader;
private Matrix mLocalMatrix;
@@ -78,7 +74,7 @@
*/
public void setLocalMatrix(Matrix localM) {
mLocalMatrix = localM;
- nativeSetLocalMatrix(native_instance, native_shader,
+ nativeSetLocalMatrix(native_instance,
localM == null ? 0 : localM.native_instance);
}
@@ -86,7 +82,7 @@
try {
super.finalize();
} finally {
- nativeDestructor(native_instance, native_shader);
+ nativeDestructor(native_instance);
}
}
@@ -112,7 +108,7 @@
}
}
- private static native void nativeDestructor(long native_shader, long native_skiaShader);
+ private static native void nativeDestructor(long native_shader);
private static native void nativeSetLocalMatrix(long native_shader,
- long native_skiaShader, long matrix_instance);
+ long matrix_instance);
}
diff --git a/graphics/java/android/graphics/SweepGradient.java b/graphics/java/android/graphics/SweepGradient.java
index 21239f7..18a748f 100644
--- a/graphics/java/android/graphics/SweepGradient.java
+++ b/graphics/java/android/graphics/SweepGradient.java
@@ -63,7 +63,6 @@
mColors = colors;
mPositions = positions;
native_instance = nativeCreate1(cx, cy, colors, positions);
- native_shader = nativePostCreate1(native_instance, cx, cy, colors, positions);
}
/**
@@ -81,7 +80,6 @@
mColor0 = color0;
mColor1 = color1;
native_instance = nativeCreate2(cx, cy, color0, color1);
- native_shader = nativePostCreate2(native_instance, cx, cy, color0, color1);
}
/**
@@ -108,10 +106,5 @@
private static native long nativeCreate1(float x, float y, int colors[], float positions[]);
private static native long nativeCreate2(float x, float y, int color0, int color1);
-
- private static native long nativePostCreate1(long native_shader, float cx, float cy,
- int[] colors, float[] positions);
- private static native long nativePostCreate2(long native_shader, float cx, float cy,
- int color0, int color1);
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 46e3401..42872e9 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -80,6 +80,22 @@
this(null, null);
}
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ final boolean changed = super.setVisible(visible, restart);
+ if (mAnim != null) {
+ if (visible) {
+ if (changed || restart) {
+ // TODO: Should this support restart?
+ mAnim.end();
+ }
+ } else {
+ mAnim.end();
+ }
+ }
+ return changed;
+ }
+
/**
* Add a new drawable to the set of keyframes.
*
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index f3fcf2c..c95ac82 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -25,6 +25,7 @@
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
+import android.graphics.Insets;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
@@ -92,6 +93,9 @@
private int mBitmapWidth;
private int mBitmapHeight;
+ /** Optical insets due to gravity. */
+ private Insets mOpticalInsets = null;
+
// Mirroring matrix for using with Shaders
private Matrix mMirrorMatrix;
@@ -456,9 +460,9 @@
@Override
protected void onBoundsChange(Rect bounds) {
- super.onBoundsChange(bounds);
mApplyGravity = true;
- Shader shader = mBitmapState.mPaint.getShader();
+
+ final Shader shader = mBitmapState.mPaint.getShader();
if (shader != null) {
if (needMirroring()) {
updateMirrorMatrix(bounds.right - bounds.left);
@@ -517,9 +521,7 @@
final boolean needMirroring = needMirroring();
if (shader == null) {
if (mApplyGravity) {
- final int layoutDirection = getLayoutDirection();
- Gravity.apply(state.mGravity, mBitmapWidth, mBitmapHeight,
- getBounds(), mDstRect, layoutDirection);
+ applyGravity();
mApplyGravity = false;
}
@@ -564,6 +566,31 @@
}
}
+ /**
+ * @hide
+ */
+ @Override
+ public Insets getOpticalInsets() {
+ if (mApplyGravity && mBitmapState.mPaint.getShader() == null) {
+ applyGravity();
+ mApplyGravity = false;
+ }
+ return mOpticalInsets == null ? Insets.NONE : mOpticalInsets;
+ }
+
+ private void applyGravity() {
+ final Rect bounds = getBounds();
+ final int layoutDirection = getLayoutDirection();
+ Gravity.apply(mBitmapState.mGravity, mBitmapWidth, mBitmapHeight,
+ bounds, mDstRect, layoutDirection);
+
+ final int left = mDstRect.left - bounds.left;
+ final int top = mDstRect.top - bounds.top;
+ final int right = bounds.right - mDstRect.right;
+ final int bottom = bounds.bottom - mDstRect.bottom;
+ mOpticalInsets = Insets.of(left, top, right, bottom);
+ }
+
@Override
public void setAlpha(int alpha) {
final int oldAlpha = mBitmapState.mPaint.getAlpha();
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 04373d4..2aef39f 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -187,6 +187,9 @@
}
if (mCurrDrawable != null) {
mCurrDrawable.setBounds(bounds);
+
+ // Must obtain optical insets after setting bounds.
+ mInsets = mCurrDrawable.getOpticalInsets();
}
}
@@ -385,7 +388,6 @@
mCurrDrawable = d;
mCurIndex = idx;
if (d != null) {
- mInsets = d.getOpticalInsets();
d.mutate();
if (mDrawableContainerState.mEnterFadeDuration > 0) {
mEnterAnimationEnd = now + mDrawableContainerState.mEnterFadeDuration;
@@ -402,6 +404,9 @@
d.setBounds(getBounds());
d.setLayoutDirection(getLayoutDirection());
d.setAutoMirrored(mDrawableContainerState.mAutoMirrored);
+
+ // Must obtain optical insets after setting bounds.
+ mInsets = d.getOpticalInsets();
} else {
mInsets = Insets.NONE;
}
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index e3ed75e..e2bd50d 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -159,7 +159,8 @@
@Override
public void setColorFilter(ColorFilter colorFilter) {
- // TODO: support color filter
+ mVectorState.mVPathRenderer.setColorFilter(colorFilter);
+ invalidateSelf();
}
@Override
@@ -365,14 +366,15 @@
private VPath[] mCurrentPaths;
private Paint mStrokePaint;
private Paint mFillPaint;
+ private ColorFilter mColorFilter;
private PathMeasure mPathMeasure;
private VGroup mCurrentGroup = new VGroup();
- float mBaseWidth = 1;
- float mBaseHeight = 1;
- float mViewportWidth;
- float mViewportHeight;
+ float mBaseWidth = 0;
+ float mBaseHeight = 0;
+ float mViewportWidth = 0;
+ float mViewportHeight = 0;
public VPathRenderer() {
}
@@ -413,6 +415,18 @@
}
}
+ public void setColorFilter(ColorFilter colorFilter) {
+ mColorFilter = colorFilter;
+
+ if (mFillPaint != null) {
+ mFillPaint.setColorFilter(colorFilter);
+ }
+
+ if (mStrokePaint != null) {
+ mStrokePaint.setColorFilter(colorFilter);
+ }
+ }
+
public void draw(Canvas canvas, int w, int h) {
if (mCurrentPaths == null) {
Log.e(LOGTAG,"mCurrentPaths == null");
@@ -470,6 +484,7 @@
if (vPath.mFillColor != 0) {
if (mFillPaint == null) {
mFillPaint = new Paint();
+ mFillPaint.setColorFilter(mColorFilter);
mFillPaint.setStyle(Paint.Style.FILL);
mFillPaint.setAntiAlias(true);
}
@@ -481,6 +496,7 @@
if (vPath.mStrokeColor != 0) {
if (mStrokePaint == null) {
mStrokePaint = new Paint();
+ mStrokePaint.setColorFilter(mColorFilter);
mStrokePaint.setStyle(Paint.Style.STROKE);
mStrokePaint.setAntiAlias(true);
}
@@ -516,24 +532,34 @@
private void parseViewport(Resources r, AttributeSet attrs)
throws XmlPullParserException {
final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
- mViewportWidth = a.getFloat(R.styleable.VectorDrawableViewport_viewportWidth, 0);
- mViewportHeight = a.getFloat(R.styleable.VectorDrawableViewport_viewportHeight, 0);
- if (mViewportWidth == 0 || mViewportHeight == 0) {
- throw new XmlPullParserException(a.getPositionDescription()+
- "<viewport> tag requires viewportWidth & viewportHeight to be set");
+ mViewportWidth = a.getFloat(R.styleable.VectorDrawableViewport_viewportWidth, mViewportWidth);
+ mViewportHeight = a.getFloat(R.styleable.VectorDrawableViewport_viewportHeight, mViewportHeight);
+
+ if (mViewportWidth <= 0) {
+ throw new XmlPullParserException(a.getPositionDescription() +
+ "<viewport> tag requires viewportWidth > 0");
+ } else if (mViewportHeight <= 0) {
+ throw new XmlPullParserException(a.getPositionDescription() +
+ "<viewport> tag requires viewportHeight > 0");
}
+
a.recycle();
}
private void parseSize(Resources r, AttributeSet attrs)
throws XmlPullParserException {
final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
- mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, 0);
- mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, 0);
- if (mBaseWidth == 0 || mBaseHeight == 0) {
- throw new XmlPullParserException(a.getPositionDescription()+
- "<size> tag requires width & height to be set");
+ mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, mBaseWidth);
+ mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, mBaseHeight);
+
+ if (mBaseWidth <= 0) {
+ throw new XmlPullParserException(a.getPositionDescription() +
+ "<size> tag requires width > 0");
+ } else if (mBaseHeight <= 0) {
+ throw new XmlPullParserException(a.getPositionDescription() +
+ "<size> tag requires height > 0");
}
+
a.recycle();
}
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 2e2ee15..5367663 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -33,6 +33,7 @@
#include "thread/TaskManager.h"
#include "AssetAtlas.h"
+#include "Extensions.h"
#include "FontRenderer.h"
#include "GammaFontRenderer.h"
#include "TextureCache.h"
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 3016814..937bf8d 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -230,6 +230,11 @@
return false;
}
+ if (op->mPaint && mOps[0].op->mPaint &&
+ op->mPaint->getShader() != mOps[0].op->mPaint->getShader()) {
+ return false;
+ }
+
/* Draw Modifiers compatibility check
*
* Shadows are ignored, as only text uses them, and in that case they are drawn
@@ -244,7 +249,6 @@
*/
const DrawModifiers& lhsMod = lhs->mDrawModifiers;
const DrawModifiers& rhsMod = rhs->mDrawModifiers;
- if (lhsMod.mShader != rhsMod.mShader) return false;
// Draw filter testing expects bit fields to be clear if filter not set.
if (lhsMod.mHasDrawFilter != rhsMod.mHasDrawFilter) return false;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index dac86cb..96c6292 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -58,11 +58,6 @@
caches.resourceCache.decrementRefcountLocked(patchResources.itemAt(i));
}
- for (size_t i = 0; i < shaders.size(); i++) {
- caches.resourceCache.decrementRefcountLocked(shaders.itemAt(i));
- caches.resourceCache.destructorLocked(shaders.itemAt(i));
- }
-
for (size_t i = 0; i < sourcePaths.size(); i++) {
caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i));
}
@@ -92,7 +87,6 @@
bitmapResources.clear();
ownedBitmapResources.clear();
patchResources.clear();
- shaders.clear();
sourcePaths.clear();
paints.clear();
regions.clear();
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index b2ead5b..11e78b0 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -56,7 +56,6 @@
class OpenGLRenderer;
class Rect;
class Layer;
-class SkiaShader;
class ClipRectOp;
class SaveLayerOp;
@@ -127,7 +126,6 @@
SortedVector<const SkPath*> sourcePaths;
Vector<const SkRegion*> regions;
Vector<const SkMatrix*> matrices;
- Vector<SkiaShader*> shaders;
Vector<Layer*> layers;
uint32_t functorCount;
bool hasDrawOps;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index e4867220..ea3e7a8 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -208,9 +208,16 @@
if (!state.mMatrix.isSimple()) return false;
// check state/paint for transparency
- if (state.mDrawModifiers.mShader ||
- state.mAlpha != 1.0f ||
- (mPaint && mPaint->getAlpha() != 0xFF)) return false;
+ if (mPaint) {
+ if (mPaint->getShader() && !mPaint->getShader()->isOpaque()) {
+ return false;
+ }
+ if (mPaint->getAlpha() != 0xFF) {
+ return false;
+ }
+ }
+
+ if (state.mAlpha != 1.0f) return false;
SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
return (mode == SkXfermode::kSrcOver_Mode ||
@@ -592,37 +599,6 @@
const SkRegion* mRegion;
};
-class ResetShaderOp : public StateOp {
-public:
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.resetShader();
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOGS("ResetShader");
- }
-
- virtual const char* name() { return "ResetShader"; }
-};
-
-class SetupShaderOp : public StateOp {
-public:
- SetupShaderOp(SkiaShader* shader)
- : mShader(shader) {}
- virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
- renderer.setupShader(mShader);
- }
-
- virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("SetupShader, shader %p", mShader);
- }
-
- virtual const char* name() { return "SetupShader"; }
-
-private:
- SkiaShader* mShader;
-};
-
class ResetPaintFilterOp : public StateOp {
public:
virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 606c67e..229afdf 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -47,7 +47,6 @@
///////////////////////////////////////////////////////////////////////////////
DisplayListData* DisplayListRenderer::finishRecording() {
- mShaderMap.clear();
mPaintMap.clear();
mRegionMap.clear();
mPathMap.clear();
@@ -394,15 +393,6 @@
return DrawGlInfo::kStatusDone;
}
-void DisplayListRenderer::resetShader() {
- addStateOp(new (alloc()) ResetShaderOp());
-}
-
-void DisplayListRenderer::setupShader(SkiaShader* shader) {
- shader = refShader(shader);
- addStateOp(new (alloc()) SetupShaderOp(shader));
-}
-
void DisplayListRenderer::resetPaintFilter() {
addStateOp(new (alloc()) ResetPaintFilterOp());
}
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index d814111..f0ae00f 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -95,9 +95,6 @@
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
// Misc - should be implemented with SkPaint inspection
- virtual void resetShader();
- virtual void setupShader(SkiaShader* shader);
-
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
@@ -269,21 +266,6 @@
return bitmap;
}
- inline SkiaShader* refShader(SkiaShader* shader) {
- if (!shader) return NULL;
-
- SkiaShader* shaderCopy = mShaderMap.valueFor(shader);
- // TODO: We also need to handle generation ID changes in compose shaders
- if (shaderCopy == NULL || shaderCopy->getGenerationId() != shader->getGenerationId()) {
- shaderCopy = shader->copy();
- // replaceValueFor() performs an add if the entry doesn't exist
- mShaderMap.replaceValueFor(shader, shaderCopy);
- mDisplayListData->shaders.add(shaderCopy);
- mCaches.resourceCache.incrementRefcount(shaderCopy);
- }
- return shaderCopy;
- }
-
inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) {
mDisplayListData->patchResources.add(patch);
mCaches.resourceCache.incrementRefcount(patch);
@@ -293,7 +275,6 @@
DefaultKeyedVector<const SkPaint*, const SkPaint*> mPaintMap;
DefaultKeyedVector<const SkPath*, const SkPath*> mPathMap;
DefaultKeyedVector<const SkRegion*, const SkRegion*> mRegionMap;
- DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
Caches& mCaches;
DisplayListData* mDisplayListData;
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 647c281..4407ab0 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -73,7 +73,7 @@
}
}
renderer->setupDrawColorFilter(paint->getColorFilter());
- renderer->setupDrawShader();
+ renderer->setupDrawShader(paint->getShader());
renderer->setupDrawBlending(paint);
renderer->setupDrawProgram();
renderer->setupDrawModelView(kModelViewMode_Translate, false,
@@ -85,7 +85,7 @@
renderer->setupDrawTexture(0);
renderer->setupDrawPureColorUniforms();
renderer->setupDrawColorFilterUniforms(paint->getColorFilter());
- renderer->setupDrawShaderUniforms(pureTranslate);
+ renderer->setupDrawShaderUniforms(paint->getShader(), pureTranslate);
renderer->setupDrawTextGammaUniforms();
return NO_ERROR;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 691f1c9..71836dd5 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <SkCanvas.h>
+#include <SkShader.h>
#include <SkTypeface.h>
#include <utils/Log.h>
@@ -37,6 +38,7 @@
#include "PathTessellator.h"
#include "Properties.h"
#include "ShadowTessellator.h"
+#include "SkiaShader.h"
#include "utils/GLUtils.h"
#include "Vector.h"
#include "VertexBuffer.h"
@@ -1053,6 +1055,45 @@
#define DRAW_DOUBLE_STENCIL(DRAW_COMMAND) DRAW_DOUBLE_STENCIL_IF(true, DRAW_COMMAND)
+// This class is purely for inspection. It inherits from SkShader, but Skia does not know how to
+// use it. The OpenGLRenderer will look at it to find its Layer and whether it is opaque.
+class LayerShader : public SkShader {
+public:
+ LayerShader(Layer* layer, const SkMatrix* localMatrix)
+ : INHERITED(localMatrix)
+ , mLayer(layer) {
+ }
+
+ virtual bool asACustomShader(void** data) const {
+ if (data) {
+ *data = static_cast<void*>(mLayer);
+ }
+ return true;
+ }
+
+ virtual bool isOpaque() const {
+ return !mLayer->isBlend();
+ }
+
+protected:
+ virtual void shadeSpan(int x, int y, SkPMColor[], int count) {
+ LOG_ALWAYS_FATAL("LayerShader should never be drawn with raster backend.");
+ }
+
+ virtual void flatten(SkWriteBuffer&) const {
+ LOG_ALWAYS_FATAL("LayerShader should never be flattened.");
+ }
+
+ virtual Factory getFactory() const {
+ LOG_ALWAYS_FATAL("LayerShader should never be created from a stream.");
+ return NULL;
+ }
+private:
+ // Unowned.
+ Layer* mLayer;
+ typedef SkShader INHERITED;
+};
+
void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
if (CC_UNLIKELY(layer->region.isEmpty())) return; // nothing to draw
@@ -1066,21 +1107,19 @@
paint.setAntiAlias(true);
paint.setColor(SkColorSetARGB(int(getLayerAlpha(layer) * 255), 0, 0, 0));
- SkiaShader* oldShader = mDrawModifiers.mShader;
-
// create LayerShader to map SaveLayer content into subsequent draw
SkMatrix shaderMatrix;
shaderMatrix.setTranslate(rect.left, rect.bottom);
shaderMatrix.preScale(1, -1);
- SkiaLayerShader layerShader(layer, &shaderMatrix);
- mDrawModifiers.mShader = &layerShader;
+ LayerShader layerShader(layer, &shaderMatrix);
+ paint.setShader(&layerShader);
// Since the drawing primitive is defined in local drawing space,
// we don't need to modify the draw matrix
const SkPath* maskPath = layer->getConvexMask();
DRAW_DOUBLE_STENCIL(drawConvexPath(*maskPath, &paint));
- mDrawModifiers.mShader = oldShader;
+ paint.setShader(NULL);
restore();
return;
@@ -1627,9 +1666,9 @@
mSetShaderColor = mDescription.setColorModulate(a);
}
-void OpenGLRenderer::setupDrawShader() {
- if (mDrawModifiers.mShader) {
- mDrawModifiers.mShader->describe(mDescription, mExtensions);
+void OpenGLRenderer::setupDrawShader(const SkShader* shader) {
+ if (shader != NULL) {
+ SkiaShader::describe(&mCaches, mDescription, mExtensions, *shader);
}
}
@@ -1655,15 +1694,21 @@
}
}
+static bool isBlendedColorFilter(const SkColorFilter* filter) {
+ if (filter == NULL) {
+ return false;
+ }
+ return (filter->getFlags() & SkColorFilter::kAlphaUnchanged_Flag) == 0;
+}
+
void OpenGLRenderer::setupDrawBlending(const Layer* layer, bool swapSrcDst) {
SkXfermode::Mode mode = layer->getMode();
// When the blending mode is kClear_Mode, we need to use a modulate color
// argb=1,0,0,0
accountForClear(mode);
+ // TODO: check shader blending, once we have shader drawing support for layers.
bool blend = layer->isBlend() || getLayerAlpha(layer) < 1.0f ||
- (mColorSet && mColorA < 1.0f) ||
- (mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) ||
- layer->getColorFilter();
+ (mColorSet && mColorA < 1.0f) || isBlendedColorFilter(layer->getColorFilter());
chooseBlending(blend, mode, mDescription, swapSrcDst);
}
@@ -1673,8 +1718,8 @@
// argb=1,0,0,0
accountForClear(mode);
blend |= (mColorSet && mColorA < 1.0f) ||
- (mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) ||
- (paint && paint->getColorFilter());
+ (getShader(paint) && !getShader(paint)->isOpaque()) ||
+ isBlendedColorFilter(getColorFilter(paint));
chooseBlending(blend, mode, mDescription, swapSrcDst);
}
@@ -1717,8 +1762,8 @@
}
}
-void OpenGLRenderer::setupDrawColorUniforms() {
- if ((mColorSet && !mDrawModifiers.mShader) || (mDrawModifiers.mShader && mSetShaderColor)) {
+void OpenGLRenderer::setupDrawColorUniforms(bool hasShader) {
+ if ((mColorSet && !hasShader) || (hasShader && mSetShaderColor)) {
mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA);
}
}
@@ -1729,20 +1774,22 @@
}
}
-void OpenGLRenderer::setupDrawShaderUniforms(bool ignoreTransform) {
- if (mDrawModifiers.mShader) {
- if (ignoreTransform) {
- // if ignoreTransform=true was passed to setupDrawModelView, undo currentTransform()
- // because it was built into modelView / the geometry, and the SkiaShader needs to
- // compensate.
- mat4 modelViewWithoutTransform;
- modelViewWithoutTransform.loadInverse(*currentTransform());
- modelViewWithoutTransform.multiply(mModelViewMatrix);
- mModelViewMatrix.load(modelViewWithoutTransform);
- }
- mDrawModifiers.mShader->setupProgram(mCaches.currentProgram,
- mModelViewMatrix, *mSnapshot, &mTextureUnit);
+void OpenGLRenderer::setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform) {
+ if (shader == NULL) {
+ return;
}
+
+ if (ignoreTransform) {
+ // if ignoreTransform=true was passed to setupDrawModelView, undo currentTransform()
+ // because it was built into modelView / the geometry, and the description needs to
+ // compensate.
+ mat4 modelViewWithoutTransform;
+ modelViewWithoutTransform.loadInverse(*currentTransform());
+ modelViewWithoutTransform.multiply(mModelViewMatrix);
+ mModelViewMatrix.load(modelViewWithoutTransform);
+ }
+
+ SkiaShader::setupProgram(&mCaches, mModelViewMatrix, &mTextureUnit, mExtensions, *shader);
}
void OpenGLRenderer::setupDrawColorFilterUniforms(const SkColorFilter* filter) {
@@ -2201,7 +2248,7 @@
// Apply a scale transform on the canvas only when a shader is in use
// Skia handles the ratio between the dst and src rects as a scale factor
// when a shader is set
- bool useScaleTransform = mDrawModifiers.mShader && scaled;
+ bool useScaleTransform = getShader(paint) && scaled;
bool ignoreTransform = false;
if (CC_LIKELY(currentTransform()->isPureTranslate() && !useScaleTransform)) {
@@ -2359,13 +2406,13 @@
if (isAA) setupDrawAA();
setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, isAA);
setupDrawProgram();
setupDrawModelView(kModelViewMode_Translate, useOffset, 0, 0, 0, 0);
- setupDrawColorUniforms();
+ setupDrawColorUniforms(getShader(paint));
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms();
+ setupDrawShaderUniforms(getShader(paint));
const void* vertices = vertexBuffer.getBuffer();
bool force = mCaches.unbindMeshBuffer();
@@ -2670,7 +2717,7 @@
const float sy = y - shadow->top + textShadow.dy;
const int shadowAlpha = ((textShadow.color >> 24) & 0xFF) * mSnapshot->alpha;
- if (mDrawModifiers.mShader) {
+ if (getShader(paint)) {
textShadow.color = SK_ColorWHITE;
}
@@ -2678,7 +2725,7 @@
setupDrawWithTexture(true);
setupDrawAlpha8Color(textShadow.color, shadowAlpha < 255 ? shadowAlpha : alpha);
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
@@ -2686,7 +2733,7 @@
setupDrawTexture(shadow->id);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms();
+ setupDrawShaderUniforms(getShader(paint));
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -3008,21 +3055,6 @@
}
///////////////////////////////////////////////////////////////////////////////
-// Shaders
-///////////////////////////////////////////////////////////////////////////////
-
-void OpenGLRenderer::resetShader() {
- mDrawModifiers.mShader = NULL;
-}
-
-void OpenGLRenderer::setupShader(SkiaShader* shader) {
- mDrawModifiers.mShader = shader;
- if (mDrawModifiers.mShader) {
- mDrawModifiers.mShader->setCaches(mCaches);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
// Draw filters
///////////////////////////////////////////////////////////////////////////////
@@ -3080,7 +3112,7 @@
setupDrawWithTexture(true);
setupDrawAlpha8Color(paint->getColor(), alpha);
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, true);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
@@ -3088,7 +3120,7 @@
setupDrawTexture(texture->id);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms();
+ setupDrawShaderUniforms(getShader(paint));
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
@@ -3254,7 +3286,7 @@
int color = paint->getColor();
// If a shader is set, preserve only the alpha
- if (mDrawModifiers.mShader) {
+ if (getShader(paint)) {
color |= 0x00ffffff;
}
@@ -3290,15 +3322,15 @@
setupDraw();
setupDrawNoTexture();
setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawColorFilter(getColorFilter(paint));
setupDrawBlending(paint);
setupDrawProgram();
setupDrawDirtyRegionsDisabled();
setupDrawModelView(kModelViewMode_Translate, false,
0.0f, 0.0f, 0.0f, 0.0f, ignoreTransform);
- setupDrawColorUniforms();
- setupDrawShaderUniforms();
+ setupDrawColorUniforms(getShader(paint));
+ setupDrawShaderUniforms(getShader(paint));
setupDrawColorFilterUniforms(getColorFilter(paint));
if (dirty && hasLayer()) {
@@ -3314,21 +3346,21 @@
const SkPaint* paint, bool ignoreTransform) {
int color = paint->getColor();
// If a shader is set, preserve only the alpha
- if (mDrawModifiers.mShader) {
+ if (getShader(paint)) {
color |= 0x00ffffff;
}
setupDraw();
setupDrawNoTexture();
setupDrawColor(color, ((color >> 24) & 0xFF) * currentSnapshot()->alpha);
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawColorFilter(getColorFilter(paint));
setupDrawBlending(paint);
setupDrawProgram();
setupDrawModelView(kModelViewMode_TranslateAndScale, false,
left, top, right, bottom, ignoreTransform);
- setupDrawColorUniforms();
- setupDrawShaderUniforms(ignoreTransform);
+ setupDrawColorUniforms(getShader(paint));
+ setupDrawShaderUniforms(getShader(paint), ignoreTransform);
setupDrawColorFilterUniforms(getColorFilter(paint));
setupDrawSimpleMesh();
@@ -3441,7 +3473,7 @@
setupDrawAlpha8Color(color, alpha);
}
setupDrawColorFilter(getColorFilter(paint));
- setupDrawShader();
+ setupDrawShader(getShader(paint));
setupDrawBlending(paint, true);
setupDrawProgram();
if (!dirty) setupDrawDirtyRegionsDisabled();
@@ -3449,7 +3481,7 @@
setupDrawTexture(texture);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms(getColorFilter(paint));
- setupDrawShaderUniforms(ignoreTransform);
+ setupDrawShaderUniforms(getShader(paint), ignoreTransform);
setupDrawMesh(vertices, texCoords);
glDrawArrays(drawMode, 0, elementsCount);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index c6d9071..fc27947 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -26,7 +26,6 @@
#include <SkMatrix.h>
#include <SkPaint.h>
#include <SkRegion.h>
-#include <SkShader.h>
#include <SkXfermode.h>
#include <utils/Blur.h>
@@ -45,13 +44,15 @@
#include "Program.h"
#include "Rect.h"
#include "Renderer.h"
-#include "StatefulBaseRenderer.h"
#include "Snapshot.h"
+#include "StatefulBaseRenderer.h"
#include "UvMapper.h"
#include "Vertex.h"
#include "Caches.h"
#include "CanvasProperty.h"
+class SkShader;
+
namespace android {
namespace uirenderer {
@@ -59,7 +60,6 @@
class RenderNode;
class TextSetupFunctor;
class VertexBuffer;
-class SkiaShader;
struct DrawModifiers {
DrawModifiers() {
@@ -70,7 +70,6 @@
memset(this, 0, sizeof(DrawModifiers));
}
- SkiaShader* mShader;
float mOverrideLayerAlpha;
// Draw filters
@@ -217,9 +216,6 @@
status_t drawShadow(const mat4& casterTransformXY, const mat4& casterTransformZ,
float casterAlpha, bool casterUnclipped, const SkPath* casterPerimeter);
- virtual void resetShader();
- virtual void setupShader(SkiaShader* shader);
-
virtual void resetPaintFilter();
virtual void setupPaintFilter(int clearBits, int setBits);
@@ -467,6 +463,14 @@
}
/**
+ * Safely retrieves the Shader from the given Paint. If the paint is
+ * null then null is returned.
+ */
+ static inline const SkShader* getShader(const SkPaint* paint) {
+ return paint ? paint->getShader() : NULL;
+ }
+
+ /**
* Set to true to suppress error checks at the end of a frame.
*/
virtual bool suppressErrorChecks() const {
@@ -838,7 +842,7 @@
void setupDrawColor(float r, float g, float b, float a);
void setupDrawAlpha8Color(int color, int alpha);
void setupDrawTextGamma(const SkPaint* paint);
- void setupDrawShader();
+ void setupDrawShader(const SkShader* shader);
void setupDrawColorFilter(const SkColorFilter* filter);
void setupDrawBlending(const Layer* layer, bool swapSrcDst = false);
void setupDrawBlending(const SkPaint* paint, bool blend = true, bool swapSrcDst = false);
@@ -862,9 +866,17 @@
*/
void setupDrawModelView(ModelViewMode mode, bool offset,
float left, float top, float right, float bottom, bool ignoreTransform = false);
- void setupDrawColorUniforms();
+ void setupDrawColorUniforms(bool hasShader);
void setupDrawPureColorUniforms();
- void setupDrawShaderUniforms(bool ignoreTransform = false);
+
+ /**
+ * Setup uniforms for the current shader.
+ *
+ * @param shader SkShader on the current paint.
+ *
+ * @param ignoreTransform Set to true to ignore the transform in shader.
+ */
+ void setupDrawShaderUniforms(const SkShader* shader, bool ignoreTransform = false);
void setupDrawColorFilterUniforms(const SkColorFilter* paint);
void setupDrawSimpleMesh();
void setupDrawTexture(GLuint texture);
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index e191a26..23cab0e 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -35,7 +35,6 @@
class Layer;
class Matrix4;
class SkiaColorFilter;
-class SkiaShader;
class Patch;
enum DrawOpMode {
@@ -183,9 +182,6 @@
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0;
// Misc - should be implemented with SkPaint inspection
- virtual void resetShader() = 0;
- virtual void setupShader(SkiaShader* shader) = 0;
-
virtual void resetPaintFilter() = 0;
virtual void setupPaintFilter(int clearBits, int setBits) = 0;
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 13a3e8e..8b553d1 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -71,11 +71,6 @@
incrementRefcount((void*) pathResource, kPath);
}
-void ResourceCache::incrementRefcount(SkiaShader* shaderResource) {
- SkSafeRef(shaderResource->getSkShader());
- incrementRefcount((void*) shaderResource, kShader);
-}
-
void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) {
incrementRefcount((void*) patchResource, kNinePatch);
}
@@ -104,11 +99,6 @@
incrementRefcountLocked((void*) pathResource, kPath);
}
-void ResourceCache::incrementRefcountLocked(SkiaShader* shaderResource) {
- SkSafeRef(shaderResource->getSkShader());
- incrementRefcountLocked((void*) shaderResource, kShader);
-}
-
void ResourceCache::incrementRefcountLocked(const Res_png_9patch* patchResource) {
incrementRefcountLocked((void*) patchResource, kNinePatch);
}
@@ -132,11 +122,6 @@
decrementRefcount((void*) pathResource);
}
-void ResourceCache::decrementRefcount(SkiaShader* shaderResource) {
- SkSafeUnref(shaderResource->getSkShader());
- decrementRefcount((void*) shaderResource);
-}
-
void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) {
decrementRefcount((void*) patchResource);
}
@@ -168,11 +153,6 @@
decrementRefcountLocked((void*) pathResource);
}
-void ResourceCache::decrementRefcountLocked(SkiaShader* shaderResource) {
- SkSafeUnref(shaderResource->getSkShader());
- decrementRefcountLocked((void*) shaderResource);
-}
-
void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) {
decrementRefcountLocked((void*) patchResource);
}
@@ -227,25 +207,6 @@
}
}
-void ResourceCache::destructor(SkiaShader* resource) {
- Mutex::Autolock _l(mLock);
- destructorLocked(resource);
-}
-
-void ResourceCache::destructorLocked(SkiaShader* resource) {
- ssize_t index = mCache->indexOfKey(resource);
- ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL;
- if (ref == NULL) {
- // If we're not tracking this resource, just delete it
- delete resource;
- return;
- }
- ref->destroyed = true;
- if (ref->refCount == 0) {
- deleteResourceReferenceLocked(resource, ref);
- }
-}
-
void ResourceCache::destructor(Res_png_9patch* resource) {
Mutex::Autolock _l(mLock);
destructorLocked(resource);
@@ -333,11 +294,6 @@
}
}
break;
- case kShader: {
- SkiaShader* shader = (SkiaShader*) resource;
- delete shader;
- }
- break;
case kNinePatch: {
if (Caches::hasInstance()) {
Caches::getInstance().patchCache.removeDeferred((Res_png_9patch*) resource);
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 4097ba4..3864d4b 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -20,7 +20,6 @@
#include <cutils/compiler.h>
#include <SkBitmap.h>
-#include <SkiaShader.h>
#include <utils/KeyedVector.h>
@@ -36,7 +35,6 @@
*/
enum ResourceType {
kBitmap,
- kShader,
kNinePatch,
kPath,
kLayer
@@ -70,36 +68,30 @@
void incrementRefcount(const SkPath* resource);
void incrementRefcount(const SkBitmap* resource);
- void incrementRefcount(SkiaShader* resource);
void incrementRefcount(const Res_png_9patch* resource);
void incrementRefcount(Layer* resource);
void incrementRefcountLocked(const SkPath* resource);
void incrementRefcountLocked(const SkBitmap* resource);
- void incrementRefcountLocked(SkiaShader* resource);
void incrementRefcountLocked(const Res_png_9patch* resource);
void incrementRefcountLocked(Layer* resource);
void decrementRefcount(const SkBitmap* resource);
void decrementRefcount(const SkPath* resource);
- void decrementRefcount(SkiaShader* resource);
void decrementRefcount(const Res_png_9patch* resource);
void decrementRefcount(Layer* resource);
void decrementRefcountLocked(const SkBitmap* resource);
void decrementRefcountLocked(const SkPath* resource);
- void decrementRefcountLocked(SkiaShader* resource);
void decrementRefcountLocked(const Res_png_9patch* resource);
void decrementRefcountLocked(Layer* resource);
void destructor(SkPath* resource);
void destructor(const SkBitmap* resource);
- void destructor(SkiaShader* resource);
void destructor(Res_png_9patch* resource);
void destructorLocked(SkPath* resource);
void destructorLocked(const SkBitmap* resource);
- void destructorLocked(SkiaShader* resource);
void destructorLocked(Res_png_9patch* resource);
bool recycle(SkBitmap* resource);
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 6a4a0c8..c672bc4 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -21,9 +21,10 @@
#include <SkMatrix.h>
#include "Caches.h"
+#include "Layer.h"
+#include "Matrix.h"
#include "SkiaShader.h"
#include "Texture.h"
-#include "Matrix.h"
namespace android {
namespace uirenderer {
@@ -54,89 +55,142 @@
a);
}
-///////////////////////////////////////////////////////////////////////////////
-// Base shader
-///////////////////////////////////////////////////////////////////////////////
-
-void SkiaShader::copyFrom(const SkiaShader& shader) {
- mType = shader.mType;
- mKey = shader.mKey;
- mTileX = shader.mTileX;
- mTileY = shader.mTileY;
- mBlend = shader.mBlend;
- mUnitMatrix = shader.mUnitMatrix;
- mShaderMatrix = shader.mShaderMatrix;
- mGenerationId = shader.mGenerationId;
-}
-
-SkiaShader::SkiaShader(): mCaches(NULL) {
-}
-
-SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
- SkShader::TileMode tileY, const SkMatrix* matrix, bool blend):
- mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend),
- mCaches(NULL) {
- setMatrix(matrix);
- mGenerationId = 0;
-}
-
-SkiaShader::~SkiaShader() {
-}
-
-void SkiaShader::describe(ProgramDescription& description, const Extensions& extensions) {
-}
-
-void SkiaShader::setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit) {
-}
-
-void SkiaShader::bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT) {
- mCaches->bindTexture(texture->id);
+static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) {
+ caches->bindTexture(texture->id);
texture->setWrapST(wrapS, wrapT);
}
-void SkiaShader::computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView) {
- screenSpace.loadMultiply(mUnitMatrix, mShaderMatrix);
- screenSpace.multiply(modelView);
+/**
+ * Compute the matrix to transform to screen space.
+ * @param screenSpace Output param for the computed matrix.
+ * @param unitMatrix The unit matrix for gradient shaders, as returned by SkShader::asAGradient,
+ * or identity.
+ * @param localMatrix Local matrix, as returned by SkShader::getLocalMatrix().
+ * @param modelViewMatrix Model view matrix, as supplied by the OpenGLRenderer.
+ */
+static void computeScreenSpaceMatrix(mat4& screenSpace, const SkMatrix& unitMatrix,
+ const SkMatrix& localMatrix, const mat4& modelViewMatrix) {
+ mat4 shaderMatrix;
+ // uses implicit construction
+ shaderMatrix.loadInverse(localMatrix);
+ // again, uses implicit construction
+ screenSpace.loadMultiply(unitMatrix, shaderMatrix);
+ screenSpace.multiply(modelViewMatrix);
+}
+
+// Returns true if one is a bitmap and the other is a gradient
+static bool bitmapAndGradient(SkiaShaderType type1, SkiaShaderType type2) {
+ return (type1 == kBitmap_SkiaShaderType && type2 == kGradient_SkiaShaderType)
+ || (type2 == kBitmap_SkiaShaderType && type1 == kGradient_SkiaShaderType);
+}
+
+SkiaShaderType SkiaShader::getType(const SkShader& shader) {
+ // First check for a gradient shader.
+ switch (shader.asAGradient(NULL)) {
+ case SkShader::kNone_GradientType:
+ // Not a gradient shader. Fall through to check for other types.
+ break;
+ case SkShader::kLinear_GradientType:
+ case SkShader::kRadial_GradientType:
+ case SkShader::kSweep_GradientType:
+ return kGradient_SkiaShaderType;
+ default:
+ // This is a Skia gradient that has no SkiaShader equivalent. Return None to skip.
+ return kNone_SkiaShaderType;
+ }
+
+ // The shader is not a gradient. Check for a bitmap shader.
+ if (shader.asABitmap(NULL, NULL, NULL) == SkShader::kDefault_BitmapType) {
+ return kBitmap_SkiaShaderType;
+ }
+
+ // Check for a ComposeShader.
+ SkShader::ComposeRec rec;
+ if (shader.asACompose(&rec)) {
+ const SkiaShaderType shaderAType = getType(*rec.fShaderA);
+ const SkiaShaderType shaderBType = getType(*rec.fShaderB);
+
+ // Compose is only supported if one is a bitmap and the other is a
+ // gradient. Otherwise, return None to skip.
+ if (!bitmapAndGradient(shaderAType, shaderBType)) {
+ return kNone_SkiaShaderType;
+ }
+ return kCompose_SkiaShaderType;
+ }
+
+ if (shader.asACustomShader(NULL)) {
+ return kLayer_SkiaShaderType;
+ }
+
+ return kNone_SkiaShaderType;
+}
+
+typedef void (*describeProc)(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+
+describeProc gDescribeProc[] = {
+ InvalidSkiaShader::describe,
+ SkiaBitmapShader::describe,
+ SkiaGradientShader::describe,
+ SkiaComposeShader::describe,
+ SkiaLayerShader::describe,
+};
+
+typedef void (*setupProgramProc)(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+
+setupProgramProc gSetupProgramProc[] = {
+ InvalidSkiaShader::setupProgram,
+ SkiaBitmapShader::setupProgram,
+ SkiaGradientShader::setupProgram,
+ SkiaComposeShader::setupProgram,
+ SkiaLayerShader::setupProgram,
+};
+
+void SkiaShader::describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ gDescribeProc[getType(shader)](caches, description, extensions, shader);
+}
+
+void SkiaShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+
+ gSetupProgramProc[getType(shader)](caches, modelViewMatrix, textureUnit, extensions, shader);
}
///////////////////////////////////////////////////////////////////////////////
// Layer shader
///////////////////////////////////////////////////////////////////////////////
-SkiaLayerShader::SkiaLayerShader(Layer* layer, const SkMatrix* matrix):
- SkiaShader(kBitmap, NULL, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
- matrix, layer->isBlend()), mLayer(layer) {
- updateLocalMatrix(matrix);
-}
-
-SkiaShader* SkiaLayerShader::copy() {
- SkiaLayerShader* copy = new SkiaLayerShader();
- copy->copyFrom(*this);
- copy->mLayer = mLayer;
- return copy;
-}
-
-void SkiaLayerShader::describe(ProgramDescription& description, const Extensions& extensions) {
+void SkiaLayerShader::describe(Caches*, ProgramDescription& description,
+ const Extensions&, const SkShader& shader) {
description.hasBitmap = true;
}
-void SkiaLayerShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot& snapshot, GLuint* textureUnit) {
- GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().activeTexture(textureSlot);
+void SkiaLayerShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions&, const SkShader& shader) {
+ Layer* layer;
+ if (!shader.asACustomShader(reinterpret_cast<void**>(&layer))) {
+ LOG_ALWAYS_FATAL("SkiaLayerShader::setupProgram called on the wrong type of shader!");
+ }
- const float width = mLayer->getWidth();
- const float height = mLayer->getHeight();
+ GLuint textureSlot = (*textureUnit)++;
+ caches->activeTexture(textureSlot);
+
+ const float width = layer->getWidth();
+ const float height = layer->getHeight();
mat4 textureTransform;
- computeScreenSpaceMatrix(textureTransform, modelView);
+ computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
+
// Uniforms
- mLayer->bindTexture();
- mLayer->setWrap(GL_CLAMP_TO_EDGE);
- mLayer->setFilter(GL_LINEAR);
+ layer->bindTexture();
+ layer->setWrap(GL_CLAMP_TO_EDGE);
+ layer->setFilter(GL_LINEAR);
+ Program* program = caches->currentProgram;
glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
GL_FALSE, &textureTransform.data[0]);
@@ -147,67 +201,99 @@
// Bitmap shader
///////////////////////////////////////////////////////////////////////////////
-SkiaBitmapShader::SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
- SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
- SkiaShader(kBitmap, key, tileX, tileY, matrix, blend), mBitmap(bitmap), mTexture(NULL) {
- updateLocalMatrix(matrix);
-}
+struct BitmapShaderInfo {
+ float width;
+ float height;
+ GLenum wrapS;
+ GLenum wrapT;
+ Texture* texture;
+};
-SkiaShader* SkiaBitmapShader::copy() {
- SkiaBitmapShader* copy = new SkiaBitmapShader();
- copy->copyFrom(*this);
- copy->mBitmap = mBitmap;
- return copy;
-}
-
-void SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
- Texture* texture = mCaches->textureCache.get(mBitmap);
- if (!texture) return;
- mTexture = texture;
+static bool bitmapShaderHelper(Caches* caches, ProgramDescription* description,
+ BitmapShaderInfo* shaderInfo,
+ const Extensions& extensions,
+ const SkBitmap& bitmap, SkShader::TileMode tileModes[2]) {
+ Texture* texture = caches->textureCache.get(&bitmap);
+ if (!texture) return false;
const float width = texture->width;
const float height = texture->height;
+ GLenum wrapS, wrapT;
- description.hasBitmap = true;
+ if (description) {
+ description->hasBitmap = true;
+ }
// The driver does not support non-power of two mirrored/repeated
// textures, so do it ourselves
if (!extensions.hasNPot() && (!isPowerOfTwo(width) || !isPowerOfTwo(height)) &&
- (mTileX != SkShader::kClamp_TileMode || mTileY != SkShader::kClamp_TileMode)) {
- description.isBitmapNpot = true;
- description.bitmapWrapS = gTileModes[mTileX];
- description.bitmapWrapT = gTileModes[mTileY];
- mWrapS = GL_CLAMP_TO_EDGE;
- mWrapT = GL_CLAMP_TO_EDGE;
+ (tileModes[0] != SkShader::kClamp_TileMode ||
+ tileModes[1] != SkShader::kClamp_TileMode)) {
+ if (description) {
+ description->isBitmapNpot = true;
+ description->bitmapWrapS = gTileModes[tileModes[0]];
+ description->bitmapWrapT = gTileModes[tileModes[1]];
+ }
+ wrapS = GL_CLAMP_TO_EDGE;
+ wrapT = GL_CLAMP_TO_EDGE;
} else {
- mWrapS = gTileModes[mTileX];
- mWrapT = gTileModes[mTileY];
+ wrapS = gTileModes[tileModes[0]];
+ wrapT = gTileModes[tileModes[1]];
}
+
+ if (shaderInfo) {
+ shaderInfo->width = width;
+ shaderInfo->height = height;
+ shaderInfo->wrapS = wrapS;
+ shaderInfo->wrapT = wrapT;
+ shaderInfo->texture = texture;
+ }
+ return true;
}
-void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot&, GLuint* textureUnit) {
+void SkiaBitmapShader::describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ SkBitmap bitmap;
+ SkShader::TileMode xy[2];
+ if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
+ LOG_ALWAYS_FATAL("SkiaBitmapShader::describe called with a different kind of shader!");
+ }
+ bitmapShaderHelper(caches, &description, NULL, extensions, bitmap, xy);
+}
+
+void SkiaBitmapShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+ SkBitmap bitmap;
+ SkShader::TileMode xy[2];
+ if (shader.asABitmap(&bitmap, NULL, xy) != SkShader::kDefault_BitmapType) {
+ LOG_ALWAYS_FATAL("SkiaBitmapShader::setupProgram called with a different kind of shader!");
+ }
+
GLuint textureSlot = (*textureUnit)++;
Caches::getInstance().activeTexture(textureSlot);
- Texture* texture = mTexture;
- mTexture = NULL;
- if (!texture) return;
+ BitmapShaderInfo shaderInfo;
+ if (!bitmapShaderHelper(caches, NULL, &shaderInfo, extensions, bitmap, xy)) {
+ return;
+ }
+
+ Program* program = caches->currentProgram;
+ Texture* texture = shaderInfo.texture;
+
const AutoTexture autoCleanup(texture);
- const float width = texture->width;
- const float height = texture->height;
-
mat4 textureTransform;
- computeScreenSpaceMatrix(textureTransform, modelView);
+ computeScreenSpaceMatrix(textureTransform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
// Uniforms
- bindTexture(texture, mWrapS, mWrapT);
+ bindTexture(caches, texture, shaderInfo.wrapS, shaderInfo.wrapT);
texture->setFilter(GL_LINEAR);
glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
GL_FALSE, &textureTransform.data[0]);
- glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
+ glUniform2f(program->getUniform("textureDimension"), 1.0f / shaderInfo.width,
+ 1.0f / shaderInfo.height);
}
///////////////////////////////////////////////////////////////////////////////
@@ -225,74 +311,6 @@
matrix->postScale(inv, inv);
}
-SkiaLinearGradientShader::SkiaLinearGradientShader(float* bounds, uint32_t* colors,
- float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
- SkMatrix* matrix, bool blend):
- SkiaShader(kLinearGradient, key, tileMode, tileMode, matrix, blend),
- mBounds(bounds), mColors(colors), mPositions(positions), mCount(count) {
- SkPoint points[2];
- points[0].set(bounds[0], bounds[1]);
- points[1].set(bounds[2], bounds[3]);
-
- SkMatrix unitMatrix;
- toUnitMatrix(points, &unitMatrix);
- mUnitMatrix.load(unitMatrix);
-
- updateLocalMatrix(matrix);
-
- mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
-}
-
-SkiaLinearGradientShader::~SkiaLinearGradientShader() {
- delete[] mBounds;
- delete[] mColors;
- delete[] mPositions;
-}
-
-SkiaShader* SkiaLinearGradientShader::copy() {
- SkiaLinearGradientShader* copy = new SkiaLinearGradientShader();
- copy->copyFrom(*this);
- copy->mBounds = new float[4];
- memcpy(copy->mBounds, mBounds, sizeof(float) * 4);
- copy->mColors = new uint32_t[mCount];
- memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
- copy->mPositions = new float[mCount];
- memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
- copy->mCount = mCount;
- copy->mIsSimple = mIsSimple;
- return copy;
-}
-
-void SkiaLinearGradientShader::describe(ProgramDescription& description,
- const Extensions& extensions) {
- description.hasGradient = true;
- description.gradientType = ProgramDescription::kGradientLinear;
- description.isSimpleGradient = mIsSimple;
-}
-
-void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot&, GLuint* textureUnit) {
- if (CC_UNLIKELY(!mIsSimple)) {
- GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().activeTexture(textureSlot);
-
- Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);
-
- // Uniforms
- bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
- glUniform1i(program->getUniform("gradientSampler"), textureSlot);
- } else {
- bindUniformColor(program->getUniform("startColor"), mColors[0]);
- bindUniformColor(program->getUniform("endColor"), mColors[1]);
- }
-
- Caches::getInstance().dither.setupProgram(program, textureUnit);
-
- mat4 screenSpace;
- computeScreenSpaceMatrix(screenSpace, modelView);
- glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
-}
-
///////////////////////////////////////////////////////////////////////////////
// Circular gradient shader
///////////////////////////////////////////////////////////////////////////////
@@ -304,37 +322,6 @@
matrix->postScale(inv, inv);
}
-SkiaCircularGradientShader::SkiaCircularGradientShader(float x, float y, float radius,
- uint32_t* colors, float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
- SkMatrix* matrix, bool blend):
- SkiaSweepGradientShader(kCircularGradient, colors, positions, count, key,
- tileMode, matrix, blend) {
- SkMatrix unitMatrix;
- toCircularUnitMatrix(x, y, radius, &unitMatrix);
- mUnitMatrix.load(unitMatrix);
-
- updateLocalMatrix(matrix);
-}
-
-SkiaShader* SkiaCircularGradientShader::copy() {
- SkiaCircularGradientShader* copy = new SkiaCircularGradientShader();
- copy->copyFrom(*this);
- copy->mColors = new uint32_t[mCount];
- memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
- copy->mPositions = new float[mCount];
- memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
- copy->mCount = mCount;
- copy->mIsSimple = mIsSimple;
- return copy;
-}
-
-void SkiaCircularGradientShader::describe(ProgramDescription& description,
- const Extensions& extensions) {
- description.hasGradient = true;
- description.gradientType = ProgramDescription::kGradientCircular;
- description.isSimpleGradient = mIsSimple;
-}
-
///////////////////////////////////////////////////////////////////////////////
// Sweep gradient shader
///////////////////////////////////////////////////////////////////////////////
@@ -343,74 +330,103 @@
matrix->setTranslate(-x, -y);
}
-SkiaSweepGradientShader::SkiaSweepGradientShader(float x, float y, uint32_t* colors,
- float* positions, int count, SkShader* key, SkMatrix* matrix, bool blend):
- SkiaShader(kSweepGradient, key, SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode, matrix, blend),
- mColors(colors), mPositions(positions), mCount(count) {
- SkMatrix unitMatrix;
- toSweepUnitMatrix(x, y, &unitMatrix);
- mUnitMatrix.load(unitMatrix);
+///////////////////////////////////////////////////////////////////////////////
+// Common gradient code
+///////////////////////////////////////////////////////////////////////////////
- updateLocalMatrix(matrix);
-
- mIsSimple = count == 2;
+static bool isSimpleGradient(const SkShader::GradientInfo& gradInfo) {
+ return gradInfo.fColorCount == 2 && gradInfo.fTileMode == SkShader::kClamp_TileMode;
}
-SkiaSweepGradientShader::SkiaSweepGradientShader(Type type, uint32_t* colors,
- float* positions, int count, SkShader* key, SkShader::TileMode tileMode,
- SkMatrix* matrix, bool blend):
- SkiaShader(type, key, tileMode, tileMode, matrix, blend),
- mColors(colors), mPositions(positions), mCount(count) {
- // protected method, that doesn't setup mUnitMatrix - should be handled by subclass
+void SkiaGradientShader::describe(Caches*, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ SkShader::GradientInfo gradInfo;
+ gradInfo.fColorCount = 0;
+ gradInfo.fColors = NULL;
+ gradInfo.fColorOffsets = NULL;
- mIsSimple = count == 2 && tileMode == SkShader::kClamp_TileMode;
-}
-
-SkiaSweepGradientShader::~SkiaSweepGradientShader() {
- delete[] mColors;
- delete[] mPositions;
-}
-
-SkiaShader* SkiaSweepGradientShader::copy() {
- SkiaSweepGradientShader* copy = new SkiaSweepGradientShader();
- copy->copyFrom(*this);
- copy->mColors = new uint32_t[mCount];
- memcpy(copy->mColors, mColors, sizeof(uint32_t) * mCount);
- copy->mPositions = new float[mCount];
- memcpy(copy->mPositions, mPositions, sizeof(float) * mCount);
- copy->mCount = mCount;
- copy->mIsSimple = mIsSimple;
- return copy;
-}
-
-void SkiaSweepGradientShader::describe(ProgramDescription& description,
- const Extensions& extensions) {
+ switch (shader.asAGradient(&gradInfo)) {
+ case SkShader::kLinear_GradientType:
+ description.gradientType = ProgramDescription::kGradientLinear;
+ break;
+ case SkShader::kRadial_GradientType:
+ description.gradientType = ProgramDescription::kGradientCircular;
+ break;
+ case SkShader::kSweep_GradientType:
+ description.gradientType = ProgramDescription::kGradientSweep;
+ break;
+ default:
+ // Do nothing. This shader is unsupported.
+ return;
+ }
description.hasGradient = true;
- description.gradientType = ProgramDescription::kGradientSweep;
- description.isSimpleGradient = mIsSimple;
+ description.isSimpleGradient = isSimpleGradient(gradInfo);
}
-void SkiaSweepGradientShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot& snapshot, GLuint* textureUnit) {
- if (CC_UNLIKELY(!mIsSimple)) {
- GLuint textureSlot = (*textureUnit)++;
- Caches::getInstance().activeTexture(textureSlot);
+void SkiaGradientShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions&, const SkShader& shader) {
+ // SkShader::GradientInfo.fColorCount is an in/out parameter. As input, it tells asAGradient
+ // how much space has been allocated for fColors and fColorOffsets. 10 was chosen
+ // arbitrarily, but should be >= 2.
+ // As output, it tells the number of actual colors/offsets in the gradient.
+ const int COLOR_COUNT = 10;
+ SkAutoSTMalloc<COLOR_COUNT, SkColor> colorStorage(COLOR_COUNT);
+ SkAutoSTMalloc<COLOR_COUNT, SkScalar> positionStorage(COLOR_COUNT);
- Texture* texture = mCaches->gradientCache.get(mColors, mPositions, mCount);
+ SkShader::GradientInfo gradInfo;
+ gradInfo.fColorCount = COLOR_COUNT;
+ gradInfo.fColors = colorStorage.get();
+ gradInfo.fColorOffsets = positionStorage.get();
+
+ SkShader::GradientType gradType = shader.asAGradient(&gradInfo);
+
+ Program* program = caches->currentProgram;
+ if (CC_UNLIKELY(!isSimpleGradient(gradInfo))) {
+ if (gradInfo.fColorCount > COLOR_COUNT) {
+ // There was not enough room in our arrays for all the colors and offsets. Try again,
+ // now that we know the true number of colors.
+ gradInfo.fColors = colorStorage.reset(gradInfo.fColorCount);
+ gradInfo.fColorOffsets = positionStorage.reset(gradInfo.fColorCount);
+
+ shader.asAGradient(&gradInfo);
+ }
+ GLuint textureSlot = (*textureUnit)++;
+ caches->activeTexture(textureSlot);
+
+#ifndef SK_SCALAR_IS_FLOAT
+ #error Need to convert gradInfo.fColorOffsets to float!
+#endif
+ Texture* texture = caches->gradientCache.get(gradInfo.fColors, gradInfo.fColorOffsets,
+ gradInfo.fColorCount);
// Uniforms
- bindTexture(texture, gTileModes[mTileX], gTileModes[mTileY]);
+ bindTexture(caches, texture, gTileModes[gradInfo.fTileMode], gTileModes[gradInfo.fTileMode]);
glUniform1i(program->getUniform("gradientSampler"), textureSlot);
} else {
- bindUniformColor(program->getUniform("startColor"), mColors[0]);
- bindUniformColor(program->getUniform("endColor"), mColors[1]);
+ bindUniformColor(program->getUniform("startColor"), gradInfo.fColors[0]);
+ bindUniformColor(program->getUniform("endColor"), gradInfo.fColors[1]);
}
- mCaches->dither.setupProgram(program, textureUnit);
+ caches->dither.setupProgram(program, textureUnit);
+
+ SkMatrix unitMatrix;
+ switch (gradType) {
+ case SkShader::kLinear_GradientType:
+ toUnitMatrix(gradInfo.fPoint, &unitMatrix);
+ break;
+ case SkShader::kRadial_GradientType:
+ toCircularUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY,
+ gradInfo.fRadius[0], &unitMatrix);
+ break;
+ case SkShader::kSweep_GradientType:
+ toSweepUnitMatrix(gradInfo.fPoint[0].fX, gradInfo.fPoint[0].fY, &unitMatrix);
+ break;
+ default:
+ LOG_ALWAYS_FATAL("Invalid SkShader gradient type %d", gradType);
+ }
mat4 screenSpace;
- computeScreenSpaceMatrix(screenSpace, modelView);
+ computeScreenSpaceMatrix(screenSpace, unitMatrix, shader.getLocalMatrix(), modelViewMatrix);
glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]);
}
@@ -418,49 +434,39 @@
// Compose shader
///////////////////////////////////////////////////////////////////////////////
-SkiaComposeShader::SkiaComposeShader(SkiaShader* first, SkiaShader* second,
- SkXfermode::Mode mode, SkShader* key):
- SkiaShader(kCompose, key, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
- NULL, first->blend() || second->blend()),
- mFirst(first), mSecond(second), mMode(mode), mCleanup(false) {
-}
-
-SkiaComposeShader::~SkiaComposeShader() {
- if (mCleanup) {
- delete mFirst;
- delete mSecond;
+void SkiaComposeShader::describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ SkShader::ComposeRec rec;
+ if (!shader.asACompose(&rec)) {
+ LOG_ALWAYS_FATAL("SkiaComposeShader::describe called on the wrong shader type!");
}
-}
-
-SkiaShader* SkiaComposeShader::copy() {
- SkiaComposeShader* copy = new SkiaComposeShader();
- copy->copyFrom(*this);
- copy->mFirst = mFirst->copy();
- copy->mSecond = mSecond->copy();
- copy->mMode = mMode;
- copy->cleanup();
- return copy;
-}
-
-void SkiaComposeShader::describe(ProgramDescription& description, const Extensions& extensions) {
- mFirst->describe(description, extensions);
- mSecond->describe(description, extensions);
- if (mFirst->type() == kBitmap) {
+ SkiaShader::describe(caches, description, extensions, *rec.fShaderA);
+ SkiaShader::describe(caches, description, extensions, *rec.fShaderB);
+ if (SkiaShader::getType(*rec.fShaderA) == kBitmap_SkiaShaderType) {
description.isBitmapFirst = true;
}
- description.shadersMode = mMode;
+ if (!SkXfermode::AsMode(rec.fMode, &description.shadersMode)) {
+ // TODO: Support other modes.
+ description.shadersMode = SkXfermode::kSrcOver_Mode;
+ }
}
-void SkiaComposeShader::setupProgram(Program* program, const mat4& modelView,
- const Snapshot& snapshot, GLuint* textureUnit) {
+void SkiaComposeShader::setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+ SkShader::ComposeRec rec;
+ if (!shader.asACompose(&rec)) {
+ LOG_ALWAYS_FATAL("SkiaComposeShader::setupProgram called on the wrong shader type!");
+ }
+
// Apply this compose shader's local transform and pass it down to
// the child shaders. They will in turn apply their local transform
// to this matrix.
mat4 transform;
- computeScreenSpaceMatrix(transform, modelView);
+ computeScreenSpaceMatrix(transform, SkMatrix::I(), shader.getLocalMatrix(),
+ modelViewMatrix);
- mFirst->setupProgram(program, transform, snapshot, textureUnit);
- mSecond->setupProgram(program, transform, snapshot, textureUnit);
+ SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderA);
+ SkiaShader::setupProgram(caches, transform, textureUnit, extensions, *rec.fShaderB);
}
}; // namespace uirenderer
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 9f30257..034c3f6 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -28,249 +28,90 @@
#include "ProgramCache.h"
#include "TextureCache.h"
#include "GradientCache.h"
-#include "Snapshot.h"
namespace android {
namespace uirenderer {
class Caches;
-
-///////////////////////////////////////////////////////////////////////////////
-// Base shader
-///////////////////////////////////////////////////////////////////////////////
+class Layer;
/**
- * Represents a Skia shader. A shader will modify the GL context and active
- * program to recreate the original effect.
+ * Type of Skia shader in use.
*/
+enum SkiaShaderType {
+ kNone_SkiaShaderType,
+ kBitmap_SkiaShaderType,
+ kGradient_SkiaShaderType,
+ kCompose_SkiaShaderType,
+ kLayer_SkiaShaderType
+};
+
class SkiaShader {
public:
- /**
- * Type of Skia shader in use.
- */
- enum Type {
- kNone,
- kBitmap,
- kLinearGradient,
- kCircularGradient,
- kSweepGradient,
- kCompose
- };
+ static SkiaShaderType getType(const SkShader& shader);
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+};
- ANDROID_API SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
- SkShader::TileMode tileY, const SkMatrix* matrix, bool blend);
- virtual ~SkiaShader();
-
- virtual SkiaShader* copy() = 0;
- void copyFrom(const SkiaShader& shader);
-
- virtual void describe(ProgramDescription& description, const Extensions& extensions);
- virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
- inline SkShader* getSkShader() {
- return mKey;
+class InvalidSkiaShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader) {
+ // This shader is unsupported. Skip it.
+ }
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader) {
+ // This shader is unsupported. Skip it.
}
- inline bool blend() const {
- return mBlend;
- }
-
- Type type() const {
- return mType;
- }
-
- virtual void setCaches(Caches& caches) {
- mCaches = &caches;
- }
-
- uint32_t getGenerationId() {
- return mGenerationId;
- }
-
- void setMatrix(const SkMatrix* matrix) {
- updateLocalMatrix(matrix);
- mGenerationId++;
- }
-
- void updateLocalMatrix(const SkMatrix* matrix) {
- if (matrix) {
- mat4 localMatrix(*matrix);
- mShaderMatrix.loadInverse(localMatrix);
- } else {
- mShaderMatrix.loadIdentity();
- }
- }
-
- void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView);
-
-protected:
- SkiaShader();
-
- /**
- * The appropriate texture unit must have been activated prior to invoking
- * this method.
- */
- inline void bindTexture(Texture* texture, GLenum wrapS, GLenum wrapT);
-
- Type mType;
- SkShader* mKey;
- SkShader::TileMode mTileX;
- SkShader::TileMode mTileY;
- bool mBlend;
-
- Caches* mCaches;
-
- mat4 mUnitMatrix;
- mat4 mShaderMatrix;
-
-private:
- uint32_t mGenerationId;
-}; // struct SkiaShader
-
-
-///////////////////////////////////////////////////////////////////////////////
-// Implementations
-///////////////////////////////////////////////////////////////////////////////
-
+};
/**
* A shader that draws a layer.
*/
-struct SkiaLayerShader: public SkiaShader {
- SkiaLayerShader(Layer* layer, const SkMatrix* matrix);
- SkiaShader* copy();
-
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
-private:
- SkiaLayerShader() {
- }
-
- Layer* mLayer;
-}; // struct SkiaLayerShader
+class SkiaLayerShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+}; // class SkiaLayerShader
/**
* A shader that draws a bitmap.
*/
-struct SkiaBitmapShader: public SkiaShader {
- ANDROID_API SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
- SkShader::TileMode tileY, SkMatrix* matrix, bool blend);
- SkiaShader* copy();
+class SkiaBitmapShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-private:
- SkiaBitmapShader() : mBitmap(NULL), mTexture(NULL) {
- }
-
- SkBitmap* mBitmap;
- Texture* mTexture;
- GLenum mWrapS;
- GLenum mWrapT;
-}; // struct SkiaBitmapShader
+}; // class SkiaBitmapShader
/**
- * A shader that draws a linear gradient.
+ * A shader that draws one of three types of gradient, depending on shader param.
*/
-struct SkiaLinearGradientShader: public SkiaShader {
- ANDROID_API SkiaLinearGradientShader(float* bounds, uint32_t* colors, float* positions,
- int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
- ~SkiaLinearGradientShader();
- SkiaShader* copy();
-
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
-private:
- SkiaLinearGradientShader() {
- }
-
- bool mIsSimple;
- float* mBounds;
- uint32_t* mColors;
- float* mPositions;
- int mCount;
-}; // struct SkiaLinearGradientShader
-
-/**
- * A shader that draws a sweep gradient.
- */
-struct SkiaSweepGradientShader: public SkiaShader {
- ANDROID_API SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions,
- int count, SkShader* key, SkMatrix* matrix, bool blend);
- ~SkiaSweepGradientShader();
- SkiaShader* copy();
-
- virtual void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
-protected:
- SkiaSweepGradientShader(Type type, uint32_t* colors, float* positions,
- int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
- SkiaSweepGradientShader() {
- }
-
- bool mIsSimple;
- uint32_t* mColors;
- float* mPositions;
- int mCount;
-}; // struct SkiaSweepGradientShader
-
-/**
- * A shader that draws a circular gradient.
- */
-struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
- ANDROID_API SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors,
- float* positions, int count, SkShader* key,SkShader::TileMode tileMode,
- SkMatrix* matrix, bool blend);
- SkiaShader* copy();
-
- void describe(ProgramDescription& description, const Extensions& extensions);
-
-private:
- SkiaCircularGradientShader() {
- }
-}; // struct SkiaCircularGradientShader
+class SkiaGradientShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+};
/**
* A shader that draws two shaders, composited with an xfermode.
*/
-struct SkiaComposeShader: public SkiaShader {
- ANDROID_API SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode,
- SkShader* key);
- ~SkiaComposeShader();
- SkiaShader* copy();
-
- void setCaches(Caches& caches) {
- SkiaShader::setCaches(caches);
- mFirst->setCaches(caches);
- mSecond->setCaches(caches);
- }
-
- void describe(ProgramDescription& description, const Extensions& extensions);
- void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
- GLuint* textureUnit);
-
-private:
- SkiaComposeShader(): mCleanup(false) {
- }
-
- void cleanup() {
- mCleanup = true;
- }
-
- SkiaShader* mFirst;
- SkiaShader* mSecond;
- SkXfermode::Mode mMode;
-
- bool mCleanup;
-}; // struct SkiaComposeShader
+class SkiaComposeShader {
+public:
+ static void describe(Caches* caches, ProgramDescription& description,
+ const Extensions& extensions, const SkShader& shader);
+ static void setupProgram(Caches* caches, const mat4& modelViewMatrix,
+ GLuint* textureUnit, const Extensions& extensions, const SkShader& shader);
+}; // class SkiaComposeShader
}; // namespace uirenderer
}; // namespace android
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 34e2265..60b4b96 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -34,7 +34,7 @@
///////////////////////////////////////////////////////////////////////////////
TextureCache::TextureCache():
- mCache(LruCache<const SkBitmap*, Texture*>::kUnlimitedCapacity),
+ mCache(LruCache<const SkPixelRef*, Texture*>::kUnlimitedCapacity),
mSize(0), mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) {
char property[PROPERTY_VALUE_MAX];
@@ -58,7 +58,7 @@
}
TextureCache::TextureCache(uint32_t maxByteSize):
- mCache(LruCache<const SkBitmap*, Texture*>::kUnlimitedCapacity),
+ mCache(LruCache<const SkPixelRef*, Texture*>::kUnlimitedCapacity),
mSize(0), mMaxSize(maxByteSize) {
init();
}
@@ -103,7 +103,7 @@
// Callbacks
///////////////////////////////////////////////////////////////////////////////
-void TextureCache::operator()(const SkBitmap*&, Texture*& texture) {
+void TextureCache::operator()(const SkPixelRef*&, Texture*& texture) {
// This will be called already locked
if (texture) {
mSize -= texture->bitmapSize;
@@ -122,7 +122,7 @@
///////////////////////////////////////////////////////////////////////////////
void TextureCache::resetMarkInUse() {
- LruCache<const SkBitmap*, Texture*>::Iterator iter(mCache);
+ LruCache<const SkPixelRef*, Texture*>::Iterator iter(mCache);
while (iter.next()) {
iter.value()->isInUse = false;
}
@@ -140,7 +140,7 @@
// Returns a prepared Texture* that either is already in the cache or can fit
// in the cache (and is thus added to the cache)
Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
- Texture* texture = mCache.get(bitmap);
+ Texture* texture = mCache.get(bitmap->pixelRef());
if (!texture) {
if (!canMakeTextureFromBitmap(bitmap)) {
@@ -170,7 +170,7 @@
if (mDebugEnabled) {
ALOGD("Texture created, size = %d", size);
}
- mCache.put(bitmap, texture);
+ mCache.put(bitmap->pixelRef(), texture);
}
} else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) {
// Texture was in the cache but is dirty, re-upload
@@ -218,7 +218,7 @@
}
void TextureCache::remove(const SkBitmap* bitmap) {
- mCache.remove(bitmap);
+ mCache.remove(bitmap->pixelRef());
}
void TextureCache::removeDeferred(const SkBitmap* bitmap) {
@@ -231,7 +231,7 @@
size_t count = mGarbage.size();
for (size_t i = 0; i < count; i++) {
const SkBitmap* bitmap = mGarbage.itemAt(i);
- mCache.remove(bitmap);
+ mCache.remove(bitmap->pixelRef());
delete bitmap;
}
mGarbage.clear();
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index 48a10c2..e5b5c1a 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -49,7 +49,7 @@
* Any texture added to the cache causing the cache to grow beyond the maximum
* allowed size will also cause the oldest texture to be kicked out.
*/
-class TextureCache: public OnEntryRemoved<const SkBitmap*, Texture*> {
+class TextureCache: public OnEntryRemoved<const SkPixelRef*, Texture*> {
public:
TextureCache();
TextureCache(uint32_t maxByteSize);
@@ -59,7 +59,7 @@
* Used as a callback when an entry is removed from the cache.
* Do not invoke directly.
*/
- void operator()(const SkBitmap*& bitmap, Texture*& texture);
+ void operator()(const SkPixelRef*& pixelRef, Texture*& texture);
/**
* Resets all Textures to not be marked as in use
@@ -147,7 +147,7 @@
void init();
- LruCache<const SkBitmap*, Texture*> mCache;
+ LruCache<const SkPixelRef*, Texture*> mCache;
uint32_t mSize;
uint32_t mMaxSize;
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index d4a23b8..8355f83 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -52,6 +52,7 @@
: hasFunctors(false)
, hasAnimations(false)
, requiresUiRedraw(false)
+ , canDrawThisFrame(true)
{}
bool hasFunctors;
// This is only updated if evaluateAnimations is true
@@ -60,6 +61,13 @@
// animate itself, such as if hasFunctors is true
// This is only set if hasAnimations is true
bool requiresUiRedraw;
+ // This is set to true if draw() can be called this frame
+ // false means that we must delay until the next vsync pulse as frame
+ // production is outrunning consumption
+ // NOTE that if this is false CanvasContext will set either requiresUiRedraw
+ // *OR* will post itself for the next vsync automatically, use this
+ // only to avoid calling draw()
+ bool canDrawThisFrame;
} out;
// TODO: Damage calculations
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 839ef91..b6b3428 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -360,7 +360,9 @@
setSurface(NULL);
}
-void CanvasContext::setSurface(EGLNativeWindowType window) {
+void CanvasContext::setSurface(ANativeWindow* window) {
+ mNativeWindow = window;
+
if (mEglSurface != EGL_NO_SURFACE) {
mGlobalContext->destroySurface(mEglSurface);
mEglSurface = EGL_NO_SURFACE;
@@ -393,7 +395,7 @@
makeCurrent();
}
-bool CanvasContext::initialize(EGLNativeWindowType window) {
+bool CanvasContext::initialize(ANativeWindow* window) {
if (mCanvas) return false;
setSurface(window);
mCanvas = new OpenGLRenderer();
@@ -401,11 +403,11 @@
return true;
}
-void CanvasContext::updateSurface(EGLNativeWindowType window) {
+void CanvasContext::updateSurface(ANativeWindow* window) {
setSurface(window);
}
-void CanvasContext::pauseSurface(EGLNativeWindowType window) {
+void CanvasContext::pauseSurface(ANativeWindow* window) {
// TODO: For now we just need a fence, in the future suspend any animations
// and such to prevent from trying to render into this surface
}
@@ -456,7 +458,15 @@
info.frameTimeMs = mRenderThread.timeLord().frameTimeMs();
mRootRenderNode->prepareTree(info);
- if (info.out.hasAnimations) {
+ int runningBehind = 0;
+ // TODO: This query is moderately expensive, investigate adding some sort
+ // of fast-path based off when we last called eglSwapBuffers() as well as
+ // last vsync time. Or something.
+ mNativeWindow->query(mNativeWindow.get(),
+ NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind);
+ info.out.canDrawThisFrame = !runningBehind;
+
+ if (info.out.hasAnimations || !info.out.canDrawThisFrame) {
if (info.out.hasFunctors) {
info.out.requiresUiRedraw = true;
} else if (!info.out.requiresUiRedraw) {
@@ -467,6 +477,11 @@
}
}
+void CanvasContext::notifyFramePending() {
+ ATRACE_CALL();
+ mRenderThread.pushBackFrameCallback(this);
+}
+
void CanvasContext::draw(Rect* dirty) {
LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
"drawDisplayList called on a context with no canvas or surface!");
@@ -515,7 +530,9 @@
info.prepareTextures = false;
prepareTree(info);
- draw(NULL);
+ if (info.out.canDrawThisFrame) {
+ draw(NULL);
+ }
}
void CanvasContext::invokeFunctor(Functor* functor) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 4232f27..a54b33e 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -48,9 +48,9 @@
CanvasContext(bool translucent, RenderNode* rootRenderNode);
virtual ~CanvasContext();
- bool initialize(EGLNativeWindowType window);
- void updateSurface(EGLNativeWindowType window);
- void pauseSurface(EGLNativeWindowType window);
+ bool initialize(ANativeWindow* window);
+ void updateSurface(ANativeWindow* window);
+ void pauseSurface(ANativeWindow* window);
void setup(int width, int height, const Vector3& lightCenter, float lightRadius);
void setOpaque(bool opaque);
void makeCurrent();
@@ -73,11 +73,15 @@
ANDROID_API static void setTextureAtlas(const sp<GraphicBuffer>& buffer,
int64_t* map, size_t mapSize);
+ void notifyFramePending();
+
private:
+ friend class RegisterFrameCallbackTask;
+
void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
void prepareTree(TreeInfo& info);
- void setSurface(EGLNativeWindowType window);
+ void setSurface(ANativeWindow* window);
void swapBuffers();
void requireSurface();
@@ -85,6 +89,7 @@
GlobalContext* mGlobalContext;
RenderThread& mRenderThread;
+ sp<ANativeWindow> mNativeWindow;
EGLSurface mEglSurface;
bool mDirtyRegionsEnabled;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 3b8786c..ee3e059 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -87,7 +87,13 @@
void DrawFrameTask::run() {
ATRACE_NAME("DrawFrame");
- bool canUnblockUiThread = syncFrameState();
+ bool canUnblockUiThread;
+ bool canDrawThisFrame;
+ {
+ TreeInfo info;
+ canUnblockUiThread = syncFrameState(info);
+ canDrawThisFrame = info.out.canDrawThisFrame;
+ }
// Grab a copy of everything we need
Rect dirty(mDirty);
@@ -98,7 +104,9 @@
unblockUiThread();
}
- context->draw(&dirty);
+ if (CC_LIKELY(canDrawThisFrame)) {
+ context->draw(&dirty);
+ }
if (!canUnblockUiThread) {
unblockUiThread();
@@ -111,12 +119,11 @@
info.evaluateAnimations = true;
}
-bool DrawFrameTask::syncFrameState() {
+bool DrawFrameTask::syncFrameState(TreeInfo& info) {
ATRACE_CALL();
mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos);
mContext->makeCurrent();
Caches::getInstance().textureCache.resetMarkInUse();
- TreeInfo info;
initTreeInfo(info);
mContext->prepareDraw(&mLayers, info);
if (info.out.hasAnimations) {
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index b9307e1..acbc02a 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -24,6 +24,7 @@
#include "RenderTask.h"
#include "../Rect.h"
+#include "../TreeInfo.h"
namespace android {
namespace uirenderer {
@@ -65,7 +66,7 @@
private:
void postAndWait();
- bool syncFrameState();
+ bool syncFrameState(TreeInfo& info);
void unblockUiThread();
Mutex mLock;
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index ef8e45b..2e103d8 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -112,7 +112,7 @@
return (bool) postAndWait(task);
}
-CREATE_BRIDGE2(initialize, CanvasContext* context, EGLNativeWindowType window) {
+CREATE_BRIDGE2(initialize, CanvasContext* context, ANativeWindow* window) {
return (void*) args->context->initialize(args->window);
}
@@ -123,7 +123,7 @@
return (bool) postAndWait(task);
}
-CREATE_BRIDGE2(updateSurface, CanvasContext* context, EGLNativeWindowType window) {
+CREATE_BRIDGE2(updateSurface, CanvasContext* context, ANativeWindow* window) {
args->context->updateSurface(args->window);
return NULL;
}
@@ -135,7 +135,7 @@
postAndWait(task);
}
-CREATE_BRIDGE2(pauseSurface, CanvasContext* context, EGLNativeWindowType window) {
+CREATE_BRIDGE2(pauseSurface, CanvasContext* context, ANativeWindow* window) {
args->context->pauseSurface(args->window);
return NULL;
}
@@ -292,6 +292,17 @@
postAndWait(task);
}
+CREATE_BRIDGE1(notifyFramePending, CanvasContext* context) {
+ args->context->notifyFramePending();
+ return NULL;
+}
+
+void RenderProxy::notifyFramePending() {
+ SETUP_TASK(notifyFramePending);
+ args->context = mContext;
+ mRenderThread.queueAtFront(task);
+}
+
void RenderProxy::post(RenderTask* task) {
mRenderThread.queue(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 4d3499e..8aeb264 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -82,6 +82,7 @@
ANDROID_API void destroyLayer(DeferredLayerUpdater* layer);
ANDROID_API void fence();
+ ANDROID_API void notifyFramePending();
private:
RenderThread& mRenderThread;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 35a3eab..4a4e254 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -37,7 +37,7 @@
static const size_t EVENT_BUFFER_SIZE = 100;
// Slight delay to give the UI time to push us a new frame before we replay
-static const int DISPATCH_FRAME_CALLBACKS_DELAY = 0;
+static const int DISPATCH_FRAME_CALLBACKS_DELAY = 4;
TaskQueue::TaskQueue() : mHead(0), mTail(0) {}
@@ -91,6 +91,15 @@
}
}
+void TaskQueue::queueAtFront(RenderTask* task) {
+ if (mTail) {
+ task->mNext = mHead;
+ mHead = task;
+ } else {
+ mTail = mHead = task;
+ }
+}
+
void TaskQueue::remove(RenderTask* task) {
// TaskQueue is strict here to enforce that users are keeping track of
// their RenderTasks due to how their memory is managed
@@ -188,20 +197,22 @@
return latest;
}
-void RenderThread::drainDisplayEventQueue() {
+void RenderThread::drainDisplayEventQueue(bool skipCallbacks) {
+ ATRACE_CALL();
nsecs_t vsyncEvent = latestVsyncEvent(mDisplayEventReceiver);
if (vsyncEvent > 0) {
mVsyncRequested = false;
mTimeLord.vsyncReceived(vsyncEvent);
- if (!mFrameCallbackTaskPending) {
+ if (!skipCallbacks && !mFrameCallbackTaskPending) {
+ ATRACE_NAME("queue mFrameCallbackTask");
mFrameCallbackTaskPending = true;
- //queueDelayed(mFrameCallbackTask, DISPATCH_FRAME_CALLBACKS_DELAY);
- queue(mFrameCallbackTask);
+ queueDelayed(mFrameCallbackTask, DISPATCH_FRAME_CALLBACKS_DELAY);
}
}
}
void RenderThread::dispatchFrameCallbacks() {
+ ATRACE_CALL();
mFrameCallbackTaskPending = false;
std::set<IFrameCallback*> callbacks;
@@ -212,6 +223,15 @@
}
}
+void RenderThread::requestVsync() {
+ if (!mVsyncRequested) {
+ mVsyncRequested = true;
+ status_t status = mDisplayEventReceiver->requestNextVsync();
+ LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
+ "requestNextVsync failed with status: %d", status);
+ }
+}
+
bool RenderThread::threadLoop() {
initializeDisplayEventReceiver();
@@ -236,6 +256,14 @@
timeoutMillis = 0;
}
}
+
+ if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
+ drainDisplayEventQueue(true);
+ mFrameCallbacks.insert(
+ mPendingRegistrationFrameCallbacks.begin(), mPendingRegistrationFrameCallbacks.end());
+ mPendingRegistrationFrameCallbacks.clear();
+ requestVsync();
+ }
}
return false;
@@ -250,6 +278,12 @@
}
}
+void RenderThread::queueAtFront(RenderTask* task) {
+ AutoMutex _lock(mLock);
+ mQueue.queueAtFront(task);
+ mLooper->wake();
+}
+
void RenderThread::queueDelayed(RenderTask* task, int delayMs) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
task->mRunAt = now + milliseconds_to_nanoseconds(delayMs);
@@ -262,17 +296,18 @@
}
void RenderThread::postFrameCallback(IFrameCallback* callback) {
- mFrameCallbacks.insert(callback);
- if (!mVsyncRequested) {
- mVsyncRequested = true;
- status_t status = mDisplayEventReceiver->requestNextVsync();
- LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
- "requestNextVsync failed with status: %d", status);
- }
+ mPendingRegistrationFrameCallbacks.insert(callback);
}
void RenderThread::removeFrameCallback(IFrameCallback* callback) {
mFrameCallbacks.erase(callback);
+ mPendingRegistrationFrameCallbacks.erase(callback);
+}
+
+void RenderThread::pushBackFrameCallback(IFrameCallback* callback) {
+ if (mFrameCallbacks.erase(callback)) {
+ mPendingRegistrationFrameCallbacks.insert(callback);
+ }
}
RenderTask* RenderThread::nextTask(nsecs_t* nextWakeup) {
@@ -281,11 +316,13 @@
if (!next) {
mNextWakeup = LLONG_MAX;
} else {
+ mNextWakeup = next->mRunAt;
// Most tasks won't be delayed, so avoid unnecessary systemTime() calls
if (next->mRunAt <= 0 || next->mRunAt <= systemTime(SYSTEM_TIME_MONOTONIC)) {
next = mQueue.next();
+ } else {
+ next = 0;
}
- mNextWakeup = next->mRunAt;
}
if (nextWakeup) {
*nextWakeup = mNextWakeup;
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 215d294..4412584 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -44,6 +44,7 @@
RenderTask* next();
void queue(RenderTask* task);
+ void queueAtFront(RenderTask* task);
RenderTask* peek();
void remove(RenderTask* task);
@@ -66,12 +67,16 @@
// RenderThread takes complete ownership of tasks that are queued
// and will delete them after they are run
ANDROID_API void queue(RenderTask* task);
+ ANDROID_API void queueAtFront(RenderTask* task);
void queueDelayed(RenderTask* task, int delayMs);
void remove(RenderTask* task);
// Mimics android.view.Choreographer
void postFrameCallback(IFrameCallback* callback);
void removeFrameCallback(IFrameCallback* callback);
+ // If the callback is currently registered, it will be pushed back until
+ // the next vsync. If it is not currently registered this does nothing.
+ void pushBackFrameCallback(IFrameCallback* callback);
TimeLord& timeLord() { return mTimeLord; }
@@ -87,8 +92,9 @@
void initializeDisplayEventReceiver();
static int displayEventReceiverCallback(int fd, int events, void* data);
- void drainDisplayEventQueue();
+ void drainDisplayEventQueue(bool skipCallbacks = false);
void dispatchFrameCallbacks();
+ void requestVsync();
// Returns the next task to be run. If this returns NULL nextWakeup is set
// to the time to requery for the nextTask to run. mNextWakeup is also
@@ -104,6 +110,11 @@
DisplayEventReceiver* mDisplayEventReceiver;
bool mVsyncRequested;
std::set<IFrameCallback*> mFrameCallbacks;
+ // We defer the actual registration of these callbacks until
+ // both mQueue *and* mDisplayEventReceiver have been drained off all
+ // immediate events. This makes sure that we catch the next vsync, not
+ // the previous one
+ std::set<IFrameCallback*> mPendingRegistrationFrameCallbacks;
bool mFrameCallbackTaskPending;
DispatchFrameCallbacks* mFrameCallbackTask;
diff --git a/media/java/android/media/DngCreator.java b/media/java/android/media/DngCreator.java
deleted file mode 100644
index 76c6d46..0000000
--- a/media/java/android/media/DngCreator.java
+++ /dev/null
@@ -1,368 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.media;
-
-import android.graphics.Bitmap;
-import android.graphics.ImageFormat;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CaptureResult;
-import android.hardware.camera2.impl.CameraMetadataNative;
-import android.location.Location;
-import android.util.Size;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.ByteBuffer;
-
-/**
- * The {@link DngCreator} class provides functions to write raw pixel data as a DNG file.
- *
- * <p>
- * This class is designed to be used with the {@link android.graphics.ImageFormat#RAW_SENSOR}
- * buffers available from {@link android.hardware.camera2.CameraDevice}, or with Bayer-type raw
- * pixel data that is otherwise generated by an application. The DNG metadata tags will be
- * generated from a {@link android.hardware.camera2.CaptureResult} object or set directly.
- * </p>
- *
- * <p>
- * The DNG file format is a cross-platform file format that is used to store pixel data from
- * camera sensors with minimal pre-processing applied. DNG files allow for pixel data to be
- * defined in a user-defined colorspace, and have associated metadata that allow for this
- * pixel data to be converted to the standard CIE XYZ colorspace during post-processing.
- * </p>
- *
- * <p>
- * For more information on the DNG file format and associated metadata, please refer to the
- * <a href=
- * "https://wwwimages2.adobe.com/content/dam/Adobe/en/products/photoshop/pdfs/dng_spec_1.4.0.0.pdf">
- * Adobe DNG 1.4.0.0 specification</a>.
- * </p>
- */
-public final class DngCreator implements AutoCloseable {
-
- /**
- * Create a new DNG object.
- *
- * <p>
- * It is not necessary to call any set methods to write a well-formatted DNG file.
- * </p>
- * <p>
- * DNG metadata tags will be generated from the corresponding parameters in the
- * {@link android.hardware.camera2.CaptureResult} object. This removes or overrides
- * all previous tags set.
- * </p>
- *
- * @param characteristics an object containing the static
- * {@link android.hardware.camera2.CameraCharacteristics}.
- * @param metadata a metadata object to generate tags from.
- */
- public DngCreator(CameraCharacteristics characteristics, CaptureResult metadata) {
- if (characteristics == null || metadata == null) {
- throw new NullPointerException("Null argument to DngCreator constructor");
- }
- nativeInit(characteristics.getNativeCopy(), metadata.getNativeCopy());
- }
-
- /**
- * Set the orientation value to write.
- *
- * <p>
- * This will be written as the TIFF "Orientation" tag {@code (0x0112)}.
- * Calling this will override any prior settings for this tag.
- * </p>
- *
- * @param orientation the orientation value to set, one of:
- * <ul>
- * <li>{@link android.media.ExifInterface#ORIENTATION_NORMAL}</li>
- * <li>{@link android.media.ExifInterface#ORIENTATION_FLIP_HORIZONTAL}</li>
- * <li>{@link android.media.ExifInterface#ORIENTATION_ROTATE_180}</li>
- * <li>{@link android.media.ExifInterface#ORIENTATION_FLIP_VERTICAL}</li>
- * <li>{@link android.media.ExifInterface#ORIENTATION_TRANSPOSE}</li>
- * <li>{@link android.media.ExifInterface#ORIENTATION_ROTATE_90}</li>
- * <li>{@link android.media.ExifInterface#ORIENTATION_TRANSVERSE}</li>
- * <li>{@link android.media.ExifInterface#ORIENTATION_ROTATE_270}</li>
- * </ul>
- * @return this {@link #DngCreator} object.
- */
- public DngCreator setOrientation(int orientation) {
-
- if (orientation < ExifInterface.ORIENTATION_UNDEFINED ||
- orientation > ExifInterface.ORIENTATION_ROTATE_270) {
- throw new IllegalArgumentException("Orientation " + orientation +
- " is not a valid EXIF orientation value");
- }
- nativeSetOrientation(orientation);
- return this;
- }
-
- /**
- * Set the thumbnail image.
- *
- * <p>
- * Pixel data will be converted to a Baseline TIFF RGB image, with 8 bits per color channel.
- * The alpha channel will be discarded.
- * </p>
- *
- * <p>
- * The given bitmap should not be altered while this object is in use.
- * </p>
- *
- * @param pixels a {@link android.graphics.Bitmap} of pixel data.
- * @return this {@link #DngCreator} object.
- */
- public DngCreator setThumbnail(Bitmap pixels) {
- if (pixels == null) {
- throw new NullPointerException("Null argument to setThumbnail");
- }
-
- Bitmap.Config config = pixels.getConfig();
-
- if (config != Bitmap.Config.ARGB_8888) {
- pixels = pixels.copy(Bitmap.Config.ARGB_8888, false);
- if (pixels == null) {
- throw new IllegalArgumentException("Unsupported Bitmap format " + config);
- }
- nativeSetThumbnailBitmap(pixels);
- }
-
- return this;
- }
-
- /**
- * Set the thumbnail image.
- *
- * <p>
- * Pixel data is interpreted as a {@link android.graphics.ImageFormat#YUV_420_888} image.
- * </p>
- *
- * <p>
- * The given image should not be altered while this object is in use.
- * </p>
- *
- * @param pixels an {@link android.media.Image} object with the format
- * {@link android.graphics.ImageFormat#YUV_420_888}.
- * @return this {@link #DngCreator} object.
- */
- public DngCreator setThumbnail(Image pixels) {
- if (pixels == null) {
- throw new NullPointerException("Null argument to setThumbnail");
- }
-
- int format = pixels.getFormat();
- if (format != ImageFormat.YUV_420_888) {
- throw new IllegalArgumentException("Unsupported image format " + format);
- }
-
- Image.Plane[] planes = pixels.getPlanes();
- nativeSetThumbnailImage(pixels.getWidth(), pixels.getHeight(), planes[0].getBuffer(),
- planes[0].getRowStride(), planes[0].getPixelStride(), planes[1].getBuffer(),
- planes[1].getRowStride(), planes[1].getPixelStride(), planes[1].getBuffer(),
- planes[1].getRowStride(), planes[1].getPixelStride());
-
- return this;
- }
-
-
- /**
- * Set image location metadata.
- *
- * <p>
- * The given location object must contain at least a valid time, latitude, and longitude
- * (equivalent to the values returned by {@link android.location.Location#getTime()},
- * {@link android.location.Location#getLatitude()}, and
- * {@link android.location.Location#getLongitude()} methods).
- * </p>
- *
- * @param location an {@link android.location.Location} object to set.
- * @return this {@link #DngCreator} object.
- *
- * @throws java.lang.IllegalArgumentException if the given location object doesn't
- * contain enough information to set location metadata.
- */
- public DngCreator setLocation(Location location) {
- /*TODO*/
- return this;
- }
-
- /**
- * Set the user description string to write.
- *
- * <p>
- * This is equivalent to setting the TIFF "ImageDescription" tag {@code (0x010E)}.
- * </p>
- *
- * @param description the user description string.
- * @return this {@link #DngCreator} object.
- */
- public DngCreator setDescription(String description) {
- /*TODO*/
- return this;
- }
-
- /**
- * Write the {@link android.graphics.ImageFormat#RAW_SENSOR} pixel data to a DNG file with
- * the currently configured metadata.
- *
- * <p>
- * Raw pixel data must have 16 bits per pixel, and the input must contain at least
- * {@code offset + 2 * width * height)} bytes. The width and height of
- * the input are taken from the width and height set in the {@link DngCreator} metadata tags,
- * and will typically be equal to the width and height of
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
- * The pixel layout in the input is determined from the reported color filter arrangement (CFA)
- * set in {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}. If insufficient
- * metadata is available to write a well-formatted DNG file, an
- * {@link java.lang.IllegalStateException} will be thrown.
- * </p>
- *
- * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
- * @param size the {@link Size} of the image to write, in pixels.
- * @param pixels an {@link java.io.InputStream} of pixel data to write.
- * @param offset the offset of the raw image in bytes. This indicates how many bytes will
- * be skipped in the input before any pixel data is read.
- *
- * @throws IOException if an error was encountered in the input or output stream.
- * @throws java.lang.IllegalStateException if not enough metadata information has been
- * set to write a well-formatted DNG file.
- * @throws java.lang.IllegalArgumentException if the size passed in does not match the
- */
- public void writeInputStream(OutputStream dngOutput, Size size, InputStream pixels, long offset)
- throws IOException {
- if (dngOutput == null || pixels == null) {
- throw new NullPointerException("Null argument to writeImage");
- }
- nativeWriteInputStream(dngOutput, pixels, offset);
- }
-
- /**
- * Write the {@link android.graphics.ImageFormat#RAW_SENSOR} pixel data to a DNG file with
- * the currently configured metadata.
- *
- * <p>
- * Raw pixel data must have 16 bits per pixel, and the input must contain at least
- * {@code offset + 2 * width * height)} bytes. The width and height of
- * the input are taken from the width and height set in the {@link DngCreator} metadata tags,
- * and will typically be equal to the width and height of
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
- * The pixel layout in the input is determined from the reported color filter arrangement (CFA)
- * set in {@link CameraCharacteristics#SENSOR_INFO_COLOR_FILTER_ARRANGEMENT}. If insufficient
- * metadata is available to write a well-formatted DNG file, an
- * {@link java.lang.IllegalStateException} will be thrown.
- * </p>
- *
- * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
- * @param pixels an {@link java.nio.ByteBuffer} of pixel data to write.
- * @param offset the offset of the raw image in bytes. This indicates how many bytes will
- * be skipped in the input before any pixel data is read.
- *
- * @throws IOException if an error was encountered in the input or output stream.
- * @throws java.lang.IllegalStateException if not enough metadata information has been
- * set to write a well-formatted DNG file.
- */
- public void writeByteBuffer(OutputStream dngOutput, Size size, ByteBuffer pixels, long offset)
- throws IOException {
- if (dngOutput == null || pixels == null) {
- throw new NullPointerException("Null argument to writeImage");
- }
- nativeWriteByteBuffer(dngOutput, pixels, offset);
- }
-
- /**
- * Write the pixel data to a DNG file with the currently configured metadata.
- *
- * <p>
- * For this method to succeed, the {@link android.media.Image} input must contain
- * {@link android.graphics.ImageFormat#RAW_SENSOR} pixel data, otherwise an
- * {@link java.lang.IllegalArgumentException} will be thrown.
- * </p>
- *
- * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
- * @param pixels an {@link android.media.Image} to write.
- *
- * @throws java.io.IOException if an error was encountered in the output stream.
- * @throws java.lang.IllegalArgumentException if an image with an unsupported format was used.
- * @throws java.lang.IllegalStateException if not enough metadata information has been
- * set to write a well-formatted DNG file.
- */
- public void writeImage(OutputStream dngOutput, Image pixels) throws IOException {
- if (dngOutput == null || pixels == null) {
- throw new NullPointerException("Null argument to writeImage");
- }
-
- int format = pixels.getFormat();
- if (format != ImageFormat.RAW_SENSOR) {
- throw new IllegalArgumentException("Unsupported image format " + format);
- }
-
- Image.Plane[] planes = pixels.getPlanes();
- nativeWriteImage(dngOutput, pixels.getWidth(), pixels.getHeight(), planes[0].getBuffer(),
- planes[0].getRowStride(), planes[0].getPixelStride());
- }
-
- @Override
- public void close() {
- nativeDestroy();
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- close();
- } finally {
- super.finalize();
- }
- }
-
- /**
- * This field is used by native code, do not access or modify.
- */
- private long mNativeContext;
-
- private static native void nativeClassInit();
-
- private synchronized native void nativeInit(CameraMetadataNative nativeCharacteristics,
- CameraMetadataNative nativeResult);
-
- private synchronized native void nativeDestroy();
-
- private synchronized native void nativeSetOrientation(int orientation);
-
- private synchronized native void nativeSetThumbnailBitmap(Bitmap bitmap);
-
- private synchronized native void nativeSetThumbnailImage(int width, int height,
- ByteBuffer yBuffer, int yRowStride,
- int yPixStride, ByteBuffer uBuffer,
- int uRowStride, int uPixStride,
- ByteBuffer vBuffer, int vRowStride,
- int vPixStride);
-
- private synchronized native void nativeWriteImage(OutputStream out, int width, int height,
- ByteBuffer rawBuffer, int rowStride,
- int pixStride) throws IOException;
-
- private synchronized native void nativeWriteByteBuffer(OutputStream out, ByteBuffer rawBuffer,
- long offset) throws IOException;
-
- private synchronized native void nativeWriteInputStream(OutputStream out, InputStream rawStream,
- long offset) throws IOException;
-
- static {
- System.loadLibrary("media_jni");
- nativeClassInit();
- }
-}
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index d658654..90fe695 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -2,7 +2,6 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- android_media_DngCreator.cpp \
android_media_ImageReader.cpp \
android_media_MediaCrypto.cpp \
android_media_MediaCodec.cpp \
@@ -42,7 +41,6 @@
libjhead \
libexif \
libstagefright_amrnb_common \
- libimg_utils \
LOCAL_REQUIRED_MODULES := \
libjhead_jni
@@ -55,7 +53,6 @@
external/tremor/Tremor \
frameworks/base/core/jni \
frameworks/av/media/libmedia \
- frameworks/av/media/img_utils/include \
frameworks/av/media/libstagefright \
frameworks/av/media/libstagefright/codecs/amrnb/enc/src \
frameworks/av/media/libstagefright/codecs/amrnb/common \
diff --git a/media/jni/android_media_DngCreator.cpp b/media/jni/android_media_DngCreator.cpp
deleted file mode 100644
index 860d896..0000000
--- a/media/jni/android_media_DngCreator.cpp
+++ /dev/null
@@ -1,772 +0,0 @@
-/*
- * Copyright 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "DngCreator_JNI"
-
-#include <system/camera_metadata.h>
-#include <camera/CameraMetadata.h>
-#include <img_utils/DngUtils.h>
-#include <img_utils/TagDefinitions.h>
-#include <img_utils/TiffIfd.h>
-#include <img_utils/TiffWriter.h>
-#include <img_utils/Output.h>
-
-#include <utils/Log.h>
-#include <utils/Errors.h>
-#include <utils/StrongPointer.h>
-#include <utils/RefBase.h>
-#include <cutils/properties.h>
-
-#include "android_runtime/AndroidRuntime.h"
-#include "android_runtime/android_hardware_camera2_CameraMetadata.h"
-
-#include <jni.h>
-#include <JNIHelp.h>
-
-using namespace android;
-using namespace img_utils;
-
-#define BAIL_IF_INVALID(expr, jnienv, tagId) \
- if ((expr) != OK) { \
- jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
- "Invalid metadata for tag %x", tagId); \
- return; \
- }
-
-#define BAIL_IF_EMPTY(entry, jnienv, tagId) \
- if (entry.count == 0) { \
- jniThrowExceptionFmt(jnienv, "java/lang/IllegalArgumentException", \
- "Missing metadata fields for tag %x", tagId); \
- return; \
- }
-
-#define ANDROID_MEDIA_DNGCREATOR_CTX_JNI_ID "mNativeContext"
-
-static struct {
- jfieldID mNativeContext;
-} gDngCreatorClassInfo;
-
-static struct {
- jmethodID mWriteMethod;
-} gOutputStreamClassInfo;
-
-enum {
- BITS_PER_SAMPLE = 16,
- BYTES_PER_SAMPLE = 2,
- TIFF_IFD_0 = 0
-};
-
-// ----------------------------------------------------------------------------
-
-// This class is not intended to be used across JNI calls.
-class JniOutputStream : public Output, public LightRefBase<JniOutputStream> {
-public:
- JniOutputStream(JNIEnv* env, jobject outStream);
-
- virtual ~JniOutputStream();
-
- status_t open();
- status_t write(const uint8_t* buf, size_t offset, size_t count);
- status_t close();
-private:
- enum {
- BYTE_ARRAY_LENGTH = 1024
- };
- jobject mOutputStream;
- JNIEnv* mEnv;
- jbyteArray mByteArray;
-};
-
-JniOutputStream::JniOutputStream(JNIEnv* env, jobject outStream) : mOutputStream(outStream),
- mEnv(env) {
- mByteArray = env->NewByteArray(BYTE_ARRAY_LENGTH);
- if (mByteArray == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError", "Could not allocate byte array.");
- }
-}
-
-JniOutputStream::~JniOutputStream() {
- mEnv->DeleteLocalRef(mByteArray);
-}
-
-status_t JniOutputStream::open() {
- // Do nothing
- return OK;
-}
-
-status_t JniOutputStream::write(const uint8_t* buf, size_t offset, size_t count) {
- while(count > 0) {
- size_t len = BYTE_ARRAY_LENGTH;
- len = (count > len) ? len : count;
- mEnv->SetByteArrayRegion(mByteArray, 0, len, reinterpret_cast<const jbyte*>(buf + offset));
-
- if (mEnv->ExceptionCheck()) {
- return BAD_VALUE;
- }
-
- mEnv->CallVoidMethod(mOutputStream, gOutputStreamClassInfo.mWriteMethod, mByteArray,
- 0, len);
-
- if (mEnv->ExceptionCheck()) {
- return BAD_VALUE;
- }
-
- count -= len;
- offset += len;
- }
- return OK;
-}
-
-status_t JniOutputStream::close() {
- // Do nothing
- return OK;
-}
-
-// ----------------------------------------------------------------------------
-
-extern "C" {
-
-static TiffWriter* DngCreator_getCreator(JNIEnv* env, jobject thiz) {
- ALOGV("%s:", __FUNCTION__);
- return reinterpret_cast<TiffWriter*>(env->GetLongField(thiz,
- gDngCreatorClassInfo.mNativeContext));
-}
-
-static void DngCreator_setCreator(JNIEnv* env, jobject thiz, sp<TiffWriter> writer) {
- ALOGV("%s:", __FUNCTION__);
- TiffWriter* current = DngCreator_getCreator(env, thiz);
- if (writer != NULL) {
- writer->incStrong((void*) DngCreator_setCreator);
- }
- if (current) {
- current->decStrong((void*) DngCreator_setCreator);
- }
- env->SetLongField(thiz, gDngCreatorClassInfo.mNativeContext,
- reinterpret_cast<jlong>(writer.get()));
-}
-
-static void DngCreator_nativeClassInit(JNIEnv* env, jclass clazz) {
- ALOGV("%s:", __FUNCTION__);
-
- gDngCreatorClassInfo.mNativeContext = env->GetFieldID(clazz,
- ANDROID_MEDIA_DNGCREATOR_CTX_JNI_ID, "J");
- LOG_ALWAYS_FATAL_IF(gDngCreatorClassInfo.mNativeContext == NULL,
- "can't find android/media/DngCreator.%s", ANDROID_MEDIA_DNGCREATOR_CTX_JNI_ID);
-
- jclass outputStreamClazz = env->FindClass("java/io/OutputStream");
- LOG_ALWAYS_FATAL_IF(outputStreamClazz == NULL, "Can't find java/io/OutputStream class");
- gOutputStreamClassInfo.mWriteMethod = env->GetMethodID(outputStreamClazz, "write", "([BII)V");
- LOG_ALWAYS_FATAL_IF(gOutputStreamClassInfo.mWriteMethod == NULL, "Can't find write method");
-}
-
-static void DngCreator_init(JNIEnv* env, jobject thiz, jobject characteristicsPtr,
- jobject resultsPtr) {
- ALOGV("%s:", __FUNCTION__);
- CameraMetadata characteristics;
- CameraMetadata results;
- if (CameraMetadata_getNativeMetadata(env, characteristicsPtr, &characteristics) != OK) {
- jniThrowException(env, "java/lang/AssertionError",
- "No native metadata defined for camera characteristics.");
- return;
- }
- if (CameraMetadata_getNativeMetadata(env, resultsPtr, &results) != OK) {
- jniThrowException(env, "java/lang/AssertionError",
- "No native metadata defined for capture results.");
- return;
- }
-
- sp<TiffWriter> writer = new TiffWriter();
-
- writer->addIfd(TIFF_IFD_0);
-
- status_t err = OK;
-
- const uint32_t samplesPerPixel = 1;
- const uint32_t bitsPerSample = BITS_PER_SAMPLE;
- const uint32_t bitsPerByte = BITS_PER_SAMPLE / BYTES_PER_SAMPLE;
- uint32_t imageWidth = 0;
- uint32_t imageHeight = 0;
-
- OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
-
- // TODO: Greensplit.
- // TODO: UniqueCameraModel
- // TODO: Add remaining non-essential tags
- {
- // Set orientation
- uint16_t orientation = 1; // Normal
- BAIL_IF_INVALID(writer->addEntry(TAG_ORIENTATION, 1, &orientation, TIFF_IFD_0), env,
- TAG_ORIENTATION);
- }
-
- {
- // Set subfiletype
- uint32_t subfileType = 0; // Main image
- BAIL_IF_INVALID(writer->addEntry(TAG_NEWSUBFILETYPE, 1, &subfileType, TIFF_IFD_0), env,
- TAG_NEWSUBFILETYPE);
- }
-
- {
- // Set bits per sample
- uint16_t bits = static_cast<uint16_t>(bitsPerSample);
- BAIL_IF_INVALID(writer->addEntry(TAG_BITSPERSAMPLE, 1, &bits, TIFF_IFD_0), env,
- TAG_BITSPERSAMPLE);
- }
-
- {
- // Set compression
- uint16_t compression = 1; // None
- BAIL_IF_INVALID(writer->addEntry(TAG_COMPRESSION, 1, &compression, TIFF_IFD_0), env,
- TAG_COMPRESSION);
- }
-
- {
- // Set dimensions
- camera_metadata_entry entry =
- characteristics.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
- BAIL_IF_EMPTY(entry, env, TAG_IMAGEWIDTH);
- uint32_t width = static_cast<uint32_t>(entry.data.i32[2]);
- uint32_t height = static_cast<uint32_t>(entry.data.i32[3]);
- BAIL_IF_INVALID(writer->addEntry(TAG_IMAGEWIDTH, 1, &width, TIFF_IFD_0), env,
- TAG_IMAGEWIDTH);
- BAIL_IF_INVALID(writer->addEntry(TAG_IMAGELENGTH, 1, &height, TIFF_IFD_0), env,
- TAG_IMAGELENGTH);
- imageWidth = width;
- imageHeight = height;
- }
-
- {
- // Set photometric interpretation
- uint16_t interpretation = 32803;
- BAIL_IF_INVALID(writer->addEntry(TAG_PHOTOMETRICINTERPRETATION, 1, &interpretation,
- TIFF_IFD_0), env, TAG_PHOTOMETRICINTERPRETATION);
- }
-
- {
- // Set blacklevel tags
- camera_metadata_entry entry =
- characteristics.find(ANDROID_SENSOR_BLACK_LEVEL_PATTERN);
- BAIL_IF_EMPTY(entry, env, TAG_BLACKLEVEL);
- const uint32_t* blackLevel = reinterpret_cast<const uint32_t*>(entry.data.i32);
- BAIL_IF_INVALID(writer->addEntry(TAG_BLACKLEVEL, entry.count, blackLevel, TIFF_IFD_0), env,
- TAG_BLACKLEVEL);
-
- uint16_t repeatDim[2] = {2, 2};
- BAIL_IF_INVALID(writer->addEntry(TAG_BLACKLEVELREPEATDIM, 2, repeatDim, TIFF_IFD_0), env,
- TAG_BLACKLEVELREPEATDIM);
- }
-
- {
- // Set samples per pixel
- uint16_t samples = static_cast<uint16_t>(samplesPerPixel);
- BAIL_IF_INVALID(writer->addEntry(TAG_SAMPLESPERPIXEL, 1, &samples, TIFF_IFD_0),
- env, TAG_SAMPLESPERPIXEL);
- }
-
- {
- // Set planar configuration
- uint16_t config = 1; // Chunky
- BAIL_IF_INVALID(writer->addEntry(TAG_PLANARCONFIGURATION, 1, &config, TIFF_IFD_0),
- env, TAG_PLANARCONFIGURATION);
- }
-
- {
- // Set CFA pattern dimensions
- uint16_t repeatDim[2] = {2, 2};
- BAIL_IF_INVALID(writer->addEntry(TAG_CFAREPEATPATTERNDIM, 2, repeatDim, TIFF_IFD_0),
- env, TAG_CFAREPEATPATTERNDIM);
- }
-
- {
- // Set CFA pattern
- camera_metadata_entry entry =
- characteristics.find(ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT);
- BAIL_IF_EMPTY(entry, env, TAG_CFAPATTERN);
- camera_metadata_enum_android_sensor_info_color_filter_arrangement_t cfa =
- static_cast<camera_metadata_enum_android_sensor_info_color_filter_arrangement_t>(
- entry.data.u8[0]);
- switch(cfa) {
- case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB: {
- uint8_t cfa[4] = {0, 1, 1, 2};
- BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
- env, TAG_CFAPATTERN);
- opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
- break;
- }
- case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG: {
- uint8_t cfa[4] = {1, 0, 2, 1};
- BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
- env, TAG_CFAPATTERN);
- opcodeCfaLayout = OpcodeListBuilder::CFA_GRBG;
- break;
- }
- case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG: {
- uint8_t cfa[4] = {1, 2, 0, 1};
- BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
- env, TAG_CFAPATTERN);
- opcodeCfaLayout = OpcodeListBuilder::CFA_GBRG;
- break;
- }
- case ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR: {
- uint8_t cfa[4] = {2, 1, 1, 0};
- BAIL_IF_INVALID(writer->addEntry(TAG_CFAPATTERN, 4, cfa, TIFF_IFD_0),
- env, TAG_CFAPATTERN);
- opcodeCfaLayout = OpcodeListBuilder::CFA_BGGR;
- break;
- }
- default: {
- jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
- "Invalid metadata for tag %d", TAG_CFAPATTERN);
- return;
- }
- }
- }
-
- {
- // Set CFA plane color
- uint8_t cfaPlaneColor[3] = {0, 1, 2};
- BAIL_IF_INVALID(writer->addEntry(TAG_CFAPLANECOLOR, 3, cfaPlaneColor, TIFF_IFD_0),
- env, TAG_CFAPLANECOLOR);
- }
-
- {
- // Set CFA layout
- uint16_t cfaLayout = 1;
- BAIL_IF_INVALID(writer->addEntry(TAG_CFALAYOUT, 1, &cfaLayout, TIFF_IFD_0),
- env, TAG_CFALAYOUT);
- }
-
- {
- // Set DNG version information
- uint8_t version[4] = {1, 4, 0, 0};
- BAIL_IF_INVALID(writer->addEntry(TAG_DNGVERSION, 4, version, TIFF_IFD_0),
- env, TAG_DNGVERSION);
-
- uint8_t backwardVersion[4] = {1, 1, 0, 0};
- BAIL_IF_INVALID(writer->addEntry(TAG_DNGBACKWARDVERSION, 4, backwardVersion, TIFF_IFD_0),
- env, TAG_DNGBACKWARDVERSION);
- }
-
- {
- // Set whitelevel
- camera_metadata_entry entry =
- characteristics.find(ANDROID_SENSOR_INFO_WHITE_LEVEL);
- BAIL_IF_EMPTY(entry, env, TAG_WHITELEVEL);
- uint32_t whiteLevel = static_cast<uint32_t>(entry.data.i32[0]);
- BAIL_IF_INVALID(writer->addEntry(TAG_WHITELEVEL, 1, &whiteLevel, TIFF_IFD_0), env,
- TAG_WHITELEVEL);
- }
-
- {
- // Set default scale
- uint32_t defaultScale[4] = {1, 1, 1, 1};
- BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTSCALE, 2, defaultScale, TIFF_IFD_0),
- env, TAG_DEFAULTSCALE);
- }
-
- bool singleIlluminant = false;
- {
- // Set calibration illuminants
- camera_metadata_entry entry1 =
- characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT1);
- BAIL_IF_EMPTY(entry1, env, TAG_CALIBRATIONILLUMINANT1);
- camera_metadata_entry entry2 =
- characteristics.find(ANDROID_SENSOR_REFERENCE_ILLUMINANT2);
- if (entry2.count == 0) {
- singleIlluminant = true;
- }
- uint16_t ref1 = entry1.data.u8[0];
-
- BAIL_IF_INVALID(writer->addEntry(TAG_CALIBRATIONILLUMINANT1, 1, &ref1,
- TIFF_IFD_0), env, TAG_CALIBRATIONILLUMINANT1);
-
- if (!singleIlluminant) {
- uint16_t ref2 = entry2.data.u8[0];
- BAIL_IF_INVALID(writer->addEntry(TAG_CALIBRATIONILLUMINANT2, 1, &ref2,
- TIFF_IFD_0), env, TAG_CALIBRATIONILLUMINANT2);
- }
- }
-
- {
- // Set color transforms
- camera_metadata_entry entry1 =
- characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM1);
- BAIL_IF_EMPTY(entry1, env, TAG_COLORMATRIX1);
-
- int32_t colorTransform1[entry1.count * 2];
-
- size_t ctr = 0;
- for(size_t i = 0; i < entry1.count; ++i) {
- colorTransform1[ctr++] = entry1.data.r[i].numerator;
- colorTransform1[ctr++] = entry1.data.r[i].denominator;
- }
-
- BAIL_IF_INVALID(writer->addEntry(TAG_COLORMATRIX1, entry1.count, colorTransform1, TIFF_IFD_0),
- env, TAG_COLORMATRIX1);
-
- if (!singleIlluminant) {
- camera_metadata_entry entry2 = characteristics.find(ANDROID_SENSOR_COLOR_TRANSFORM2);
- BAIL_IF_EMPTY(entry2, env, TAG_COLORMATRIX2);
- int32_t colorTransform2[entry2.count * 2];
-
- ctr = 0;
- for(size_t i = 0; i < entry2.count; ++i) {
- colorTransform2[ctr++] = entry2.data.r[i].numerator;
- colorTransform2[ctr++] = entry2.data.r[i].denominator;
- }
-
- BAIL_IF_INVALID(writer->addEntry(TAG_COLORMATRIX2, entry2.count, colorTransform2, TIFF_IFD_0),
- env, TAG_COLORMATRIX2);
- }
- }
-
- {
- // Set calibration transforms
- camera_metadata_entry entry1 =
- characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM1);
- BAIL_IF_EMPTY(entry1, env, TAG_CAMERACALIBRATION1);
-
- int32_t calibrationTransform1[entry1.count * 2];
-
- size_t ctr = 0;
- for(size_t i = 0; i < entry1.count; ++i) {
- calibrationTransform1[ctr++] = entry1.data.r[i].numerator;
- calibrationTransform1[ctr++] = entry1.data.r[i].denominator;
- }
-
- BAIL_IF_INVALID(writer->addEntry(TAG_CAMERACALIBRATION1, entry1.count, calibrationTransform1,
- TIFF_IFD_0), env, TAG_CAMERACALIBRATION1);
-
- if (!singleIlluminant) {
- camera_metadata_entry entry2 =
- characteristics.find(ANDROID_SENSOR_CALIBRATION_TRANSFORM2);
- BAIL_IF_EMPTY(entry2, env, TAG_CAMERACALIBRATION2);
- int32_t calibrationTransform2[entry2.count * 2];
-
- ctr = 0;
- for(size_t i = 0; i < entry2.count; ++i) {
- calibrationTransform2[ctr++] = entry2.data.r[i].numerator;
- calibrationTransform2[ctr++] = entry2.data.r[i].denominator;
- }
-
- BAIL_IF_INVALID(writer->addEntry(TAG_CAMERACALIBRATION2, entry2.count, calibrationTransform1,
- TIFF_IFD_0), env, TAG_CAMERACALIBRATION2);
- }
- }
-
- {
- // Set forward transforms
- camera_metadata_entry entry1 =
- characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX1);
- BAIL_IF_EMPTY(entry1, env, TAG_FORWARDMATRIX1);
-
- int32_t forwardTransform1[entry1.count * 2];
-
- size_t ctr = 0;
- for(size_t i = 0; i < entry1.count; ++i) {
- forwardTransform1[ctr++] = entry1.data.r[i].numerator;
- forwardTransform1[ctr++] = entry1.data.r[i].denominator;
- }
-
- BAIL_IF_INVALID(writer->addEntry(TAG_FORWARDMATRIX1, entry1.count, forwardTransform1,
- TIFF_IFD_0), env, TAG_FORWARDMATRIX1);
-
- if (!singleIlluminant) {
- camera_metadata_entry entry2 =
- characteristics.find(ANDROID_SENSOR_FORWARD_MATRIX2);
- BAIL_IF_EMPTY(entry2, env, TAG_FORWARDMATRIX2);
- int32_t forwardTransform2[entry2.count * 2];
-
- ctr = 0;
- for(size_t i = 0; i < entry2.count; ++i) {
- forwardTransform2[ctr++] = entry2.data.r[i].numerator;
- forwardTransform2[ctr++] = entry2.data.r[i].denominator;
- }
-
- BAIL_IF_INVALID(writer->addEntry(TAG_FORWARDMATRIX2, entry2.count, forwardTransform2,
- TIFF_IFD_0), env, TAG_FORWARDMATRIX2);
- }
- }
-
- {
- // Set camera neutral
- camera_metadata_entry entry =
- results.find(ANDROID_SENSOR_NEUTRAL_COLOR_POINT);
- BAIL_IF_EMPTY(entry, env, TAG_ASSHOTNEUTRAL);
- uint32_t cameraNeutral[entry.count * 2];
-
- size_t ctr = 0;
- for(size_t i = 0; i < entry.count; ++i) {
- cameraNeutral[ctr++] =
- static_cast<uint32_t>(entry.data.r[i].numerator);
- cameraNeutral[ctr++] =
- static_cast<uint32_t>(entry.data.r[i].denominator);
- }
-
- BAIL_IF_INVALID(writer->addEntry(TAG_ASSHOTNEUTRAL, entry.count, cameraNeutral,
- TIFF_IFD_0), env, TAG_ASSHOTNEUTRAL);
- }
-
- {
- // Setup data strips
- // TODO: Switch to tiled implementation.
- uint32_t offset = 0;
- BAIL_IF_INVALID(writer->addEntry(TAG_STRIPOFFSETS, 1, &offset, TIFF_IFD_0), env,
- TAG_STRIPOFFSETS);
-
- BAIL_IF_INVALID(writer->addEntry(TAG_ROWSPERSTRIP, 1, &imageHeight, TIFF_IFD_0), env,
- TAG_ROWSPERSTRIP);
-
- uint32_t byteCount = imageWidth * imageHeight * bitsPerSample * samplesPerPixel /
- bitsPerByte;
- BAIL_IF_INVALID(writer->addEntry(TAG_STRIPBYTECOUNTS, 1, &byteCount, TIFF_IFD_0), env,
- TAG_STRIPBYTECOUNTS);
- }
-
- {
- // Setup default crop + crop origin tags
- uint32_t margin = 8; // Default margin recommended by Adobe for interpolation.
- uint32_t dimensionLimit = 128; // Smallest image dimension crop margin from.
- if (imageWidth >= dimensionLimit && imageHeight >= dimensionLimit) {
- uint32_t defaultCropOrigin[] = {margin, margin};
- uint32_t defaultCropSize[] = {imageWidth - margin, imageHeight - margin};
- BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTCROPORIGIN, 2, defaultCropOrigin,
- TIFF_IFD_0), env, TAG_DEFAULTCROPORIGIN);
- BAIL_IF_INVALID(writer->addEntry(TAG_DEFAULTCROPSIZE, 2, defaultCropSize,
- TIFF_IFD_0), env, TAG_DEFAULTCROPSIZE);
- }
- }
-
- {
- // Setup unique camera model tag
- char model[PROPERTY_VALUE_MAX];
- property_get("ro.product.model", model, "");
-
- char manufacturer[PROPERTY_VALUE_MAX];
- property_get("ro.product.manufacturer", manufacturer, "");
-
- char brand[PROPERTY_VALUE_MAX];
- property_get("ro.product.brand", brand, "");
-
- String8 cameraModel(model);
- cameraModel += "-";
- cameraModel += manufacturer;
- cameraModel += "-";
- cameraModel += brand;
-
- BAIL_IF_INVALID(writer->addEntry(TAG_UNIQUECAMERAMODEL, cameraModel.size() + 1,
- reinterpret_cast<const uint8_t*>(cameraModel.string()), TIFF_IFD_0), env,
- TAG_UNIQUECAMERAMODEL);
- }
-
- {
- // Setup opcode List 2
- camera_metadata_entry entry1 =
- characteristics.find(ANDROID_LENS_INFO_SHADING_MAP_SIZE);
- BAIL_IF_EMPTY(entry1, env, TAG_OPCODELIST2);
- uint32_t lsmWidth = static_cast<uint32_t>(entry1.data.i32[0]);
- uint32_t lsmHeight = static_cast<uint32_t>(entry1.data.i32[1]);
-
- camera_metadata_entry entry2 =
- results.find(ANDROID_STATISTICS_LENS_SHADING_MAP);
- BAIL_IF_EMPTY(entry2, env, TAG_OPCODELIST2);
- if (entry2.count == lsmWidth * lsmHeight * 4) {
-
- OpcodeListBuilder builder;
- status_t err = builder.addGainMapsForMetadata(lsmWidth,
- lsmHeight,
- 0,
- 0,
- imageHeight,
- imageWidth,
- opcodeCfaLayout,
- entry2.data.f);
- if (err == OK) {
- size_t listSize = builder.getSize();
- uint8_t opcodeListBuf[listSize];
- err = builder.buildOpList(opcodeListBuf);
- if (err == OK) {
- BAIL_IF_INVALID(writer->addEntry(TAG_OPCODELIST2, listSize, opcodeListBuf,
- TIFF_IFD_0), env, TAG_OPCODELIST2);
- } else {
- ALOGE("%s: Could not build Lens shading map opcode.", __FUNCTION__);
- jniThrowRuntimeException(env, "failed to construct lens shading map opcode.");
- }
- } else {
- ALOGE("%s: Could not add Lens shading map.", __FUNCTION__);
- jniThrowRuntimeException(env, "failed to add lens shading map.");
- }
- } else {
- ALOGW("%s: Lens shading map not present in results, skipping...", __FUNCTION__);
- }
- }
-
- DngCreator_setCreator(env, thiz, writer);
-}
-
-static void DngCreator_destroy(JNIEnv* env, jobject thiz) {
- ALOGV("%s:", __FUNCTION__);
- DngCreator_setCreator(env, thiz, NULL);
-}
-
-static void DngCreator_nativeSetOrientation(JNIEnv* env, jobject thiz) {
- ALOGV("%s:", __FUNCTION__);
- jniThrowRuntimeException(env, "nativeSetOrientation is not implemented");
-}
-
-static void DngCreator_nativeSetThumbnailBitmap(JNIEnv* env, jobject thiz, jobject bitmap) {
- ALOGV("%s:", __FUNCTION__);
- jniThrowRuntimeException(env, "nativeSetThumbnailBitmap is not implemented");
-}
-
-static void DngCreator_nativeSetThumbnailImage(JNIEnv* env, jobject thiz, jint width, jint height,
- jobject yBuffer, jint yRowStride, jint yPixStride, jobject uBuffer, jint uRowStride,
- jint uPixStride, jobject vBuffer, jint vRowStride, jint vPixStride) {
- ALOGV("%s:", __FUNCTION__);
- jniThrowRuntimeException(env, "nativeSetThumbnailImage is not implemented");
-}
-
-static void DngCreator_nativeWriteImage(JNIEnv* env, jobject thiz, jobject outStream, jint width,
- jint height, jobject inBuffer, jint rowStride, jint pixStride) {
- ALOGV("%s:", __FUNCTION__);
-
- sp<JniOutputStream> out = new JniOutputStream(env, outStream);
- if(env->ExceptionCheck()) {
- ALOGE("%s: Could not allocate buffers for output stream", __FUNCTION__);
- return;
- }
-
- uint8_t* pixelBytes = reinterpret_cast<uint8_t*>(env->GetDirectBufferAddress(inBuffer));
- if (pixelBytes == NULL) {
- ALOGE("%s: Could not get native byte buffer", __FUNCTION__);
- jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid bytebuffer");
- return;
- }
-
- TiffWriter* writer = DngCreator_getCreator(env, thiz);
- if (writer == NULL) {
- ALOGE("%s: Failed to initialize DngCreator", __FUNCTION__);
- jniThrowException(env, "java/lang/AssertionError",
- "Write called with uninitialized DngCreator");
- return;
- }
- // TODO: handle lens shading map, etc. conversions for other raw buffer sizes.
- uint32_t metadataWidth = *(writer->getEntry(TAG_IMAGEWIDTH, TIFF_IFD_0)->getData<uint32_t>());
- uint32_t metadataHeight = *(writer->getEntry(TAG_IMAGELENGTH, TIFF_IFD_0)->getData<uint32_t>());
- if (metadataWidth != width) {
- jniThrowExceptionFmt(env, "java/lang/IllegalStateException", \
- "Metadata width %d doesn't match image width %d", metadataWidth, width);
- return;
- }
-
- if (metadataHeight != height) {
- jniThrowExceptionFmt(env, "java/lang/IllegalStateException", \
- "Metadata height %d doesn't match image height %d", metadataHeight, height);
- return;
- }
-
- uint32_t stripOffset = writer->getTotalSize();
-
- BAIL_IF_INVALID(writer->addEntry(TAG_STRIPOFFSETS, 1, &stripOffset, TIFF_IFD_0), env,
- TAG_STRIPOFFSETS);
-
- if (writer->write(out.get()) != OK) {
- if (!env->ExceptionCheck()) {
- jniThrowException(env, "java/io/IOException", "Failed to write metadata");
- }
- return;
- }
-
- size_t fullSize = rowStride * height;
- jlong capacity = env->GetDirectBufferCapacity(inBuffer);
- if (capacity < 0 || fullSize > capacity) {
- jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
- "Invalid size %d for Image, size given in metadata is %d at current stride",
- capacity, fullSize);
- return;
- }
-
- if (pixStride == BYTES_PER_SAMPLE && rowStride == width * BYTES_PER_SAMPLE) {
- if (out->write(pixelBytes, 0, fullSize) != OK || env->ExceptionCheck()) {
- if (!env->ExceptionCheck()) {
- jniThrowException(env, "java/io/IOException", "Failed to write pixel data");
- }
- return;
- }
- } else if (pixStride == BYTES_PER_SAMPLE) {
- for (size_t i = 0; i < height; ++i) {
- if (out->write(pixelBytes, i * rowStride, pixStride * width) != OK ||
- env->ExceptionCheck()) {
- if (!env->ExceptionCheck()) {
- jniThrowException(env, "java/io/IOException", "Failed to write pixel data");
- }
- return;
- }
- }
- } else {
- for (size_t i = 0; i < height; ++i) {
- for (size_t j = 0; j < width; ++j) {
- if (out->write(pixelBytes, i * rowStride + j * pixStride,
- BYTES_PER_SAMPLE) != OK || !env->ExceptionCheck()) {
- if (env->ExceptionCheck()) {
- jniThrowException(env, "java/io/IOException", "Failed to write pixel data");
- }
- return;
- }
- }
- }
- }
-
-}
-
-static void DngCreator_nativeWriteByteBuffer(JNIEnv* env, jobject thiz, jobject outStream,
- jobject rawBuffer, jlong offset) {
- ALOGV("%s:", __FUNCTION__);
- jniThrowRuntimeException(env, "nativeWriteByteBuffer is not implemented.");
-}
-
-static void DngCreator_nativeWriteInputStream(JNIEnv* env, jobject thiz, jobject outStream,
- jobject inStream, jlong offset) {
- ALOGV("%s:", __FUNCTION__);
- jniThrowRuntimeException(env, "nativeWriteInputStream is not implemented.");
-}
-
-} /*extern "C" */
-
-static JNINativeMethod gDngCreatorMethods[] = {
- {"nativeClassInit", "()V", (void*) DngCreator_nativeClassInit},
- {"nativeInit", "(Landroid/hardware/camera2/impl/CameraMetadataNative;"
- "Landroid/hardware/camera2/impl/CameraMetadataNative;)V", (void*) DngCreator_init},
- {"nativeDestroy", "()V", (void*) DngCreator_destroy},
- {"nativeSetOrientation", "(I)V", (void*) DngCreator_nativeSetOrientation},
- {"nativeSetThumbnailBitmap","(Landroid/graphics/Bitmap;)V",
- (void*) DngCreator_nativeSetThumbnailBitmap},
- {"nativeSetThumbnailImage",
- "(IILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;IILjava/nio/ByteBuffer;II)V",
- (void*) DngCreator_nativeSetThumbnailImage},
- {"nativeWriteImage", "(Ljava/io/OutputStream;IILjava/nio/ByteBuffer;II)V",
- (void*) DngCreator_nativeWriteImage},
- {"nativeWriteByteBuffer", "(Ljava/io/OutputStream;Ljava/nio/ByteBuffer;J)V",
- (void*) DngCreator_nativeWriteByteBuffer},
- {"nativeWriteInputStream", "(Ljava/io/OutputStream;Ljava/io/InputStream;J)V",
- (void*) DngCreator_nativeWriteInputStream},
-};
-
-int register_android_media_DngCreator(JNIEnv *env) {
- return AndroidRuntime::registerNativeMethods(env,
- "android/media/DngCreator", gDngCreatorMethods, NELEM(gDngCreatorMethods));
-}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 9d03cc38..6f42057 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -884,7 +884,6 @@
"android/media/MediaPlayer", gMethods, NELEM(gMethods));
}
-extern int register_android_media_DngCreator(JNIEnv *env);
extern int register_android_media_ImageReader(JNIEnv *env);
extern int register_android_media_Crypto(JNIEnv *env);
extern int register_android_media_Drm(JNIEnv *env);
@@ -914,11 +913,6 @@
}
assert(env != NULL);
- if (register_android_media_DngCreator(env) < 0) {
- ALOGE("ERROR: ImageReader native registration failed");
- goto bail;
- }
-
if (register_android_media_ImageReader(env) < 0) {
ALOGE("ERROR: ImageReader native registration failed");
goto bail;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
index a77b647..a3caba2 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -17,6 +17,7 @@
package com.android.mediaframeworktest.unit;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
import android.util.Range;
import android.util.Rational;
import android.util.SizeF;
@@ -26,6 +27,8 @@
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.util.Size;
import android.hardware.camera2.impl.CameraMetadataNative;
@@ -46,6 +49,7 @@
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.util.List;
/**
* <pre>
@@ -56,6 +60,10 @@
*/
public class CameraMetadataTest extends junit.framework.TestCase {
+ private static final boolean VERBOSE = false;
+ private static final String TAG = "CameraMetadataTest";
+
+
CameraMetadataNative mMetadata;
// Sections
@@ -940,7 +948,7 @@
};
int availableFormatTag = CameraMetadataNative.getTag("android.scaler.availableFormats");
- Key<int[]> formatKey = CameraCharacteristics.SCALER_AVAILABLE_FORMATS;
+ Key<int[]> formatKey = CameraCharacteristics.SCALER_AVAILABLE_FORMATS.getNativeKey();
validateArrayMetadataReadWriteOverride(formatKey, availableFormats,
expectedIntValues, availableFormatTag);
@@ -1046,7 +1054,7 @@
0x20, 320, 240, INPUT, // RAW16
};
Key<StreamConfiguration[]> configKey =
- CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
+ CameraCharacteristics.SCALER_AVAILABLE_STREAM_CONFIGURATIONS.getNativeKey();
mMetadata.writeValues(configKey.getTag(),
toByteArray(rawAvailableStreamConfigs));
@@ -1074,7 +1082,7 @@
0x21, 1920, 1080, 33333338 // BLOB
};
Key<StreamConfigurationDuration[]> durationKey =
- CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS;
+ CameraCharacteristics.SCALER_AVAILABLE_MIN_FRAME_DURATIONS.getNativeKey();
mMetadata.writeValues(durationKey.getTag(),
toByteArray(rawAvailableMinDurations));
@@ -1100,7 +1108,7 @@
0x21, 1920, 1080, 33333338 // BLOB
};
Key<StreamConfigurationDuration[]> stallDurationKey =
- CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS;
+ CameraCharacteristics.SCALER_AVAILABLE_STALL_DURATIONS.getNativeKey();
mMetadata.writeValues(stallDurationKey.getTag(),
toByteArray(rawAvailableStallDurations));
@@ -1158,6 +1166,31 @@
}
}
+ @SmallTest
+ public void testCaptureResult() {
+ mMetadata.set(CaptureRequest.CONTROL_AE_MODE,
+ CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH);
+
+ if (VERBOSE) mMetadata.dumpToLog();
+
+ CaptureResult captureResult = new CaptureResult(mMetadata, /*sequenceId*/0);
+
+ List<CaptureResult.Key<?>> allKeys = captureResult.getKeys();
+ if (VERBOSE) Log.v(TAG, "testCaptureResult: key list size " + allKeys);
+ for (CaptureResult.Key<?> key : captureResult.getKeys()) {
+ if (VERBOSE) {
+ Log.v(TAG,
+ "testCaptureResult: key " + key + " value" + captureResult.get(key));
+ }
+ }
+
+ assertTrue(allKeys.size() >= 1); // FIXME: android.statistics.faces counts as a key
+ assertTrue(allKeys.contains(CaptureResult.CONTROL_AE_MODE));
+
+ assertEquals(CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH,
+ (int)captureResult.get(CaptureResult.CONTROL_AE_MODE));
+ }
+
private static void checkStreamConfigurationMapByFormatSize(StreamConfigurationMap configMap,
int format, int width, int height,
boolean output) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 6b62c25..e9cb197 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -52,6 +52,8 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
+ <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+
<!-- Physical hardware -->
<uses-permission android:name="android.permission.MANAGE_USB" />
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index c209434..e9dcea2 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -246,7 +246,7 @@
<dimen name="notification_side_padding">8dp</dimen>
<!-- Z distance between notifications if they are in the stack -->
- <dimen name="z_distance_between_notifications">2dp</dimen>
+ <dimen name="z_distance_between_notifications">1dp</dimen>
<!-- The padding between the individual notification cards when dimmed. -->
<dimen name="notification_padding_dimmed">0dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index c0f9bf2..191bac9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.net.ConnectivityManager;
import android.provider.Settings.Global;
import com.android.systemui.R;
@@ -52,10 +53,9 @@
}
private void setEnabled(boolean enabled) {
- mSetting.setValue(enabled ? 1 : 0);
- final Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- intent.putExtra("state", enabled);
- mContext.sendBroadcast(intent);
+ final ConnectivityManager mgr =
+ (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mgr.setAirplaneMode(enabled);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index ac16164..e3dac4a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -21,15 +21,25 @@
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapShader;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.RectF;
+import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
import android.view.animation.PathInterpolator;
-
import com.android.systemui.R;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
/**
* Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer}
@@ -41,6 +51,36 @@
private static final int BACKGROUND_ANIMATION_LENGTH_MS = 220;
private static final int ACTIVATE_ANIMATION_LENGTH = 220;
+ /**
+ * The amount of width, which is kept in the end when performing a disappear animation (also
+ * the amount from which the horizontal appearing begins)
+ */
+ private static final float HORIZONTAL_COLLAPSED_REST_PARTIAL = 0.05f;
+
+ /**
+ * At which point from [0,1] does the horizontal collapse animation end (or start when
+ * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
+ */
+ private static final float HORIZONTAL_ANIMATION_END = 0.2f;
+
+ /**
+ * At which point from [0,1] does the alpha animation end (or start when
+ * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
+ */
+ private static final float ALPHA_ANIMATION_END = 0.0f;
+
+ /**
+ * At which point from [0,1] does the horizontal collapse animation start (or start when
+ * expanding)? 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
+ */
+ private static final float HORIZONTAL_ANIMATION_START = 1.0f;
+
+ /**
+ * At which point from [0,1] does the vertical collapse animation start (or end when
+ * expanding) 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
+ */
+ private static final float VERTICAL_ANIMATION_START = 1.0f;
+
private static final Interpolator ACTIVATE_INVERSE_INTERPOLATOR
= new PathInterpolator(0.6f, 0, 0.5f, 1);
private static final Interpolator ACTIVATE_INVERSE_ALPHA_INTERPOLATOR
@@ -53,6 +93,7 @@
private int mBgTint = 0;
private int mDimmedBgTint = 0;
+ private final int mRoundedRectCornerRadius;
/**
* Flag to indicate that the notification has been touched once and the second touch will
@@ -66,22 +107,41 @@
private OnActivatedListener mOnActivatedListener;
- private Interpolator mLinearOutSlowInInterpolator;
- private Interpolator mFastOutSlowInInterpolator;
+ private final Interpolator mLinearOutSlowInInterpolator;
+ private final Interpolator mFastOutSlowInInterpolator;
+ private final Interpolator mSlowOutFastInInterpolator;
+ private final Interpolator mSlowOutLinearInInterpolator;
+ private final Interpolator mLinearInterpolator;
+ private Interpolator mCurrentAppearInterpolator;
+ private Interpolator mCurrentAlphaInterpolator;
private NotificationBackgroundView mBackgroundNormal;
private NotificationBackgroundView mBackgroundDimmed;
private ObjectAnimator mBackgroundAnimator;
+ private RectF mAppearAnimationRect = new RectF();
+ private PorterDuffColorFilter mAppearAnimationFilter;
+ private float mAnimationTranslationY;
+ private boolean mDrawingAppearAnimation;
+ private Paint mAppearPaint = new Paint();
+ private ValueAnimator mAppearAnimator;
+ private float mAppearAnimationFraction = -1.0f;
+ private float mAppearAnimationTranslation;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mFastOutSlowInInterpolator =
AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in);
+ mSlowOutFastInInterpolator = new PathInterpolator(0.8f, 0.0f, 0.6f, 1.0f);
mLinearOutSlowInInterpolator =
AnimationUtils.loadInterpolator(context, android.R.interpolator.linear_out_slow_in);
+ mSlowOutLinearInInterpolator = new PathInterpolator(0.8f, 0.0f, 1.0f, 1.0f);
+ mLinearInterpolator = new LinearInterpolator();
setClipChildren(false);
setClipToPadding(false);
+ mAppearAnimationFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
+ mRoundedRectCornerRadius = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_quantum_rounded_rect_radius);
}
@Override
@@ -316,6 +376,202 @@
mBackgroundDimmed.setClipTopAmount(clipTopAmount);
}
+ @Override
+ public void performRemoveAnimation(float translationDirection, Runnable onFinishedRunnable) {
+ enableAppearDrawing(true);
+ if (mDrawingAppearAnimation) {
+ startAppearAnimation(false /* isAppearing */, translationDirection,
+ 0, onFinishedRunnable);
+ }
+ }
+
+ @Override
+ public void performAddAnimation(long delay) {
+ enableAppearDrawing(true);
+ if (mDrawingAppearAnimation) {
+ startAppearAnimation(true /* isAppearing */, -1.0f, delay, null);
+ }
+ }
+
+ private void startAppearAnimation(boolean isAppearing,
+ float translationDirection, long delay, final Runnable onFinishedRunnable) {
+ if (mAppearAnimator != null) {
+ mAppearAnimator.cancel();
+ }
+ mAnimationTranslationY = translationDirection * mActualHeight;
+ if (mAppearAnimationFraction == -1.0f) {
+ // not initialized yet, we start anew
+ if (isAppearing) {
+ mAppearAnimationFraction = 0.0f;
+ mAppearAnimationTranslation = mAnimationTranslationY;
+ } else {
+ mAppearAnimationFraction = 1.0f;
+ mAppearAnimationTranslation = 0;
+ }
+ }
+
+ float targetValue;
+ if (isAppearing) {
+ mCurrentAppearInterpolator = mSlowOutFastInInterpolator;
+ mCurrentAlphaInterpolator = mLinearOutSlowInInterpolator;
+ targetValue = 1.0f;
+ } else {
+ mCurrentAppearInterpolator = mFastOutSlowInInterpolator;
+ mCurrentAlphaInterpolator = mSlowOutLinearInInterpolator;
+ targetValue = 0.0f;
+ }
+ mAppearAnimator = ValueAnimator.ofFloat(mAppearAnimationFraction,
+ targetValue);
+ mAppearAnimator.setInterpolator(mLinearInterpolator);
+ mAppearAnimator.setDuration(
+ (long) (StackStateAnimator.ANIMATION_DURATION_APPEAR_DISAPPEAR
+ * Math.abs(mAppearAnimationFraction - targetValue)));
+ mAppearAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mAppearAnimationFraction = (float) animation.getAnimatedValue();
+ updateAppearAnimationAlpha();
+ updateAppearRect();
+ invalidate();
+ }
+ });
+ if (delay > 0) {
+ // we need to apply the initial state already to avoid drawn frames in the wrong state
+ updateAppearAnimationAlpha();
+ updateAppearRect();
+ mAppearAnimator.setStartDelay(delay);
+ }
+ mAppearAnimator.addListener(new AnimatorListenerAdapter() {
+ private boolean mWasCancelled;
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (onFinishedRunnable != null) {
+ onFinishedRunnable.run();
+ }
+ if (!mWasCancelled) {
+ mAppearAnimationFraction = -1;
+ setOutlineRect(null);
+ enableAppearDrawing(false);
+ }
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mWasCancelled = false;
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mWasCancelled = true;
+ }
+ });
+ mAppearAnimator.start();
+ }
+
+ private void updateAppearRect() {
+ float inverseFraction = (1.0f - mAppearAnimationFraction);
+ float translationFraction = mCurrentAppearInterpolator.getInterpolation(inverseFraction);
+ float translateYTotalAmount = translationFraction * mAnimationTranslationY;
+ mAppearAnimationTranslation = translateYTotalAmount;
+
+ // handle width animation
+ float widthFraction = (inverseFraction - (1.0f - HORIZONTAL_ANIMATION_START))
+ / (HORIZONTAL_ANIMATION_START - HORIZONTAL_ANIMATION_END);
+ widthFraction = Math.min(1.0f, Math.max(0.0f, widthFraction));
+ widthFraction = mCurrentAppearInterpolator.getInterpolation(widthFraction);
+ float left = (getWidth() * (0.5f - HORIZONTAL_COLLAPSED_REST_PARTIAL / 2.0f) *
+ widthFraction);
+ float right = getWidth() - left;
+
+ // handle top animation
+ float heightFraction = (inverseFraction - (1.0f - VERTICAL_ANIMATION_START)) /
+ VERTICAL_ANIMATION_START;
+ heightFraction = Math.max(0.0f, heightFraction);
+ heightFraction = mCurrentAppearInterpolator.getInterpolation(heightFraction);
+
+ float top;
+ float bottom;
+ if (mAnimationTranslationY > 0.0f) {
+ bottom = mActualHeight - heightFraction * mAnimationTranslationY * 0.1f
+ - translateYTotalAmount;
+ top = bottom * heightFraction;
+ } else {
+ top = heightFraction * (mActualHeight + mAnimationTranslationY) * 0.1f -
+ translateYTotalAmount;
+ bottom = mActualHeight * (1 - heightFraction) + top * heightFraction;
+ }
+ mAppearAnimationRect.set(left, top, right, bottom);
+ setOutlineRect(left, top + mAppearAnimationTranslation, right,
+ bottom + mAppearAnimationTranslation);
+ }
+
+ private void updateAppearAnimationAlpha() {
+ int backgroundColor = getBackgroundColor();
+ if (backgroundColor != -1) {
+ float contentAlphaProgress = mAppearAnimationFraction;
+ contentAlphaProgress = contentAlphaProgress / (1.0f - ALPHA_ANIMATION_END);
+ contentAlphaProgress = Math.min(1.0f, contentAlphaProgress);
+ contentAlphaProgress = mCurrentAlphaInterpolator.getInterpolation(contentAlphaProgress);
+ int sourceColor = Color.argb((int) (255 * (1.0f - contentAlphaProgress)),
+ Color.red(backgroundColor), Color.green(backgroundColor),
+ Color.blue(backgroundColor));
+ mAppearAnimationFilter.setColor(sourceColor);
+ mAppearPaint.setColorFilter(mAppearAnimationFilter);
+ }
+ }
+
+ private int getBackgroundColor() {
+ // TODO: get real color
+ return 0xfffafafa;
+ }
+
+ /**
+ * When we draw the appear animation, we render the view in a bitmap and render this bitmap
+ * as a shader of a rect. This call creates the Bitmap and switches the drawing mode,
+ * such that the normal drawing of the views does not happen anymore.
+ *
+ * @param enable Should it be enabled.
+ */
+ private void enableAppearDrawing(boolean enable) {
+ if (enable != mDrawingAppearAnimation) {
+ if (enable) {
+ if (getWidth() == 0 || getActualHeight() == 0) {
+ // TODO: This should not happen, but it can during expansion. Needs
+ // investigation
+ return;
+ }
+ Bitmap bitmap = Bitmap.createBitmap(getWidth(), getActualHeight(),
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ draw(canvas);
+ mAppearPaint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP,
+ Shader.TileMode.CLAMP));
+ } else {
+ mAppearPaint.setShader(null);
+ }
+ mDrawingAppearAnimation = enable;
+ invalidate();
+ }
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ if (!mDrawingAppearAnimation) {
+ super.dispatchDraw(canvas);
+ } else {
+ drawAppearRect(canvas);
+ }
+ }
+
+ private void drawAppearRect(Canvas canvas) {
+ canvas.save();
+ canvas.translate(0, mAppearAnimationTranslation);
+ canvas.drawRoundRect(mAppearAnimationRect, mRoundedRectCornerRadius,
+ mRoundedRectCornerRadius, mAppearPaint);
+ canvas.restore();
+ }
+
public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
mOnActivatedListener = onActivatedListener;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 457d32e..9435e85 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -22,6 +22,7 @@
import android.app.PendingIntent;
import android.app.TaskStackBuilder;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -46,6 +47,7 @@
import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
+import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.text.TextUtils;
import android.util.Log;
@@ -79,6 +81,7 @@
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Locale;
public abstract class BaseStatusBar extends SystemUI implements
@@ -86,6 +89,7 @@
public static final String TAG = "StatusBar";
public static final boolean DEBUG = false;
public static final boolean MULTIUSER_DEBUG = false;
+ private static final boolean USE_NOTIFICATION_LISTENER = false;
protected static final int MSG_SHOW_RECENT_APPS = 1019;
protected static final int MSG_HIDE_RECENT_APPS = 1020;
@@ -158,6 +162,7 @@
protected WindowManager mWindowManager;
protected IWindowManager mWindowManagerService;
+
protected abstract void refreshLayout(int layoutDirection);
protected Display mDisplay;
@@ -253,6 +258,49 @@
}
};
+ private final NotificationListenerService mNotificationListener =
+ new NotificationListenerService() {
+ @Override
+ public void onListenerConnected() {
+ if (DEBUG) Log.d(TAG, "onListenerConnected");
+ final StatusBarNotification[] notifications = getActiveNotifications();
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ for (StatusBarNotification sbn : notifications) {
+ addNotificationInternal(sbn);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onNotificationPosted(final StatusBarNotification sbn) {
+ if (DEBUG) Log.d(TAG, "onNotificationPosted: " + sbn);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mNotificationData.findByKey(sbn.getKey()) != null) {
+ updateNotificationInternal(sbn);
+ } else {
+ addNotificationInternal(sbn);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onNotificationRemoved(final StatusBarNotification sbn) {
+ if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ removeNotificationInternal(sbn.getKey());
+ }
+ });
+ }
+ };
+
private void updateCurrentProfilesCache() {
synchronized (mCurrentProfiles) {
mCurrentProfiles.clear();
@@ -299,14 +347,13 @@
// Connect in to the status bar manager service
StatusBarIconList iconList = new StatusBarIconList();
- ArrayList<IBinder> notificationKeys = new ArrayList<IBinder>();
ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>();
mCommandQueue = new CommandQueue(this, iconList);
int[] switches = new int[8];
ArrayList<IBinder> binders = new ArrayList<IBinder>();
try {
- mBarService.registerStatusBar(mCommandQueue, iconList, notificationKeys, notifications,
+ mBarService.registerStatusBar(mCommandQueue, iconList, notifications,
switches, binders);
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
@@ -332,17 +379,23 @@
}
}
- // Set up the initial notification state
- N = notificationKeys.size();
- if (N == notifications.size()) {
- for (int i=0; i<N; i++) {
- addNotification(notificationKeys.get(i), notifications.get(i));
+ // Set up the initial notification state.
+ if (USE_NOTIFICATION_LISTENER) {
+ try {
+ mNotificationListener.registerAsSystemService(
+ new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
+ UserHandle.USER_ALL);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to register notification listener", e);
}
} else {
- Log.wtf(TAG, "Notification list length mismatch: keys=" + N
- + " notifications=" + notifications.size());
+ N = notifications.size();
+ for (int i=0; i<N; i++) {
+ addNotification(notifications.get(i));
+ }
}
+
if (DEBUG) {
Log.d(TAG, String.format(
"init: icons=%d disabled=0x%08x lights=0x%08x menu=0x%08x imeButton=0x%08x",
@@ -1018,8 +1071,8 @@
*
* WARNING: this will call back into us. Don't hold any locks.
*/
- void handleNotificationError(IBinder key, StatusBarNotification n, String message) {
- removeNotification(key);
+ void handleNotificationError(StatusBarNotification n, String message) {
+ removeNotification(n.getKey());
try {
mBarService.onNotificationError(n.getPackageName(), n.getTag(), n.getId(), n.getUid(),
n.getInitialPid(), message, n.getUserId());
@@ -1028,7 +1081,7 @@
}
}
- protected StatusBarNotification removeNotificationViews(IBinder key) {
+ protected StatusBarNotification removeNotificationViews(String key) {
NotificationData.Entry entry = mNotificationData.remove(key);
if (entry == null) {
Log.w(TAG, "removeNotification for unknown key: " + key);
@@ -1039,14 +1092,14 @@
if (rowParent != null) rowParent.removeView(entry.row);
updateRowStates();
updateNotificationIcons();
+ updateSpeedBump();
return entry.notification;
}
- protected NotificationData.Entry createNotificationViews(IBinder key,
- StatusBarNotification notification) {
+ protected NotificationData.Entry createNotificationViews(StatusBarNotification notification) {
if (DEBUG) {
- Log.d(TAG, "createNotificationViews(key=" + key + ", notification=" + notification);
+ Log.d(TAG, "createNotificationViews(notification=" + notification);
}
// Construct the icon.
final StatusBarIconView iconView = new StatusBarIconView(mContext,
@@ -1061,13 +1114,13 @@
notification.getNotification().number,
notification.getNotification().tickerText);
if (!iconView.set(ic)) {
- handleNotificationError(key, notification, "Couldn't create icon: " + ic);
+ handleNotificationError(notification, "Couldn't create icon: " + ic);
return null;
}
// Construct the expanded view.
- NotificationData.Entry entry = new NotificationData.Entry(key, notification, iconView);
+ NotificationData.Entry entry = new NotificationData.Entry(notification, iconView);
if (!inflateViews(entry, mStackScroller)) {
- handleNotificationError(key, notification, "Couldn't expand RemoteViews for: "
+ handleNotificationError(notification, "Couldn't expand RemoteViews for: "
+ notification);
return null;
}
@@ -1083,12 +1136,26 @@
if (DEBUG) {
Log.d(TAG, "addNotificationViews: added at " + pos);
}
- updateNotificationIcons();
updateRowStates();
+ updateNotificationIcons();
+ updateSpeedBump();
}
- private void addNotificationViews(IBinder key, StatusBarNotification notification) {
- addNotificationViews(createNotificationViews(key, notification));
+ protected void updateSpeedBump() {
+ int n = mNotificationData.size();
+ int speedBumpIndex = -1;
+ for (int i = n-1; i >= 0; i--) {
+ NotificationData.Entry entry = mNotificationData.get(i);
+ if (entry.row.getVisibility() != View.GONE && speedBumpIndex == -1
+ && entry.row.isBelowSpeedBump() ) {
+ speedBumpIndex = n - 1 - i;
+ }
+ }
+ mStackScroller.updateSpeedBumpIndex(speedBumpIndex);
+ }
+
+ private void addNotificationViews(StatusBarNotification notification) {
+ addNotificationViews(createNotificationViews(notification));
}
/**
@@ -1104,7 +1171,6 @@
mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
int n = mNotificationData.size();
int visibleNotifications = 0;
- int speedBumpIndex = -1;
boolean onKeyguard = mState == StatusBarState.KEYGUARD;
for (int i = n-1; i >= 0; i--) {
NotificationData.Entry entry = mNotificationData.get(i);
@@ -1125,17 +1191,14 @@
mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
}
} else {
- if (entry.row.getVisibility() == View.GONE) {
+ boolean wasGone = entry.row.getVisibility() == View.GONE;
+ entry.row.setVisibility(View.VISIBLE);
+ if (wasGone) {
// notify the scroller of a child addition
mStackScroller.generateAddAnimation(entry.row);
}
- entry.row.setVisibility(View.VISIBLE);
visibleNotifications++;
}
- if (entry.row.getVisibility() != View.GONE && speedBumpIndex == -1
- && entry.row.isBelowSpeedBump() ) {
- speedBumpIndex = n - 1 - i;
- }
}
if (onKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) {
@@ -1143,8 +1206,6 @@
} else {
mKeyguardIconOverflowContainer.setVisibility(View.GONE);
}
-
- mStackScroller.updateSpeedBumpIndex(speedBumpIndex);
}
private boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
@@ -1160,7 +1221,7 @@
protected abstract void haltTicker();
protected abstract void setAreThereNotifications();
protected abstract void updateNotificationIcons();
- protected abstract void tick(IBinder key, StatusBarNotification n, boolean firstTime);
+ protected abstract void tick(StatusBarNotification n, boolean firstTime);
protected abstract void updateExpandedViewPos(int expandedPosition);
protected abstract boolean shouldDisableNavbarGestures();
@@ -1168,12 +1229,37 @@
return parent != null && parent.indexOfChild(entry.row) == 0;
}
- public void updateNotification(IBinder key, StatusBarNotification notification) {
- if (DEBUG) Log.d(TAG, "updateNotification(" + key + " -> " + notification + ")");
- final NotificationData.Entry oldEntry = mNotificationData.findByKey(key);
+ @Override
+ public void addNotification(StatusBarNotification notification) {
+ if (!USE_NOTIFICATION_LISTENER) {
+ addNotificationInternal(notification);
+ }
+ }
+
+ public abstract void addNotificationInternal(StatusBarNotification notification);
+
+ @Override
+ public void removeNotification(String key) {
+ if (!USE_NOTIFICATION_LISTENER) {
+ removeNotificationInternal(key);
+ }
+ }
+
+ protected abstract void removeNotificationInternal(String key);
+
+ public void updateNotification(StatusBarNotification notification) {
+ if (!USE_NOTIFICATION_LISTENER) {
+ updateNotificationInternal(notification);
+ }
+ }
+
+ public void updateNotificationInternal(StatusBarNotification notification) {
+ if (DEBUG) Log.d(TAG, "updateNotification(" + notification + ")");
+
+ final NotificationData.Entry oldEntry = mNotificationData.findByKey(notification.getKey());
if (oldEntry == null) {
- Log.w(TAG, "updateNotification for unknown key: " + key);
+ Log.w(TAG, "updateNotification for unknown key: " + notification.getKey());
return;
}
@@ -1244,15 +1330,15 @@
boolean orderUnchanged =
notification.getNotification().when == oldNotification.getNotification().when
&& notification.getScore() == oldNotification.getScore();
- // score now encompasses/supersedes isOngoing()
+ // score now encompasses/supersedes isOngoing()
boolean updateTicker = notification.getNotification().tickerText != null
&& !TextUtils.equals(notification.getNotification().tickerText,
- oldEntry.notification.getNotification().tickerText);
+ oldEntry.notification.getNotification().tickerText);
boolean isTopAnyway = isTopNotification(rowParent, oldEntry);
if (contentsUnchanged && bigContentsUnchanged && headsUpContentsUnchanged && publicUnchanged
&& (orderUnchanged || isTopAnyway)) {
- if (DEBUG) Log.d(TAG, "reusing notification for key: " + key);
+ if (DEBUG) Log.d(TAG, "reusing notification for key: " + notification.getKey());
oldEntry.notification = notification;
try {
updateNotificationViews(oldEntry, notification);
@@ -1276,25 +1362,27 @@
notification.getNotification().number,
notification.getNotification().tickerText);
if (!oldEntry.icon.set(ic)) {
- handleNotificationError(key, notification, "Couldn't update icon: " + ic);
+ handleNotificationError(notification, "Couldn't update icon: " + ic);
return;
}
updateRowStates();
+ updateSpeedBump();
}
catch (RuntimeException e) {
// It failed to add cleanly. Log, and remove the view from the panel.
Log.w(TAG, "Couldn't reapply views for package " + contentView.getPackage(), e);
- removeNotificationViews(key);
- addNotificationViews(key, notification);
+ removeNotificationViews(notification.getKey());
+ addNotificationViews(notification);
}
} else {
- if (DEBUG) Log.d(TAG, "not reusing notification for key: " + key);
+ if (DEBUG) Log.d(TAG, "not reusing notification for key: " + notification.getKey());
if (DEBUG) Log.d(TAG, "contents was " + (contentsUnchanged ? "unchanged" : "changed"));
if (DEBUG) Log.d(TAG, "order was " + (orderUnchanged ? "unchanged" : "changed"));
if (DEBUG) Log.d(TAG, "notification is " + (isTopAnyway ? "top" : "not top"));
- removeNotificationViews(key);
- addNotificationViews(key, notification); // will also replace the heads up
- final NotificationData.Entry newEntry = mNotificationData.findByKey(key);
+ removeNotificationViews(notification.getKey());
+ addNotificationViews(notification); // will also replace the heads up
+ final NotificationData.Entry newEntry = mNotificationData.findByKey(
+ notification.getKey());
final boolean userChangedExpansion = oldEntry.row.hasUserChangedExpansion();
if (userChangedExpansion) {
boolean userExpanded = oldEntry.row.isUserExpanded();
@@ -1314,7 +1402,7 @@
// Restart the ticker if it's still running
if (updateTicker && isForCurrentUser) {
haltTicker();
- tick(key, notification, false);
+ tick(notification, false);
}
// Recalculate the position of the sliding windows and the titles.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index b4a347b..aaeadb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -21,7 +21,6 @@
import android.os.Message;
import android.service.notification.StatusBarNotification;
-import com.android.internal.policy.IKeyguardShowCallback;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarIconList;
@@ -73,11 +72,6 @@
private Callbacks mCallbacks;
private Handler mHandler = new H();
- private class NotificationQueueEntry {
- IBinder key;
- StatusBarNotification notification;
- }
-
/**
* These methods are called back on the main thread.
*/
@@ -86,9 +80,9 @@
public void updateIcon(String slot, int index, int viewIndex,
StatusBarIcon old, StatusBarIcon icon);
public void removeIcon(String slot, int index, int viewIndex);
- public void addNotification(IBinder key, StatusBarNotification notification);
- public void updateNotification(IBinder key, StatusBarNotification notification);
- public void removeNotification(IBinder key);
+ public void addNotification(StatusBarNotification notification);
+ public void updateNotification(StatusBarNotification notification);
+ public void removeNotification(String key);
public void disable(int state);
public void animateExpandNotificationsPanel();
public void animateCollapsePanels(int flags);
@@ -106,7 +100,6 @@
public void showSearchPanel();
public void hideSearchPanel();
public void setWindowState(int window, int state);
-
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -130,25 +123,21 @@
}
}
- public void addNotification(IBinder key, StatusBarNotification notification) {
+ @Override
+ public void addNotification(StatusBarNotification notification) {
synchronized (mList) {
- NotificationQueueEntry ne = new NotificationQueueEntry();
- ne.key = key;
- ne.notification = notification;
- mHandler.obtainMessage(MSG_ADD_NOTIFICATION, 0, 0, ne).sendToTarget();
+ mHandler.obtainMessage(MSG_ADD_NOTIFICATION, 0, 0, notification).sendToTarget();
}
}
- public void updateNotification(IBinder key, StatusBarNotification notification) {
+ @Override
+ public void updateNotification(StatusBarNotification notification) {
synchronized (mList) {
- NotificationQueueEntry ne = new NotificationQueueEntry();
- ne.key = key;
- ne.notification = notification;
- mHandler.obtainMessage(MSG_UPDATE_NOTIFICATION, 0, 0, ne).sendToTarget();
+ mHandler.obtainMessage(MSG_UPDATE_NOTIFICATION, 0, 0, notification).sendToTarget();
}
}
- public void removeNotification(IBinder key) {
+ public void removeNotification(String key) {
synchronized (mList) {
mHandler.obtainMessage(MSG_REMOVE_NOTIFICATION, 0, 0, key).sendToTarget();
}
@@ -291,17 +280,15 @@
break;
}
case MSG_ADD_NOTIFICATION: {
- final NotificationQueueEntry ne = (NotificationQueueEntry)msg.obj;
- mCallbacks.addNotification(ne.key, ne.notification);
+ mCallbacks.addNotification((StatusBarNotification) msg.obj);
break;
}
case MSG_UPDATE_NOTIFICATION: {
- final NotificationQueueEntry ne = (NotificationQueueEntry)msg.obj;
- mCallbacks.updateNotification(ne.key, ne.notification);
+ mCallbacks.updateNotification((StatusBarNotification) msg.obj);
break;
}
case MSG_REMOVE_NOTIFICATION: {
- mCallbacks.removeNotification((IBinder)msg.obj);
+ mCallbacks.removeNotification((String) msg.obj);
break;
}
case MSG_DISABLE:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
index a42c194..843db04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -18,8 +18,8 @@
import android.content.Context;
import android.graphics.Outline;
+import android.graphics.RectF;
import android.util.AttributeSet;
-import android.widget.FrameLayout;
/**
* Like {@link ExpandableView}, but setting an outline for the height and clipping.
@@ -27,9 +27,12 @@
public abstract class ExpandableOutlineView extends ExpandableView {
private final Outline mOutline = new Outline();
+ private boolean mCustomOutline;
+ private float mDensity;
public ExpandableOutlineView(Context context, AttributeSet attrs) {
super(context, attrs);
+ mDensity = getResources().getDisplayMetrics().density;
}
@Override
@@ -50,11 +53,37 @@
updateOutline();
}
- private void updateOutline() {
- mOutline.setRect(0,
- mClipTopAmount,
- getWidth(),
- Math.max(mActualHeight, mClipTopAmount));
+ protected void setOutlineRect(RectF rect) {
+ if (rect != null) {
+ setOutlineRect(rect.left, rect.top, rect.right, rect.bottom);
+ } else {
+ mCustomOutline = false;
+ updateOutline();
+ }
+ }
+
+ protected void setOutlineRect(float left, float top, float right, float bottom) {
+ mCustomOutline = true;
+
+ int rectLeft = (int) left;
+ int rectTop = (int) top;
+ int rectRight = (int) right;
+ int rectBottom = (int) bottom;
+
+ // Outlines need to be at least 1 dp
+ rectBottom = (int) Math.max(top + mDensity, rectBottom);
+ rectRight = (int) Math.max(left + mDensity, rectRight);
+ mOutline.setRect(rectLeft, rectTop, rectRight, rectBottom);
setOutline(mOutline);
}
+
+ private void updateOutline() {
+ if (!mCustomOutline) {
+ mOutline.setRect(0,
+ mClipTopAmount,
+ getWidth(),
+ Math.max(mActualHeight, mClipTopAmount));
+ setOutline(mOutline);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index eaaac10..088f076 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -205,6 +205,21 @@
}
/**
+ * Perform a remove animation on this view.
+ *
+ * @param translationDirection The direction value from [-1 ... 1] indicating in which the
+ * animation should be performed. A value of -1 means that The
+ * remove animation should be performed upwards,
+ * such that the child appears to be going away to the top. 1
+ * Should mean the opposite.
+ * @param onFinishedRunnable A runnable which should be run when the animation is finished.
+ */
+ public abstract void performRemoveAnimation(float translationDirection,
+ Runnable onFinishedRunnable);
+
+ public abstract void performAddAnimation(long delay);
+
+ /**
* A listener notifying when {@link #getActualHeight} changes.
*/
public interface OnHeightChangedListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
index 8440b9f..0555879 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
@@ -18,8 +18,6 @@
import android.app.Notification;
import android.content.Context;
-import android.os.Binder;
-import android.os.IBinder;
import android.os.Process;
import android.provider.Settings;
import android.service.notification.StatusBarNotification;
@@ -33,13 +31,14 @@
public class InterceptedNotifications {
private static final String TAG = "InterceptedNotifications";
private static final String EXTRA_INTERCEPT = "android.intercept";
+ private static final String SYNTHETIC_KEY = "InterceptedNotifications.SYNTHETIC_KEY";
private final Context mContext;
private final PhoneStatusBar mBar;
- private final ArrayMap<IBinder, StatusBarNotification> mIntercepted
- = new ArrayMap<IBinder, StatusBarNotification>();
+ private final ArrayMap<String, StatusBarNotification> mIntercepted
+ = new ArrayMap<String, StatusBarNotification>();
- private Binder mSynKey;
+ private String mSynKey;
public InterceptedNotifications(Context context, PhoneStatusBar bar) {
mContext = context;
@@ -49,36 +48,35 @@
public void releaseIntercepted() {
final int n = mIntercepted.size();
for (int i = 0; i < n; i++) {
- final IBinder key = mIntercepted.keyAt(i);
final StatusBarNotification sbn = mIntercepted.valueAt(i);
sbn.getNotification().extras.putBoolean(EXTRA_INTERCEPT, false);
- mBar.addNotification(key, sbn);
+ mBar.addNotificationInternal(sbn);
}
mIntercepted.clear();
updateSyntheticNotification();
}
- public boolean tryIntercept(IBinder key, StatusBarNotification notification) {
+ public boolean tryIntercept(StatusBarNotification notification) {
if (!notification.getNotification().extras.getBoolean(EXTRA_INTERCEPT)) return false;
if (shouldDisplayIntercepted()) return false;
- mIntercepted.put(key, notification);
+ mIntercepted.put(notification.getKey(), notification);
updateSyntheticNotification();
return true;
}
- public void remove(IBinder key) {
+ public void remove(String key) {
if (mIntercepted.remove(key) != null) {
updateSyntheticNotification();
}
}
public boolean isSyntheticEntry(Entry ent) {
- return mSynKey != null && ent.key.equals(mSynKey);
+ return ent.key.equals(SYNTHETIC_KEY);
}
- public void update(IBinder key, StatusBarNotification notification) {
- if (mIntercepted.containsKey(key)) {
- mIntercepted.put(key, notification);
+ public void update(StatusBarNotification notification) {
+ if (mIntercepted.containsKey(notification.getKey())) {
+ mIntercepted.put(notification.getKey(), notification);
}
}
@@ -90,7 +88,7 @@
private void updateSyntheticNotification() {
if (mIntercepted.isEmpty()) {
if (mSynKey != null) {
- mBar.removeNotification(mSynKey);
+ mBar.removeNotificationInternal(mSynKey);
mSynKey = null;
}
return;
@@ -108,10 +106,10 @@
TAG.hashCode(), TAG, Process.myUid(), Process.myPid(), 0, n,
mBar.getCurrentUserHandle());
if (mSynKey == null) {
- mSynKey = new Binder();
- mBar.addNotification(mSynKey, sbn);
+ mSynKey = sbn.getKey();
+ mBar.addNotificationInternal(sbn);
} else {
- mBar.updateNotification(mSynKey, sbn);
+ mBar.updateNotificationInternal(sbn);
}
final NotificationData.Entry entry = mBar.mNotificationData.findByKey(mSynKey);
entry.row.setOnClickListener(mSynClickListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
index 3c080fe..1c2ca91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationBackgroundView.java
@@ -34,7 +34,6 @@
public NotificationBackgroundView(Context context, AttributeSet attrs) {
super(context, attrs);
- setWillNotDraw(false);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index b1a5750..5696246 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar;
-import android.os.IBinder;
import android.service.notification.StatusBarNotification;
import android.view.View;
import android.widget.ImageView;
@@ -29,7 +28,7 @@
*/
public class NotificationData {
public static final class Entry {
- public IBinder key;
+ public String key;
public StatusBarNotification notification;
public StatusBarIconView icon;
public ExpandableNotificationRow row; // the outer expanded view
@@ -39,8 +38,8 @@
public View expandedBig;
private boolean interruption;
public Entry() {}
- public Entry(IBinder key, StatusBarNotification n, StatusBarIconView ic) {
- this.key = key;
+ public Entry(StatusBarNotification n, StatusBarIconView ic) {
+ this.key = n.getKey();
this.notification = n;
this.icon = ic;
}
@@ -63,6 +62,7 @@
interruption = true;
}
}
+
private final ArrayList<Entry> mEntries = new ArrayList<Entry>();
private final Comparator<Entry> mEntryCmp = new Comparator<Entry>() {
// sort first by score, then by when
@@ -88,9 +88,9 @@
return mEntries.get(i);
}
- public Entry findByKey(IBinder key) {
+ public Entry findByKey(String key) {
for (Entry e : mEntries) {
- if (e.key == key) {
+ if (e.key.equals(key)) {
return e;
}
}
@@ -100,7 +100,7 @@
public int add(Entry entry) {
int i;
int N = mEntries.size();
- for (i=0; i<N; i++) {
+ for (i = 0; i < N; i++) {
if (mEntryCmp.compare(mEntries.get(i), entry) > 0) {
break;
}
@@ -109,7 +109,7 @@
return i;
}
- public Entry remove(IBinder key) {
+ public Entry remove(String key) {
Entry e = findByKey(key);
if (e != null) {
mEntries.remove(e);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
index 8ae503a..a2f8991 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
@@ -184,7 +184,7 @@
}
public void performVisibilityAnimation(boolean nowVisible) {
- animateDivider(nowVisible);
+ animateDivider(nowVisible, null /* onFinishedRunnable */);
// Animate explanation Text
if (mIsExpanded) {
@@ -192,7 +192,14 @@
}
}
- public void animateDivider(boolean nowVisible) {
+ /**
+ * Animate the divider to a new visibility.
+ *
+ * @param nowVisible should it now be visible
+ * @param onFinishedRunnable A runnable which should be run when the animation is
+ * finished.
+ */
+ public void animateDivider(boolean nowVisible, Runnable onFinishedRunnable) {
if (nowVisible != mDividerVisible) {
// Animate dividers
float endValue = nowVisible ? 1.0f : 0.0f;
@@ -204,7 +211,8 @@
.scaleX(endValue)
.scaleY(endValue)
.translationX(endTranslationXLeft)
- .setInterpolator(mFastOutSlowInInterpolator);
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .withEndAction(onFinishedRunnable);
mLineRight.animate()
.alpha(endValue)
.withLayer()
@@ -216,6 +224,10 @@
// Animate dots
mDots.performVisibilityAnimation(nowVisible);
mDividerVisible = nowVisible;
+ } else {
+ if (onFinishedRunnable != null) {
+ onFinishedRunnable.run();
+ }
}
}
@@ -250,6 +262,16 @@
}
}
+ @Override
+ public void performRemoveAnimation(float translationDirection, Runnable onFinishedRunnable) {
+ performVisibilityAnimation(false);
+ }
+
+ @Override
+ public void performAddAnimation(long delay) {
+ performVisibilityAnimation(true);
+ }
+
private void resetExplanationText() {
mExplanationText.setTranslationY(0);
mExplanationText.setVisibility(INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index fe7546d..0a44904 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -214,7 +214,7 @@
mClockAnimationTarget = -1;
}
});
- StackStateAnimator.startInstantly(mClockAnimator);
+ mClockAnimator.start();
return true;
}
});
@@ -478,6 +478,7 @@
mHeader.setExpansion(height);
setQsTranslation(height);
setQsStackScrollerPadding(height);
+ mStatusBar.userActivity();
}
private void setQsTranslation(float height) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 54af2c5..152ca3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1027,18 +1027,19 @@
return new UserHandle(mCurrentUserId);
}
- public void addNotification(IBinder key, StatusBarNotification notification) {
+ @Override
+ public void addNotificationInternal(StatusBarNotification notification) {
if (DEBUG) Log.d(TAG, "addNotification score=" + notification.getScore());
- Entry shadeEntry = createNotificationViews(key, notification);
+ Entry shadeEntry = createNotificationViews(notification);
if (shadeEntry == null) {
return;
}
- if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(key, notification)) {
+ if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(notification)) {
return;
}
if (mUseHeadsUp && shouldInterrupt(notification)) {
if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
- Entry interruptionCandidate = new Entry(key, notification, null);
+ Entry interruptionCandidate = new Entry(notification, null);
ViewGroup holder = mHeadsUpNotificationView.getHolder();
if (inflateViewsForHeadsUp(interruptionCandidate, holder)) {
mInterruptingNotificationTime = System.currentTimeMillis();
@@ -1070,7 +1071,7 @@
// show the ticker if there isn't already a heads up
if (mInterruptingNotificationEntry == null) {
- tick(null, notification, true);
+ tick(notification, true);
}
}
addNotificationViews(shadeEntry);
@@ -1089,12 +1090,13 @@
}
@Override
- public void updateNotification(IBinder key, StatusBarNotification notification) {
- super.updateNotification(key, notification);
- mIntercepted.update(key, notification);
+ public void updateNotification(StatusBarNotification notification) {
+ super.updateNotification(notification);
+ mIntercepted.update(notification);
}
- public void removeNotification(IBinder key) {
+ @Override
+ public void removeNotificationInternal(String key) {
StatusBarNotification old = removeNotificationViews(key);
if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
@@ -2019,7 +2021,7 @@
public void setHardKeyboardStatus(boolean available, boolean enabled) {}
@Override
- protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
+ protected void tick(StatusBarNotification n, boolean firstTime) {
// no ticking in lights-out mode
if (!areLightsOn()) return;
@@ -2766,6 +2768,7 @@
updateStackScrollerState();
updatePublicMode();
updateRowStates();
+ updateSpeedBump();
checkBarModes();
updateNotificationIcons();
updateCarrierLabelVisibility(false);
@@ -2776,9 +2779,8 @@
}
public void userActivity() {
- if (mState == StatusBarState.KEYGUARD) {
- mKeyguardViewMediatorCallback.userActivity();
- }
+ mHandler.removeCallbacks(mUserActivity);
+ mHandler.post(mUserActivity);
}
public boolean interceptMediaKey(KeyEvent event) {
@@ -2936,4 +2938,13 @@
public void onScreenTurnedOn() {
mStackScroller.setAnimationsEnabled(true);
}
+
+ private final Runnable mUserActivity = new Runnable() {
+ @Override
+ public void run() {
+ if (mState == StatusBarState.KEYGUARD) {
+ mKeyguardViewMediatorCallback.userActivity();
+ }
+ }
+ };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
index 41914ed..5e2d06b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/AnimationFilter.java
@@ -28,6 +28,7 @@
boolean animateScale;
boolean animateHeight;
boolean animateDimmed;
+ boolean hasDelays;
public AnimationFilter animateAlpha() {
animateAlpha = true;
@@ -39,6 +40,11 @@
return this;
}
+ public AnimationFilter hasDelays() {
+ hasDelays = true;
+ return this;
+ }
+
public AnimationFilter animateZ() {
animateZ = true;
return this;
@@ -79,6 +85,7 @@
animateScale |= filter.animateScale;
animateHeight |= filter.animateHeight;
animateDimmed |= filter.animateDimmed;
+ hasDelays |= filter.hasDelays;
}
private void reset() {
@@ -88,5 +95,6 @@
animateScale = false;
animateHeight = false;
animateDimmed = false;
+ hasDelays = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 90f3d17..079b184 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -103,6 +103,7 @@
private ArrayList<View> mChildrenToRemoveAnimated = new ArrayList<View>();
private ArrayList<View> mSnappedBackChildren = new ArrayList<View>();
private ArrayList<View> mDragAnimPendingChildren = new ArrayList<View>();
+ private ArrayList<View> mChildrenChangingPositions = new ArrayList<View>();
private ArrayList<AnimationEvent> mAnimationEvents
= new ArrayList<AnimationEvent>();
private ArrayList<View> mSwipedOutViews = new ArrayList<View>();
@@ -969,9 +970,24 @@
}
/**
+ * @return The first child which has visibility unequal to GONE which is currently below the
+ * given translationY or equal to it.
+ */
+ private View getFirstChildBelowTranlsationY(float translationY) {
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child.getVisibility() != View.GONE && child.getTranslationY() >= translationY) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ /**
* @return the last child which has visibility unequal to GONE
*/
- private View getLastChildNotGone() {
+ public View getLastChildNotGone() {
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
View child = getChildAt(i);
@@ -1094,23 +1110,41 @@
@Override
protected void onViewRemoved(View child) {
super.onViewRemoved(child);
+ mStackScrollAlgorithm.notifyChildrenChanged(this);
+ if (mChildrenChangingPositions.contains(child)) {
+ // This is only a position change, don't do anything special
+ return;
+ }
((ExpandableView) child).setOnHeightChangedListener(null);
mCurrentStackScrollState.removeViewStateForView(child);
- mStackScrollAlgorithm.notifyChildrenChanged(this);
updateScrollStateForRemovedChild(child);
- generateRemoveAnimation(child);
+ boolean animationGenerated = generateRemoveAnimation(child);
+ if (animationGenerated && !mSwipedOutViews.contains(child)) {
+ // Add this view to an overlay in order to ensure that it will still be temporary
+ // drawn when removed
+ getOverlay().add(child);
+ }
}
- private void generateRemoveAnimation(View child) {
+ /**
+ * Generate a remove animation for a child view.
+ *
+ * @param child The view to generate the remove animation for.
+ * @return Whether an animation was generated.
+ */
+ private boolean generateRemoveAnimation(View child) {
if (mIsExpanded && mAnimationsEnabled) {
if (!mChildrenToAddAnimated.contains(child)) {
// Generate Animations
mChildrenToRemoveAnimated.add(child);
mNeedsAnimation = true;
+ return true;
} else {
mChildrenToAddAnimated.remove(child);
+ return false;
}
}
+ return false;
}
/**
@@ -1155,9 +1189,7 @@
super.onViewAdded(child);
mStackScrollAlgorithm.notifyChildrenChanged(this);
((ExpandableView) child).setOnHeightChangedListener(this);
- if (child.getVisibility() != View.GONE) {
- generateAddAnimation(child);
- }
+ generateAddAnimation(child);
}
public void setAnimationsEnabled(boolean animationsEnabled) {
@@ -1168,10 +1200,13 @@
return mNeedsAnimation
&& (!mChildrenToAddAnimated.isEmpty() || !mChildrenToRemoveAnimated.isEmpty());
}
-
+ /**
+ * Generate an animation for an added child view.
+ *
+ * @param child The view to be added.
+ */
public void generateAddAnimation(View child) {
- if (mIsExpanded && mAnimationsEnabled) {
-
+ if (mIsExpanded && mAnimationsEnabled && !mChildrenChangingPositions.contains(child)) {
// Generate Animations
mChildrenToAddAnimated.add(child);
mNeedsAnimation = true;
@@ -1186,9 +1221,10 @@
*/
public void changeViewPosition(View child, int newIndex) {
if (child != null && child.getParent() == this) {
+ mChildrenChangingPositions.add(child);
removeView(child);
addView(child, newIndex);
- // TODO: handle events
+ mNeedsAnimation = true;
}
}
@@ -1197,16 +1233,18 @@
generateChildHierarchyEvents();
mNeedsAnimation = false;
}
- if (!mAnimationEvents.isEmpty()) {
+ if (!mAnimationEvents.isEmpty() || isCurrentlyAnimating()) {
mStateAnimator.startAnimationForEvents(mAnimationEvents, mCurrentStackScrollState);
+ mAnimationEvents.clear();
} else {
applyCurrentState();
}
}
private void generateChildHierarchyEvents() {
- generateChildAdditionEvents();
generateChildRemovalEvents();
+ generateChildAdditionEvents();
+ generatePositionChangeEvents();
generateSnapBackEvents();
generateDragEvents();
generateTopPaddingEvent();
@@ -1237,12 +1275,24 @@
int animationType = childWasSwipedOut
? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
: AnimationEvent.ANIMATION_TYPE_REMOVE;
- mAnimationEvents.add(new AnimationEvent(child, animationType));
+ AnimationEvent event = new AnimationEvent(child, animationType);
+
+ // we need to know the view after this one
+ event.viewAfterChangingView = getFirstChildBelowTranlsationY(child.getTranslationY());
+ mAnimationEvents.add(event);
}
mSwipedOutViews.clear();
mChildrenToRemoveAnimated.clear();
}
+ private void generatePositionChangeEvents() {
+ for (View child : mChildrenChangingPositions) {
+ mAnimationEvents.add(new AnimationEvent(child,
+ AnimationEvent.ANIMATION_TYPE_CHANGE_POSITION));
+ }
+ mChildrenChangingPositions.clear();
+ }
+
private void generateChildAdditionEvents() {
for (View child : mChildrenToAddAnimated) {
mAnimationEvents.add(new AnimationEvent(child,
@@ -1467,7 +1517,6 @@
public void onChildAnimationFinished() {
requestChildrenUpdate();
- mAnimationEvents.clear();
}
/**
@@ -1513,9 +1562,9 @@
}
private void updateSpeedBump(boolean visible) {
- int newVisibility = visible ? VISIBLE : GONE;
- int oldVisibility = mSpeedBumpView.getVisibility();
- if (newVisibility != oldVisibility) {
+ boolean notGoneBefore = mSpeedBumpView.getVisibility() != GONE;
+ if (visible != notGoneBefore) {
+ int newVisibility = visible ? VISIBLE : GONE;
mSpeedBumpView.setVisibility(newVisibility);
if (visible) {
mSpeedBumpView.collapse();
@@ -1551,21 +1600,24 @@
.animateAlpha()
.animateHeight()
.animateY()
- .animateZ(),
+ .animateZ()
+ .hasDelays(),
// ANIMATION_TYPE_REMOVE
new AnimationFilter()
.animateAlpha()
.animateHeight()
.animateY()
- .animateZ(),
+ .animateZ()
+ .hasDelays(),
// ANIMATION_TYPE_REMOVE_SWIPED_OUT
new AnimationFilter()
.animateAlpha()
.animateHeight()
.animateY()
- .animateZ(),
+ .animateZ()
+ .hasDelays(),
// ANIMATION_TYPE_TOP_PADDING_CHANGED
new AnimationFilter()
@@ -1593,16 +1645,23 @@
new AnimationFilter()
.animateY()
.animateScale()
- .animateDimmed()
+ .animateDimmed(),
+
+ // ANIMATION_TYPE_CHANGE_POSITION
+ new AnimationFilter()
+ .animateAlpha()
+ .animateHeight()
+ .animateY()
+ .animateZ()
};
static int[] LENGTHS = new int[] {
// ANIMATION_TYPE_ADD
- StackStateAnimator.ANIMATION_DURATION_STANDARD,
+ StackStateAnimator.ANIMATION_DURATION_APPEAR_DISAPPEAR,
// ANIMATION_TYPE_REMOVE
- StackStateAnimator.ANIMATION_DURATION_STANDARD,
+ StackStateAnimator.ANIMATION_DURATION_APPEAR_DISAPPEAR,
// ANIMATION_TYPE_REMOVE_SWIPED_OUT
StackStateAnimator.ANIMATION_DURATION_STANDARD,
@@ -1621,22 +1680,27 @@
// ANIMATION_TYPE_DIMMED
StackStateAnimator.ANIMATION_DURATION_DIMMED_ACTIVATED,
+
+ // ANIMATION_TYPE_CHANGE_POSITION
+ StackStateAnimator.ANIMATION_DURATION_STANDARD,
};
- static int ANIMATION_TYPE_ADD = 0;
- static int ANIMATION_TYPE_REMOVE = 1;
- static int ANIMATION_TYPE_REMOVE_SWIPED_OUT = 2;
- static int ANIMATION_TYPE_TOP_PADDING_CHANGED = 3;
- static int ANIMATION_TYPE_START_DRAG = 4;
- static int ANIMATION_TYPE_SNAP_BACK = 5;
- static int ANIMATION_TYPE_ACTIVATED_CHILD = 6;
- static int ANIMATION_TYPE_DIMMED = 7;
+ static final int ANIMATION_TYPE_ADD = 0;
+ static final int ANIMATION_TYPE_REMOVE = 1;
+ static final int ANIMATION_TYPE_REMOVE_SWIPED_OUT = 2;
+ static final int ANIMATION_TYPE_TOP_PADDING_CHANGED = 3;
+ static final int ANIMATION_TYPE_START_DRAG = 4;
+ static final int ANIMATION_TYPE_SNAP_BACK = 5;
+ static final int ANIMATION_TYPE_ACTIVATED_CHILD = 6;
+ static final int ANIMATION_TYPE_DIMMED = 7;
+ static final int ANIMATION_TYPE_CHANGE_POSITION = 8;
final long eventStartTime;
final View changingView;
final int animationType;
final AnimationFilter filter;
final long length;
+ View viewAfterChangingView;
AnimationEvent(View view, int type) {
eventStartTime = AnimationUtils.currentAnimationTimeMillis();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index d572ea5..bd2541a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -208,6 +208,8 @@
for (int i = 0; i < childCount; i++) {
ExpandableView v = (ExpandableView) hostView.getChildAt(i);
if (v.getVisibility() != View.GONE) {
+ StackScrollState.ViewState viewState = resultState.getViewStateForView(v);
+ viewState.notGoneIndex = state.visibleChildren.size();
state.visibleChildren.add(v);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 011411c..ae2acab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -39,14 +39,10 @@
private final ViewGroup mHostView;
private Map<ExpandableView, ViewState> mStateMap;
private final Rect mClipRect = new Rect();
- private int mBackgroundRoundedRectCornerRadius;
- private final Outline mChildOutline = new Outline();
public StackScrollState(ViewGroup hostView) {
mHostView = hostView;
mStateMap = new HashMap<ExpandableView, ViewState>();
- mBackgroundRoundedRectCornerRadius = hostView.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_quantum_rounded_rect_radius);
}
public ViewGroup getHostView() {
@@ -66,6 +62,7 @@
viewState.height = child.getIntrinsicHeight();
viewState.gone = child.getVisibility() == View.GONE;
viewState.alpha = 1;
+ viewState.notGoneIndex = -1;
}
}
@@ -190,7 +187,7 @@
if (nextChild != null) {
ViewState nextState = getViewStateForView(nextChild);
boolean startIsAboveNext = nextState.yTranslation > speedBumpStart;
- speedBump.animateDivider(startIsAboveNext);
+ speedBump.animateDivider(startIsAboveNext, null /* onFinishedRunnable */);
// handle expanded case
if (speedBump.isExpanded()) {
@@ -272,6 +269,11 @@
boolean dimmed;
/**
+ * The index of the view, only accounting for views not equal to GONE
+ */
+ int notGoneIndex;
+
+ /**
* The location this view is currently rendered at.
*
* <p>See <code>LOCATION_</code> flags.</p>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index a9dcdd6..f019e6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -39,7 +39,11 @@
public class StackStateAnimator {
public static final int ANIMATION_DURATION_STANDARD = 360;
+ public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464;
public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220;
+ public static final int ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING = 80;
+ public static final int ANIMATION_DELAY_PER_ELEMENT_MANUAL = 32;
+ private static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
private static final int TAG_ANIMATOR_TRANSLATION_Y = R.id.translation_y_animator_tag;
private static final int TAG_ANIMATOR_TRANSLATION_Z = R.id.translation_z_animator_tag;
@@ -62,10 +66,9 @@
private final Interpolator mFastOutSlowInInterpolator;
public NotificationStackScrollLayout mHostLayout;
- private ArrayList<NotificationStackScrollLayout.AnimationEvent> mHandledEvents =
- new ArrayList<>();
private ArrayList<NotificationStackScrollLayout.AnimationEvent> mNewEvents =
new ArrayList<>();
+ private ArrayList<View> mNewAddChildren = new ArrayList<>();
private Set<Animator> mAnimatorSet = new HashSet<Animator>();
private Stack<AnimatorListenerAdapter> mAnimationListenerPool
= new Stack<AnimatorListenerAdapter>();
@@ -96,57 +99,130 @@
mCurrentLength = NotificationStackScrollLayout.AnimationEvent.combineLength(mNewEvents);
for (int i = 0; i < childCount; i++) {
final ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
+
StackScrollState.ViewState viewState = finalState.getViewStateForView(child);
- if (viewState == null) {
+ if (viewState == null || child.getVisibility() == View.GONE) {
continue;
}
- startAnimations(child, viewState);
-
child.setClipBounds(null);
+ startAnimations(child, viewState, finalState);
}
if (!isRunning()) {
// no child has preformed any animation, lets finish
onAnimationFinished();
}
+ mNewEvents.clear();
+ mNewAddChildren.clear();
}
/**
* Start an animation to the given viewState
*/
- private void startAnimations(final ExpandableView child, StackScrollState.ViewState viewState) {
+ private void startAnimations(final ExpandableView child, StackScrollState.ViewState viewState,
+ StackScrollState finalState) {
int childVisibility = child.getVisibility();
boolean wasVisible = childVisibility == View.VISIBLE;
final float alpha = viewState.alpha;
if (!wasVisible && alpha != 0 && !viewState.gone) {
child.setVisibility(View.VISIBLE);
}
+
+ boolean yTranslationChanging = child.getTranslationY() != viewState.yTranslation;
+ boolean zTranslationChanging = child.getTranslationZ() != viewState.zTranslation;
+ boolean scaleChanging = child.getScaleX() != viewState.scale;
+ boolean alphaChanging = alpha != child.getAlpha();
+ boolean heightChanging = viewState.height != child.getActualHeight();
+ boolean wasAdded = mNewAddChildren.contains(child);
+ boolean hasDelays = mAnimationFilter.hasDelays;
+ boolean isDelayRelevant = yTranslationChanging || zTranslationChanging || scaleChanging ||
+ alphaChanging || heightChanging;
+ long delay = 0;
+ if (hasDelays && isDelayRelevant || wasAdded) {
+ delay = calculateChildAnimationDelay(viewState, finalState);
+ }
+
// start translationY animation
- if (child.getTranslationY() != viewState.yTranslation) {
- startYTranslationAnimation(child, viewState);
+ if (yTranslationChanging) {
+ startYTranslationAnimation(child, viewState, delay);
}
+
// start translationZ animation
- if (child.getTranslationZ() != viewState.zTranslation) {
- startZTranslationAnimation(child, viewState);
+ if (zTranslationChanging) {
+ startZTranslationAnimation(child, viewState, delay);
}
+
// start scale animation
- if (child.getScaleX() != viewState.scale) {
+ if (scaleChanging) {
startScaleAnimation(child, viewState);
}
+
// start alpha animation
- if (alpha != child.getAlpha()) {
- startAlphaAnimation(child, viewState);
+ if (alphaChanging) {
+ startAlphaAnimation(child, viewState, delay);
}
+
// start height animation
- if (viewState.height != child.getActualHeight()) {
- startHeightAnimation(child, viewState);
+ if (heightChanging) {
+ startHeightAnimation(child, viewState, delay);
}
+
// start dimmed animation
child.setDimmed(viewState.dimmed, mAnimationFilter.animateDimmed);
+
+ if (wasAdded) {
+ child.performAddAnimation(delay);
+ }
+ }
+
+ private long calculateChildAnimationDelay(StackScrollState.ViewState viewState,
+ StackScrollState finalState) {
+ long minDelay = 0;
+ for (NotificationStackScrollLayout.AnimationEvent event : mNewEvents) {
+ long delayPerElement = ANIMATION_DELAY_PER_ELEMENT_INTERRUPTING;
+ switch (event.animationType) {
+ case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_ADD: {
+ int ownIndex = viewState.notGoneIndex;
+ int changingIndex = finalState
+ .getViewStateForView(event.changingView).notGoneIndex;
+ int difference = Math.abs(ownIndex - changingIndex);
+ difference = Math.max(0, Math.min(DELAY_EFFECT_MAX_INDEX_DIFFERENCE,
+ difference - 1));
+ long delay = (DELAY_EFFECT_MAX_INDEX_DIFFERENCE - difference) * delayPerElement;
+ minDelay = Math.max(delay, minDelay);
+ break;
+ }
+ case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT:
+ delayPerElement = ANIMATION_DELAY_PER_ELEMENT_MANUAL;
+ case NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE: {
+ int ownIndex = viewState.notGoneIndex;
+ boolean noNextView = event.viewAfterChangingView == null;
+ View viewAfterChangingView = noNextView
+ ? mHostLayout.getLastChildNotGone()
+ : event.viewAfterChangingView;
+
+ int nextIndex = finalState
+ .getViewStateForView(viewAfterChangingView).notGoneIndex;
+ if (ownIndex >= nextIndex) {
+ // we only have the view afterwards
+ ownIndex++;
+ }
+ int difference = Math.abs(ownIndex - nextIndex);
+ difference = Math.max(0, Math.min(DELAY_EFFECT_MAX_INDEX_DIFFERENCE,
+ difference - 1));
+ long delay = difference * delayPerElement;
+ minDelay = Math.max(delay, minDelay);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return minDelay;
}
private void startHeightAnimation(final ExpandableView child,
- StackScrollState.ViewState viewState) {
+ StackScrollState.ViewState viewState, long delay) {
Integer previousStartValue = getChildTag(child, TAG_START_HEIGHT);
Integer previousEndValue = getChildTag(child, TAG_END_HEIGHT);
int newEndValue = viewState.height;
@@ -185,6 +261,9 @@
animator.setInterpolator(mFastOutSlowInInterpolator);
long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator);
animator.setDuration(newDuration);
+ if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) {
+ animator.setStartDelay(delay);
+ }
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
@@ -195,14 +274,14 @@
child.setTag(TAG_END_HEIGHT, null);
}
});
- startInstantly(animator);
+ startAnimator(animator);
child.setTag(TAG_ANIMATOR_HEIGHT, animator);
child.setTag(TAG_START_HEIGHT, child.getActualHeight());
child.setTag(TAG_END_HEIGHT, newEndValue);
}
private void startAlphaAnimation(final ExpandableView child,
- final StackScrollState.ViewState viewState) {
+ final StackScrollState.ViewState viewState, long delay) {
Float previousStartValue = getChildTag(child,TAG_START_ALPHA);
Float previousEndValue = getChildTag(child,TAG_END_ALPHA);
final float newEndValue = viewState.alpha;
@@ -236,14 +315,13 @@
child.getAlpha(), newEndValue);
animator.setInterpolator(mFastOutSlowInInterpolator);
// Handle layer type
- final int currentLayerType = child.getLayerType();
child.setLayerType(View.LAYER_TYPE_HARDWARE, null);
animator.addListener(new AnimatorListenerAdapter() {
public boolean mWasCancelled;
@Override
public void onAnimationEnd(Animator animation) {
- child.setLayerType(currentLayerType, null);
+ child.setLayerType(View.LAYER_TYPE_NONE, null);
if (newEndValue == 0 && !mWasCancelled) {
child.setVisibility(View.INVISIBLE);
}
@@ -264,6 +342,9 @@
});
long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator);
animator.setDuration(newDuration);
+ if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) {
+ animator.setStartDelay(delay);
+ }
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
@@ -272,14 +353,14 @@
}
});
- startInstantly(animator);
+ startAnimator(animator);
child.setTag(TAG_ANIMATOR_ALPHA, animator);
child.setTag(TAG_START_ALPHA, child.getAlpha());
child.setTag(TAG_END_ALPHA, newEndValue);
}
private void startZTranslationAnimation(final ExpandableView child,
- final StackScrollState.ViewState viewState) {
+ final StackScrollState.ViewState viewState, long delay) {
Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Z);
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Z);
float newEndValue = viewState.zTranslation;
@@ -311,6 +392,9 @@
animator.setInterpolator(mFastOutSlowInInterpolator);
long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator);
animator.setDuration(newDuration);
+ if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) {
+ animator.setStartDelay(delay);
+ }
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
@@ -321,14 +405,14 @@
child.setTag(TAG_END_TRANSLATION_Z, null);
}
});
- startInstantly(animator);
+ startAnimator(animator);
child.setTag(TAG_ANIMATOR_TRANSLATION_Z, animator);
child.setTag(TAG_START_TRANSLATION_Z, child.getTranslationZ());
child.setTag(TAG_END_TRANSLATION_Z, newEndValue);
}
private void startYTranslationAnimation(final ExpandableView child,
- StackScrollState.ViewState viewState) {
+ StackScrollState.ViewState viewState, long delay) {
Float previousStartValue = getChildTag(child,TAG_START_TRANSLATION_Y);
Float previousEndValue = getChildTag(child,TAG_END_TRANSLATION_Y);
float newEndValue = viewState.yTranslation;
@@ -361,6 +445,9 @@
animator.setInterpolator(mFastOutSlowInInterpolator);
long newDuration = cancelAnimatorAndGetNewDuration(previousAnimator);
animator.setDuration(newDuration);
+ if (delay > 0 && (previousAnimator == null || !previousAnimator.isRunning())) {
+ animator.setStartDelay(delay);
+ }
animator.addListener(getGlobalAnimationFinishedListener());
// remove the tag when the animation is finished
animator.addListener(new AnimatorListenerAdapter() {
@@ -371,7 +458,7 @@
child.setTag(TAG_END_TRANSLATION_Y, null);
}
});
- startInstantly(animator);
+ startAnimator(animator);
child.setTag(TAG_ANIMATOR_TRANSLATION_Y, animator);
child.setTag(TAG_START_TRANSLATION_Y, child.getTranslationY());
child.setTag(TAG_END_TRANSLATION_Y, newEndValue);
@@ -425,18 +512,15 @@
child.setTag(TAG_END_SCALE, null);
}
});
- startInstantly(animator);
+ startAnimator(animator);
child.setTag(TAG_ANIMATOR_SCALE, animator);
child.setTag(TAG_START_SCALE, child.getScaleX());
child.setTag(TAG_END_SCALE, newEndValue);
}
- /**
- * Start an animator instantly instead of waiting on the next synchronization frame
- */
- public static void startInstantly(ValueAnimator animator) {
+ private void startAnimator(ValueAnimator animator) {
+ mAnimatorSet.add(animator);
animator.start();
- animator.setCurrentPlayTime(0);
}
/**
@@ -468,7 +552,6 @@
@Override
public void onAnimationStart(Animator animation) {
- mAnimatorSet.add(animation);
mWasCancelled = false;
}
};
@@ -497,8 +580,6 @@
}
private void onAnimationFinished() {
- mHandledEvents.clear();
- mNewEvents.clear();
mHostLayout.onChildAnimationFinished();
}
@@ -511,27 +592,60 @@
private void processAnimationEvents(
ArrayList<NotificationStackScrollLayout.AnimationEvent> animationEvents,
StackScrollState finalState) {
- mNewEvents.clear();
for (NotificationStackScrollLayout.AnimationEvent event : animationEvents) {
- View changingView = event.changingView;
- if (!mHandledEvents.contains(event)) {
- if (event.animationType == NotificationStackScrollLayout.AnimationEvent
- .ANIMATION_TYPE_ADD) {
+ final ExpandableView changingView = (ExpandableView) event.changingView;
+ if (event.animationType ==
+ NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_ADD) {
- // This item is added, initialize it's properties.
- StackScrollState.ViewState viewState = finalState
- .getViewStateForView(changingView);
- if (viewState == null) {
- // The position for this child was never generated, let's continue.
- continue;
- }
- changingView.setAlpha(0);
- changingView.setTranslationY(viewState.yTranslation);
- changingView.setTranslationZ(viewState.zTranslation);
+ // This item is added, initialize it's properties.
+ StackScrollState.ViewState viewState = finalState
+ .getViewStateForView(changingView);
+ if (viewState == null) {
+ // The position for this child was never generated, let's continue.
+ continue;
}
- mHandledEvents.add(event);
- mNewEvents.add(event);
+ if (changingView.getVisibility() == View.GONE) {
+ // The view was set to gone but the state never removed
+ finalState.removeViewStateForView(changingView);
+ continue;
+ }
+ changingView.setAlpha(viewState.alpha);
+ changingView.setTranslationY(viewState.yTranslation);
+ changingView.setTranslationZ(viewState.zTranslation);
+ changingView.setActualHeight(viewState.height, false);
+ mNewAddChildren.add(changingView);
+
+ } else if (event.animationType ==
+ NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_REMOVE) {
+ if (changingView.getVisibility() == View.GONE) {
+ continue;
+ }
+
+ // Find the amount to translate up. This is needed in order to understand the
+ // direction of the remove animation (either downwards or upwards)
+ StackScrollState.ViewState viewState = finalState
+ .getViewStateForView(event.viewAfterChangingView);
+ int actualHeight = changingView.getActualHeight();
+ // upwards by default
+ float translationDirection = -1.0f;
+ if (viewState != null) {
+ // there was a view after this one, Approximate the distance the next child
+ // travelled
+ translationDirection = ((viewState.yTranslation
+ - (changingView.getTranslationY() + actualHeight / 2.0f)) * 2 /
+ actualHeight);
+ translationDirection = Math.max(Math.min(translationDirection, 1.0f),-1.0f);
+
+ }
+ changingView.performRemoveAnimation(translationDirection, new Runnable() {
+ @Override
+ public void run() {
+ // remove the temporary overlay
+ mHostLayout.getOverlay().remove(changingView);
+ }
+ });
}
+ mNewEvents.add(event);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 9006c9a..25147b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -46,15 +46,23 @@
}
@Override
- public void addNotification(IBinder key, StatusBarNotification notification) {
+ public void addNotification(StatusBarNotification notification) {
}
@Override
- public void updateNotification(IBinder key, StatusBarNotification notification) {
+ public void addNotificationInternal(StatusBarNotification notification) {
}
@Override
- public void removeNotification(IBinder key) {
+ public void updateNotification(StatusBarNotification notification) {
+ }
+
+ @Override
+ protected void removeNotificationInternal(String key) {
+ }
+
+ @Override
+ public void removeNotification(String key) {
}
@Override
@@ -113,7 +121,7 @@
}
@Override
- protected void tick(IBinder key, StatusBarNotification n, boolean firstTime) {
+ protected void tick(StatusBarNotification n, boolean firstTime) {
}
@Override
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 0d2cee8..5cfc49c 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -47,12 +47,14 @@
import android.util.Slog;
import com.android.internal.widget.ILockSettings;
+import com.android.internal.widget.ILockSettingsObserver;
import com.android.internal.widget.LockPatternUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -65,6 +67,9 @@
public class LockSettingsService extends ILockSettings.Stub {
private static final String PERMISSION = "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE";
+
+ private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
+
private final DatabaseHelper mOpenHelper;
private static final String TAG = "LockSettingsService";
@@ -85,6 +90,8 @@
private LockPatternUtils mLockPatternUtils;
private boolean mFirstCallToVold;
+ private final ArrayList<LockSettingsObserver> mObservers = new ArrayList<>();
+
public LockSettingsService(Context context) {
mContext = context;
// Open the database
@@ -222,6 +229,52 @@
return readFromDb(key, defaultValue, userId);
}
+ @Override
+ public void registerObserver(ILockSettingsObserver remote) throws RemoteException {
+ synchronized (mObservers) {
+ for (int i = 0; i < mObservers.size(); i++) {
+ if (mObservers.get(i).remote.asBinder() == remote.asBinder()) {
+ boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
+ if (isDebuggable) {
+ throw new IllegalStateException("Observer was already registered.");
+ } else {
+ Log.e(TAG, "Observer was already registered.");
+ return;
+ }
+ }
+ }
+ LockSettingsObserver o = new LockSettingsObserver();
+ o.remote = remote;
+ o.remote.asBinder().linkToDeath(o, 0);
+ mObservers.add(o);
+ }
+ }
+
+ @Override
+ public void unregisterObserver(ILockSettingsObserver remote) throws RemoteException {
+ synchronized (mObservers) {
+ for (int i = 0; i < mObservers.size(); i++) {
+ if (mObservers.get(i).remote.asBinder() == remote.asBinder()) {
+ mObservers.remove(i);
+ return;
+ }
+ }
+ }
+ }
+
+ public void notifyObservers(String key, int userId) {
+ synchronized (mObservers) {
+ for (int i = 0; i < mObservers.size(); i++) {
+ try {
+ mObservers.get(i).remote.onLockSettingChanged(key, userId);
+ } catch (RemoteException e) {
+ // The stack trace is not really helpful here.
+ Log.e(TAG, "Failed to notify ILockSettingsObserver: " + e);
+ }
+ }
+ }
+ }
+
private String getLockPatternFilename(int userId) {
String dataSystemDirectory =
android.os.Environment.getDataDirectory().getAbsolutePath() +
@@ -438,6 +491,7 @@
private void writeToDb(String key, String value, int userId) {
writeToDb(mOpenHelper.getWritableDatabase(), key, value, userId);
+ notifyObservers(key, userId);
}
private void writeToDb(SQLiteDatabase db, String key, String value, int userId) {
@@ -583,4 +637,13 @@
}
return null;
}
+
+ private class LockSettingsObserver implements DeathRecipient {
+ ILockSettingsObserver remote;
+
+ @Override
+ public void binderDied() {
+ mObservers.remove(this);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 584145f..b94ea62 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -175,7 +175,10 @@
public void registerService(IInterface service, ComponentName component, int userid) {
checkNotNull(service);
- registerServiceImpl(service, component, userid);
+ ManagedServiceInfo info = registerServiceImpl(service, component, userid);
+ if (info != null) {
+ onServiceAdded(info);
+ }
}
/**
@@ -464,7 +467,7 @@
}
}
- private void registerServiceImpl(final IInterface service,
+ private ManagedServiceInfo registerServiceImpl(final IInterface service,
final ComponentName component, final int userid) {
synchronized (mMutex) {
try {
@@ -472,10 +475,12 @@
true /*isSystem*/, null, Build.VERSION_CODES.L);
service.asBinder().linkToDeath(info, 0);
mServices.add(info);
+ return info;
} catch (RemoteException e) {
// already dead
}
}
+ return null;
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index 125158fd..db17f3a 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -20,7 +20,6 @@
import android.content.Context;
import android.util.Slog;
-import com.android.internal.R;
import com.android.server.notification.NotificationManagerService.NotificationRecord;
/**
@@ -39,7 +38,7 @@
if (DBG) Slog.d(TAG, "Initializing " + getClass().getSimpleName() + ".");
}
- public RankingFuture process(NotificationRecord record) {
+ public RankingReconsideration process(NotificationRecord record) {
if (record == null || record.getNotification() == null) {
if (DBG) Slog.d(TAG, "skipping empty notification");
return null;
@@ -54,10 +53,15 @@
record.setRecentlyIntusive(true);
}
- return new RankingFuture(record, HANG_TIME_MS) {
+ return new RankingReconsideration(record.getKey(), HANG_TIME_MS) {
@Override
public void work() {
- mRecord.setRecentlyIntusive(false);
+ // pass
+ }
+
+ @Override
+ public void applyChangesLocked(NotificationRecord record) {
+ record.setRecentlyIntusive(false);
}
};
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0b3e02a6..bbc3091 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -111,7 +111,6 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/** {@hide} */
@@ -453,11 +452,10 @@
- public static final class NotificationRecord
- {
+ public static final class NotificationRecord {
final StatusBarNotification sbn;
SingleNotificationStats stats;
- IBinder statusBarKey;
+ boolean isCanceled;
// These members are used by NotificationSignalExtractors
// to communicate with the ranking module.
@@ -472,6 +470,7 @@
public Notification getNotification() { return sbn.getNotification(); }
public int getFlags() { return sbn.getNotification().flags; }
public int getUserId() { return sbn.getUserId(); }
+ public String getKey() { return sbn.getKey(); }
void dump(PrintWriter pw, String prefix, Context baseContext) {
final Notification notification = sbn.getNotification();
@@ -555,13 +554,13 @@
return mContactAffinity;
}
- public boolean isRecentlyIntrusive() {
- return mRecentlyIntrusive;
- }
-
public void setRecentlyIntusive(boolean recentlyIntrusive) {
mRecentlyIntrusive = recentlyIntrusive;
}
+
+ public boolean isRecentlyIntrusive() {
+ return mRecentlyIntrusive;
+ }
}
private static final class ToastRecord
@@ -1263,7 +1262,7 @@
@Override
public void registerListener(final INotificationListener listener,
final ComponentName component, final int userid) {
- checkCallerIsSystem();
+ enforceSystemOrSystemUI("INotificationManager.registerListener");
mListeners.registerService(listener, component, userid);
}
@@ -1634,8 +1633,8 @@
if (!mSignalExtractors.isEmpty()) {
for (NotificationSignalExtractor extractor : mSignalExtractors) {
try {
- RankingFuture future = extractor.process(r);
- scheduleRankingReconsideration(future);
+ RankingReconsideration recon = extractor.process(r);
+ scheduleRankingReconsideration(recon);
} catch (Throwable t) {
Slog.w(TAG, "NotificationSignalExtractor failed.", t);
}
@@ -1668,7 +1667,7 @@
"pkg=" + pkg + " canInterrupt=" + canInterrupt + " intercept=" + intercept);
synchronized (mNotificationList) {
NotificationRecord old = null;
- int index = indexOfNotificationLocked(pkg, tag, id, userId);
+ int index = indexOfNotificationLocked(n.getKey());
if (index < 0) {
mNotificationList.add(r);
mUsageStats.registerPostedByApp(r);
@@ -1677,12 +1676,8 @@
mNotificationList.set(index, r);
mUsageStats.registerUpdatedByApp(r, old);
// Make sure we don't lose the foreground service state.
- if (old != null) {
- notification.flags |=
- old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
- }
- }
- if (old != null) {
+ notification.flags |=
+ old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
mNotificationsByKey.remove(old.sbn.getKey());
}
mNotificationsByKey.put(n.getKey(), r);
@@ -1705,18 +1700,17 @@
}
if (notification.icon != 0) {
- if (old != null && old.statusBarKey != null) {
- r.statusBarKey = old.statusBarKey;
+ if (old != null && !old.isCanceled) {
final long identity = Binder.clearCallingIdentity();
try {
- mStatusBar.updateNotification(r.statusBarKey, n);
+ mStatusBar.updateNotification(n);
} finally {
Binder.restoreCallingIdentity(identity);
}
} else {
final long identity = Binder.clearCallingIdentity();
try {
- r.statusBarKey = mStatusBar.addNotification(n);
+ mStatusBar.addNotification(n);
if ((n.getNotification().flags & Notification.FLAG_SHOW_LIGHTS) != 0
&& canInterrupt) {
mAttentionLight.pulse();
@@ -1733,10 +1727,10 @@
mListeners.notifyPostedLocked(r.sbn, cloneNotificationListLocked());
} else {
Slog.e(TAG, "Not posting notification with icon==0: " + notification);
- if (old != null && old.statusBarKey != null) {
+ if (old != null && !old.isCanceled) {
final long identity = Binder.clearCallingIdentity();
try {
- mStatusBar.removeNotification(old.statusBarKey);
+ mStatusBar.removeNotification(r.getKey());
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1986,37 +1980,38 @@
}
}
- private void scheduleRankingReconsideration(RankingFuture future) {
- if (future != null) {
- Message m = Message.obtain(mRankingHandler, MESSAGE_RECONSIDER_RANKING, future);
- long delay = future.getDelay(TimeUnit.MILLISECONDS);
+ private void scheduleRankingReconsideration(RankingReconsideration recon) {
+ if (recon != null) {
+ Message m = Message.obtain(mRankingHandler, MESSAGE_RECONSIDER_RANKING, recon);
+ long delay = recon.getDelay(TimeUnit.MILLISECONDS);
mRankingHandler.sendMessageDelayed(m, delay);
}
}
private void handleRankingReconsideration(Message message) {
- if (!(message.obj instanceof RankingFuture)) return;
-
- RankingFuture future = (RankingFuture) message.obj;
- future.run();
- try {
- NotificationRecord record = future.get();
- synchronized (mNotificationList) {
- int before = mNotificationList.indexOf(record);
- if (before != -1) {
- Collections.sort(mNotificationList, mRankingComparator);
- int after = mNotificationList.indexOf(record);
-
- if (before != after) {
- scheduleSendRankingUpdate();
- }
- }
+ if (!(message.obj instanceof RankingReconsideration)) return;
+ RankingReconsideration recon = (RankingReconsideration) message.obj;
+ recon.run();
+ boolean orderChanged;
+ synchronized (mNotificationList) {
+ final NotificationRecord record = mNotificationsByKey.get(recon.getKey());
+ if (record == null) {
+ return;
}
- } catch (InterruptedException e) {
- // we're running the future explicitly, so this should never happen
- } catch (ExecutionException e) {
- // we're running the future explicitly, so this should never happen
+ int before = findNotificationRecordIndexLocked(record);
+ recon.applyChangesLocked(record);
+ Collections.sort(mNotificationList, mRankingComparator);
+ int after = findNotificationRecordIndexLocked(record);
+ orderChanged = before != after;
}
+ if (orderChanged) {
+ scheduleSendRankingUpdate();
+ }
+ }
+
+ // lock on mNotificationList
+ private int findNotificationRecordIndexLocked(NotificationRecord target) {
+ return Collections.binarySearch(mNotificationList, target, mRankingComparator);
}
private void scheduleSendRankingUpdate() {
@@ -2120,11 +2115,11 @@
if (r.getNotification().icon != 0) {
final long identity = Binder.clearCallingIdentity();
try {
- mStatusBar.removeNotification(r.statusBarKey);
+ mStatusBar.removeNotification(r.getKey());
} finally {
Binder.restoreCallingIdentity(identity);
}
- r.statusBarKey = null;
+ r.isCanceled = true;
mListeners.notifyRemovedLocked(r.sbn, cloneNotificationListLocked());
}
@@ -2392,6 +2387,18 @@
return -1;
}
+ // lock on mNotificationList
+ int indexOfNotificationLocked(String key) {
+ NotificationRecord r = mNotificationsByKey.get(key);
+ if (r == null) {
+ return -1;
+ }
+ int index = Collections.binarySearch(mNotificationList, r, mRankingComparator);
+ // Guarantee to return -1 when not found.
+ return (index >= 0) ? index : -1;
+ }
+
+
private void updateNotificationPulse() {
synchronized (mNotificationList) {
updateLightsLocked();
diff --git a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
index a41fdfe..71c819e 100644
--- a/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationSignalExtractor.java
@@ -18,6 +18,8 @@
import android.content.Context;
+import com.android.server.notification.NotificationManagerService.NotificationRecord;
+
/**
* Extracts signals that will be useful to the {@link NotificationComparator} and caches them
* on the {@link NotificationManagerService.NotificationRecord} object. These annotations will
@@ -32,10 +34,10 @@
* Called once per notification that is posted or updated.
*
* @return null if the work is done, or a future if there is more to do. The
- * {@link RankingFuture} will be run on a worker thread, and if notifications are re-ordered
- * by that execution, the {@link NotificationManagerService} may send order update
- * events to the {@link android.service.notification.NotificationListenerService}s.
+ * {@link RankingReconsideration} will be run on a worker thread, and if notifications
+ * are re-ordered by that execution, the {@link NotificationManagerService} may send order
+ * update events to the {@link android.service.notification.NotificationListenerService}s.
*/
- public RankingFuture process(NotificationManagerService.NotificationRecord notification);
+ public RankingReconsideration process(NotificationRecord notification);
}
diff --git a/services/core/java/com/android/server/notification/RankingFuture.java b/services/core/java/com/android/server/notification/RankingFuture.java
deleted file mode 100644
index d711d02..0000000
--- a/services/core/java/com/android/server/notification/RankingFuture.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.notification;
-
-import java.util.concurrent.Delayed;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-public abstract class RankingFuture
- implements ScheduledFuture<NotificationManagerService.NotificationRecord> {
- private static final long IMMEDIATE = 0l;
-
- private static final int START = 0;
- private static final int RUNNING = 1;
- private static final int DONE = 2;
- private static final int CANCELLED = 3;
-
- private int mState;
- private long mDelay;
- protected NotificationManagerService.NotificationRecord mRecord;
-
- public RankingFuture(NotificationManagerService.NotificationRecord record) {
- this(record, IMMEDIATE);
- }
-
- public RankingFuture(NotificationManagerService.NotificationRecord record, long delay) {
- mDelay = delay;
- mRecord = record;
- mState = START;
- }
-
- public void run() {
- if (mState == START) {
- mState = RUNNING;
-
- work();
-
- mState = DONE;
- synchronized (this) {
- notifyAll();
- }
- }
- }
-
- @Override
- public long getDelay(TimeUnit unit) {
- return unit.convert(mDelay, TimeUnit.MILLISECONDS);
- }
-
- @Override
- public int compareTo(Delayed another) {
- return Long.compare(getDelay(TimeUnit.MILLISECONDS),
- another.getDelay(TimeUnit.MILLISECONDS));
- }
-
- @Override
- public boolean cancel(boolean mayInterruptIfRunning) {
- if (mState == START) { // can't cancel if running or done
- mState = CANCELLED;
- return true;
- }
- return false;
- }
-
- @Override
- public boolean isCancelled() {
- return mState == CANCELLED;
- }
-
- @Override
- public boolean isDone() {
- return mState == DONE;
- }
-
- @Override
- public NotificationManagerService.NotificationRecord get()
- throws InterruptedException, ExecutionException {
- while (!isDone()) {
- synchronized (this) {
- this.wait();
- }
- }
- return mRecord;
- }
-
- @Override
- public NotificationManagerService.NotificationRecord get(long timeout, TimeUnit unit)
- throws InterruptedException, ExecutionException, TimeoutException {
- long timeoutMillis = unit.convert(timeout, TimeUnit.MILLISECONDS);
- long start = System.currentTimeMillis();
- long now = System.currentTimeMillis();
- while (!isDone() && (now - start) < timeoutMillis) {
- try {
- wait(timeoutMillis - (now - start));
- } catch (InterruptedException e) {
- now = System.currentTimeMillis();
- }
- }
- return mRecord;
- }
-
- public abstract void work();
-}
diff --git a/services/core/java/com/android/server/notification/RankingReconsideration.java b/services/core/java/com/android/server/notification/RankingReconsideration.java
new file mode 100644
index 0000000..cf5e210
--- /dev/null
+++ b/services/core/java/com/android/server/notification/RankingReconsideration.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.notification;
+
+import com.android.server.notification.NotificationManagerService.NotificationRecord;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Represents future work required to extract signals from notifications for ranking.
+ *
+ * {@hide}
+ */
+public abstract class RankingReconsideration implements Runnable {
+ private static final long IMMEDIATE = 0l;
+
+ private static final int START = 0;
+ private static final int RUNNING = 1;
+ private static final int DONE = 2;
+ private static final int CANCELLED = 3;
+
+ private int mState;
+ private long mDelay;
+ protected String mKey;
+
+ public RankingReconsideration(String key) {
+ this(key, IMMEDIATE);
+ }
+
+ public RankingReconsideration(String key, long delay) {
+ mDelay = delay;
+ mKey = key;
+ mState = START;
+ }
+
+ public String getKey() {
+ return mKey;
+ }
+
+ public void run() {
+ if (mState == START) {
+ mState = RUNNING;
+
+ work();
+
+ mState = DONE;
+ synchronized (this) {
+ notifyAll();
+ }
+ }
+ }
+
+ public long getDelay(TimeUnit unit) {
+ return unit.convert(mDelay, TimeUnit.MILLISECONDS);
+ }
+
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ if (mState == START) { // can't cancel if running or done
+ mState = CANCELLED;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isCancelled() {
+ return mState == CANCELLED;
+ }
+
+ public boolean isDone() {
+ return mState == DONE;
+ }
+
+ /**
+ * Analyse the notification. This will be called on a worker thread. To
+ * avoid concurrency issues, do not use held references to modify the
+ * {@link NotificationRecord}.
+ */
+ public abstract void work();
+
+ /**
+ * Apply any computed changes to the notification record. This method will be
+ * called on the main service thread, synchronized on he mNotificationList.
+ * @param record The locked record to be updated.
+ */
+ public abstract void applyChangesLocked(NotificationRecord record);
+}
diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
index b5c2730..157d749 100644
--- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
+++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java
@@ -59,7 +59,7 @@
// maps raw person handle to resolved person object
private LruCache<String, LookupResult> mPeopleCache;
- private RankingFuture validatePeople(NotificationRecord record) {
+ private RankingReconsideration validatePeople(final NotificationRecord record) {
float affinity = NONE;
Bundle extras = record.getNotification().extras;
if (extras == null) {
@@ -99,11 +99,11 @@
}
if (DEBUG) Slog.d(TAG, "Pending: future work scheduled for: " + record.sbn.getKey());
- return new RankingFuture(record) {
+ return new RankingReconsideration(record.getKey()) {
+ float mContactAffinity = NONE;
@Override
public void work() {
- if (INFO) Slog.i(TAG, "Executing: validation for: " + mRecord.sbn.getKey());
- float affinity = NONE;
+ if (INFO) Slog.i(TAG, "Executing: validation for: " + record.getKey());
for (final String handle: pendingLookups) {
LookupResult lookupResult = null;
final Uri uri = Uri.parse(handle);
@@ -124,13 +124,16 @@
synchronized (mPeopleCache) {
mPeopleCache.put(handle, lookupResult);
}
- affinity = Math.max(affinity, lookupResult.getAffinity());
+ mContactAffinity = Math.max(mContactAffinity, lookupResult.getAffinity());
}
}
- float affinityBound = mRecord.getContactAffinity();
- affinity = Math.max(affinity, affinityBound);
- mRecord.setContactAffinity(affinity);
- if (INFO) Slog.i(TAG, "final affinity: " + affinity);
+ }
+
+ @Override
+ public void applyChangesLocked(NotificationRecord operand) {
+ float affinityBound = operand.getContactAffinity();
+ operand.setContactAffinity(Math.max(mContactAffinity, affinityBound));
+ if (INFO) Slog.i(TAG, "final affinity: " + operand.getContactAffinity());
}
};
}
@@ -229,7 +232,7 @@
mContext.getContentResolver(), SETTING_ENABLE_PEOPLE_VALIDATOR, 1);
}
- public RankingFuture process(NotificationManagerService.NotificationRecord record) {
+ public RankingReconsideration process(NotificationRecord record) {
if (!mEnabled) {
if (INFO) Slog.i(TAG, "disabled");
return null;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 0fa0b14..b06b090 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -6140,7 +6140,12 @@
}
final String nativeLibraryPath = (new File(libDir, apkName)).getPath();
pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
- pkgSetting.nativeLibraryPathString = nativeLibraryPath;
+ // pkgSetting might be null during rescan following uninstall of updates
+ // to a bundled app, so accommodate that possibility. The settings in
+ // that case will be established later from the parsed package.
+ if (pkgSetting != null) {
+ pkgSetting.nativeLibraryPathString = nativeLibraryPath;
+ }
}
// Deduces the required ABI of an upgraded system app.
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 4f75189..8d905ba 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -23,7 +23,7 @@
public interface StatusBarManagerInternal {
void setNotificationDelegate(NotificationDelegate delegate);
- IBinder addNotification(StatusBarNotification notification);
- void updateNotification(IBinder key, StatusBarNotification notification);
- void removeNotification(IBinder key);
+ void addNotification(StatusBarNotification notification);
+ void updateNotification(StatusBarNotification notification);
+ void removeNotification(String key);
}
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 8b8c73d..55b5e3b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -60,8 +60,8 @@
private NotificationDelegate mNotificationDelegate;
private volatile IStatusBar mBar;
private StatusBarIconList mIcons = new StatusBarIconList();
- private HashMap<IBinder,StatusBarNotification> mNotifications
- = new HashMap<IBinder,StatusBarNotification>();
+ private HashMap<String,StatusBarNotification> mNotifications
+ = new HashMap<String,StatusBarNotification>();
// for disabling the status bar
private final ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
@@ -117,30 +117,29 @@
}
@Override
- public IBinder addNotification(StatusBarNotification notification) {
+ public void addNotification(StatusBarNotification notification) {
synchronized (mNotifications) {
- IBinder key = new Binder();
- mNotifications.put(key, notification);
+ mNotifications.put(notification.getKey(), notification);
if (mBar != null) {
try {
- mBar.addNotification(key, notification);
+ mBar.addNotification(notification);
} catch (RemoteException ex) {
}
}
- return key;
}
}
@Override
- public void updateNotification(IBinder key, StatusBarNotification notification) {
+ public void updateNotification(StatusBarNotification notification) {
synchronized (mNotifications) {
+ String key = notification.getKey();
if (!mNotifications.containsKey(key)) {
throw new IllegalArgumentException("updateNotification key not found: " + key);
}
- mNotifications.put(key, notification);
+ mNotifications.put(notification.getKey(), notification);
if (mBar != null) {
try {
- mBar.updateNotification(key, notification);
+ mBar.updateNotification(notification);
} catch (RemoteException ex) {
}
}
@@ -148,7 +147,7 @@
}
@Override
- public void removeNotification(IBinder key) {
+ public void removeNotification(String key) {
synchronized (mNotifications) {
final StatusBarNotification n = mNotifications.remove(key);
if (n == null) {
@@ -512,8 +511,7 @@
// ================================================================================
@Override
public void registerStatusBar(IStatusBar bar, StatusBarIconList iconList,
- List<IBinder> notificationKeys, List<StatusBarNotification> notifications,
- int switches[], List<IBinder> binders) {
+ List<StatusBarNotification> notifications, int switches[], List<IBinder> binders) {
enforceStatusBarService();
Slog.i(TAG, "registerStatusBar bar=" + bar);
@@ -522,9 +520,8 @@
iconList.copyFrom(mIcons);
}
synchronized (mNotifications) {
- for (Map.Entry<IBinder,StatusBarNotification> e: mNotifications.entrySet()) {
- notificationKeys.add(e.getKey());
- notifications.add(e.getValue());
+ for (StatusBarNotification sbn : mNotifications.values()) {
+ notifications.add(sbn);
}
}
synchronized (mLock) {
@@ -714,7 +711,7 @@
synchronized (mNotifications) {
int i=0;
pw.println("Notification list:");
- for (Map.Entry<IBinder,StatusBarNotification> e: mNotifications.entrySet()) {
+ for (Map.Entry<String,StatusBarNotification> e: mNotifications.entrySet()) {
pw.printf(" %2d: %s\n", i, e.getValue().toString());
i++;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 4e4d127..5395f60 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3351,6 +3351,44 @@
}
@Override
+ public UserHandle createUser(ComponentName who, String name) {
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+
+ long id = Binder.clearCallingIdentity();
+ try {
+ UserInfo userInfo = mUserManager.createUser(name, 0 /* flags */);
+ if (userInfo != null) {
+ return userInfo.getUserHandle();
+ }
+ return null;
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+ }
+
+ @Override
+ public boolean removeUser(ComponentName who, UserHandle userHandle) {
+ synchronized (this) {
+ if (who == null) {
+ throw new NullPointerException("ComponentName is null");
+ }
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+
+ long id = Binder.clearCallingIdentity();
+ try {
+ return mUserManager.removeUser(userHandle.getIdentifier());
+ } finally {
+ restoreCallingIdentity(id);
+ }
+ }
+ }
+
+ @Override
public Bundle getApplicationRestrictions(ComponentName who, String packageName) {
final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
index 6ad01a0..0f4e122 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/DisplayModifier.java
@@ -302,6 +302,36 @@
paint.setShader(ResourceModifiers.instance().mVertGradient);
}
});
+ put("radGradient", new DisplayModifier() {
+ @Override
+ public void modifyDrawing(Paint paint, Canvas canvas) {
+ paint.setShader(ResourceModifiers.instance().mRadGradient);
+ }
+ });
+ put("sweepGradient", new DisplayModifier() {
+ @Override
+ public void modifyDrawing(Paint paint, Canvas canvas) {
+ paint.setShader(ResourceModifiers.instance().mSweepGradient);
+ }
+ });
+ put("composeShader", new DisplayModifier() {
+ @Override
+ public void modifyDrawing(Paint paint, Canvas canvas) {
+ paint.setShader(ResourceModifiers.instance().mComposeShader);
+ }
+ });
+ put("bad composeShader", new DisplayModifier() {
+ @Override
+ public void modifyDrawing(Paint paint, Canvas canvas) {
+ paint.setShader(ResourceModifiers.instance().mBadComposeShader);
+ }
+ });
+ put("bad composeShader 2", new DisplayModifier() {
+ @Override
+ public void modifyDrawing(Paint paint, Canvas canvas) {
+ paint.setShader(ResourceModifiers.instance().mAnotherBadComposeShader);
+ }
+ });
}
});
diff --git a/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java b/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java
index c705443..d522481 100644
--- a/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java
+++ b/tests/CanvasCompare/src/com/android/test/hwuicompare/ResourceModifiers.java
@@ -23,7 +23,11 @@
import android.graphics.BitmapFactory;
import android.graphics.BitmapShader;
import android.graphics.Color;
+import android.graphics.ComposeShader;
import android.graphics.LinearGradient;
+import android.graphics.PorterDuff;
+import android.graphics.RadialGradient;
+import android.graphics.SweepGradient;
import android.graphics.Matrix;
import android.graphics.Shader;
@@ -38,6 +42,11 @@
public final LinearGradient mHorGradient;
public final LinearGradient mDiagGradient;
public final LinearGradient mVertGradient;
+ public final RadialGradient mRadGradient;
+ public final SweepGradient mSweepGradient;
+ public final ComposeShader mComposeShader;
+ public final ComposeShader mBadComposeShader;
+ public final ComposeShader mAnotherBadComposeShader;
public final Bitmap mBitmap;
private final Matrix mMtx1;
private final Matrix mMtx2;
@@ -90,6 +99,12 @@
mVertGradient = new LinearGradient(0.0f, 0.0f, 0.0f, mDrawHeight / 2.0f,
Color.YELLOW, Color.MAGENTA, Shader.TileMode.MIRROR);
+ mSweepGradient = new SweepGradient(mDrawWidth / 2.0f, mDrawHeight / 2.0f,
+ Color.YELLOW, Color.MAGENTA);
+
+ mComposeShader = new ComposeShader(mRepeatShader, mHorGradient,
+ PorterDuff.Mode.MULTIPLY);
+
final float width = mBitmap.getWidth() / 8.0f;
final float height = mBitmap.getHeight() / 8.0f;
@@ -106,6 +121,16 @@
0xff00ff00, 0xff0000ff, 0xffff0000, 0xff00ff00,
0x00ff0000, 0x0000ff00, 0x000000ff, 0x00ff0000,
};
+
+ // Use a repeating gradient with many colors to test the non simple case.
+ mRadGradient = new RadialGradient(mDrawWidth / 4.0f, mDrawHeight / 4.0f, 4.0f,
+ mBitmapColors, null, Shader.TileMode.REPEAT);
+
+ mBadComposeShader = new ComposeShader(mRadGradient, mComposeShader,
+ PorterDuff.Mode.MULTIPLY);
+
+ mAnotherBadComposeShader = new ComposeShader(mRadGradient, mVertGradient,
+ PorterDuff.Mode.MULTIPLY);
}
}