Merge "Restore windowMinWidthMajor/Minor in alert dialog overlay theme"
diff --git a/api/current.txt b/api/current.txt
index 2ddbcce..180f0d41 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -13178,6 +13178,7 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AF;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> DEPTH_DEPTH_IS_EXCLUSIVE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> EDGE_AVAILABLE_EDGE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> FLASH_INFO_AVAILABLE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES;
@@ -13406,6 +13407,7 @@
field public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2; // 0x2
field public static final int HOT_PIXEL_MODE_OFF = 0; // 0x0
field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1
+ field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; // 0x3
field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2
field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0
field public static final int LENS_FACING_BACK = 1; // 0x1
@@ -13424,6 +13426,7 @@
field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0
field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0
field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6
+ field public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8; // 0x8
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
field public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4; // 0x4
@@ -14911,9 +14914,12 @@
method public int getSampleRate();
method public int getState();
method public int read(byte[], int, int);
+ method public int read(byte[], int, int, int);
method public int read(short[], int, int);
+ method public int read(short[], int, int, int);
method public int read(float[], int, int, int);
method public int read(java.nio.ByteBuffer, int);
+ method public int read(java.nio.ByteBuffer, int, int);
method public void release();
method public int setNotificationMarkerPosition(int);
method public int setPositionNotificationPeriod(int);
@@ -14996,7 +15002,9 @@
method public int setVolume(float);
method public void stop() throws java.lang.IllegalStateException;
method public int write(byte[], int, int);
+ method public int write(byte[], int, int, int);
method public int write(short[], int, int);
+ method public int write(short[], int, int, int);
method public int write(float[], int, int, int);
method public int write(java.nio.ByteBuffer, int, int);
field public static final int ERROR = -1; // 0xffffffff
diff --git a/api/system-current.txt b/api/system-current.txt
index ea97e1a..76c0261 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -13474,6 +13474,7 @@
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AF;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Integer> CONTROL_MAX_REGIONS_AWB;
+ field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> DEPTH_DEPTH_IS_EXCLUSIVE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> EDGE_AVAILABLE_EDGE_MODES;
field public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> FLASH_INFO_AVAILABLE;
field public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES;
@@ -13702,6 +13703,7 @@
field public static final int HOT_PIXEL_MODE_HIGH_QUALITY = 2; // 0x2
field public static final int HOT_PIXEL_MODE_OFF = 0; // 0x0
field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1
+ field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3; // 0x3
field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2; // 0x2
field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0
field public static final int LENS_FACING_BACK = 1; // 0x1
@@ -13720,6 +13722,7 @@
field public static final int NOISE_REDUCTION_MODE_OFF = 0; // 0x0
field public static final int REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE = 0; // 0x0
field public static final int REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE = 6; // 0x6
+ field public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8; // 0x8
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING = 2; // 0x2
field public static final int REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR = 1; // 0x1
field public static final int REQUEST_AVAILABLE_CAPABILITIES_OPAQUE_REPROCESSING = 4; // 0x4
@@ -16121,9 +16124,12 @@
method public int getSampleRate();
method public int getState();
method public int read(byte[], int, int);
+ method public int read(byte[], int, int, int);
method public int read(short[], int, int);
+ method public int read(short[], int, int, int);
method public int read(float[], int, int, int);
method public int read(java.nio.ByteBuffer, int);
+ method public int read(java.nio.ByteBuffer, int, int);
method public void release();
method public int setNotificationMarkerPosition(int);
method public int setPositionNotificationPeriod(int);
@@ -16208,7 +16214,9 @@
method public int setVolume(float);
method public void stop() throws java.lang.IllegalStateException;
method public int write(byte[], int, int);
+ method public int write(byte[], int, int, int);
method public int write(short[], int, int);
+ method public int write(short[], int, int, int);
method public int write(float[], int, int, int);
method public int write(java.nio.ByteBuffer, int, int);
field public static final int ERROR = -1; // 0xffffffff
@@ -32712,10 +32720,6 @@
field public static final java.lang.String BOOL_CARRIER_VOLTE_TTY_SUPPORTED = "bool_carrier_volte_tty_supported";
field public static final java.lang.String BOOL_SHOW_APN_SETTING_CDMA = "bool_show_apn_setting_cdma";
field public static final java.lang.String INT_VOLTE_REPLACEMENT_RAT = "int_volte_replacement_rat";
- field public static final java.lang.String SHORT_VVM_PORT_NUMBER = "string_vvm_port_number";
- field public static final java.lang.String STRING_VVM_DESTINATION_NUMBER = "string_vvm_destination_number";
- field public static final java.lang.String STRING_VVM_TYPE = "string_vvm_type";
- field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
public final class CellIdentityCdma implements android.os.Parcelable {
diff --git a/cmds/app_process/Android.mk b/cmds/app_process/Android.mk
index dd5e0ea..ce6d7b5 100644
--- a/cmds/app_process/Android.mk
+++ b/cmds/app_process/Android.mk
@@ -56,6 +56,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_EXECUTABLES)/asan
LOCAL_MODULE_STEM := app_process
LOCAL_ADDRESS_SANITIZER := true
+LOCAL_CLANG := true
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 256d87d..add7af2 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -93,15 +93,20 @@
}
static boolean sSystemReady = false;
+ static public void broadcastStickyIntent(Intent intent, String permission, int userId) {
+ broadcastStickyIntent(intent, permission, AppOpsManager.OP_NONE, userId);
+ }
+
/**
* Convenience for sending a sticky broadcast. For internal use only.
* If you don't care about permission, use null.
*/
- static public void broadcastStickyIntent(Intent intent, String permission, int userId) {
+ static public void broadcastStickyIntent(Intent intent, String permission, int appOp,
+ int userId) {
try {
getDefault().broadcastIntent(
null, intent, null, null, Activity.RESULT_OK, null, null,
- null /*permission*/, AppOpsManager.OP_NONE, false, true, userId);
+ null /*permission*/, appOp, false, true, userId);
} catch (RemoteException ex) {
}
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 381c20c..06ece8e 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -16,6 +16,7 @@
package android.app;
+import android.Manifest;
import android.annotation.SystemApi;
import android.app.usage.UsageStatsManager;
import android.content.Context;
@@ -212,8 +213,10 @@
public static final int OP_ASSIST_STRUCTURE = 49;
/** @hide Received a screenshot from assist. */
public static final int OP_ASSIST_SCREENSHOT = 50;
+ /** @hide Read the phone state. */
+ public static final int OP_READ_PHONE_STATE = 51;
/** @hide */
- public static final int _NUM_OP = 51;
+ public static final int _NUM_OP = 52;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION =
@@ -294,6 +297,7 @@
OP_WRITE_WALLPAPER,
OP_ASSIST_STRUCTURE,
OP_ASSIST_SCREENSHOT,
+ OP_READ_PHONE_STATE
};
/**
@@ -352,6 +356,7 @@
null,
null,
null,
+ null
};
/**
@@ -409,7 +414,8 @@
"ACTIVATE_VPN",
"WRITE_WALLPAPER",
"ASSIST_STRUCTURE",
- "ASSIST_SCREENSHOT"
+ "ASSIST_SCREENSHOT",
+ "OP_READ_PHONE_STATE"
};
/**
@@ -468,6 +474,7 @@
null, // no permission for supporting wallpaper
null, // no permission for receiving assist structure
null, // no permission for receiving assist screenshot
+ Manifest.permission.READ_PHONE_STATE
};
/**
@@ -527,6 +534,7 @@
UserManager.DISALLOW_WALLPAPER, // WRITE_WALLPAPER
null, // ASSIST_STRUCTURE
null, // ASSIST_SCREENSHOT
+ null // READ_PHONE_STATE
};
/**
@@ -585,6 +593,7 @@
false, //WALLPAPER
false, //ASSIST_STRUCTURE
false, //ASSIST_SCREENSHOT
+ false, //READ_PHONE_STATE
};
/**
@@ -642,6 +651,7 @@
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
AppOpsManager.MODE_ALLOWED,
+ AppOpsManager.MODE_ALLOWED
};
/**
@@ -703,6 +713,7 @@
false,
false,
false,
+ false
};
private static HashMap<String, Integer> sOpStrToOp = new HashMap<String, Integer>();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4ccd69f..81a78f6 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -860,13 +860,19 @@
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission) {
+ sendBroadcastAsUser(intent, user, receiverPermission, AppOpsManager.OP_NONE);
+ }
+
+ @Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user,
+ String receiverPermission, int appOp) {
String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
try {
intent.prepareToLeaveProcess();
ActivityManagerNative.getDefault().broadcastIntent(
- mMainThread.getApplicationThread(), intent, resolvedType, null,
- Activity.RESULT_OK, null, null, receiverPermission, AppOpsManager.OP_NONE, false, false,
- user.getIdentifier());
+ mMainThread.getApplicationThread(), intent, resolvedType, null,
+ Activity.RESULT_OK, null, null, receiverPermission, appOp, false, false,
+ user.getIdentifier());
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index e446700..46da025 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -332,10 +332,10 @@
}});
registerService(Context.NETWORK_POLICY_SERVICE, NetworkPolicyManager.class,
- new StaticServiceFetcher<NetworkPolicyManager>() {
+ new CachedServiceFetcher<NetworkPolicyManager>() {
@Override
- public NetworkPolicyManager createService() {
- return new NetworkPolicyManager(INetworkPolicyManager.Stub.asInterface(
+ public NetworkPolicyManager createService(ContextImpl ctx) {
+ return new NetworkPolicyManager(ctx, INetworkPolicyManager.Stub.asInterface(
ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)));
}});
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 370f61c..3bf3f85 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1608,6 +1608,28 @@
public abstract void sendBroadcastAsUser(Intent intent, UserHandle user,
@Nullable String receiverPermission);
+
+ /**
+ * Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the
+ * user the broadcast will be sent to. This is not available to applications
+ * that are not pre-installed on the system image. Using it requires holding
+ * the INTERACT_ACROSS_USERS permission.
+ *
+ * @param intent The Intent to broadcast; all receivers matching this
+ * Intent will receive the broadcast.
+ * @param user UserHandle to send the intent to.
+ * @param receiverPermission (optional) String naming a permission that
+ * a receiver must hold in order to receive your broadcast.
+ * If null, no permission is required.
+ * @param appOp The app op associated with the broadcast.
+ *
+ * @see #sendBroadcast(Intent, String)
+ *
+ * @hide
+ */
+ public abstract void sendBroadcastAsUser(Intent intent, UserHandle user,
+ @Nullable String receiverPermission, int appOp);
+
/**
* Version of
* {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)}
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 92f0079..fb9e194 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -444,6 +444,13 @@
mBase.sendBroadcastAsUser(intent, user, receiverPermission);
}
+ /** @hide */
+ @Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user,
+ String receiverPermission, int appOp) {
+ mBase.sendBroadcastAsUser(intent, user, receiverPermission, appOp);
+ }
+
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 8f7aed4..87a1ca9 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1030,12 +1030,13 @@
* point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity
* (depth) in pixel coordinates.</p>
* <p><b>Units</b>:
- * Pixels in the android.sensor.activeArraySize coordinate
+ * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
* system.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#LENS_POSE_ROTATION
* @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<float[]> LENS_INTRINSIC_CALIBRATION =
@@ -1330,6 +1331,7 @@
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS READ_SENSOR_SETTINGS}</li>
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE BURST_CAPTURE}</li>
* <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING YUV_REPROCESSING}</li>
+ * <li>{@link #REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT DEPTH_OUTPUT}</li>
* </ul></p>
* <p>This key is available on all devices.</p>
*
@@ -1342,6 +1344,7 @@
* @see #REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS
* @see #REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE
* @see #REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING
+ * @see #REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT
*/
@PublicKey
public static final Key<int[]> REQUEST_AVAILABLE_CAPABILITIES =
@@ -2542,11 +2545,23 @@
* post-processing, arbitrary cropping regions, and has relaxed performance constraints.</p>
* <p>Each higher level supports everything the lower level supports
* in this order: FULL <code>></code> LIMITED <code>></code> LEGACY.</p>
+ * <p>A HIGH_RESOLUTION device is equivalent to a FULL device, except that:</p>
+ * <ul>
+ * <li>At least one output resolution of 8 megapixels or higher in uncompressed YUV is
+ * supported at <code>>=</code> 20 fps.</li>
+ * <li>Maximum-size (sensor resolution) uncompressed YUV is supported at <code>>=</code> 10
+ * fps.</li>
+ * <li>For devices that list the RAW capability and support either RAW10 or RAW12 output,
+ * maximum-resolution RAW10 or RAW12 capture will operate at least at the rate of
+ * maximum-resolution YUV capture, and at least one supported output resolution of
+ * 8 megapixels or higher in RAW10 or RAW12 is supported <code>>=</code> 20 fps.</li>
+ * </ul>
* <p><b>Possible values:</b>
* <ul>
* <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}</li>
* <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}</li>
* <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}</li>
+ * <li>{@link #INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION HIGH_RESOLUTION}</li>
* </ul></p>
* <p>This key is available on all devices.</p>
*
@@ -2564,6 +2579,7 @@
* @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
* @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL
* @see #INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
+ * @see #INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION
*/
@PublicKey
public static final Key<Integer> INFO_SUPPORTED_HARDWARE_LEVEL =
@@ -2694,6 +2710,29 @@
public static final Key<android.hardware.camera2.params.StreamConfigurationDuration[]> DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS =
new Key<android.hardware.camera2.params.StreamConfigurationDuration[]>("android.depth.availableDepthStallDurations", android.hardware.camera2.params.StreamConfigurationDuration[].class);
+ /**
+ * <p>Indicates whether a capture request may target both a
+ * DEPTH16 / DEPTH_POINT_CLOUD output, and normal color outputs (such as
+ * YUV_420_888, JPEG, or RAW) simultaneously.</p>
+ * <p>If TRUE, including both depth and color outputs in a single
+ * capture request is not supported. An application must interleave color
+ * and depth requests. If FALSE, a single request can target both types
+ * of output.</p>
+ * <p>Typically, this restriction exists on camera devices that
+ * need to emit a specific pattern or wavelength of light to
+ * measure depth values, which causes the color image to be
+ * corrupted during depth measurement.</p>
+ * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+ * <p><b>Limited capability</b> -
+ * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+ * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+ *
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ */
+ @PublicKey
+ public static final Key<Boolean> DEPTH_DEPTH_IS_EXCLUSIVE =
+ new Key<Boolean>("android.depth.depthIsExclusive", boolean.class);
+
/*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
* End generated code
*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~O@*/
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 4a5bd08..e3f1d73 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -303,10 +303,13 @@
* <p>The minimal set of capabilities that every camera
* device (regardless of {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel})
* supports.</p>
- * <p>This capability is listed by all devices, and
+ * <p>This capability is listed by all normal devices, and
* indicates that the camera device has a feature set
* that's comparable to the baseline requirements for the
* older android.hardware.Camera API.</p>
+ * <p>Devices with the DEPTH_OUTPUT capability might not list this
+ * capability, indicating that they support only depth measurement,
+ * not standard color output.</p>
*
* @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
* @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
@@ -545,6 +548,11 @@
* {@link CameraCharacteristics#CONTROL_AWB_LOCK_AVAILABLE android.control.awbLockAvailable} are also guaranteed
* to be <code>true</code> so burst capture with these two locks ON
* yields consistent image output.</p>
+ * <p>On a camera device that reports the HIGH_RESOLUTION hardware
+ * level, meaning the device supports very large capture sizes,
+ * BURST_CAPTURE means that at least 8-megapixel images can be
+ * captured at <code>>=</code> 20 fps, and maximum-resolution images can be
+ * captured at <code>>=</code> 10 fps.</p>
*
* @see CameraCharacteristics#CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES
* @see CameraCharacteristics#CONTROL_AE_LOCK_AVAILABLE
@@ -596,6 +604,42 @@
*/
public static final int REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING = 7;
+ /**
+ * <p>The camera device can produce depth measurements from its field of view.</p>
+ * <p>This capability requires the camera device to support the following:</p>
+ * <ul>
+ * <li>DEPTH16 is supported as an output format.</li>
+ * <li>DEPTH_POINT_CLOUD is optionally supported as an output format.</li>
+ * <li>This camera device, and all camera devices with the same android.lens.info.facing,
+ * will list the following calibration entries in both CameraCharacteristics and
+ * CaptureResults:<ul>
+ * <li>{@link CameraCharacteristics#LENS_POSE_TRANSLATION android.lens.poseTranslation}</li>
+ * <li>{@link CameraCharacteristics#LENS_POSE_ROTATION android.lens.poseRotation}</li>
+ * <li>android.lens.intrinsicCalibration</li>
+ * <li>android.lens.radialDistortion</li>
+ * </ul>
+ * </li>
+ * <li>The {@link CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE android.depth.depthIsExclusive} entry is listed by this device.</li>
+ * <li>A LIMITED camera with only the DEPTH_OUTPUT capability does not have to support
+ * normal YUV_420_888, JPEG, and PRIV-format outputs. It only has to support the DEPTH16
+ * format.</li>
+ * </ul>
+ * <p>Generally, depth output operates at a slower frame rate than standard color capture,
+ * so the DEPTH16 and DEPTH_POINT_CLOUD formats will commonly have a stall duration that
+ * should be accounted for (see
+ * android.hardware.camera2.StreamConfigurationMap#getOutputStallDuration). On a device
+ * that supports both depth and color-based output, to enable smooth preview, using a
+ * repeating burst is recommended, where a depth-output target is only included once
+ * every N frames, where N is the ratio between preview output rate and depth output
+ * rate, including depth stall time.</p>
+ *
+ * @see CameraCharacteristics#DEPTH_DEPTH_IS_EXCLUSIVE
+ * @see CameraCharacteristics#LENS_POSE_ROTATION
+ * @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
+ */
+ public static final int REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT = 8;
+
//
// Enumeration values for CameraCharacteristics#SCALER_CROPPING_TYPE
//
@@ -808,6 +852,13 @@
*/
public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY = 2;
+ /**
+ * <p>This camera device is capable of supporting advanced imaging applications at full rate,
+ * and additional high-resolution outputs at lower rates.</p>
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ */
+ public static final int INFO_SUPPORTED_HARDWARE_LEVEL_HIGH_RESOLUTION = 3;
+
//
// Enumeration values for CameraCharacteristics#SYNC_MAX_LATENCY
//
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 4134d28..ef5d75c 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -2628,12 +2628,13 @@
* point, <code>z_s = 1</code>, and <code>w_s</code> is a measurement of disparity
* (depth) in pixel coordinates.</p>
* <p><b>Units</b>:
- * Pixels in the android.sensor.activeArraySize coordinate
+ * Pixels in the {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize} coordinate
* system.</p>
* <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
*
* @see CameraCharacteristics#LENS_POSE_ROTATION
* @see CameraCharacteristics#LENS_POSE_TRANSLATION
+ * @see CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE
*/
@PublicKey
public static final Key<float[]> LENS_INTRINSIC_CALIBRATION =
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
index 7e92de2..db7c35c 100644
--- a/core/java/android/net/INetworkPolicyManager.aidl
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -45,7 +45,7 @@
/** Control network policies atomically. */
void setNetworkPolicies(in NetworkPolicy[] policies);
- NetworkPolicy[] getNetworkPolicies();
+ NetworkPolicy[] getNetworkPolicies(String callingPackage);
/** Snooze limit on policy matching given template. */
void snoozeLimit(in NetworkTemplate template);
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index a7ffee9..25ad9285 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -61,12 +61,14 @@
*/
public static final String EXTRA_NETWORK_TEMPLATE = "android.net.NETWORK_TEMPLATE";
+ private final Context mContext;
private INetworkPolicyManager mService;
- public NetworkPolicyManager(INetworkPolicyManager service) {
+ public NetworkPolicyManager(Context context, INetworkPolicyManager service) {
if (service == null) {
throw new IllegalArgumentException("missing INetworkPolicyManager");
}
+ mContext = context;
mService = service;
}
@@ -158,7 +160,7 @@
public NetworkPolicy[] getNetworkPolicies() {
try {
- return mService.getNetworkPolicies();
+ return mService.getNetworkPolicies(mContext.getOpPackageName());
} catch (RemoteException e) {
return null;
}
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index e9f2353..ec8f802 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -283,7 +283,7 @@
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
- nDrawPatch(mNativeCanvasWrapper, bitmap, patch.mNativeChunk,
+ nDrawPatch(mNativeCanvasWrapper, bitmap.getSkBitmap(), patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
}
@@ -293,11 +293,11 @@
Bitmap bitmap = patch.getBitmap();
throwIfCannotDraw(bitmap);
final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
- nDrawPatch(mNativeCanvasWrapper, bitmap, patch.mNativeChunk,
+ nDrawPatch(mNativeCanvasWrapper, bitmap.getSkBitmap(), patch.mNativeChunk,
dst.left, dst.top, dst.right, dst.bottom, nativePaint);
}
- private static native void nDrawPatch(long renderer, Bitmap bitmap, long chunk,
+ private static native void nDrawPatch(long renderer, long bitmap, long chunk,
float left, float top, float right, float bottom, long paint);
public void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 25c5127..87d5d9a 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -360,7 +360,7 @@
@Override
boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
return nCopyLayerInto(mNativeProxy,
- layer.getDeferredLayerUpdater(), bitmap);
+ layer.getDeferredLayerUpdater(), bitmap.getSkBitmap());
}
@Override
@@ -460,6 +460,8 @@
if (buffer != null) {
long[] map = atlas.getMap();
if (map != null) {
+ // TODO Remove after fixing b/15425820
+ validateMap(context, map);
nSetAtlas(renderProxy, buffer, map);
}
// If IAssetAtlas is not the same class as the IBinder
@@ -474,6 +476,32 @@
Log.w(LOG_TAG, "Could not acquire atlas", e);
}
}
+
+ private static void validateMap(Context context, long[] map) {
+ Log.d("Atlas", "Validating map...");
+ HashSet<Long> preloadedPointers = new HashSet<Long>();
+
+ // We only care about drawables that hold bitmaps
+ final Resources resources = context.getResources();
+ final LongSparseArray<Drawable.ConstantState> drawables = resources.getPreloadedDrawables();
+
+ final int count = drawables.size();
+ ArrayList<Bitmap> tmpList = new ArrayList<Bitmap>();
+ for (int i = 0; i < count; i++) {
+ drawables.valueAt(i).addAtlasableBitmaps(tmpList);
+ for (int j = 0; j < tmpList.size(); j++) {
+ preloadedPointers.add(tmpList.get(j).getSkBitmap());
+ }
+ tmpList.clear();
+ }
+
+ for (int i = 0; i < map.length; i += 4) {
+ if (!preloadedPointers.contains(map[i])) {
+ Log.w("Atlas", String.format("Pointer 0x%X, not in getPreloadedDrawables?", map[i]));
+ map[i] = 0;
+ }
+ }
+ }
}
static native void setupShadersDiskCache(String cacheFile);
@@ -503,7 +531,7 @@
private static native long nCreateTextureLayer(long nativeProxy);
private static native void nBuildLayer(long nativeProxy, long node);
- private static native boolean nCopyLayerInto(long nativeProxy, long layer, Bitmap bitmap);
+ private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
private static native void nPushLayerUpdate(long nativeProxy, long layer);
private static native void nCancelLayerUpdate(long nativeProxy, long layer);
private static native void nDetachSurfaceTexture(long nativeProxy, long layer);
diff --git a/core/java/android/widget/CalendarViewMaterialDelegate.java b/core/java/android/widget/CalendarViewMaterialDelegate.java
index 7bce756..0ed75d5 100644
--- a/core/java/android/widget/CalendarViewMaterialDelegate.java
+++ b/core/java/android/widget/CalendarViewMaterialDelegate.java
@@ -19,6 +19,7 @@
import android.annotation.StyleRes;
import android.content.Context;
import android.util.AttributeSet;
+import android.widget.DayPickerView.OnDaySelectedListener;
import java.util.Calendar;
@@ -109,8 +110,7 @@
mOnDateChangeListener = listener;
}
- private final DayPickerView.OnDaySelectedListener mOnDaySelectedListener =
- new DayPickerView.OnDaySelectedListener() {
+ private final OnDaySelectedListener mOnDaySelectedListener = new OnDaySelectedListener() {
@Override
public void onDaySelected(DayPickerView view, Calendar day) {
if (mOnDateChangeListener != null) {
diff --git a/core/java/android/widget/DatePickerCalendarDelegate.java b/core/java/android/widget/DatePickerCalendarDelegate.java
index 06a5bd2..d38a225 100755
--- a/core/java/android/widget/DatePickerCalendarDelegate.java
+++ b/core/java/android/widget/DatePickerCalendarDelegate.java
@@ -34,8 +34,6 @@
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
import android.widget.DayPickerView.OnDaySelectedListener;
import android.widget.YearPickerView.OnYearSelectedListener;
@@ -549,7 +547,7 @@
final int listPosition = ss.getListPosition();
if (listPosition != -1) {
if (currentView == VIEW_MONTH_DAY) {
- mDayPickerView.setCurrentItem(listPosition);
+ mDayPickerView.setPosition(listPosition);
} else if (currentView == VIEW_YEAR) {
final int listPositionOffset = ss.getListPositionOffset();
mYearPickerView.setSelectionFromTop(listPosition, listPositionOffset);
diff --git a/core/java/android/widget/DayPickerAdapter.java b/core/java/android/widget/DayPickerPagerAdapter.java
similarity index 92%
rename from core/java/android/widget/DayPickerAdapter.java
rename to core/java/android/widget/DayPickerPagerAdapter.java
index 9a4b6f5..478fa00 100644
--- a/core/java/android/widget/DayPickerAdapter.java
+++ b/core/java/android/widget/DayPickerPagerAdapter.java
@@ -36,7 +36,7 @@
/**
* An adapter for a list of {@link android.widget.SimpleMonthView} items.
*/
-class DayPickerAdapter extends PagerAdapter {
+class DayPickerPagerAdapter extends PagerAdapter {
private static final int MONTHS_IN_YEAR = 12;
private final Calendar mMinDate = Calendar.getInstance();
@@ -63,7 +63,7 @@
private int mCount;
private int mFirstDayOfWeek;
- public DayPickerAdapter(@NonNull Context context, @LayoutRes int layoutResId,
+ public DayPickerPagerAdapter(@NonNull Context context, @LayoutRes int layoutResId,
@IdRes int calendarViewId) {
mInflater = LayoutInflater.from(context);
mLayoutResId = layoutResId;
@@ -200,7 +200,8 @@
final int yearOffset = (day.get(Calendar.YEAR) - mMinDate.get(Calendar.YEAR));
final int monthOffset = (day.get(Calendar.MONTH) - mMinDate.get(Calendar.MONTH));
- return yearOffset * MONTHS_IN_YEAR + monthOffset;
+ final int position = yearOffset * MONTHS_IN_YEAR + monthOffset;
+ return position;
}
@Override
@@ -253,8 +254,6 @@
v.setMonthParams(selectedDay, month, year, mFirstDayOfWeek,
enabledDayRangeStart, enabledDayRangeEnd);
- v.setPrevEnabled(position > 0);
- v.setNextEnabled(position < mCount - 1);
final ViewHolder holder = new ViewHolder(position, itemView, v);
mItems.put(position, holder);
@@ -298,17 +297,10 @@
setSelectedDay(day);
if (mOnDaySelectedListener != null) {
- mOnDaySelectedListener.onDaySelected(DayPickerAdapter.this, day);
+ mOnDaySelectedListener.onDaySelected(DayPickerPagerAdapter.this, day);
}
}
}
-
- @Override
- public void onNavigationClick(SimpleMonthView view, int direction, boolean animate) {
- if (mOnDaySelectedListener != null) {
- mOnDaySelectedListener.onNavigationClick(DayPickerAdapter.this, direction, animate);
- }
- }
};
private static class ViewHolder {
@@ -324,7 +316,6 @@
}
public interface OnDaySelectedListener {
- public void onDaySelected(DayPickerAdapter view, Calendar day);
- public void onNavigationClick(DayPickerAdapter view, int direction, boolean animate);
+ public void onDaySelected(DayPickerPagerAdapter view, Calendar day);
}
}
diff --git a/core/java/android/widget/DayPickerView.java b/core/java/android/widget/DayPickerView.java
index 0e0b2d3..c6b4d7e 100644
--- a/core/java/android/widget/DayPickerView.java
+++ b/core/java/android/widget/DayPickerView.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2015 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.
@@ -16,37 +16,44 @@
package android.widget;
-import com.android.internal.widget.ViewPager;
import com.android.internal.R;
+import com.android.internal.widget.ViewPager;
+import com.android.internal.widget.ViewPager.OnPageChangeListener;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
-import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.MathUtils;
+import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
-import java.util.ArrayList;
import java.util.Calendar;
import java.util.Locale;
import libcore.icu.LocaleData;
-/**
- * This displays a list of months in a calendar format with selectable days.
- */
-class DayPickerView extends ViewPager {
+class DayPickerView extends ViewGroup {
+ private static final int DEFAULT_LAYOUT = R.layout.day_picker_content_material;
private static final int DEFAULT_START_YEAR = 1900;
private static final int DEFAULT_END_YEAR = 2100;
+ private static final int[] ATTRS_TEXT_COLOR = new int[] { R.attr.textColor };
+
private final Calendar mSelectedDay = Calendar.getInstance();
private final Calendar mMinDate = Calendar.getInstance();
private final Calendar mMaxDate = Calendar.getInstance();
- private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
+ private final AccessibilityManager mAccessibilityManager;
- private final DayPickerAdapter mAdapter;
+ private final ViewPager mViewPager;
+ private final ImageButton mPrevButton;
+ private final ImageButton mNextButton;
+
+ private final DayPickerPagerAdapter mAdapter;
/** Temporary calendar used for date calculations. */
private Calendar mTempCalendar;
@@ -57,17 +64,21 @@
this(context, null);
}
- public DayPickerView(Context context, AttributeSet attrs) {
+ public DayPickerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, R.attr.calendarViewStyle);
}
- public DayPickerView(Context context, AttributeSet attrs, int defStyleAttr) {
+ public DayPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
- public DayPickerView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ public DayPickerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ mAccessibilityManager = (AccessibilityManager) context.getSystemService(
+ Context.ACCESSIBILITY_SERVICE);
+
final TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.CalendarView, defStyleAttr, defStyleRes);
@@ -93,14 +104,44 @@
a.recycle();
// Set up adapter.
- mAdapter = new DayPickerAdapter(context,
+ mAdapter = new DayPickerPagerAdapter(context,
R.layout.date_picker_month_item_material, R.id.month_view);
mAdapter.setMonthTextAppearance(monthTextAppearanceResId);
mAdapter.setDayOfWeekTextAppearance(dayOfWeekTextAppearanceResId);
mAdapter.setDayTextAppearance(dayTextAppearanceResId);
mAdapter.setDaySelectorColor(daySelectorColor);
- setAdapter(mAdapter);
+ final LayoutInflater inflater = LayoutInflater.from(context);
+ final ViewGroup content = (ViewGroup) inflater.inflate(DEFAULT_LAYOUT, this, false);
+
+ // Transfer all children from content to here.
+ while (content.getChildCount() > 0) {
+ final View child = content.getChildAt(0);
+ content.removeViewAt(0);
+ addView(child);
+ }
+
+ mPrevButton = (ImageButton) findViewById(R.id.prev);
+ mPrevButton.setOnClickListener(mOnClickListener);
+
+ mNextButton = (ImageButton) findViewById(R.id.next);
+ mNextButton.setOnClickListener(mOnClickListener);
+
+ mViewPager = (ViewPager) findViewById(R.id.day_picker_view_pager);
+ mViewPager.setAdapter(mAdapter);
+ mViewPager.setOnPageChangeListener(mOnPageChangedListener);
+
+ // Proxy the month text color into the previous and next buttons.
+ if (monthTextAppearanceResId != 0) {
+ final TypedArray ta = mContext.obtainStyledAttributes(null,
+ ATTRS_TEXT_COLOR, 0, monthTextAppearanceResId);
+ final ColorStateList monthColor = ta.getColorStateList(0);
+ if (monthColor != null) {
+ mPrevButton.setImageTintList(monthColor);
+ mNextButton.setImageTintList(monthColor);
+ }
+ ta.recycle();
+ }
// Set up min and max dates.
final Calendar tempDate = Calendar.getInstance();
@@ -127,109 +168,68 @@
setDate(setDateMillis, false);
// Proxy selection callbacks to our own listener.
- mAdapter.setOnDaySelectedListener(new DayPickerAdapter.OnDaySelectedListener() {
+ mAdapter.setOnDaySelectedListener(new DayPickerPagerAdapter.OnDaySelectedListener() {
@Override
- public void onDaySelected(DayPickerAdapter adapter, Calendar day) {
+ public void onDaySelected(DayPickerPagerAdapter adapter, Calendar day) {
if (mOnDaySelectedListener != null) {
mOnDaySelectedListener.onDaySelected(DayPickerView.this, day);
}
}
-
- @Override
- public void onNavigationClick(DayPickerAdapter view, int direction, boolean animate) {
- // ViewPager clamps input values, so we don't need to worry
- // about passing invalid indices.
- final int nextItem = getCurrentItem() + direction;
- setCurrentItem(nextItem, animate);
- }
});
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- populate();
+ final ViewPager viewPager = mViewPager;
+ measureChild(viewPager, widthMeasureSpec, heightMeasureSpec);
- // Everything below is mostly copied from FrameLayout.
- int count = getChildCount();
+ final int measuredWidthAndState = viewPager.getMeasuredWidthAndState();
+ final int measuredHeightAndState = viewPager.getMeasuredHeightAndState();
+ setMeasuredDimension(measuredWidthAndState, measuredHeightAndState);
- final boolean measureMatchParentChildren =
- MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
- MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
+ final int pagerWidth = viewPager.getMeasuredWidth();
+ final int pagerHeight = viewPager.getMeasuredHeight();
+ final int buttonWidthSpec = MeasureSpec.makeMeasureSpec(pagerWidth, MeasureSpec.AT_MOST);
+ final int buttonHeightSpec = MeasureSpec.makeMeasureSpec(pagerHeight, MeasureSpec.AT_MOST);
+ mPrevButton.measure(buttonWidthSpec, buttonHeightSpec);
+ mNextButton.measure(buttonWidthSpec, buttonHeightSpec);
+ }
- int maxHeight = 0;
- int maxWidth = 0;
- int childState = 0;
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ final ImageButton leftButton = mPrevButton;
+ final ImageButton rightButton = mNextButton;
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() != GONE) {
- measureChild(child, widthMeasureSpec, heightMeasureSpec);
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
- maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
- maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
- childState = combineMeasuredStates(childState, child.getMeasuredState());
- if (measureMatchParentChildren) {
- if (lp.width == LayoutParams.MATCH_PARENT ||
- lp.height == LayoutParams.MATCH_PARENT) {
- mMatchParentChildren.add(child);
- }
- }
- }
+ final int width = right - left;
+ final int height = bottom - top;
+ mViewPager.layout(0, 0, width, height);
+
+ if (mViewPager.getChildCount() < 1) {
+ leftButton.setVisibility(View.INVISIBLE);
+ rightButton.setVisibility(View.INVISIBLE);
+ return;
}
- // Account for padding too
- maxWidth += getPaddingLeft() + getPaddingRight();
- maxHeight += getPaddingTop() + getPaddingBottom();
+ final SimpleMonthView monthView = (SimpleMonthView) mViewPager.getChildAt(0);
+ final int monthHeight = monthView.getMonthHeight();
+ final int cellWidth = monthView.getCellWidth();
- // Check against our minimum height and width
- maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
- maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
+ // Vertically center the previous/next buttons within the month
+ // header, horizontally center within the day cell.
+ final int leftDW = leftButton.getMeasuredWidth();
+ final int leftDH = leftButton.getMeasuredHeight();
+ final int leftIconTop = monthView.getPaddingTop() + (monthHeight - leftDH) / 2;
+ final int leftIconLeft = monthView.getPaddingLeft() + (cellWidth - leftDW) / 2;
+ leftButton.layout(leftIconLeft, leftIconTop, leftIconLeft + leftDW, leftIconTop + leftDH);
+ leftButton.setVisibility(View.VISIBLE);
- // Check against our foreground's minimum height and width
- final Drawable drawable = getForeground();
- if (drawable != null) {
- maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
- maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
- }
-
- setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
- resolveSizeAndState(maxHeight, heightMeasureSpec,
- childState << MEASURED_HEIGHT_STATE_SHIFT));
-
- count = mMatchParentChildren.size();
- if (count > 1) {
- for (int i = 0; i < count; i++) {
- final View child = mMatchParentChildren.get(i);
-
- final LayoutParams lp = (LayoutParams) child.getLayoutParams();
- final int childWidthMeasureSpec;
- final int childHeightMeasureSpec;
-
- if (lp.width == LayoutParams.MATCH_PARENT) {
- childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
- getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
- MeasureSpec.EXACTLY);
- } else {
- childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
- getPaddingLeft() + getPaddingRight(),
- lp.width);
- }
-
- if (lp.height == LayoutParams.MATCH_PARENT) {
- childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
- getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),
- MeasureSpec.EXACTLY);
- } else {
- childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
- getPaddingTop() + getPaddingBottom(),
- lp.height);
- }
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
- }
-
- mMatchParentChildren.clear();
+ final int rightDW = rightButton.getMeasuredWidth();
+ final int rightDH = rightButton.getMeasuredHeight();
+ final int rightIconTop = monthView.getPaddingTop() + (monthHeight - rightDH) / 2;
+ final int rightIconRight = width - monthView.getPaddingRight() - (cellWidth - rightDW) / 2;
+ rightButton.layout(rightIconRight - rightDW, rightIconTop,
+ rightIconRight, rightIconTop + rightDH);
+ rightButton.setVisibility(View.VISIBLE);
}
public void setDayOfWeekTextAppearance(int resId) {
@@ -284,8 +284,8 @@
}
final int position = getPositionFromDay(timeInMillis);
- if (position != getCurrentItem()) {
- setCurrentItem(position, animate);
+ if (position != mViewPager.getCurrentItem()) {
+ mViewPager.setCurrentItem(position, animate);
}
mTempCalendar.setTimeInMillis(timeInMillis);
@@ -365,10 +365,57 @@
* Gets the position of the view that is most prominently displayed within the list view.
*/
public int getMostVisiblePosition() {
- return getCurrentItem();
+ return mViewPager.getCurrentItem();
}
+ public void setPosition(int position) {
+ mViewPager.setCurrentItem(position, false);
+ }
+
+ private final OnPageChangeListener mOnPageChangedListener = new OnPageChangeListener() {
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ final float alpha = Math.abs(0.5f - positionOffset) * 2.0f;
+ mPrevButton.setAlpha(alpha);
+ mNextButton.setAlpha(alpha);
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {}
+
+ @Override
+ public void onPageSelected(int position) {
+ mPrevButton.setVisibility(
+ position > 0 ? View.VISIBLE : View.INVISIBLE);
+ mNextButton.setVisibility(
+ position < (mAdapter.getCount() - 1) ? View.VISIBLE : View.INVISIBLE);
+ }
+ };
+
+ private final OnClickListener mOnClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final int direction;
+ if (v == mPrevButton) {
+ direction = -1;
+ } else if (v == mNextButton) {
+ direction = 1;
+ } else {
+ return;
+ }
+
+ // Animation is expensive for accessibility services since it sends
+ // lots of scroll and content change events.
+ final boolean animate = !mAccessibilityManager.isEnabled();
+
+ // ViewPager clamps input values, so we don't need to worry
+ // about passing invalid indices.
+ final int nextItem = mViewPager.getCurrentItem() + direction;
+ mViewPager.setCurrentItem(nextItem, animate);
+ }
+ };
+
public interface OnDaySelectedListener {
- public void onDaySelected(DayPickerView view, Calendar day);
+ void onDaySelected(DayPickerView view, Calendar day);
}
}
diff --git a/core/java/android/widget/DayPickerViewPager.java b/core/java/android/widget/DayPickerViewPager.java
new file mode 100644
index 0000000..bb6e3a4
--- /dev/null
+++ b/core/java/android/widget/DayPickerViewPager.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2015 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.widget;
+
+import com.android.internal.widget.ViewPager;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+import java.util.ArrayList;
+
+/**
+ * This displays a list of months in a calendar format with selectable days.
+ */
+class DayPickerViewPager extends ViewPager {
+ private final ArrayList<View> mMatchParentChildren = new ArrayList<>(1);
+
+ public DayPickerViewPager(Context context) {
+ this(context, null);
+ }
+
+ public DayPickerViewPager(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public DayPickerViewPager(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public DayPickerViewPager(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ populate();
+
+ // Everything below is mostly copied from FrameLayout.
+ int count = getChildCount();
+
+ final boolean measureMatchParentChildren =
+ MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
+ MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
+
+ int maxHeight = 0;
+ int maxWidth = 0;
+ int childState = 0;
+
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() != GONE) {
+ measureChild(child, widthMeasureSpec, heightMeasureSpec);
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
+ maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
+ childState = combineMeasuredStates(childState, child.getMeasuredState());
+ if (measureMatchParentChildren) {
+ if (lp.width == LayoutParams.MATCH_PARENT ||
+ lp.height == LayoutParams.MATCH_PARENT) {
+ mMatchParentChildren.add(child);
+ }
+ }
+ }
+ }
+
+ // Account for padding too
+ maxWidth += getPaddingLeft() + getPaddingRight();
+ maxHeight += getPaddingTop() + getPaddingBottom();
+
+ // Check against our minimum height and width
+ maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
+ maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
+
+ // Check against our foreground's minimum height and width
+ final Drawable drawable = getForeground();
+ if (drawable != null) {
+ maxHeight = Math.max(maxHeight, drawable.getMinimumHeight());
+ maxWidth = Math.max(maxWidth, drawable.getMinimumWidth());
+ }
+
+ setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
+ resolveSizeAndState(maxHeight, heightMeasureSpec,
+ childState << MEASURED_HEIGHT_STATE_SHIFT));
+
+ count = mMatchParentChildren.size();
+ if (count > 1) {
+ for (int i = 0; i < count; i++) {
+ final View child = mMatchParentChildren.get(i);
+
+ final LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ final int childWidthMeasureSpec;
+ final int childHeightMeasureSpec;
+
+ if (lp.width == LayoutParams.MATCH_PARENT) {
+ childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
+ getMeasuredWidth() - getPaddingLeft() - getPaddingRight(),
+ MeasureSpec.EXACTLY);
+ } else {
+ childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
+ getPaddingLeft() + getPaddingRight(),
+ lp.width);
+ }
+
+ if (lp.height == LayoutParams.MATCH_PARENT) {
+ childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ getMeasuredHeight() - getPaddingTop() - getPaddingBottom(),
+ MeasureSpec.EXACTLY);
+ } else {
+ childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
+ getPaddingTop() + getPaddingBottom(),
+ lp.height);
+ }
+
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+ }
+
+ mMatchParentChildren.clear();
+ }
+}
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index aa7f0b6..0249c22 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -26,7 +26,6 @@
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.TextPaint;
import android.text.format.DateFormat;
@@ -60,12 +59,6 @@
private static final String DEFAULT_TITLE_FORMAT = "MMMMy";
private static final String DAY_OF_WEEK_FORMAT = "EEEEE";
- /** Virtual view ID for previous button. */
- private static final int ITEM_ID_PREV = 0x101;
-
- /** Virtual view ID for next button. */
- private static final int ITEM_ID_NEXT = 0x100;
-
private final TextPaint mMonthPaint = new TextPaint();
private final TextPaint mDayOfWeekPaint = new TextPaint();
private final TextPaint mDayPaint = new TextPaint();
@@ -87,14 +80,6 @@
private final int mDesiredCellWidth;
private final int mDesiredDaySelectorRadius;
- // Next/previous drawables.
- private final Drawable mPrevDrawable;
- private final Drawable mNextDrawable;
- private final Rect mPrevHitArea;
- private final Rect mNextHitArea;
- private final CharSequence mPrevContentDesc;
- private final CharSequence mNextContentDesc;
-
private CharSequence mTitle;
private int mMonth;
@@ -137,9 +122,6 @@
/** The day of month for the last (inclusive) enabled day. */
private int mEnabledDayEnd = 31;
- /** The number of week rows needed to display the current month. */
- private int mNumWeeks = MAX_WEEKS_IN_MONTH;
-
/** Optional listener for handling day click actions. */
private OnDayClickListener mOnDayClickListener;
@@ -147,9 +129,6 @@
private int mTouchedItem = -1;
- private boolean mPrevEnabled;
- private boolean mNextEnabled;
-
public SimpleMonthView(Context context) {
this(context, null);
}
@@ -170,14 +149,8 @@
mDesiredDayOfWeekHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_of_week_height);
mDesiredDayHeight = res.getDimensionPixelSize(R.dimen.date_picker_day_height);
mDesiredCellWidth = res.getDimensionPixelSize(R.dimen.date_picker_day_width);
- mDesiredDaySelectorRadius = res.getDimensionPixelSize(R.dimen.date_picker_day_selector_radius);
-
- mPrevDrawable = context.getDrawable(R.drawable.ic_chevron_left);
- mNextDrawable = context.getDrawable(R.drawable.ic_chevron_right);
- mPrevHitArea = mPrevDrawable != null ? new Rect() : null;
- mNextHitArea = mNextDrawable != null ? new Rect() : null;
- mPrevContentDesc = res.getText(R.string.date_picker_prev_month_button);
- mNextContentDesc = res.getText(R.string.date_picker_next_month_button);
+ mDesiredDaySelectorRadius = res.getDimensionPixelSize(
+ R.dimen.date_picker_day_selector_radius);
// Set up accessibility components.
mTouchHelper = new MonthViewTouchHelper(this);
@@ -193,18 +166,6 @@
initPaints(res);
}
- public void setNextEnabled(boolean enabled) {
- mNextEnabled = enabled;
- mTouchHelper.invalidateRoot();
- invalidate();
- }
-
- public void setPrevEnabled(boolean enabled) {
- mPrevEnabled = enabled;
- mTouchHelper.invalidateRoot();
- invalidate();
- }
-
/**
* Applies the specified text appearance resource to a paint, returning the
* text color if one is set in the text appearance.
@@ -236,16 +197,16 @@
return textColor;
}
+ public int getMonthHeight() {
+ return mMonthHeight;
+ }
+
+ public int getCellWidth() {
+ return mCellWidth;
+ }
+
public void setMonthTextAppearance(int resId) {
- final ColorStateList monthColor = applyTextAppearance(mMonthPaint, resId);
- if (monthColor != null) {
- if (mPrevDrawable != null) {
- mPrevDrawable.setTintList(monthColor);
- }
- if (mNextDrawable != null) {
- mNextDrawable.setTintList(monthColor);
- }
- }
+ applyTextAppearance(mMonthPaint, resId);
invalidate();
}
@@ -360,7 +321,7 @@
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
- final int touchedItem = getItemAtLocation(x, y);
+ final int touchedItem = getDayAtLocation(x, y);
if (mTouchedItem != touchedItem) {
mTouchedItem = touchedItem;
invalidate();
@@ -368,8 +329,8 @@
break;
case MotionEvent.ACTION_UP:
- final int clickedItem = getItemAtLocation(x, y);
- onItemClicked(clickedItem, true);
+ final int clickedDay = getDayAtLocation(x, y);
+ onDayClicked(clickedDay);
// Fall through.
case MotionEvent.ACTION_CANCEL:
// Reset touched day on stream end.
@@ -389,7 +350,6 @@
drawMonth(canvas);
drawDaysOfWeek(canvas);
drawDays(canvas);
- drawButtons(canvas);
canvas.translate(-paddingLeft, -paddingTop);
}
@@ -482,16 +442,6 @@
}
}
- private void drawButtons(Canvas canvas) {
- if (mPrevEnabled && mPrevDrawable != null) {
- mPrevDrawable.draw(canvas);
- }
-
- if (mNextEnabled && mNextDrawable != null) {
- mNextDrawable.draw(canvas);
- }
- }
-
private static boolean isValidDayOfWeek(int day) {
return day >= Calendar.SUNDAY && day <= Calendar.SATURDAY;
}
@@ -674,33 +624,6 @@
mDaySelectorRadius = Math.min(mDesiredDaySelectorRadius,
Math.min(maxSelectorWidth, maxSelectorHeight));
- // Vertically center the previous/next drawables within the month
- // header, horizontally center within the day cell, then expand the
- // hit area to ensure it's at least 48x48dp.
- final Drawable prevDrawable = mPrevDrawable;
- if (prevDrawable != null) {
- final int dW = prevDrawable.getIntrinsicWidth();
- final int dH = prevDrawable.getIntrinsicHeight();
- final int iconTop = (monthHeight - dH) / 2;
- final int iconLeft = (cellWidth - dW) / 2;
-
- // Button bounds don't include padding, but hit area does.
- prevDrawable.setBounds(iconLeft, iconTop, iconLeft + dW, iconTop + dH);
- mPrevHitArea.set(0, 0, paddingLeft + cellWidth, paddingTop + monthHeight);
- }
-
- final Drawable nextDrawable = mNextDrawable;
- if (nextDrawable != null) {
- final int dW = nextDrawable.getIntrinsicWidth();
- final int dH = nextDrawable.getIntrinsicHeight();
- final int iconTop = (monthHeight - dH) / 2;
- final int iconRight = paddedWidth - (cellWidth - dW) / 2;
-
- // Button bounds don't include padding, but hit area does.
- nextDrawable.setBounds(iconRight - dW, iconTop, iconRight, iconTop + dH);
- mNextHitArea.set(paddedRight - cellWidth, 0, w, paddingTop + monthHeight);
- }
-
// Invalidate cached accessibility information.
mTouchHelper.invalidateRoot();
}
@@ -714,22 +637,15 @@
}
/**
- * Calculates the day of the month or item identifier at the specified
- * touch position. Returns the day of the month or -1 if the position
- * wasn't in a valid day.
+ * Calculates the day of the month at the specified touch position. Returns
+ * the day of the month or -1 if the position wasn't in a valid day.
*
* @param x the x position of the touch event
* @param y the y position of the touch event
- * @return the day of the month at (x, y), an item identifier, or -1 if the
- * position wasn't in a valid day or item
+ * @return the day of the month at (x, y), or -1 if the position wasn't in
+ * a valid day
*/
- private int getItemAtLocation(int x, int y) {
- if (mNextEnabled && mNextDrawable != null && mNextHitArea.contains(x, y)) {
- return ITEM_ID_NEXT;
- } else if (mPrevEnabled && mPrevDrawable != null && mPrevHitArea.contains(x, y)) {
- return ITEM_ID_PREV;
- }
-
+ private int getDayAtLocation(int x, int y) {
final int paddedX = x - getPaddingLeft();
if (paddedX < 0 || paddedX >= mPaddedWidth) {
return -1;
@@ -755,22 +671,10 @@
/**
* Calculates the bounds of the specified day.
*
- * @param id the day of the month, or an item identifier
+ * @param id the day of the month
* @param outBounds the rect to populate with bounds
*/
- private boolean getBoundsForItem(int id, Rect outBounds) {
- if (mNextEnabled && id == ITEM_ID_NEXT) {
- if (mNextDrawable != null) {
- outBounds.set(mNextHitArea);
- return true;
- }
- } else if (mPrevEnabled && id == ITEM_ID_PREV) {
- if (mPrevDrawable != null) {
- outBounds.set(mPrevHitArea);
- return true;
- }
- }
-
+ private boolean getBoundsForDay(int id, Rect outBounds) {
if (id < 1 || id > mDaysInMonth) {
return false;
}
@@ -789,16 +693,8 @@
final int top = getPaddingTop() + headerHeight + row * rowHeight;
outBounds.set(left, top, left + colWidth, top + rowHeight);
- return true;
- }
- /**
- * Called when an item is clicked.
- *
- * @param id the day number or item identifier
- */
- private boolean onItemClicked(int id, boolean animate) {
- return onNavigationClicked(id, animate) || onDayClicked(id);
+ return true;
}
/**
@@ -824,31 +720,6 @@
}
/**
- * Called when the user clicks on a navigation button. Handles callbacks to
- * the {@link OnDayClickListener} if one is set.
- *
- * @param id the item identifier
- */
- private boolean onNavigationClicked(int id, boolean animate) {
- final int direction;
- if (id == ITEM_ID_NEXT) {
- direction = 1;
- } else if (id == ITEM_ID_PREV) {
- direction = -1;
- } else {
- return false;
- }
-
- if (mOnDayClickListener != null) {
- mOnDayClickListener.onNavigationClick(this, direction, animate);
- }
-
- // This is a no-op if accessibility is turned off.
- mTouchHelper.sendEventForVirtualView(id, AccessibilityEvent.TYPE_VIEW_CLICKED);
- return true;
- }
-
- /**
* Provides a virtual view hierarchy for interfacing with an accessibility
* service.
*/
@@ -864,7 +735,7 @@
@Override
protected int getVirtualViewAt(float x, float y) {
- final int day = getItemAtLocation((int) (x + 0.5f), (int) (y + 0.5f));
+ final int day = getDayAtLocation((int) (x + 0.5f), (int) (y + 0.5f));
if (day >= 0) {
return day;
}
@@ -873,14 +744,6 @@
@Override
protected void getVisibleVirtualViews(IntArray virtualViewIds) {
- if (mNextEnabled && mNextDrawable != null) {
- virtualViewIds.add(ITEM_ID_PREV);
- }
-
- if (mPrevEnabled && mPrevDrawable != null) {
- virtualViewIds.add(ITEM_ID_NEXT);
- }
-
for (int day = 1; day <= mDaysInMonth; day++) {
virtualViewIds.add(day);
}
@@ -888,12 +751,12 @@
@Override
protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) {
- event.setContentDescription(getItemDescription(virtualViewId));
+ event.setContentDescription(getDayDescription(virtualViewId));
}
@Override
protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfo node) {
- final boolean hasBounds = getBoundsForItem(virtualViewId, mTempRect);
+ final boolean hasBounds = getBoundsForDay(virtualViewId, mTempRect);
if (!hasBounds) {
// The day is invalid, kill the node.
@@ -904,8 +767,8 @@
return;
}
- node.setText(getItemText(virtualViewId));
- node.setContentDescription(getItemDescription(virtualViewId));
+ node.setText(getDayText(virtualViewId));
+ node.setContentDescription(getDayDescription(virtualViewId));
node.setBoundsInParent(mTempRect);
node.addAction(AccessibilityAction.ACTION_CLICK);
@@ -921,7 +784,7 @@
Bundle arguments) {
switch (action) {
case AccessibilityNodeInfo.ACTION_CLICK:
- return onItemClicked(virtualViewId, false);
+ return onDayClicked(virtualViewId);
}
return false;
@@ -930,15 +793,11 @@
/**
* Generates a description for a given virtual view.
*
- * @param id the day or item identifier to generate a description for
+ * @param id the day to generate a description for
* @return a description of the virtual view
*/
- private CharSequence getItemDescription(int id) {
- if (id == ITEM_ID_NEXT) {
- return mNextContentDesc;
- } else if (id == ITEM_ID_PREV) {
- return mPrevContentDesc;
- } else if (id >= 1 && id <= mDaysInMonth) {
+ private CharSequence getDayDescription(int id) {
+ if (id >= 1 && id <= mDaysInMonth) {
mTempCalendar.set(mYear, mMonth, id);
return DateFormat.format(DATE_FORMAT, mTempCalendar.getTimeInMillis());
}
@@ -949,13 +808,11 @@
/**
* Generates displayed text for a given virtual view.
*
- * @param id the day or item identifier to generate text for
+ * @param id the day to generate text for
* @return the visible text of the virtual view
*/
- private CharSequence getItemText(int id) {
- if (id == ITEM_ID_NEXT || id == ITEM_ID_PREV) {
- return null;
- } else if (id >= 1 && id <= mDaysInMonth) {
+ private CharSequence getDayText(int id) {
+ if (id >= 1 && id <= mDaysInMonth) {
return Integer.toString(id);
}
@@ -967,7 +824,6 @@
* Handles callbacks when the user clicks on a time object.
*/
public interface OnDayClickListener {
- public void onDayClick(SimpleMonthView view, Calendar day);
- public void onNavigationClick(SimpleMonthView view, int direction, boolean animate);
+ void onDayClick(SimpleMonthView view, Calendar day);
}
}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 5c95f8a..7a934bd 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -857,13 +857,6 @@
bitmap->unlockPixels();
}
-static jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- SkPixelRef* pixelRef = bitmap ? bitmap->pixelRef() : nullptr;
- SkSafeRef(pixelRef);
- return reinterpret_cast<jlong>(pixelRef);
-}
-
///////////////////////////////////////////////////////////////////////////////
static JNINativeMethod gBitmapMethods[] = {
@@ -903,7 +896,6 @@
(void*)Bitmap_copyPixelsFromBuffer },
{ "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
{ "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
- { "nativeRefPixelRef", "(J)J", (void*)Bitmap_refPixelRef },
};
int register_android_graphics_Bitmap(JNIEnv* env)
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index f0bd8d1..f0bd5dd 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -373,7 +373,7 @@
return legacyBitmapConfigToColorType(c);
}
-android::Canvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) {
+SkCanvas* GraphicsJNI::getNativeCanvas(JNIEnv* env, jobject canvas) {
SkASSERT(env);
SkASSERT(canvas);
SkASSERT(env->IsInstanceOf(canvas, gCanvas_class));
@@ -381,7 +381,9 @@
if (!canvasHandle) {
return NULL;
}
- return reinterpret_cast<android::Canvas*>(canvasHandle);
+ SkCanvas* c = reinterpret_cast<android::Canvas*>(canvasHandle)->asSkCanvas();
+ SkASSERT(c);
+ return c;
}
SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region)
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 8eb43f8..49def13 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -8,7 +8,6 @@
#include "SkPoint.h"
#include "SkRect.h"
#include "SkImageDecoder.h"
-#include <Canvas.h>
#include <jni.h>
class SkBitmapRegionDecoder;
@@ -48,7 +47,7 @@
static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point);
static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
- static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
+ static SkCanvas* getNativeCanvas(JNIEnv*, jobject canvas);
static SkBitmap* getSkBitmapDeprecated(JNIEnv*, jobject bitmap);
static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
static SkPixelRef* getSkPixelRef(JNIEnv*, jobject bitmap);
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 348b0ec..3f8bfe2 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -64,7 +64,7 @@
return JNI_FALSE;
}
- static jlong validateNinePatchChunk(JNIEnv* env, jobject, jbyteArray obj) {
+ static jlong validateNinePatchChunk(JNIEnv* env, jobject, jlong, jbyteArray obj) {
size_t chunkSize = env->GetArrayLength(obj);
if (chunkSize < (int) (sizeof(Res_png_9patch))) {
jniThrowRuntimeException(env, "Array too small for chunk.");
@@ -88,13 +88,13 @@
}
}
- static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds, const SkBitmap& bitmap,
+ static void draw(JNIEnv* env, SkCanvas* canvas, SkRect& bounds, const SkBitmap* bitmap,
Res_png_9patch* chunk, const SkPaint* paint, jint destDensity, jint srcDensity) {
if (destDensity == srcDensity || destDensity == 0 || srcDensity == 0) {
ALOGV("Drawing unscaled 9-patch: (%g,%g)-(%g,%g)",
SkScalarToFloat(bounds.fLeft), SkScalarToFloat(bounds.fTop),
SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom));
- NinePatch_Draw(canvas, bounds, bitmap, *chunk, paint, NULL);
+ NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
} else {
canvas->save();
@@ -111,25 +111,25 @@
SkScalarToFloat(bounds.fRight), SkScalarToFloat(bounds.fBottom),
srcDensity, destDensity);
- NinePatch_Draw(canvas, bounds, bitmap, *chunk, paint, NULL);
+ NinePatch_Draw(canvas, bounds, *bitmap, *chunk, paint, NULL);
canvas->restore();
}
}
static void drawF(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRectF,
- jobject jbitmap, jlong chunkHandle, jlong paintHandle,
+ jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
jint destDensity, jint srcDensity) {
SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->asSkCanvas();
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
SkASSERT(canvas);
SkASSERT(boundsRectF);
+ SkASSERT(bitmap);
SkASSERT(chunk);
// paint is optional
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
SkRect bounds;
GraphicsJNI::jrectf_to_rect(env, boundsRectF, &bounds);
@@ -137,36 +137,36 @@
}
static void drawI(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRect,
- jobject jbitmap, jlong chunkHandle, jlong paintHandle,
+ jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
jint destDensity, jint srcDensity) {
SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->asSkCanvas();
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
SkASSERT(canvas);
SkASSERT(boundsRect);
+ SkASSERT(bitmap);
SkASSERT(chunk);
// paint is optional
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
SkRect bounds;
GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
draw(env, canvas, bounds, bitmap, chunk, paint, destDensity, srcDensity);
}
- static jlong getTransparentRegion(JNIEnv* env, jobject, jobject jbitmap,
+ static jlong getTransparentRegion(JNIEnv* env, jobject, jlong bitmapHandle,
jlong chunkHandle, jobject boundsRect) {
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
+ SkASSERT(bitmap);
SkASSERT(chunk);
SkASSERT(boundsRect);
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
SkRect bounds;
GraphicsJNI::jrect_to_rect(env, boundsRect, &bounds);
SkRegion* region = NULL;
- NinePatch_Draw(NULL, bounds, bitmap, *chunk, NULL, ®ion);
+ NinePatch_Draw(NULL, bounds, *bitmap, *chunk, NULL, ®ion);
return reinterpret_cast<jlong>(region);
}
@@ -176,16 +176,13 @@
/////////////////////////////////////////////////////////////////////////////////////////
static JNINativeMethod gNinePatchMethods[] = {
- { "isNinePatchChunk", "([B)Z", (void*) SkNinePatchGlue::isNinePatchChunk },
- { "validateNinePatchChunk", "([B)J",
- (void*) SkNinePatchGlue::validateNinePatchChunk },
- { "nativeFinalize", "(J)V", (void*) SkNinePatchGlue::finalize },
- { "nativeDraw", "(JLandroid/graphics/RectF;Landroid/graphics/Bitmap;JJII)V",
- (void*) SkNinePatchGlue::drawF },
- { "nativeDraw", "(JLandroid/graphics/Rect;Landroid/graphics/Bitmap;JJII)V",
- (void*) SkNinePatchGlue::drawI },
- { "nativeGetTransparentRegion", "(Landroid/graphics/Bitmap;JLandroid/graphics/Rect;)J",
- (void*) SkNinePatchGlue::getTransparentRegion }
+ { "isNinePatchChunk", "([B)Z", (void*) SkNinePatchGlue::isNinePatchChunk },
+ { "validateNinePatchChunk", "(J[B)J", (void*) SkNinePatchGlue::validateNinePatchChunk },
+ { "nativeFinalize", "(J)V", (void*) SkNinePatchGlue::finalize },
+ { "nativeDraw", "(JLandroid/graphics/RectF;JJJII)V", (void*) SkNinePatchGlue::drawF },
+ { "nativeDraw", "(JLandroid/graphics/Rect;JJJII)V", (void*) SkNinePatchGlue::drawI },
+ { "nativeGetTransparentRegion", "(JJLandroid/graphics/Rect;)J",
+ (void*) SkNinePatchGlue::getTransparentRegion }
};
int register_android_graphics_NinePatch(JNIEnv* env) {
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index d0f7591..6591d29 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -80,12 +80,11 @@
///////////////////////////////////////////////////////////////////////////////////////////////
-static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jobject jbitmap,
+static jlong BitmapShader_constructor(JNIEnv* env, jobject o, jlong bitmapHandle,
jint tileModeX, jint tileModeY)
{
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
- SkShader* s = SkShader::CreateBitmapShader(bitmap,
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkShader* s = SkShader::CreateBitmapShader(*bitmap,
(SkShader::TileMode)tileModeX,
(SkShader::TileMode)tileModeY);
@@ -250,7 +249,7 @@
};
static JNINativeMethod gBitmapShaderMethods[] = {
- { "nativeCreate", "(Landroid/graphics/Bitmap;II)J", (void*)BitmapShader_constructor },
+ { "nativeCreate", "(JII)J", (void*)BitmapShader_constructor },
};
static JNINativeMethod gLinearGradientMethods[] = {
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 9b5fb3a..a2c1609 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -39,22 +39,17 @@
}
// Native wrapper constructor used by Canvas(Bitmap)
-static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) {
- SkBitmap bitmap;
- if (jbitmap != NULL) {
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
- }
+static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
}
// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
// optionally copying canvas matrix & clip state.
-static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) {
- SkBitmap bitmap;
- if (jbitmap != NULL) {
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
- }
- get_canvas(canvasHandle)->setBitmap(bitmap);
+static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
+ jboolean copyState) {
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ get_canvas(canvasHandle)->setBitmap(bitmap, copyState);
}
static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
@@ -318,12 +313,11 @@
indices, indexCount, *paint);
}
-static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap,
+static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jlong bitmapHandle,
jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
jint screenDensity, jint bitmapDensity) {
Canvas* canvas = get_canvas(canvasHandle);
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
@@ -333,9 +327,9 @@
filteredPaint = *paint;
}
filteredPaint.setFilterQuality(kLow_SkFilterQuality);
- canvas->drawBitmap(bitmap, left, top, &filteredPaint);
+ canvas->drawBitmap(*bitmap, left, top, &filteredPaint);
} else {
- canvas->drawBitmap(bitmap, left, top, paint);
+ canvas->drawBitmap(*bitmap, left, top, paint);
}
} else {
canvas->save(SkCanvas::kMatrixClip_SaveFlag);
@@ -349,39 +343,37 @@
}
filteredPaint.setFilterQuality(kLow_SkFilterQuality);
- canvas->drawBitmap(bitmap, 0, 0, &filteredPaint);
+ canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
canvas->restore();
}
}
-static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
+static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
jlong matrixHandle, jlong paintHandle) {
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
- get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint);
+ get_canvas(canvasHandle)->drawBitmap(*bitmap, *matrix, paint);
}
-static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
+static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom,
jlong paintHandle, jint screenDensity, jint bitmapDensity) {
Canvas* canvas = get_canvas(canvasHandle);
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
if (screenDensity != 0 && screenDensity != bitmapDensity) {
Paint filteredPaint;
if (paint) {
filteredPaint = *paint;
}
filteredPaint.setFilterQuality(kLow_SkFilterQuality);
- canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
+ canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
} else {
- canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
+ canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
dstLeft, dstTop, dstRight, dstBottom, paint);
}
}
@@ -409,17 +401,16 @@
get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
}
-static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
+static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
jint meshWidth, jint meshHeight, jfloatArray jverts,
jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
const int ptCount = (meshWidth + 1) * (meshHeight + 1);
AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
- get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight,
+ get_canvas(canvasHandle)->drawBitmapMesh(*bitmap, meshWidth, meshHeight,
vertA.ptr(), colorA.ptr(), paint);
}
@@ -667,8 +658,8 @@
static JNINativeMethod gMethods[] = {
{"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
- {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
- {"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
+ {"initRaster", "(J)J", (void*) CanvasJNI::initRaster},
+ {"native_setBitmap", "(JJZ)V", (void*) CanvasJNI::setBitmap},
{"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
{"native_getWidth","(J)I", (void*) CanvasJNI::getWidth},
{"native_getHeight","(J)I", (void*) CanvasJNI::getHeight},
@@ -704,11 +695,11 @@
{"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
{"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
{"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
- {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
- {"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
- {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
+ {"native_drawBitmap","(JJFFJIII)V", (void*) CanvasJNI::drawBitmap},
+ {"nativeDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix},
+ {"native_drawBitmap","(JJFFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
{"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
- {"nativeDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
+ {"nativeDrawBitmapMesh", "(JJII[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
{"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
{"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
{"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index c9b0e76..33db4a85 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -356,95 +356,58 @@
android_media_AudioRecord_release(env, thiz);
}
-
-// ----------------------------------------------------------------------------
-static jint android_media_AudioRecord_readInByteArray(JNIEnv *env, jobject thiz,
- jbyteArray javaAudioData,
- jint offsetInBytes, jint sizeInBytes) {
- jbyte* recordBuff = NULL;
- // get the audio recorder from which we'll read new audio samples
- sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
- if (lpRecorder == NULL) {
- ALOGE("Unable to retrieve AudioRecord object, can't record");
- return 0;
- }
-
- if (!javaAudioData) {
- ALOGE("Invalid Java array to store recorded audio, can't record");
- return 0;
- }
-
- // get the pointer to where we'll record the audio
- // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
- // a way that it becomes much more efficient. When doing so, we will have to prevent the
- // AudioSystem callback to be called while in critical section (in case of media server
- // process crash for instance)
- recordBuff = (jbyte *)env->GetByteArrayElements(javaAudioData, NULL);
-
- if (recordBuff == NULL) {
- ALOGE("Error retrieving destination for recorded audio data, can't record");
- return 0;
- }
-
- // read the new audio data from the native AudioRecord object
- ssize_t readSize = lpRecorder->read(recordBuff + offsetInBytes, sizeInBytes);
- env->ReleaseByteArrayElements(javaAudioData, recordBuff, 0);
-
- if (readSize < 0) {
- readSize = (jint)AUDIO_JAVA_INVALID_OPERATION;
- }
- return (jint) readSize;
+// overloaded JNI array helper functions
+static inline
+jbyte *envGetArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) {
+ return env->GetByteArrayElements(array, isCopy);
}
-// ----------------------------------------------------------------------------
-static jint android_media_AudioRecord_readInShortArray(JNIEnv *env, jobject thiz,
- jshortArray javaAudioData,
- jint offsetInShorts, jint sizeInShorts) {
-
- jshort* recordBuff = NULL;
- // get the audio recorder from which we'll read new audio samples
- sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
- if (lpRecorder == NULL) {
- ALOGE("Unable to retrieve AudioRecord object, can't record");
- return 0;
- }
-
- if (!javaAudioData) {
- ALOGE("Invalid Java array to store recorded audio, can't record");
- return 0;
- }
-
- // get the pointer to where we'll record the audio
- // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
- // a way that it becomes much more efficient. When doing so, we will have to prevent the
- // AudioSystem callback to be called while in critical section (in case of media server
- // process crash for instance)
- recordBuff = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
-
- if (recordBuff == NULL) {
- ALOGE("Error retrieving destination for recorded audio data, can't record");
- return 0;
- }
-
- // read the new audio data from the native AudioRecord object
- const size_t sizeInBytes = sizeInShorts * sizeof(short);
- ssize_t readSize = lpRecorder->read(recordBuff + offsetInShorts, sizeInBytes);
-
- env->ReleaseShortArrayElements(javaAudioData, recordBuff, 0);
-
- if (readSize < 0) {
- readSize = (jint)AUDIO_JAVA_INVALID_OPERATION;
- } else {
- readSize /= sizeof(short);
- }
- return (jint) readSize;
+static inline
+void envReleaseArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode) {
+ env->ReleaseByteArrayElements(array, elems, mode);
}
-// ----------------------------------------------------------------------------
-static jint android_media_AudioRecord_readInFloatArray(JNIEnv *env, jobject thiz,
- jfloatArray javaAudioData,
- jint offsetInFloats, jint sizeInFloats,
- jboolean isReadBlocking) {
+static inline
+jshort *envGetArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy) {
+ return env->GetShortArrayElements(array, isCopy);
+}
+
+static inline
+void envReleaseArrayElements(JNIEnv *env, jshortArray array, jshort *elems, jint mode) {
+ env->ReleaseShortArrayElements(array, elems, mode);
+}
+
+static inline
+jfloat *envGetArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy) {
+ return env->GetFloatArrayElements(array, isCopy);
+}
+
+static inline
+void envReleaseArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, jint mode) {
+ env->ReleaseFloatArrayElements(array, elems, mode);
+}
+
+static inline
+jint interpretReadSizeError(ssize_t readSize) {
+ ALOGE_IF(readSize != WOULD_BLOCK, "Error %zd during AudioRecord native read", readSize);
+ switch (readSize) {
+ case WOULD_BLOCK:
+ return (jint)0;
+ case BAD_VALUE:
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ default:
+ // may be possible for other errors such as
+ // NO_INIT to happen if restoreRecord_l fails.
+ case INVALID_OPERATION:
+ return (jint)AUDIO_JAVA_INVALID_OPERATION;
+ }
+}
+
+template <typename T>
+static jint android_media_AudioRecord_readInArray(JNIEnv *env, jobject thiz,
+ T javaAudioData,
+ jint offsetInSamples, jint sizeInSamples,
+ jboolean isReadBlocking) {
// get the audio recorder from which we'll read new audio samples
sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
if (lpRecorder == NULL) {
@@ -453,76 +416,68 @@
}
if (javaAudioData == NULL) {
- ALOGE("Invalid Java array to store recorded audio");
- return (jint)AUDIO_JAVA_BAD_VALUE;
- }
+ ALOGE("Invalid Java array to store recorded audio");
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
- // get the pointer to where we'll record the audio
// NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
// a way that it becomes much more efficient. When doing so, we will have to prevent the
// AudioSystem callback to be called while in critical section (in case of media server
// process crash for instance)
- jfloat *recordBuff = (jfloat *)env->GetFloatArrayElements(javaAudioData, NULL);
+
+ // get the pointer to where we'll record the audio
+ auto *recordBuff = envGetArrayElements(env, javaAudioData, NULL);
if (recordBuff == NULL) {
ALOGE("Error retrieving destination for recorded audio data");
return (jint)AUDIO_JAVA_BAD_VALUE;
}
// read the new audio data from the native AudioRecord object
- const size_t sizeInBytes = sizeInFloats * sizeof(float);
- ssize_t readSize = lpRecorder->read(recordBuff + offsetInFloats, sizeInBytes);
+ const size_t sizeInBytes = sizeInSamples * sizeof(*recordBuff);
+ ssize_t readSize = lpRecorder->read(
+ recordBuff + offsetInSamples, sizeInBytes, isReadBlocking == JNI_TRUE /* blocking */);
- env->ReleaseFloatArrayElements(javaAudioData, recordBuff, 0);
+ envReleaseArrayElements(env, javaAudioData, recordBuff, 0);
if (readSize < 0) {
- ALOGE_IF(readSize != WOULD_BLOCK, "Error %zd during AudioRecord native read", readSize);
- switch (readSize) {
- case WOULD_BLOCK:
- return (jint)0;
- case BAD_VALUE:
- return (jint)AUDIO_JAVA_BAD_VALUE;
- default:
- // may be possible for other errors such as
- // NO_INIT to happen if restoreRecord_l fails.
- case INVALID_OPERATION:
- return (jint)AUDIO_JAVA_INVALID_OPERATION;
- }
+ return interpretReadSizeError(readSize);
}
- return (jint)(readSize / sizeof(float));
+ return (jint)(readSize / sizeof(*recordBuff));
}
// ----------------------------------------------------------------------------
static jint android_media_AudioRecord_readInDirectBuffer(JNIEnv *env, jobject thiz,
- jobject jBuffer, jint sizeInBytes) {
+ jobject jBuffer, jint sizeInBytes,
+ jboolean isReadBlocking) {
// get the audio recorder from which we'll read new audio samples
sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
if (lpRecorder==NULL)
- return 0;
+ return (jint)AUDIO_JAVA_INVALID_OPERATION;
// direct buffer and direct access supported?
long capacity = env->GetDirectBufferCapacity(jBuffer);
if (capacity == -1) {
// buffer direct access is not supported
ALOGE("Buffer direct access is not supported, can't record");
- return 0;
+ return (jint)AUDIO_JAVA_BAD_VALUE;
}
//ALOGV("capacity = %ld", capacity);
jbyte* nativeFromJavaBuf = (jbyte*) env->GetDirectBufferAddress(jBuffer);
if (nativeFromJavaBuf==NULL) {
ALOGE("Buffer direct access is not supported, can't record");
- return 0;
+ return (jint)AUDIO_JAVA_BAD_VALUE;
}
// read new data from the recorder
ssize_t readSize = lpRecorder->read(nativeFromJavaBuf,
- capacity < sizeInBytes ? capacity : sizeInBytes);
+ capacity < sizeInBytes ? capacity : sizeInBytes,
+ isReadBlocking == JNI_TRUE /* blocking */);
if (readSize < 0) {
- readSize = (jint)AUDIO_JAVA_INVALID_OPERATION;
+ return interpretReadSizeError(readSize);
}
return (jint)readSize;
}
-
// ----------------------------------------------------------------------------
static jint android_media_AudioRecord_get_native_frame_count(JNIEnv *env, jobject thiz) {
sp<AudioRecord> lpRecorder = getAudioRecord(env, thiz);
@@ -633,12 +588,15 @@
{"native_finalize", "()V", (void *)android_media_AudioRecord_finalize},
{"native_release", "()V", (void *)android_media_AudioRecord_release},
{"native_read_in_byte_array",
- "([BII)I", (void *)android_media_AudioRecord_readInByteArray},
+ "([BIIZ)I",
+ (void *)android_media_AudioRecord_readInArray<jbyteArray>},
{"native_read_in_short_array",
- "([SII)I", (void *)android_media_AudioRecord_readInShortArray},
+ "([SIIZ)I",
+ (void *)android_media_AudioRecord_readInArray<jshortArray>},
{"native_read_in_float_array",
- "([FIIZ)I", (void *)android_media_AudioRecord_readInFloatArray},
- {"native_read_in_direct_buffer","(Ljava/lang/Object;I)I",
+ "([FIIZ)I",
+ (void *)android_media_AudioRecord_readInArray<jfloatArray>},
+ {"native_read_in_direct_buffer","(Ljava/lang/Object;IZ)I",
(void *)android_media_AudioRecord_readInDirectBuffer},
{"native_get_native_frame_count",
"()I", (void *)android_media_AudioRecord_get_native_frame_count},
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 610c7ed..8d3a9aa 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -510,14 +510,47 @@
android_media_AudioTrack_release(env, thiz);
}
+// overloaded JNI array helper functions (same as in android_media_AudioRecord)
+static inline
+jbyte *envGetArrayElements(JNIEnv *env, jbyteArray array, jboolean *isCopy) {
+ return env->GetByteArrayElements(array, isCopy);
+}
+
+static inline
+void envReleaseArrayElements(JNIEnv *env, jbyteArray array, jbyte *elems, jint mode) {
+ env->ReleaseByteArrayElements(array, elems, mode);
+}
+
+static inline
+jshort *envGetArrayElements(JNIEnv *env, jshortArray array, jboolean *isCopy) {
+ return env->GetShortArrayElements(array, isCopy);
+}
+
+static inline
+void envReleaseArrayElements(JNIEnv *env, jshortArray array, jshort *elems, jint mode) {
+ env->ReleaseShortArrayElements(array, elems, mode);
+}
+
+static inline
+jfloat *envGetArrayElements(JNIEnv *env, jfloatArray array, jboolean *isCopy) {
+ return env->GetFloatArrayElements(array, isCopy);
+}
+
+static inline
+void envReleaseArrayElements(JNIEnv *env, jfloatArray array, jfloat *elems, jint mode) {
+ env->ReleaseFloatArrayElements(array, elems, mode);
+}
+
// ----------------------------------------------------------------------------
-jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const jbyte* data,
- jint offsetInBytes, jint sizeInBytes, bool blocking = true) {
+template <typename T>
+static jint writeToTrack(const sp<AudioTrack>& track, jint audioFormat, const T *data,
+ jint offsetInSamples, jint sizeInSamples, bool blocking) {
// give the data to the native AudioTrack object (the data starts at the offset)
ssize_t written = 0;
// regular write() or copy the data to the AudioTrack's shared memory?
+ size_t sizeInBytes = sizeInSamples * sizeof(T);
if (track->sharedBuffer() == 0) {
- written = track->write(data + offsetInBytes, sizeInBytes, blocking);
+ written = track->write(data + offsetInSamples, sizeInBytes, blocking);
// for compatibility with earlier behavior of write(), return 0 in this case
if (written == (ssize_t) WOULD_BLOCK) {
written = 0;
@@ -527,55 +560,59 @@
if ((size_t)sizeInBytes > track->sharedBuffer()->size()) {
sizeInBytes = track->sharedBuffer()->size();
}
- memcpy(track->sharedBuffer()->pointer(), data + offsetInBytes, sizeInBytes);
+ memcpy(track->sharedBuffer()->pointer(), data + offsetInSamples, sizeInBytes);
written = sizeInBytes;
}
+ if (written > 0) {
+ return written / sizeof(T);
+ }
+ // for compatibility, error codes pass through unchanged
return written;
}
// ----------------------------------------------------------------------------
-static jint android_media_AudioTrack_write_byte(JNIEnv *env, jobject thiz,
- jbyteArray javaAudioData,
- jint offsetInBytes, jint sizeInBytes,
- jint javaAudioFormat,
- jboolean isWriteBlocking) {
- //ALOGV("android_media_AudioTrack_write_byte(offset=%d, sizeInBytes=%d) called",
- // offsetInBytes, sizeInBytes);
+template <typename T>
+static jint android_media_AudioTrack_writeArray(JNIEnv *env, jobject thiz,
+ T javaAudioData,
+ jint offsetInSamples, jint sizeInSamples,
+ jint javaAudioFormat,
+ jboolean isWriteBlocking) {
+ //ALOGV("android_media_AudioTrack_writeArray(offset=%d, sizeInSamples=%d) called",
+ // offsetInSamples, sizeInSamples);
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioTrack pointer for write()");
- return 0;
+ return (jint)AUDIO_JAVA_INVALID_OPERATION;
}
- // get the pointer for the audio data from the java array
+ if (javaAudioData == NULL) {
+ ALOGE("NULL java array of audio data to play");
+ return (jint)AUDIO_JAVA_BAD_VALUE;
+ }
+
// NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
// a way that it becomes much more efficient. When doing so, we will have to prevent the
// AudioSystem callback to be called while in critical section (in case of media server
// process crash for instance)
- jbyte* cAudioData = NULL;
- if (javaAudioData) {
- cAudioData = (jbyte *)env->GetByteArrayElements(javaAudioData, NULL);
- if (cAudioData == NULL) {
- ALOGE("Error retrieving source of audio data to play, can't play");
- return 0; // out of memory or no data to load
- }
- } else {
- ALOGE("NULL java array of audio data to play, can't play");
- return 0;
+
+ // get the pointer for the audio data from the java array
+ auto cAudioData = envGetArrayElements(env, javaAudioData, NULL);
+ if (cAudioData == NULL) {
+ ALOGE("Error retrieving source of audio data to play");
+ return (jint)AUDIO_JAVA_BAD_VALUE; // out of memory or no data to load
}
- jint written = writeToTrack(lpTrack, javaAudioFormat, cAudioData, offsetInBytes, sizeInBytes,
- isWriteBlocking == JNI_TRUE /* blocking */);
+ jint samplesWritten = writeToTrack(lpTrack, javaAudioFormat, cAudioData,
+ offsetInSamples, sizeInSamples, isWriteBlocking == JNI_TRUE /* blocking */);
- env->ReleaseByteArrayElements(javaAudioData, cAudioData, 0);
+ envReleaseArrayElements(env, javaAudioData, cAudioData, 0);
- //ALOGV("write wrote %d (tried %d) bytes in the native AudioTrack with offset %d",
- // (int)written, (int)(sizeInBytes), (int)offsetInBytes);
- return written;
+ //ALOGV("write wrote %d (tried %d) samples in the native AudioTrack with offset %d",
+ // (int)samplesWritten, (int)(sizeInSamples), (int)offsetInSamples);
+ return samplesWritten;
}
-
// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_write_native_bytes(JNIEnv *env, jobject thiz,
jbyteArray javaBytes, jint byteOffset, jint sizeInBytes,
@@ -586,7 +623,7 @@
if (lpTrack == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Unable to retrieve AudioTrack pointer for write()");
- return 0;
+ return (jint)AUDIO_JAVA_INVALID_OPERATION;
}
ScopedBytesRO bytes(env, javaBytes);
@@ -602,90 +639,6 @@
}
// ----------------------------------------------------------------------------
-static jint android_media_AudioTrack_write_short(JNIEnv *env, jobject thiz,
- jshortArray javaAudioData,
- jint offsetInShorts, jint sizeInShorts,
- jint javaAudioFormat) {
-
- //ALOGV("android_media_AudioTrack_write_short(offset=%d, sizeInShorts=%d) called",
- // offsetInShorts, sizeInShorts);
- sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
- if (lpTrack == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "Unable to retrieve AudioTrack pointer for write()");
- return 0;
- }
-
- // get the pointer for the audio data from the java array
- // NOTE: We may use GetPrimitiveArrayCritical() when the JNI implementation changes in such
- // a way that it becomes much more efficient. When doing so, we will have to prevent the
- // AudioSystem callback to be called while in critical section (in case of media server
- // process crash for instance)
- jshort* cAudioData = NULL;
- if (javaAudioData) {
- cAudioData = (jshort *)env->GetShortArrayElements(javaAudioData, NULL);
- if (cAudioData == NULL) {
- ALOGE("Error retrieving source of audio data to play, can't play");
- return 0; // out of memory or no data to load
- }
- } else {
- ALOGE("NULL java array of audio data to play, can't play");
- return 0;
- }
- jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
- offsetInShorts * sizeof(short), sizeInShorts * sizeof(short),
- true /*blocking write, legacy behavior*/);
- env->ReleaseShortArrayElements(javaAudioData, cAudioData, 0);
-
- if (written > 0) {
- written /= sizeof(short);
- }
- //ALOGV("write wrote %d (tried %d) shorts in the native AudioTrack with offset %d",
- // (int)written, (int)(sizeInShorts), (int)offsetInShorts);
-
- return written;
-}
-
-
-// ----------------------------------------------------------------------------
-static jint android_media_AudioTrack_write_float(JNIEnv *env, jobject thiz,
- jfloatArray javaAudioData,
- jint offsetInFloats, jint sizeInFloats,
- jint javaAudioFormat,
- jboolean isWriteBlocking) {
-
- sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
- if (lpTrack == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "Unable to retrieve AudioTrack pointer for write()");
- return 0;
- }
-
- jfloat* cAudioData = NULL;
- if (javaAudioData) {
- cAudioData = (jfloat *)env->GetFloatArrayElements(javaAudioData, NULL);
- if (cAudioData == NULL) {
- ALOGE("Error retrieving source of audio data to play, can't play");
- return 0; // out of memory or no data to load
- }
- } else {
- ALOGE("NULL java array of audio data to play, can't play");
- return 0;
- }
- jint written = writeToTrack(lpTrack, javaAudioFormat, (jbyte *)cAudioData,
- offsetInFloats * sizeof(float), sizeInFloats * sizeof(float),
- isWriteBlocking == JNI_TRUE /* blocking */);
- env->ReleaseFloatArrayElements(javaAudioData, cAudioData, 0);
-
- if (written > 0) {
- written /= sizeof(float);
- }
-
- return written;
-}
-
-
-// ----------------------------------------------------------------------------
static jint android_media_AudioTrack_get_native_frame_count(JNIEnv *env, jobject thiz) {
sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
if (lpTrack == NULL) {
@@ -976,12 +929,12 @@
(void *)android_media_AudioTrack_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_release},
- {"native_write_byte", "([BIIIZ)I",(void *)android_media_AudioTrack_write_byte},
+ {"native_write_byte", "([BIIIZ)I",(void *)android_media_AudioTrack_writeArray<jbyteArray>},
{"native_write_native_bytes",
"(Ljava/lang/Object;IIIZ)I",
(void *)android_media_AudioTrack_write_native_bytes},
- {"native_write_short", "([SIII)I", (void *)android_media_AudioTrack_write_short},
- {"native_write_float", "([FIIIZ)I",(void *)android_media_AudioTrack_write_float},
+ {"native_write_short", "([SIIIZ)I",(void *)android_media_AudioTrack_writeArray<jshortArray>},
+ {"native_write_float", "([FIIIZ)I",(void *)android_media_AudioTrack_writeArray<jfloatArray>},
{"native_setVolume", "(FF)V", (void *)android_media_AudioTrack_set_volume},
{"native_get_native_frame_count",
"()I", (void *)android_media_AudioTrack_get_native_frame_count},
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index f42c89c..f2e6c4b 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -133,10 +133,10 @@
// ----------------------------------------------------------------------------
static void android_view_DisplayListCanvas_drawPatch(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jobject jbitmap, jlong patchPtr,
+ jlong rendererPtr, jlong bitmapPtr, jlong patchPtr,
float left, float top, float right, float bottom, jlong paintPtr) {
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
+
DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr);
Paint* paint = reinterpret_cast<Paint*>(paintPtr);
@@ -276,7 +276,7 @@
{ "nCallDrawGLFunction", "(JJ)V", (void*) android_view_DisplayListCanvas_callDrawGLFunction },
- { "nDrawPatch", "(JLandroid/graphics/Bitmap;JFFFFJ)V", (void*) android_view_DisplayListCanvas_drawPatch },
+ { "nDrawPatch", "(JJJFFFFJ)V", (void*) android_view_DisplayListCanvas_drawPatch },
{ "nDrawRects", "(JJJ)V", (void*) android_view_DisplayListCanvas_drawRegionAsRects },
{ "nDrawRoundRect", "(JJJJJJJJ)V", (void*) android_view_DisplayListCanvas_drawRoundRectProps },
diff --git a/core/jni/android_view_GraphicBuffer.cpp b/core/jni/android_view_GraphicBuffer.cpp
index aa79d70..a12629f 100644
--- a/core/jni/android_view_GraphicBuffer.cpp
+++ b/core/jni/android_view_GraphicBuffer.cpp
@@ -67,6 +67,11 @@
jfieldID bottom;
} gRectClassInfo;
+static struct {
+ jfieldID mSurfaceFormat;
+ jmethodID setNativeBitmap;
+} gCanvasClassInfo;
+
#define GET_INT(object, field) \
env->GetIntField(object, field)
@@ -191,9 +196,13 @@
bitmap.setPixels(NULL);
}
- Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
- nativeCanvas->setBitmap(bitmap);
- nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom);
+ SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer->getPixelFormat());
+ INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(&bitmap));
+
+ SkRect clipRect;
+ clipRect.set(rect.left, rect.top, rect.right, rect.bottom);
+ SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
+ nativeCanvas->clipRect(clipRect);
if (dirtyRect) {
INVOKEV(dirtyRect, gRectClassInfo.set,
@@ -208,8 +217,7 @@
GraphicBufferWrapper* wrapper =
reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle);
- Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
- nativeCanvas->setBitmap(SkBitmap());
+ INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0);
if (wrapper) {
status_t status = wrapper->buffer->unlock();
@@ -294,6 +302,10 @@
gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I");
gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I");
+ clazz = FindClassOrDie(env, "android/graphics/Canvas");
+ gCanvasClassInfo.mSurfaceFormat = GetFieldIDOrDie(env, clazz, "mSurfaceFormat", "I");
+ gCanvasClassInfo.setNativeBitmap = GetMethodIDOrDie(env, clazz, "setNativeBitmap", "(J)V");
+
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 06d1e85..f1c90ea 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -74,6 +74,11 @@
jfieldID bottom;
} gRectClassInfo;
+static struct {
+ jfieldID mSurfaceFormat;
+ jmethodID setNativeBitmap;
+} gCanvasClassInfo;
+
// ----------------------------------------------------------------------------
// this is just a pointer we use to pass to inc/decStrong
@@ -314,6 +319,9 @@
return 0;
}
+ // Associate a SkCanvas object to this surface
+ env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, outBuffer.format);
+
SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
convertPixelFormat(outBuffer.format),
kPremul_SkAlphaType);
@@ -331,12 +339,12 @@
bitmap.setPixels(NULL);
}
- Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
- nativeCanvas->setBitmap(bitmap);
+ env->CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap,
+ reinterpret_cast<jlong>(&bitmap));
if (dirtyRectPtr) {
- nativeCanvas->clipRect(dirtyRect.left, dirtyRect.top,
- dirtyRect.right, dirtyRect.bottom);
+ SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
+ nativeCanvas->clipRect( SkRect::Make(reinterpret_cast<const SkIRect&>(dirtyRect)) );
}
if (dirtyRectObj) {
@@ -362,8 +370,7 @@
}
// detach the canvas from the surface
- Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
- nativeCanvas->setBitmap(SkBitmap());
+ env->CallVoidMethod(canvasObj, gCanvasClassInfo.setNativeBitmap, (jlong)0);
// unlock surface
status_t err = surface->unlockAndPost();
@@ -558,6 +565,10 @@
gSurfaceClassInfo.clazz, "mLock", "Ljava/lang/Object;");
gSurfaceClassInfo.ctor = GetMethodIDOrDie(env, gSurfaceClassInfo.clazz, "<init>", "(J)V");
+ clazz = FindClassOrDie(env, "android/graphics/Canvas");
+ gCanvasClassInfo.mSurfaceFormat = GetFieldIDOrDie(env, clazz, "mSurfaceFormat", "I");
+ gCanvasClassInfo.setNativeBitmap = GetMethodIDOrDie(env, clazz, "setNativeBitmap", "(J)V");
+
clazz = FindClassOrDie(env, "android/graphics/Rect");
gRectClassInfo.left = GetFieldIDOrDie(env, clazz, "left", "I");
gRectClassInfo.top = GetFieldIDOrDie(env, clazz, "top", "I");
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index 7e05793..c2bd0b3c4 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -48,6 +48,11 @@
} gRectClassInfo;
static struct {
+ jfieldID mSurfaceFormat;
+ jmethodID setNativeBitmap;
+} gCanvasClassInfo;
+
+static struct {
jfieldID nativeWindow;
} gTextureViewClassInfo;
@@ -167,9 +172,13 @@
bitmap.setPixels(NULL);
}
- Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
- nativeCanvas->setBitmap(bitmap);
- nativeCanvas->clipRect(rect.left, rect.top, rect.right, rect.bottom);
+ SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer.format);
+ INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(&bitmap));
+
+ SkRect clipRect;
+ clipRect.set(rect.left, rect.top, rect.right, rect.bottom);
+ SkCanvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
+ nativeCanvas->clipRect(clipRect);
if (dirtyRect) {
INVOKEV(dirtyRect, gRectClassInfo.set,
@@ -182,8 +191,7 @@
static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject,
jlong nativeWindow, jobject canvas) {
- Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvas);
- nativeCanvas->setBitmap(SkBitmap());
+ INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0);
if (nativeWindow) {
sp<ANativeWindow> window((ANativeWindow*) nativeWindow);
@@ -217,6 +225,10 @@
gRectClassInfo.right = GetFieldIDOrDie(env, clazz, "right", "I");
gRectClassInfo.bottom = GetFieldIDOrDie(env, clazz, "bottom", "I");
+ clazz = FindClassOrDie(env, "android/graphics/Canvas");
+ gCanvasClassInfo.mSurfaceFormat = GetFieldIDOrDie(env, clazz, "mSurfaceFormat", "I");
+ gCanvasClassInfo.setNativeBitmap = GetMethodIDOrDie(env, clazz, "setNativeBitmap", "(J)V");
+
clazz = FindClassOrDie(env, "android/view/TextureView");
gTextureViewClassInfo.nativeWindow = GetFieldIDOrDie(env, clazz, "mNativeWindow", "J");
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 4ccbb41..11b3805 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -21,7 +21,6 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include "core_jni_helpers.h"
-#include <GraphicsJNI.h>
#include <ScopedPrimitiveArray.h>
#include <EGL/egl.h>
@@ -348,11 +347,10 @@
}
static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz,
- jlong proxyPtr, jlong layerPtr, jobject jbitmap) {
+ jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) {
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr);
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap);
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
return proxy->copyLayerInto(layer, bitmap);
}
@@ -460,7 +458,7 @@
{ "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
{ "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
{ "nBuildLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_buildLayer },
- { "nCopyLayerInto", "(JJLandroid/graphics/Bitmap;)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
+ { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto },
{ "nPushLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_pushLayerUpdate },
{ "nCancelLayerUpdate", "(JJ)V", (void*) android_view_ThreadedRenderer_cancelLayerUpdate },
{ "nDetachSurfaceTexture", "(JJ)V", (void*) android_view_ThreadedRenderer_detachSurfaceTexture },
diff --git a/core/res/res/layout/date_picker_header_material.xml b/core/res/res/layout/date_picker_header_material.xml
index bda7de9..8125544 100644
--- a/core/res/res/layout/date_picker_header_material.xml
+++ b/core/res/res/layout/date_picker_header_material.xml
@@ -45,6 +45,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Material.DatePicker.DateLabel"
+ android:gravity="start"
android:maxLines="2"
android:ellipsize="none"
tools:text="Thu, Sep 30"
diff --git a/core/res/res/layout/day_picker_content_material.xml b/core/res/res/layout/day_picker_content_material.xml
new file mode 100644
index 0000000..1852bfa
--- /dev/null
+++ b/core/res/res/layout/day_picker_content_material.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2015 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <android.widget.DayPickerViewPager
+ android:id="@+id/day_picker_view_pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ <ImageButton
+ android:id="@+id/prev"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="48dp"
+ android:minHeight="48dp"
+ android:src="@drawable/ic_chevron_left"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/date_picker_prev_month_button"
+ android:visibility="invisible" />
+
+ <ImageButton
+ android:id="@+id/next"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:minWidth="48dp"
+ android:minHeight="48dp"
+ android:src="@drawable/ic_chevron_right"
+ android:background="?attr/selectableItemBackgroundBorderless"
+ android:contentDescription="@string/date_picker_next_month_button"
+ android:visibility="invisible" />
+
+</FrameLayout>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 180b415..98c1b8f 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2242,4 +2242,6 @@
<java-symbol type="layout" name="chooser_grid" />
<java-symbol type="layout" name="resolve_grid_item" />
<java-symbol type="id" name="title_icon" />
+ <java-symbol type="id" name="day_picker_view_pager" />
+ <java-symbol type="layout" name="day_picker_content_material" />
</resources>
diff --git a/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk b/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk
index 5fa2405..6ee6ffa 100644
--- a/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk
+++ b/core/tests/coretests/apks/install_jni_lib_open_from_apk/Android.mk
@@ -5,7 +5,6 @@
LOCAL_PACKAGE_NAME := install_jni_lib_open_from_apk
-LOCAL_JNI_SHARED_LIBRARIES_ZIP_OPTIONS := -0
LOCAL_PAGE_ALIGN_JNI_SHARED_LIBRARIES := true
include $(FrameworkCoreTests_BUILD_PACKAGE)
diff --git a/docs/html/images/tools/hierarchicalviewer-icon.png b/docs/html/images/tools/hierarchicalviewer-icon.png
new file mode 100644
index 0000000..061f952
--- /dev/null
+++ b/docs/html/images/tools/hierarchicalviewer-icon.png
Binary files differ
diff --git a/docs/html/images/tools/studio-DDMS-open-perspective-icon.png b/docs/html/images/tools/studio-DDMS-open-perspective-icon.png
new file mode 100644
index 0000000..f8e6d1a
--- /dev/null
+++ b/docs/html/images/tools/studio-DDMS-open-perspective-icon.png
Binary files differ
diff --git a/docs/html/images/tools/studio-gradle-panel.png b/docs/html/images/tools/studio-gradle-panel.png
deleted file mode 100644
index 4a76a8d..0000000
--- a/docs/html/images/tools/studio-gradle-panel.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/images/tools/studio-gradle-tab.png b/docs/html/images/tools/studio-gradle-tab.png
deleted file mode 100644
index b0f302c..0000000
--- a/docs/html/images/tools/studio-gradle-tab.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/tools/building/building-studio.jd b/docs/html/tools/building/building-studio.jd
index 68800da..4431194 100644
--- a/docs/html/tools/building/building-studio.jd
+++ b/docs/html/tools/building/building-studio.jd
@@ -67,26 +67,13 @@
<a href="{@docRoot}sdk/installing/studio-build.html">Build System</a> guide.</p>
<p>To view the list of all available build tasks in Android Studio, click <strong>Gradle</strong>
-on the right side of the IDE window. The <em>Gradle tasks</em> panel appears as shown in
-figure 2. Double-click any build task to run it in Android Studio. To hide the <em>Gradle tasks</em>
-panel, click <strong>Gradle</strong> again.</p>
+on the right side of the IDE window. The <em>Gradle tasks</em> panel appears.</p>
-<img src="{@docRoot}images/tools/studio-gradle-panel.png" alt="" />
-<p class="img-caption"><strong>Figure 2.</strong> The list of build tasks in Android Studio.</p>
<h3 id="buildRelease">Build a release version</h3>
-<p>You can now build the release version of your application for distribution. To build it from Android
-Studio:</p>
-
-<ol>
- <li>Click <strong>Gradle</strong> on the right side of the IDE window.</li>
- <li>On the <em>All tasks</em> section of the sidebar that appears, expand
- <strong>BuildSystemExample</strong>.</li>
- <li>Expand <strong>:app</strong> and double-click <strong>assembleRelease</strong>.</li>
-</ol>
-
-<p>You can use this procedure to invoke any build task from Android Studio.</p>
+<p>You can now use the <strong>Build</strong> menu options to build the release version of your
+application for distribution. </p>
<p>The build generates an APK for each build variant:
the <code>app/build/apk/</code> directory contains packages named
diff --git a/docs/html/tools/building/configuring-gradle.jd b/docs/html/tools/building/configuring-gradle.jd
index 8379508..7cca5b4 100644
--- a/docs/html/tools/building/configuring-gradle.jd
+++ b/docs/html/tools/building/configuring-gradle.jd
@@ -470,7 +470,11 @@
<li>fullRelease</li>
</ul>
-<p>To build this example, invoke the <code>assemble</code> task from Android Studio or from the
-command line.</p>
+<p>To build this example, click the <strong>Build</strong> menu option in Android Studio or invoke
+the <code>assemble</code> task from the command line. </p>
+
+<p class="note"><strong>Note:</strong> The <strong>Build > Make Project</strong> option compiles
+all the source files in the entire project that have been modified since the last compilation. The
+<strong>Build > Rebuild Project</strong> option recomplies all the source files in the project.</p>
<p>Separate output folders are created for each build variant. </p>
diff --git a/docs/html/tools/building/plugin-for-gradle.jd b/docs/html/tools/building/plugin-for-gradle.jd
index 54a03fd..a497c1b 100644
--- a/docs/html/tools/building/plugin-for-gradle.jd
+++ b/docs/html/tools/building/plugin-for-gradle.jd
@@ -15,7 +15,7 @@
<li><a href="{@docRoot}sdk/installing/studio-build.html">
Build System Overview</a></li>
<li><a href="{@docRoot}tools/building/index.html">
-Buidling and Running</a></li>
+Building and Running</a></li>
<li><a href="{@docRoot}tools/building/building-studio.html">
Building and Running from Android Studio</a></li>
</ul>
@@ -273,16 +273,9 @@
<dd><p>Performs the clean.</p></dd>
</dl>
-<p>The Android plugin provides additional tasks for <em>connectedCheck</em> and <em>deviceCheck</em>
+<p>The Android plugin provides the <em>connectedCheck</em> and <em>deviceCheck</em> tasks
for checks run on connected, emulated, and remote devices. Gradle tasks can be viewed by clicking
-the Gradle tab</a> in the right margin.
-<img src="{@docRoot}images/tools/studio-gradle-tab.png"></p>
-<p class="img-caption"><strong>Figure 1:</strong> Gradle tab</p>
-
-<p>Running a top-level task, runs all the dependent tasks. For example, the <em>assemble</em> task
-has dependent tasks for <em>assembleDebug</em> and <em>assembleRelease</em> to make the debug and
-release APKs. The <em>assemble</em> task depends on these tasks so calling it builds both APKs.
-These tasks can also be called independently to build the debug or release APK separately. </p>
+the Gradle tab</a> in the right margin.</p>
<p>You can view the list of available tasks and invoke any task from Android Studio and from
the command line, as described in
diff --git a/docs/html/tools/help/hierarchy-viewer.jd b/docs/html/tools/help/hierarchy-viewer.jd
index 4a346e0..da4cc1e 100644
--- a/docs/html/tools/help/hierarchy-viewer.jd
+++ b/docs/html/tools/help/hierarchy-viewer.jd
@@ -3,16 +3,27 @@
parent.link=index.html
@jd:body
-<p>Hierarchy Viewer allows you to debug and optimize your user
-interface. It provides a visual representation of the layout's View hierarchy
-(the Layout View) and a magnified inspector of the display (the Pixel Perfect View).
+<p>The Hierarchy Viewer allows you to debug and optimize your user
+interface. It provides a visual representation of the layout's View hierarchy
+(the Layout View) and a magnified inspector of the display (the Pixel Perfect View). </p>
+
+<p>To start the Hierarchy Viewer, do one of the following: </p>
+
+<ul>
+<li> From Android Studio, choose <strong>Tools > Android Device Monitor</strong> or click the
+Android Device Monitor icon
+<img src="{@docRoot}images/tools/hierarchicalviewer-icon.png" alt=""/>. Click the Open Perspectives
+icon <img src="{@docRoot}images/tools/studio-DDMS-open-perspective-icon.png" alt=""/> and select
+<strong>Hierarchy View</strong>. </li>
+<li>From the SDK <code>tools/</code> directory, enter:
+ <pre>monitor</pre> </li>
+</ul>
+
+<p>For more information on how to use the Hierarchy Viewer, see
+<a href="{@docRoot}tools/debugging/debugging-ui.html">Optimizing Your UI</a>.
</p>
-<p>To start Hierarchy Viewer, enter the following command from the SDK <code>tools/</code> directory:</p>
- <pre>hierarchyviewer</pre>
-</ol>
+<p class="note"><strong>Note:</strong> The command line version of Hierarchy Viewer has been
+deprecated. </p>
-<p>For more information on how to use Hierarchy Viewer, see
-<a href="{@docRoot}tools/debugging/debugging-ui.html">Debugging and Profiling UIs</a>
-</p>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index be5c52b..e2f7799 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1568,13 +1568,9 @@
nativePrepareToDraw(mSkBitmapPtr);
}
- /**
- * Refs the underlying SkPixelRef and returns a pointer to it.
- *
- * @hide
- * */
- public final long refSkPixelRef() {
- return nativeRefPixelRef(mSkBitmapPtr);
+ /** @hide */
+ public final long getSkBitmap() {
+ return mSkBitmapPtr;
}
private static class BitmapFinalizer {
@@ -1665,5 +1661,4 @@
private static native boolean nativeHasMipMap(long nativeBitmap);
private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap);
private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);
- private static native long nativeRefPixelRef(long nativeBitmap);
}
diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java
index bd74bc8..f2f890e 100644
--- a/graphics/java/android/graphics/BitmapShader.java
+++ b/graphics/java/android/graphics/BitmapShader.java
@@ -42,7 +42,8 @@
mBitmap = bitmap;
mTileX = tileX;
mTileY = tileY;
- init(nativeCreate(bitmap, tileX.nativeInt, tileY.nativeInt));
+ final long b = bitmap.getSkBitmap();
+ init(nativeCreate(b, tileX.nativeInt, tileY.nativeInt));
}
/**
@@ -55,6 +56,6 @@
return copy;
}
- private static native long nativeCreate(Bitmap bitmap, int shaderTileModeX,
+ private static native long nativeCreate(long native_bitmap, int shaderTileModeX,
int shaderTileModeY);
}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 1c56884..48afcbf 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -81,6 +81,10 @@
*/
protected int mScreenDensity = Bitmap.DENSITY_NONE;
+ // Used by native code
+ @SuppressWarnings("UnusedDeclaration")
+ private int mSurfaceFormat;
+
/**
* Flag for drawTextRun indicating left-to-right run direction.
* @hide
@@ -133,7 +137,7 @@
public Canvas() {
if (!isHardwareAccelerated()) {
// 0 means no native bitmap
- mNativeCanvasWrapper = initRaster(null);
+ mNativeCanvasWrapper = initRaster(0);
mFinalizer = new CanvasFinalizer(mNativeCanvasWrapper);
} else {
mFinalizer = null;
@@ -154,7 +158,7 @@
throw new IllegalStateException("Immutable bitmap passed to Canvas constructor");
}
throwIfCannotDraw(bitmap);
- mNativeCanvasWrapper = initRaster(bitmap);
+ mNativeCanvasWrapper = initRaster(bitmap.getSkBitmap());
mFinalizer = new CanvasFinalizer(mNativeCanvasWrapper);
mBitmap = bitmap;
mDensity = bitmap.mDensity;
@@ -211,7 +215,7 @@
}
if (bitmap == null) {
- native_setBitmap(mNativeCanvasWrapper, null);
+ native_setBitmap(mNativeCanvasWrapper, 0, false);
mDensity = Bitmap.DENSITY_NONE;
} else {
if (!bitmap.isMutable()) {
@@ -219,7 +223,7 @@
}
throwIfCannotDraw(bitmap);
- native_setBitmap(mNativeCanvasWrapper, bitmap);
+ native_setBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), true);
mDensity = bitmap.mDensity;
}
@@ -227,6 +231,13 @@
}
/**
+ * setBitmap() variant for native callers with a raw bitmap handle.
+ */
+ private void setNativeBitmap(long bitmapHandle) {
+ native_setBitmap(mNativeCanvasWrapper, bitmapHandle, false);
+ }
+
+ /**
* Set the viewport dimensions if this canvas is GL based. If it is not,
* this method is ignored and no exception is thrown.
*
@@ -1335,7 +1346,7 @@
*/
public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
throwIfCannotDraw(bitmap);
- native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top,
+ native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top,
paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity);
}
@@ -1381,7 +1392,7 @@
bottom = src.bottom;
}
- native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
+ native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top, right, bottom,
dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
bitmap.mDensity);
}
@@ -1428,7 +1439,7 @@
bottom = src.bottom;
}
- native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
+ native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top, right, bottom,
dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
bitmap.mDensity);
}
@@ -1509,7 +1520,7 @@
* @param paint May be null. The paint used to draw the bitmap
*/
public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
- nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(),
+ nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getSkBitmap(), matrix.ni(),
paint != null ? paint.getNativeInstance() : 0);
}
@@ -1564,7 +1575,7 @@
// no mul by 2, since we need only 1 color per vertex
checkRange(colors.length, colorOffset, count);
}
- nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight,
+ nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap.getSkBitmap(), meshWidth, meshHeight,
verts, vertOffset, colors, colorOffset,
paint != null ? paint.getNativeInstance() : 0);
}
@@ -1965,9 +1976,10 @@
*/
public static native void freeTextLayoutCaches();
- private static native long initRaster(Bitmap bitmap);
+ private static native long initRaster(long nativeBitmapOrZero);
private static native void native_setBitmap(long canvasHandle,
- Bitmap bitmap);
+ long bitmapHandle,
+ boolean copyState);
private static native boolean native_isOpaque(long canvasHandle);
private static native int native_getWidth(long canvasHandle);
private static native int native_getHeight(long canvasHandle);
@@ -2052,13 +2064,13 @@
private static native void native_drawPath(long nativeCanvas,
long nativePath,
long nativePaint);
- private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap,
+ private native void native_drawBitmap(long nativeCanvas, long nativeBitmap,
float left, float top,
long nativePaintOrZero,
int canvasDensity,
int screenDensity,
int bitmapDensity);
- private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap,
+ private native void native_drawBitmap(long nativeCanvas, long nativeBitmap,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom,
long nativePaintOrZero, int screenDensity, int bitmapDensity);
@@ -2068,11 +2080,11 @@
boolean hasAlpha,
long nativePaintOrZero);
private static native void nativeDrawBitmapMatrix(long nativeCanvas,
- Bitmap bitmap,
+ long nativeBitmap,
long nativeMatrix,
long nativePaint);
private static native void nativeDrawBitmapMesh(long nativeCanvas,
- Bitmap bitmap,
+ long nativeBitmap,
int meshWidth, int meshHeight,
float[] verts, int vertOffset,
int[] colors, int colorOffset,
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 21a212a..9c4299a 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -98,7 +98,7 @@
public NinePatch(Bitmap bitmap, byte[] chunk, String srcName) {
mBitmap = bitmap;
mSrcName = srcName;
- mNativeChunk = validateNinePatchChunk(chunk);
+ mNativeChunk = validateNinePatchChunk(mBitmap.getSkBitmap(), chunk);
}
/**
@@ -199,12 +199,12 @@
}
void drawSoftware(Canvas canvas, RectF location, Paint paint) {
- nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap, mNativeChunk,
+ nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.getSkBitmap(), mNativeChunk,
paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity);
}
void drawSoftware(Canvas canvas, Rect location, Paint paint) {
- nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap, mNativeChunk,
+ nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.getSkBitmap(), mNativeChunk,
paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity);
}
@@ -252,7 +252,7 @@
* that are transparent.
*/
public final Region getTransparentRegion(Rect bounds) {
- long r = nativeGetTransparentRegion(mBitmap, mNativeChunk, bounds);
+ long r = nativeGetTransparentRegion(mBitmap.getSkBitmap(), mNativeChunk, bounds);
return r != 0 ? new Region(r) : null;
}
@@ -271,11 +271,11 @@
* If validation is successful, this method returns a native Res_png_9patch*
* object used by the renderers.
*/
- private static native long validateNinePatchChunk(byte[] chunk);
+ private static native long validateNinePatchChunk(long bitmap, byte[] chunk);
private static native void nativeFinalize(long chunk);
- private static native void nativeDraw(long canvas_instance, RectF loc, Bitmap bitmap_instance,
+ private static native void nativeDraw(long canvas_instance, RectF loc, long bitmap_instance,
long c, long paint_instance_or_null, int destDensity, int srcDensity);
- private static native void nativeDraw(long canvas_instance, Rect loc, Bitmap bitmap_instance,
+ private static native void nativeDraw(long canvas_instance, Rect loc, long bitmap_instance,
long c, long paint_instance_or_null, int destDensity, int srcDensity);
- private static native long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location);
+ private static native long nativeGetTransparentRegion(long bitmap, long chunk, Rect location);
}
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index e8b8c77..22ff3e74 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -572,7 +572,7 @@
* Specifies a tint blending mode for this drawable.
* <p>
* Defines how this drawable's tint color should be blended into the drawable
- * before it is drawn to screen. Default tint mode is {@link PorterDuff.Mode#MULTIPLY}.
+ * before it is drawn to screen. Default tint mode is {@link PorterDuff.Mode#SRC_IN}.
* </p>
* <p class="note"><strong>Note:</strong> Setting a color filter via
* {@link #setColorFilter(ColorFilter)} or
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index 882826e..4d2e3a0 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -82,12 +82,12 @@
///////////////////////////////////////////////////////////////////////////////
AssetAtlas::Entry* AssetAtlas::getEntry(const SkBitmap* bitmap) const {
- ssize_t index = mEntries.indexOfKey(bitmap->pixelRef());
+ ssize_t index = mEntries.indexOfKey(bitmap);
return index >= 0 ? mEntries.valueAt(index) : nullptr;
}
Texture* AssetAtlas::getEntryTexture(const SkBitmap* bitmap) const {
- ssize_t index = mEntries.indexOfKey(bitmap->pixelRef());
+ ssize_t index = mEntries.indexOfKey(bitmap);
return index >= 0 ? mEntries.valueAt(index)->texture : nullptr;
}
@@ -120,7 +120,7 @@
const float height = float(mTexture->height);
for (int i = 0; i < count; ) {
- SkPixelRef* pixelRef = reinterpret_cast<SkPixelRef*>(map[i++]);
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(map[i++]);
// NOTE: We're converting from 64 bit signed values to 32 bit
// signed values. This is guaranteed to be safe because the "x"
// and "y" coordinate values are guaranteed to be representable
@@ -131,21 +131,21 @@
bool rotated = map[i++] > 0;
// Bitmaps should never be null, we're just extra paranoid
- if (!pixelRef) continue;
+ if (!bitmap) continue;
const UvMapper mapper(
- x / width, (x + pixelRef->info().width()) / width,
- y / height, (y + pixelRef->info().height()) / height);
+ x / width, (x + bitmap->width()) / width,
+ y / height, (y + bitmap->height()) / height);
Texture* texture = new DelegateTexture(caches, mTexture);
- texture->blend = !SkAlphaTypeIsOpaque(pixelRef->info().alphaType());
- texture->width = pixelRef->info().width();
- texture->height = pixelRef->info().height();
+ texture->blend = !bitmap->isOpaque();
+ texture->width = bitmap->width();
+ texture->height = bitmap->height();
- Entry* entry = new Entry(pixelRef, x, y, rotated, texture, mapper, *this);
+ Entry* entry = new Entry(bitmap, x, y, rotated, texture, mapper, *this);
texture->uvMapper = &entry->uvMapper;
- mEntries.add(entry->pixelRef, entry);
+ mEntries.add(entry->bitmap, entry);
}
}
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index 17c5281..1772eff 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -48,8 +48,24 @@
* Entry representing the position and rotation of a
* bitmap inside the atlas.
*/
- class Entry {
- public:
+ struct Entry {
+ /**
+ * The bitmap that generated this atlas entry.
+ */
+ SkBitmap* bitmap;
+
+ /**
+ * Location of the bitmap inside the atlas, in pixels.
+ */
+ int x;
+ int y;
+
+ /**
+ * If set, the bitmap is rotated 90 degrees (clockwise)
+ * inside the atlas.
+ */
+ bool rotated;
+
/*
* A "virtual texture" object that represents the texture
* this entry belongs to. This texture should never be
@@ -64,6 +80,11 @@
const UvMapper uvMapper;
/**
+ * Atlas this entry belongs to.
+ */
+ const AssetAtlas& atlas;
+
+ /**
* Unique identifier used to merge bitmaps and 9-patches stored
* in the atlas.
*/
@@ -72,37 +93,10 @@
}
private:
- /**
- * The pixel ref that generated this atlas entry.
- */
- SkPixelRef* pixelRef;
-
- /**
- * Location of the bitmap inside the atlas, in pixels.
- */
- int x;
- int y;
-
- /**
- * If set, the bitmap is rotated 90 degrees (clockwise)
- * inside the atlas.
- */
- bool rotated;
-
- /**
- * Atlas this entry belongs to.
- */
- const AssetAtlas& atlas;
-
- Entry(SkPixelRef* pixelRef, int x, int y, bool rotated,
- Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas)
- : texture(texture)
- , uvMapper(mapper)
- , pixelRef(pixelRef)
- , x(x)
- , y(y)
- , rotated(rotated)
- , atlas(atlas) {
+ Entry(SkBitmap* bitmap, int x, int y, bool rotated,
+ Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas):
+ bitmap(bitmap), x(x), y(y), rotated(rotated),
+ texture(texture), uvMapper(mapper), atlas(atlas) {
}
~Entry() {
@@ -184,7 +178,7 @@
const bool mBlendKey;
const bool mOpaqueKey;
- KeyedVector<const SkPixelRef*, Entry*> mEntries;
+ KeyedVector<const SkBitmap*, Entry*> mEntries;
}; // class AssetAtlas
}; // namespace uirenderer
diff --git a/libs/hwui/Canvas.h b/libs/hwui/Canvas.h
index aa24673..7ad0683 100644
--- a/libs/hwui/Canvas.h
+++ b/libs/hwui/Canvas.h
@@ -29,7 +29,7 @@
public:
virtual ~Canvas() {};
- static Canvas* create_canvas(const SkBitmap& bitmap);
+ static Canvas* create_canvas(SkBitmap* bitmap);
/**
* Create a new Canvas object which delegates to an SkCanvas.
@@ -52,7 +52,7 @@
*/
virtual SkCanvas* asSkCanvas() = 0;
- virtual void setBitmap(const SkBitmap& bitmap) = 0;
+ virtual void setBitmap(SkBitmap* bitmap, bool copyState) = 0;
virtual bool isOpaque() = 0;
virtual int width() = 0;
@@ -87,8 +87,7 @@
virtual bool quickRejectRect(float left, float top, float right, float bottom) const = 0;
virtual bool quickRejectPath(const SkPath& path) const = 0;
- virtual bool clipRect(float left, float top, float right, float bottom,
- SkRegion::Op op = SkRegion::kIntersect_Op) = 0;
+ virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) = 0;
virtual bool clipPath(const SkPath* path, SkRegion::Op op) = 0;
virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 4d596fe..8757e15 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -220,7 +220,7 @@
}
void DisplayListRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
- bitmap = refBitmap(*bitmap);
+ bitmap = refBitmap(bitmap);
paint = refPaint(paint);
addDrawOp(new (alloc()) DrawBitmapOp(bitmap, paint));
@@ -286,7 +286,7 @@
dstRight = srcRight - srcLeft;
dstBottom = srcBottom - srcTop;
- addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap),
+ addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(&bitmap),
srcLeft, srcTop, srcRight, srcBottom,
dstLeft, dstTop, dstRight, dstBottom, paint));
restore();
@@ -294,7 +294,7 @@
}
}
- addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(bitmap),
+ addDrawOp(new (alloc()) DrawBitmapRectOp(refBitmap(&bitmap),
srcLeft, srcTop, srcRight, srcBottom,
dstLeft, dstTop, dstRight, dstBottom, paint));
}
@@ -307,17 +307,17 @@
paint = refPaint(paint);
colors = refBuffer<int>(colors, vertexCount); // 1 color per vertex
- addDrawOp(new (alloc()) DrawBitmapMeshOp(refBitmap(bitmap), meshWidth, meshHeight,
+ addDrawOp(new (alloc()) DrawBitmapMeshOp(refBitmap(&bitmap), meshWidth, meshHeight,
vertices, colors, paint));
}
-void DisplayListRenderer::drawPatch(const SkBitmap& bitmap, const Res_png_9patch* patch,
+void DisplayListRenderer::drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
float left, float top, float right, float bottom, const SkPaint* paint) {
- const SkBitmap* bitmapPtr = refBitmap(bitmap);
+ bitmap = refBitmap(bitmap);
patch = refPatch(patch);
paint = refPaint(paint);
- addDrawOp(new (alloc()) DrawPatchOp(bitmapPtr, patch, left, top, right, bottom, paint));
+ addDrawOp(new (alloc()) DrawPatchOp(bitmap, patch, left, top, right, bottom, paint));
}
void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 44cf546..53fd1ad 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -100,7 +100,7 @@
// Bitmap-based
void drawBitmap(const SkBitmap* bitmap, const SkPaint* paint);
// TODO: move drawPatch() to Canvas.h
- void drawPatch(const SkBitmap& bitmap, const Res_png_9patch* patch,
+ void drawPatch(const SkBitmap* bitmap, const Res_png_9patch* patch,
float left, float top, float right, float bottom, const SkPaint* paint);
// Shapes
@@ -138,7 +138,7 @@
// ----------------------------------------------------------------------------
virtual SkCanvas* asSkCanvas() override;
- virtual void setBitmap(const SkBitmap& bitmap) override {
+ virtual void setBitmap(SkBitmap* bitmap, bool copyState) override {
LOG_ALWAYS_FATAL("DisplayListRenderer is not backed by a bitmap.");
}
@@ -347,7 +347,7 @@
return cachedRegion;
}
- inline const SkBitmap* refBitmap(const SkBitmap& bitmap) {
+ inline const SkBitmap* refBitmap(const SkBitmap* bitmap) {
// Note that this assumes the bitmap is immutable. There are cases this won't handle
// correctly, such as creating the bitmap from scratch, drawing with it, changing its
// contents, and drawing again. The only fix would be to always copy it the first time,
diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp
index 454fedc..d3b8d70 100644
--- a/libs/hwui/ResourceCache.cpp
+++ b/libs/hwui/ResourceCache.cpp
@@ -59,13 +59,13 @@
mLock.unlock();
}
-const SkBitmap* ResourceCache::insert(const SkBitmap& bitmapResource) {
+const SkBitmap* ResourceCache::insert(const SkBitmap* bitmapResource) {
Mutex::Autolock _l(mLock);
BitmapKey bitmapKey(bitmapResource);
ssize_t index = mBitmapCache.indexOfKey(bitmapKey);
if (index == NAME_NOT_FOUND) {
- SkBitmap* cachedBitmap = new SkBitmap(bitmapResource);
+ SkBitmap* cachedBitmap = new SkBitmap(*bitmapResource);
index = mBitmapCache.add(bitmapKey, cachedBitmap);
return cachedBitmap;
}
@@ -121,7 +121,7 @@
}
void ResourceCache::decrementRefcountLocked(const SkBitmap* bitmapResource) {
- BitmapKey bitmapKey(*bitmapResource);
+ BitmapKey bitmapKey(bitmapResource);
ssize_t index = mBitmapCache.indexOfKey(bitmapKey);
LOG_ALWAYS_FATAL_IF(index == NAME_NOT_FOUND,
diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h
index 6c483fa..fae55d1 100644
--- a/libs/hwui/ResourceCache.h
+++ b/libs/hwui/ResourceCache.h
@@ -53,11 +53,11 @@
class BitmapKey {
public:
- BitmapKey(const SkBitmap& bitmap)
+ BitmapKey(const SkBitmap* bitmap)
: mRefCount(1)
- , mBitmapDimensions(bitmap.dimensions())
- , mPixelRefOrigin(bitmap.pixelRefOrigin())
- , mPixelRefStableID(bitmap.pixelRef()->getStableID()) { }
+ , mBitmapDimensions(bitmap->dimensions())
+ , mPixelRefOrigin(bitmap->pixelRefOrigin())
+ , mPixelRefStableID(bitmap->pixelRef()->getStableID()) { }
void operator=(const BitmapKey& other);
bool operator==(const BitmapKey& other) const;
@@ -101,7 +101,7 @@
* The cache stores a copy of the provided resource or refs an existing resource
* if the bitmap has previously been inserted and returns the cached copy.
*/
- const SkBitmap* insert(const SkBitmap& resource);
+ const SkBitmap* insert(const SkBitmap* resource);
void incrementRefcount(const Res_png_9patch* resource);
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index a323065..8b11757 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -31,7 +31,7 @@
// Holds an SkCanvas reference plus additional native data.
class SkiaCanvas : public Canvas {
public:
- explicit SkiaCanvas(const SkBitmap& bitmap);
+ explicit SkiaCanvas(SkBitmap* bitmap);
/**
* Create a new SkiaCanvas.
@@ -49,7 +49,7 @@
return mCanvas.get();
}
- virtual void setBitmap(const SkBitmap& bitmap) override;
+ virtual void setBitmap(SkBitmap* bitmap, bool copyState) override;
virtual bool isOpaque() override;
virtual int width() override;
@@ -145,7 +145,19 @@
SkAutoTDelete<SkDeque> mSaveStack; // lazily allocated, tracks partial saves.
};
-Canvas* Canvas::create_canvas(const SkBitmap& bitmap) {
+// Construct an SkCanvas from the bitmap.
+static SkCanvas* createCanvas(SkBitmap* bitmap) {
+ if (bitmap) {
+ return SkNEW_ARGS(SkCanvas, (*bitmap));
+ }
+
+ // Create an empty bitmap device to prevent callers from crashing
+ // if they attempt to draw into this canvas.
+ SkBitmap emptyBitmap;
+ return new SkCanvas(emptyBitmap);
+}
+
+Canvas* Canvas::create_canvas(SkBitmap* bitmap) {
return new SkiaCanvas(bitmap);
}
@@ -153,8 +165,8 @@
return new SkiaCanvas(skiaCanvas);
}
-SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
- mCanvas.reset(new SkCanvas(bitmap));
+SkiaCanvas::SkiaCanvas(SkBitmap* bitmap) {
+ mCanvas.reset(createCanvas(bitmap));
}
// ----------------------------------------------------------------------------
@@ -179,11 +191,11 @@
SkCanvas* m_dstCanvas;
};
-void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
- SkCanvas* newCanvas = new SkCanvas(bitmap);
+void SkiaCanvas::setBitmap(SkBitmap* bitmap, bool copyState) {
+ SkCanvas* newCanvas = createCanvas(bitmap);
SkASSERT(newCanvas);
- if (!bitmap.isNull()) {
+ if (copyState) {
// Copy the canvas matrix & clip state.
newCanvas->setMatrix(mCanvas->getTotalMatrix());
if (NULL != mCanvas->getDevice() && NULL != newCanvas->getDevice()) {
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index d15fa39..cc87241 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -293,11 +293,11 @@
return (void*) success;
}
-bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
+bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
SETUP_TASK(copyLayerInto);
args->context = mContext;
args->layer = layer;
- args->bitmap = &bitmap;
+ args->bitmap = bitmap;
return (bool) postAndWait(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index cc475fa..29c6f08 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -83,7 +83,7 @@
ANDROID_API DeferredLayerUpdater* createTextureLayer();
ANDROID_API void buildLayer(RenderNode* node);
- ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap);
+ ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
ANDROID_API void pushLayerUpdate(DeferredLayerUpdater* layer);
ANDROID_API void cancelLayerUpdate(DeferredLayerUpdater* layer);
ANDROID_API void detachSurfaceTexture(DeferredLayerUpdater* layer);
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 9e1e055..3e771f4 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -901,21 +901,48 @@
* the parameters don't resolve to valid data and indexes.
* The number of bytes will not exceed sizeInBytes.
*/
- public int read(byte[] audioData, int offsetInBytes, int sizeInBytes) {
- if (mState != STATE_INITIALIZED) {
+ public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) {
+ return read(audioData, offsetInBytes, sizeInBytes, READ_BLOCKING);
+ }
+
+ /**
+ * Reads audio data from the audio hardware for recording into a byte array.
+ * The format specified in the AudioRecord constructor should be
+ * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
+ * @param audioData the array to which the recorded audio data is written.
+ * @param offsetInBytes index in audioData from which the data is written expressed in bytes.
+ * @param sizeInBytes the number of requested bytes.
+ * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
+ * <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
+ * is read.
+ * <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
+ * reading as much audio data as possible without blocking.
+ * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
+ * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * the parameters don't resolve to valid data and indexes.
+ * The number of bytes will not exceed sizeInBytes.
+ */
+ public int read(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
+ @ReadMode int readMode) {
+ if (mState != STATE_INITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
return ERROR_INVALID_OPERATION;
}
+ if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) {
+ Log.e(TAG, "AudioRecord.read() called with invalid blocking mode");
+ return ERROR_BAD_VALUE;
+ }
+
if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0)
|| (offsetInBytes + sizeInBytes < 0) // detect integer overflow
|| (offsetInBytes + sizeInBytes > audioData.length)) {
return ERROR_BAD_VALUE;
}
- return native_read_in_byte_array(audioData, offsetInBytes, sizeInBytes);
+ return native_read_in_byte_array(audioData, offsetInBytes, sizeInBytes,
+ readMode == READ_BLOCKING);
}
-
/**
* Reads audio data from the audio hardware for recording into a short array.
* The format specified in the AudioRecord constructor should be
@@ -928,18 +955,46 @@
* the parameters don't resolve to valid data and indexes.
* The number of shorts will not exceed sizeInShorts.
*/
- public int read(short[] audioData, int offsetInShorts, int sizeInShorts) {
- if (mState != STATE_INITIALIZED) {
+ public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) {
+ return read(audioData, offsetInShorts, sizeInShorts, READ_BLOCKING);
+ }
+
+ /**
+ * Reads audio data from the audio hardware for recording into a short array.
+ * The format specified in the AudioRecord constructor should be
+ * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
+ * @param audioData the array to which the recorded audio data is written.
+ * @param offsetInShorts index in audioData from which the data is written expressed in shorts.
+ * @param sizeInShorts the number of requested shorts.
+ * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
+ * <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
+ * is read.
+ * <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
+ * reading as much audio data as possible without blocking.
+ * @return the number of shorts that were read or {@link #ERROR_INVALID_OPERATION}
+ * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * the parameters don't resolve to valid data and indexes.
+ * The number of shorts will not exceed sizeInShorts.
+ */
+ public int read(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
+ @ReadMode int readMode) {
+ if (mState != STATE_INITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
return ERROR_INVALID_OPERATION;
}
+ if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) {
+ Log.e(TAG, "AudioRecord.read() called with invalid blocking mode");
+ return ERROR_BAD_VALUE;
+ }
+
if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0)
|| (offsetInShorts + sizeInShorts < 0) // detect integer overflow
|| (offsetInShorts + sizeInShorts > audioData.length)) {
return ERROR_BAD_VALUE;
}
- return native_read_in_short_array(audioData, offsetInShorts, sizeInShorts);
+ return native_read_in_short_array(audioData, offsetInShorts, sizeInShorts,
+ readMode == READ_BLOCKING);
}
/**
@@ -950,22 +1005,33 @@
* @param offsetInFloats index in audioData from which the data is written.
* @param sizeInFloats the number of requested floats.
* @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
- * <BR>With {@link #READ_BLOCKING}, the read will block until all the requested data
+ * <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
* is read.
- * <BR>With {@link #READ_NON_BLOCKING}, the read will return immediately after
+ * <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
* reading as much audio data as possible without blocking.
* @return the number of floats that were read or {@link #ERROR_INVALID_OPERATION}
* if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
* the parameters don't resolve to valid data and indexes.
* The number of floats will not exceed sizeInFloats.
*/
- public int read(float[] audioData, int offsetInFloats, int sizeInFloats,
+ public int read(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
@ReadMode int readMode) {
- if (mState != STATE_INITIALIZED) {
+ if (mState == STATE_UNINITIALIZED) {
+ Log.e(TAG, "AudioRecord.read() called in invalid state STATE_UNINITIALIZED");
return ERROR_INVALID_OPERATION;
}
- if ( (audioData == null) || (offsetInFloats < 0 ) || (sizeInFloats < 0)
+ if (mAudioFormat != AudioFormat.ENCODING_PCM_FLOAT) {
+ Log.e(TAG, "AudioRecord.read(float[] ...) requires format ENCODING_PCM_FLOAT");
+ return ERROR_INVALID_OPERATION;
+ }
+
+ if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) {
+ Log.e(TAG, "AudioRecord.read() called with invalid blocking mode");
+ return ERROR_BAD_VALUE;
+ }
+
+ if ((audioData == null) || (offsetInFloats < 0) || (sizeInFloats < 0)
|| (offsetInFloats + sizeInFloats < 0) // detect integer overflow
|| (offsetInFloats + sizeInFloats > audioData.length)) {
return ERROR_BAD_VALUE;
@@ -992,19 +1058,49 @@
* The number of bytes will not exceed sizeInBytes.
* The number of bytes read will truncated to be a multiple of the frame size.
*/
- public int read(ByteBuffer audioBuffer, int sizeInBytes) {
+ public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes) {
+ return read(audioBuffer, sizeInBytes, READ_BLOCKING);
+ }
+
+ /**
+ * Reads audio data from the audio hardware for recording into a direct buffer. If this buffer
+ * is not a direct buffer, this method will always return 0.
+ * Note that the value returned by {@link java.nio.Buffer#position()} on this buffer is
+ * unchanged after a call to this method.
+ * The representation of the data in the buffer will depend on the format specified in
+ * the AudioRecord constructor, and will be native endian.
+ * @param audioBuffer the direct buffer to which the recorded audio data is written.
+ * @param sizeInBytes the number of requested bytes. It is recommended but not enforced
+ * that the number of bytes requested be a multiple of the frame size (sample size in
+ * bytes multiplied by the channel count).
+ * @param readMode one of {@link #READ_BLOCKING}, {@link #READ_NON_BLOCKING}.
+ * <br>With {@link #READ_BLOCKING}, the read will block until all the requested data
+ * is read.
+ * <br>With {@link #READ_NON_BLOCKING}, the read will return immediately after
+ * reading as much audio data as possible without blocking.
+ * @return the number of bytes that were read or {@link #ERROR_INVALID_OPERATION}
+ * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * the parameters don't resolve to valid data and indexes.
+ * The number of bytes will not exceed sizeInBytes.
+ * The number of bytes read will truncated to be a multiple of the frame size.
+ */
+ public int read(@NonNull ByteBuffer audioBuffer, int sizeInBytes, @ReadMode int readMode) {
if (mState != STATE_INITIALIZED) {
return ERROR_INVALID_OPERATION;
}
+ if ((readMode != READ_BLOCKING) && (readMode != READ_NON_BLOCKING)) {
+ Log.e(TAG, "AudioRecord.read() called with invalid blocking mode");
+ return ERROR_BAD_VALUE;
+ }
+
if ( (audioBuffer == null) || (sizeInBytes < 0) ) {
return ERROR_BAD_VALUE;
}
- return native_read_in_direct_buffer(audioBuffer, sizeInBytes);
+ return native_read_in_direct_buffer(audioBuffer, sizeInBytes, readMode == READ_BLOCKING);
}
-
//--------------------------------------------------------------------------
// Initialization / configuration
//--------------------
@@ -1186,15 +1282,16 @@
private native final void native_stop();
private native final int native_read_in_byte_array(byte[] audioData,
- int offsetInBytes, int sizeInBytes);
+ int offsetInBytes, int sizeInBytes, boolean isBlocking);
private native final int native_read_in_short_array(short[] audioData,
- int offsetInShorts, int sizeInShorts);
+ int offsetInShorts, int sizeInShorts, boolean isBlocking);
private native final int native_read_in_float_array(float[] audioData,
int offsetInFloats, int sizeInFloats, boolean isBlocking);
- private native final int native_read_in_direct_buffer(Object jBuffer, int sizeInBytes);
+ private native final int native_read_in_direct_buffer(Object jBuffer,
+ int sizeInBytes, boolean isBlocking);
private native final int native_get_native_frame_count();
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 6c41a2a..44455fa 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -1540,6 +1540,8 @@
/**
* Writes the audio data to the audio sink for playback (streaming mode),
* or copies audio data for later playback (static buffer mode).
+ * The format specified in the AudioTrack constructor should be
+ * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
* In streaming mode, will block until all data has been written to the audio sink.
* In static buffer mode, copies the data to the buffer starting at offset 0.
* Note that the actual playback of this data might occur after this function
@@ -1556,13 +1558,49 @@
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
*/
+ public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes) {
+ return write(audioData, offsetInBytes, sizeInBytes, WRITE_BLOCKING);
+ }
- public int write(byte[] audioData, int offsetInBytes, int sizeInBytes) {
+ /**
+ * Writes the audio data to the audio sink for playback (streaming mode),
+ * or copies audio data for later playback (static buffer mode).
+ * The format specified in the AudioTrack constructor should be
+ * {@link AudioFormat#ENCODING_PCM_8BIT} to correspond to the data in the array.
+ * In streaming mode, will block until all data has been written to the audio sink.
+ * In static buffer mode, copies the data to the buffer starting at offset 0.
+ * Note that the actual playback of this data might occur after this function
+ * returns. This function is thread safe with respect to {@link #stop} calls,
+ * in which case all of the specified data might not be written to the audio sink.
+ *
+ * @param audioData the array that holds the data to play.
+ * @param offsetInBytes the offset expressed in bytes in audioData where the data to play
+ * starts.
+ * @param sizeInBytes the number of bytes to read in audioData after the offset.
+ * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
+ * effect in static mode.
+ * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
+ * to the audio sink.
+ * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
+ * queuing as much audio data for playback as possible without blocking.
+ * @return the number of bytes that were written or {@link #ERROR_INVALID_OPERATION}
+ * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * the parameters don't resolve to valid data and indexes, or
+ * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+ * needs to be recreated.
+ */
+ public int write(@NonNull byte[] audioData, int offsetInBytes, int sizeInBytes,
+ @WriteMode int writeMode) {
if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
return ERROR_INVALID_OPERATION;
}
+ if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
+ Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
+ return ERROR_BAD_VALUE;
+ }
+
if ( (audioData == null) || (offsetInBytes < 0 ) || (sizeInBytes < 0)
|| (offsetInBytes + sizeInBytes < 0) // detect integer overflow
|| (offsetInBytes + sizeInBytes > audioData.length)) {
@@ -1570,7 +1608,7 @@
}
int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat,
- true /*isBlocking*/);
+ writeMode == WRITE_BLOCKING);
if ((mDataLoadMode == MODE_STATIC)
&& (mState == STATE_NO_STATIC_DATA)
@@ -1582,10 +1620,11 @@
return ret;
}
-
/**
* Writes the audio data to the audio sink for playback (streaming mode),
* or copies audio data for later playback (static buffer mode).
+ * The format specified in the AudioTrack constructor should be
+ * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
* In streaming mode, will block until all data has been written to the audio sink.
* In static buffer mode, copies the data to the buffer starting at offset 0.
* Note that the actual playback of this data might occur after this function
@@ -1602,20 +1641,57 @@
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
*/
+ public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts) {
+ return write(audioData, offsetInShorts, sizeInShorts, WRITE_BLOCKING);
+ }
- public int write(short[] audioData, int offsetInShorts, int sizeInShorts) {
+ /**
+ * Writes the audio data to the audio sink for playback (streaming mode),
+ * or copies audio data for later playback (static buffer mode).
+ * The format specified in the AudioTrack constructor should be
+ * {@link AudioFormat#ENCODING_PCM_16BIT} to correspond to the data in the array.
+ * In streaming mode, will block until all data has been written to the audio sink.
+ * In static buffer mode, copies the data to the buffer starting at offset 0.
+ * Note that the actual playback of this data might occur after this function
+ * returns. This function is thread safe with respect to {@link #stop} calls,
+ * in which case all of the specified data might not be written to the audio sink.
+ *
+ * @param audioData the array that holds the data to play.
+ * @param offsetInShorts the offset expressed in shorts in audioData where the data to play
+ * starts.
+ * @param sizeInShorts the number of shorts to read in audioData after the offset.
+ * @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
+ * effect in static mode.
+ * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
+ * to the audio sink.
+ * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
+ * queuing as much audio data for playback as possible without blocking.
+ * @return the number of shorts that were written or {@link #ERROR_INVALID_OPERATION}
+ * if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
+ * the parameters don't resolve to valid data and indexes, or
+ * {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
+ * needs to be recreated.
+ */
+ public int write(@NonNull short[] audioData, int offsetInShorts, int sizeInShorts,
+ @WriteMode int writeMode) {
if (mState == STATE_UNINITIALIZED || mAudioFormat == AudioFormat.ENCODING_PCM_FLOAT) {
return ERROR_INVALID_OPERATION;
}
+ if ((writeMode != WRITE_BLOCKING) && (writeMode != WRITE_NON_BLOCKING)) {
+ Log.e(TAG, "AudioTrack.write() called with invalid blocking mode");
+ return ERROR_BAD_VALUE;
+ }
+
if ( (audioData == null) || (offsetInShorts < 0 ) || (sizeInShorts < 0)
|| (offsetInShorts + sizeInShorts < 0) // detect integer overflow
|| (offsetInShorts + sizeInShorts > audioData.length)) {
return ERROR_BAD_VALUE;
}
- int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat);
+ int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat,
+ writeMode == WRITE_BLOCKING);
if ((mDataLoadMode == MODE_STATIC)
&& (mState == STATE_NO_STATIC_DATA)
@@ -1627,10 +1703,11 @@
return ret;
}
-
/**
* Writes the audio data to the audio sink for playback (streaming mode),
* or copies audio data for later playback (static buffer mode).
+ * The format specified in the AudioTrack constructor should be
+ * {@link AudioFormat#ENCODING_PCM_FLOAT} to correspond to the data in the array.
* In static buffer mode, copies the data to the buffer starting at offset 0,
* and the write mode is ignored.
* In streaming mode, the blocking behavior will depend on the write mode.
@@ -1654,9 +1731,9 @@
* @param sizeInFloats the number of floats to read in audioData after the offset.
* @param writeMode one of {@link #WRITE_BLOCKING}, {@link #WRITE_NON_BLOCKING}. It has no
* effect in static mode.
- * <BR>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
+ * <br>With {@link #WRITE_BLOCKING}, the write will block until all data has been written
* to the audio sink.
- * <BR>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
+ * <br>With {@link #WRITE_NON_BLOCKING}, the write will return immediately after
* queuing as much audio data for playback as possible without blocking.
* @return the number of floats that were written, or {@link #ERROR_INVALID_OPERATION}
* if the object wasn't properly initialized, or {@link #ERROR_BAD_VALUE} if
@@ -1664,7 +1741,7 @@
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
*/
- public int write(float[] audioData, int offsetInFloats, int sizeInFloats,
+ public int write(@NonNull float[] audioData, int offsetInFloats, int sizeInFloats,
@WriteMode int writeMode) {
if (mState == STATE_UNINITIALIZED) {
@@ -1727,7 +1804,7 @@
* {@link AudioManager#ERROR_DEAD_OBJECT} if the AudioTrack is not valid anymore and
* needs to be recreated.
*/
- public int write(ByteBuffer audioData, int sizeInBytes,
+ public int write(@NonNull ByteBuffer audioData, int sizeInBytes,
@WriteMode int writeMode) {
if (mState == STATE_UNINITIALIZED) {
@@ -2017,7 +2094,8 @@
boolean isBlocking);
private native final int native_write_short(short[] audioData,
- int offsetInShorts, int sizeInShorts, int format);
+ int offsetInShorts, int sizeInShorts, int format,
+ boolean isBlocking);
private native final int native_write_float(float[] audioData,
int offsetInFloats, int sizeInFloats, int format,
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index c8464c7..8cf9874 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -43,7 +43,7 @@
libusbhost \
libjhead \
libexif \
- libstagefright_amrnb_common
+ libstagefright_amrnb_common \
LOCAL_REQUIRED_MODULES := \
libjhead_jni
@@ -55,7 +55,6 @@
external/libexif/ \
external/tremor/Tremor \
frameworks/base/core/jni \
- frameworks/base/libs/hwui \
frameworks/av/media/libmedia \
frameworks/av/media/libstagefright \
frameworks/av/media/libstagefright/codecs/amrnb/enc/src \
diff --git a/native/graphics/jni/Android.mk b/native/graphics/jni/Android.mk
index f89a5af..91c9ac6 100644
--- a/native/graphics/jni/Android.mk
+++ b/native/graphics/jni/Android.mk
@@ -24,8 +24,7 @@
LOCAL_C_INCLUDES += \
frameworks/base/native/include \
- frameworks/base/core/jni/android/graphics \
- frameworks/base/libs/hwui
+ frameworks/base/core/jni/android/graphics
LOCAL_MODULE:= libjnigraphics
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index f16fb5c..b828e78 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -171,6 +171,11 @@
*/
private static final String KEYGUARD_ANALYTICS_SETTING = "keyguard_analytics";
+ /**
+ * How much faster we collapse the lockscreen when authenticating with fingerprint.
+ */
+ private static final float FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR = 1.3f;
+
/** The stream type that the lock sounds are tied to. */
private int mUiSoundsStreamType;
@@ -441,7 +446,8 @@
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
mViewMediatorCallback.keyguardDone(true);
} else {
- mStatusBarKeyguardViewManager.animateCollapsePanels();
+ mStatusBarKeyguardViewManager.animateCollapsePanels(
+ FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 9f86475..de4874f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -687,13 +687,7 @@
setHeadsUpUser(newUserId);
}
- private void setHeadsUpUser(int newUserId) {
- mHeadsUpManager.setUser(newUserId);
- }
-
- public boolean isHeadsUp(String key) {
- return mHeadsUpManager.isHeadsUp(key);
- }
+ protected abstract void setHeadsUpUser(int newUserId);
@Override // NotificationData.Environment
public boolean isNotificationForCurrentProfiles(StatusBarNotification n) {
@@ -1578,7 +1572,7 @@
mCurrentUserId);
dismissKeyguardThenExecute(new OnDismissAction() {
public boolean onDismiss() {
- if (mHeadsUpManager.isHeadsUp(mNotificationKey)) {
+ if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(mNotificationKey)) {
// Release the HUN notification to the shade.
//
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
@@ -1941,20 +1935,8 @@
setAreThereNotifications();
}
- private void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt,
- boolean alertAgain) {
- final boolean wasHeadsUp = isHeadsUp(key);
- if (wasHeadsUp) {
- mHeadsUpManager.updateNotification(entry, alertAgain);
- if (!shouldInterrupt) {
- // We don't want this to be interrupting anymore, lets remove it
- mHeadsUpManager.removeNotification(key);
- }
- } else if (shouldInterrupt && alertAgain) {
- // This notification was updated to be a heads-up, show it!
- mHeadsUpManager.showNotification(entry);
- }
- }
+ protected abstract void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt,
+ boolean alertAgain);
private void logUpdate(Entry oldEntry, Notification n) {
StatusBarNotification oldNotification = oldEntry.notification;
@@ -2075,7 +2057,7 @@
return false;
}
- if (mHeadsUpManager.isSnoozed(sbn.getPackageName())) {
+ if (isSnoozedPackage(sbn)) {
return false;
}
@@ -2109,6 +2091,8 @@
return interrupt;
}
+ protected abstract boolean isSnoozedPackage(StatusBarNotification sbn);
+
public void setInteracting(int barWindow, boolean interacting) {
// hook for subclasses
}
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 c266467..96e9543 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -511,9 +511,10 @@
}
@Override
- protected void flingToHeight(float vel, boolean expand, float target) {
+ protected void flingToHeight(float vel, boolean expand, float target,
+ float collapseSpeedUpFactor) {
mHeadsUpTouchHelper.notifyFling(!expand);
- super.flingToHeight(vel, expand, target);
+ super.flingToHeight(vel, expand, target, collapseSpeedUpFactor);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index 240438a7..f3d4c7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -140,7 +140,7 @@
mPanelHolder.setSelectedPanel(mTouchingPanel);
for (PanelView pv : mPanels) {
if (pv != panel) {
- pv.collapse(false /* delayed */);
+ pv.collapse(false /* delayed */, 1.0f /* speedUpFactor */);
}
}
}
@@ -186,11 +186,11 @@
(fullyOpenedPanel!=null)?" fullyOpened":"", fullyClosed?" fullyClosed":"");
}
- public void collapseAllPanels(boolean animate, boolean delayed) {
+ public void collapseAllPanels(boolean animate, boolean delayed, float speedUpFactor) {
boolean waiting = false;
for (PanelView pv : mPanels) {
if (animate && !pv.isFullyCollapsed()) {
- pv.collapse(delayed);
+ pv.collapse(delayed, speedUpFactor);
waiting = true;
} else {
pv.resetViews();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index ddce9d5..3a30429 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -101,6 +101,12 @@
private boolean mPeekPending;
private boolean mCollapseAfterPeek;
+
+ /**
+ * Speed-up factor to be used when {@link #mFlingCollapseRunnable} runs the next time.
+ */
+ private float mNextCollapseSpeedUpFactor = 1.0f;
+
private boolean mExpanding;
private boolean mGestureWaitForTouchSlop;
private Runnable mPeekRunnable = new Runnable() {
@@ -164,7 +170,7 @@
postOnAnimation(new Runnable() {
@Override
public void run() {
- collapse(false /* delayed */);
+ collapse(false /* delayed */, 1.0f /* speedUpFactor */);
}
});
}
@@ -563,12 +569,17 @@
}
protected void fling(float vel, boolean expand) {
- cancelPeek();
- float target = expand ? getMaxPanelHeight() : 0.0f;
- flingToHeight(vel, expand, target);
+ fling(vel, expand, 1.0f /* collapseSpeedUpFactor */);
}
- protected void flingToHeight(float vel, boolean expand, float target) {
+ protected void fling(float vel, boolean expand, float collapseSpeedUpFactor) {
+ cancelPeek();
+ float target = expand ? getMaxPanelHeight() : 0.0f;
+ flingToHeight(vel, expand, target, collapseSpeedUpFactor);
+ }
+
+ protected void flingToHeight(float vel, boolean expand, float target,
+ float collapseSpeedUpFactor) {
// Hack to make the expand transition look nice when clear all button is visible - we make
// the animation only to the last notification, and then jump to the maximum panel height so
// clear all just fades in and the decelerating motion is towards the last notification.
@@ -600,7 +611,8 @@
// Make it shorter if we run a canned animation
if (vel == 0) {
animator.setDuration((long)
- (animator.getDuration() * getCannedFlingDurationFactor()));
+ (animator.getDuration() * getCannedFlingDurationFactor()
+ / collapseSpeedUpFactor));
}
}
animator.addListener(new AnimatorListenerAdapter() {
@@ -745,7 +757,7 @@
mBar = panelBar;
}
- public void collapse(boolean delayed) {
+ public void collapse(boolean delayed, float speedUpFactor) {
if (DEBUG) logf("collapse: " + this);
if (mPeekPending || mPeekAnimator != null) {
mCollapseAfterPeek = true;
@@ -761,9 +773,10 @@
mClosing = true;
notifyExpandingStarted();
if (delayed) {
+ mNextCollapseSpeedUpFactor = speedUpFactor;
postDelayed(mFlingCollapseRunnable, 120);
} else {
- fling(0, false /* expand */);
+ fling(0, false /* expand */, speedUpFactor);
}
}
}
@@ -771,7 +784,7 @@
private final Runnable mFlingCollapseRunnable = new Runnable() {
@Override
public void run() {
- fling(0, false /* expand */);
+ fling(0, false /* expand */, mNextCollapseSpeedUpFactor);
}
};
@@ -975,7 +988,7 @@
protected final Runnable mPostCollapseRunnable = new Runnable() {
@Override
public void run() {
- collapse(false /* delayed */);
+ collapse(false /* delayed */, 1.0f /* speedUpFactor */);
}
};
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 a5dad92..b6dbfce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1867,6 +1867,35 @@
}
+ protected void updateHeadsUp(String key, Entry entry, boolean shouldInterrupt,
+ boolean alertAgain) {
+ final boolean wasHeadsUp = isHeadsUp(key);
+ if (wasHeadsUp) {
+ mHeadsUpManager.updateNotification(entry, alertAgain);
+ if (!shouldInterrupt) {
+ // We don't want this to be interrupting anymore, lets remove it
+ mHeadsUpManager.removeNotification(key);
+ }
+ } else if (shouldInterrupt && alertAgain) {
+ // This notification was updated to be a heads-up, show it!
+ mHeadsUpManager.showNotification(entry);
+ }
+ }
+
+ protected void setHeadsUpUser(int newUserId) {
+ if (mHeadsUpManager != null) {
+ mHeadsUpManager.setUser(newUserId);
+ }
+ }
+
+ public boolean isHeadsUp(String key) {
+ return mHeadsUpManager.isHeadsUp(key);
+ }
+
+ protected boolean isSnoozedPackage(StatusBarNotification sbn) {
+ return mHeadsUpManager.isSnoozed(sbn.getPackageName());
+ }
+
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
@@ -1952,14 +1981,20 @@
}
public void animateCollapsePanels(int flags) {
- animateCollapsePanels(flags, false /* force */, false /* delayed */);
+ animateCollapsePanels(flags, false /* force */, false /* delayed */,
+ 1.0f /* speedUpFactor */);
}
public void animateCollapsePanels(int flags, boolean force) {
- animateCollapsePanels(flags, force, false /* delayed*/);
+ animateCollapsePanels(flags, force, false /* delayed */, 1.0f /* speedUpFactor */);
}
public void animateCollapsePanels(int flags, boolean force, boolean delayed) {
+ animateCollapsePanels(flags, force, delayed, 1.0f /* speedUpFactor */);
+ }
+
+ public void animateCollapsePanels(int flags, boolean force, boolean delayed,
+ float speedUpFactor) {
if (!force &&
(mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)) {
runPostCollapseRunnables();
@@ -1983,7 +2018,7 @@
mStatusBarWindowManager.setStatusBarFocusable(false);
mStatusBarWindow.cancelExpandHelper();
- mStatusBarView.collapseAllPanels(true /* animate */, delayed);
+ mStatusBarView.collapseAllPanels(true /* animate */, delayed, speedUpFactor);
}
}
@@ -2026,7 +2061,7 @@
public void animateCollapseQuickSettings() {
if (mState == StatusBarState.SHADE) {
- mStatusBarView.collapseAllPanels(true, false /* delayed */);
+ mStatusBarView.collapseAllPanels(true, false /* delayed */, 1.0f /* speedUpFactor */);
}
}
@@ -2039,7 +2074,8 @@
}
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
- mStatusBarView.collapseAllPanels(/*animate=*/ false, false /* delayed*/);
+ mStatusBarView.collapseAllPanels(/*animate=*/ false, false /* delayed*/,
+ 1.0f /* speedUpFactor */);
mNotificationPanel.closeQs();
@@ -2129,7 +2165,8 @@
mStatusBarWindowState = state;
if (DEBUG_WINDOW_STATE) Log.d(TAG, "Status bar " + windowStateToString(state));
if (!showing && mState == StatusBarState.SHADE) {
- mStatusBarView.collapseAllPanels(false /* animate */, false /* delayed */);
+ mStatusBarView.collapseAllPanels(false /* animate */, false /* delayed */,
+ 1.0f /* speedUpFactor */);
}
}
if (mNavigationBarView != null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 6369d5e..194a19a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -441,7 +441,8 @@
mPhoneStatusBar.keyguardGoingAway();
}
- public void animateCollapsePanels() {
- mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
+ public void animateCollapsePanels(float speedUpFactor) {
+ mPhoneStatusBar.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */,
+ false /* delayed */, speedUpFactor);
}
}
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 78122d6..dce695d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -20,8 +20,6 @@
import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowManager;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.statusbar.ActivatableNotificationView;
@@ -166,4 +164,17 @@
@Override
public void appTransitionStarting(long startTime, long duration) {
}
+
+ @Override
+ protected void updateHeadsUp(String key, NotificationData.Entry entry, boolean shouldInterrupt,
+ boolean alertAgain) {
+ }
+
+ @Override
+ protected void setHeadsUpUser(int newUserId) {
+ }
+
+ protected boolean isSnoozedPackage(StatusBarNotification sbn) {
+ return false;
+ }
}
diff --git a/rs/jni/Android.mk b/rs/jni/Android.mk
index 0658620..94f0859 100644
--- a/rs/jni/Android.mk
+++ b/rs/jni/Android.mk
@@ -25,7 +25,6 @@
$(JNI_H_INCLUDE) \
frameworks/rs \
frameworks/base/core/jni \
- frameworks/base/libs/hwui \
$(rs_generated_include_dir)
LOCAL_CFLAGS += -Wno-unused-parameter -std=c++11
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
index 26f4232..66cc29a 100644
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ b/services/core/java/com/android/server/AssetAtlasService.java
@@ -199,6 +199,11 @@
private final ArrayList<Bitmap> mBitmaps;
private final int mPixelCount;
+ private long mNativeBitmap;
+
+ // Used for debugging only
+ private Bitmap mAtlasBitmap;
+
Renderer(ArrayList<Bitmap> bitmaps, int pixelCount) {
mBitmaps = bitmaps;
mPixelCount = pixelCount;
@@ -253,9 +258,8 @@
// We always render the atlas into a bitmap. This bitmap is then
// uploaded into the GraphicBuffer using OpenGL to swizzle the content
- final Bitmap atlasBitmap = Bitmap.createBitmap(
- buffer.getWidth(), buffer.getHeight(), Bitmap.Config.ARGB_8888);
- final Canvas canvas = new Canvas(atlasBitmap);
+ final Canvas canvas = acquireCanvas(buffer.getWidth(), buffer.getHeight());
+ if (canvas == null) return false;
final Atlas.Entry entry = new Atlas.Entry();
@@ -264,78 +268,108 @@
int mapIndex = 0;
boolean result = false;
- final long startRender = System.nanoTime();
- final int count = mBitmaps.size();
+ try {
+ final long startRender = System.nanoTime();
+ final int count = mBitmaps.size();
- for (int i = 0; i < count; i++) {
- final Bitmap bitmap = mBitmaps.get(i);
- if (atlas.pack(bitmap.getWidth(), bitmap.getHeight(), entry) != null) {
- // We have more bitmaps to pack than the current configuration
- // says, we were most likely not able to detect a change in the
- // list of preloaded drawables, abort and delete the configuration
- if (mapIndex >= mAtlasMap.length) {
- deleteDataFile();
- break;
- }
+ for (int i = 0; i < count; i++) {
+ final Bitmap bitmap = mBitmaps.get(i);
+ if (atlas.pack(bitmap.getWidth(), bitmap.getHeight(), entry) != null) {
+ // We have more bitmaps to pack than the current configuration
+ // says, we were most likely not able to detect a change in the
+ // list of preloaded drawables, abort and delete the configuration
+ if (mapIndex >= mAtlasMap.length) {
+ deleteDataFile();
+ break;
+ }
- canvas.save();
- canvas.translate(entry.x, entry.y);
- if (entry.rotated) {
- canvas.translate(bitmap.getHeight(), 0.0f);
- canvas.rotate(90.0f);
+ canvas.save();
+ canvas.translate(entry.x, entry.y);
+ if (entry.rotated) {
+ canvas.translate(bitmap.getHeight(), 0.0f);
+ canvas.rotate(90.0f);
+ }
+ canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
+ canvas.restore();
+ atlasMap[mapIndex++] = bitmap.getSkBitmap();
+ atlasMap[mapIndex++] = entry.x;
+ atlasMap[mapIndex++] = entry.y;
+ atlasMap[mapIndex++] = entry.rotated ? 1 : 0;
}
- canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
- canvas.restore();
- atlasMap[mapIndex++] = bitmap.refSkPixelRef();
- atlasMap[mapIndex++] = entry.x;
- atlasMap[mapIndex++] = entry.y;
- atlasMap[mapIndex++] = entry.rotated ? 1 : 0;
}
- }
- final long endRender = System.nanoTime();
- releaseCanvas(canvas, atlasBitmap);
- result = nUploadAtlas(buffer, atlasBitmap);
- atlasBitmap.recycle();
- final long endUpload = System.nanoTime();
+ final long endRender = System.nanoTime();
+ if (mNativeBitmap != 0) {
+ result = nUploadAtlas(buffer, mNativeBitmap);
+ }
- if (DEBUG_ATLAS) {
- float renderDuration = (endRender - startRender) / 1000.0f / 1000.0f;
- float uploadDuration = (endUpload - endRender) / 1000.0f / 1000.0f;
- Log.d(LOG_TAG, String.format("Rendered atlas in %.2fms (%.2f+%.2fms)",
- renderDuration + uploadDuration, renderDuration, uploadDuration));
+ final long endUpload = System.nanoTime();
+ if (DEBUG_ATLAS) {
+ float renderDuration = (endRender - startRender) / 1000.0f / 1000.0f;
+ float uploadDuration = (endUpload - endRender) / 1000.0f / 1000.0f;
+ Log.d(LOG_TAG, String.format("Rendered atlas in %.2fms (%.2f+%.2fms)",
+ renderDuration + uploadDuration, renderDuration, uploadDuration));
+ }
+
+ } finally {
+ releaseCanvas(canvas);
}
return result;
}
/**
+ * Returns a Canvas for the specified buffer. If {@link #DEBUG_ATLAS_TEXTURE}
+ * is turned on, the returned Canvas will render into a local bitmap that
+ * will then be saved out to disk for debugging purposes.
+ * @param width
+ * @param height
+ */
+ private Canvas acquireCanvas(int width, int height) {
+ if (DEBUG_ATLAS_TEXTURE) {
+ mAtlasBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ return new Canvas(mAtlasBitmap);
+ } else {
+ Canvas canvas = new Canvas();
+ mNativeBitmap = nAcquireAtlasCanvas(canvas, width, height);
+ return canvas;
+ }
+ }
+
+ /**
* Releases the canvas used to render into the buffer. Calling this method
* will release any resource previously acquired. If {@link #DEBUG_ATLAS_TEXTURE}
* is turend on, calling this method will write the content of the atlas
* to disk in /data/system/atlas.png for debugging.
*/
- private void releaseCanvas(Canvas canvas, Bitmap atlasBitmap) {
- canvas.setBitmap(null);
+ private void releaseCanvas(Canvas canvas) {
if (DEBUG_ATLAS_TEXTURE) {
+ canvas.setBitmap(null);
File systemDirectory = new File(Environment.getDataDirectory(), "system");
File dataFile = new File(systemDirectory, "atlas.png");
try {
FileOutputStream out = new FileOutputStream(dataFile);
- atlasBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
+ mAtlasBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
out.close();
} catch (FileNotFoundException e) {
// Ignore
} catch (IOException e) {
// Ignore
}
+
+ mAtlasBitmap.recycle();
+ mAtlasBitmap = null;
+ } else {
+ nReleaseAtlasCanvas(canvas, mNativeBitmap);
}
}
}
- private static native boolean nUploadAtlas(GraphicBuffer buffer, Bitmap bitmap);
+ private static native long nAcquireAtlasCanvas(Canvas canvas, int width, int height);
+ private static native void nReleaseAtlasCanvas(Canvas canvas, long bitmap);
+ private static native boolean nUploadAtlas(GraphicBuffer buffer, long bitmap);
@Override
public boolean isCompatible(int ppid) {
diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java
index 16689ee..a31a1a7 100644
--- a/services/core/java/com/android/server/LockSettingsService.java
+++ b/services/core/java/com/android/server/LockSettingsService.java
@@ -134,7 +134,11 @@
public void systemReady() {
migrateOldData();
- getGateKeeperService();
+ try {
+ getGateKeeperService();
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failure retrieving IGateKeeperService", e);
+ }
mStorage.prefetchUser(UserHandle.USER_OWNER);
}
@@ -695,7 +699,16 @@
return null;
}
- private synchronized IGateKeeperService getGateKeeperService() {
+ private class GateKeeperDiedRecipient implements IBinder.DeathRecipient {
+ @Override
+ public void binderDied() {
+ mGateKeeperService.asBinder().unlinkToDeath(this, 0);
+ mGateKeeperService = null;
+ }
+ }
+
+ private synchronized IGateKeeperService getGateKeeperService()
+ throws RemoteException {
if (mGateKeeperService != null) {
return mGateKeeperService;
}
@@ -703,6 +716,7 @@
final IBinder service =
ServiceManager.getService("android.service.gatekeeper.IGateKeeperService");
if (service != null) {
+ service.linkToDeath(new GateKeeperDiedRecipient(), 0);
mGateKeeperService = IGateKeeperService.Stub.asInterface(service);
return mGateKeeperService;
}
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 4c937f7..7e4df58 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -61,6 +61,7 @@
import android.os.storage.StorageVolume;
import android.os.storage.VolumeInfo;
import android.text.TextUtils;
+import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.AtomicFile;
import android.util.DebugUtils;
@@ -533,7 +534,11 @@
break;
}
case H_FSTRIM: {
- waitForReady();
+ if (!isReady()) {
+ Slog.i(TAG, "fstrim requested, but no daemon connection yet; trying again");
+ sendMessageDelayed(obtainMessage(H_FSTRIM), DateUtils.SECOND_IN_MILLIS);
+ }
+
Slog.i(TAG, "Running fstrim idle maintenance");
// Remember when we kicked it off
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 908ee22..4ee6657 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -17,6 +17,7 @@
package com.android.server;
import android.app.ActivityManager;
+import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -84,7 +85,7 @@
private static final boolean VDBG = false; // STOPSHIP if true
private static class Record {
- String pkgForDebug;
+ String callingPackage;
IBinder binder;
@@ -109,7 +110,8 @@
@Override
public String toString() {
- return "{pkgForDebug=" + pkgForDebug + " binder=" + binder + " callback=" + callback
+ return "{callingPackage=" + callingPackage + " binder=" + binder
+ + " callback=" + callback
+ " onSubscriptionsChangedListenererCallback="
+ onSubscriptionsChangedListenerCallback
+ " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
@@ -125,6 +127,8 @@
private final IBatteryStats mBatteryStats;
+ private final AppOpsManager mAppOps;
+
private boolean hasNotifySubscriptionInfoChangedOccurred = false;
private int mNumPhones;
@@ -327,6 +331,8 @@
}
}
mConnectedApns = new ArrayList<String>();
+
+ mAppOps = mContext.getSystemService(AppOpsManager.class);
}
public void systemRunning() {
@@ -340,18 +346,24 @@
}
@Override
- public void addOnSubscriptionsChangedListener(String pkgForDebug,
+ public void addOnSubscriptionsChangedListener(String callingPackage,
IOnSubscriptionsChangedListener callback) {
int callerUid = UserHandle.getCallingUserId();
int myUid = UserHandle.myUserId();
if (VDBG) {
- log("listen oscl: E pkg=" + pkgForDebug + " myUid=" + myUid
+ log("listen oscl: E pkg=" + callingPackage + " myUid=" + myUid
+ " callerUid=" + callerUid + " callback=" + callback
+ " callback.asBinder=" + callback.asBinder());
}
- /* Checks permission and throws Security exception */
- checkOnSubscriptionsChangedListenerPermission();
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.READ_PHONE_STATE, null);
+
+ if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
+ callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ return;
+ }
+
Record r = null;
synchronized (mRecords) {
@@ -372,7 +384,7 @@
}
r.onSubscriptionsChangedListenerCallback = callback;
- r.pkgForDebug = pkgForDebug;
+ r.callingPackage = callingPackage;
r.callerUid = callerUid;
r.events = 0;
if (DBG) {
@@ -401,12 +413,6 @@
remove(callback.asBinder());
}
- private void checkOnSubscriptionsChangedListenerPermission() {
- mContext.enforceCallingOrSelfPermission(
- SubscriptionManager.OnSubscriptionsChangedListener
- .PERMISSION_ON_SUBSCRIPTIONS_CHANGED, null);
- }
-
@Override
public void notifySubscriptionInfoChanged() {
if (VDBG) log("notifySubscriptionInfoChanged:");
@@ -446,12 +452,12 @@
listen(pkgForDebug, callback, events, notifyNow, subId);
}
- private void listen(String pkgForDebug, IPhoneStateListener callback, int events,
+ private void listen(String callingPackage, IPhoneStateListener callback, int events,
boolean notifyNow, int subId) {
int callerUid = UserHandle.getCallingUserId();
int myUid = UserHandle.myUserId();
if (VDBG) {
- log("listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events)
+ log("listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events)
+ " notifyNow=" + notifyNow + " subId=" + subId + " myUid=" + myUid
+ " callerUid=" + callerUid);
}
@@ -459,6 +465,14 @@
if (events != PhoneStateListener.LISTEN_NONE) {
/* Checks permission and throws Security exception */
checkListenerPermission(events);
+
+ if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
+ if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
+ callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ return;
+ }
+ }
+
synchronized (mRecords) {
// register
Record r = null;
@@ -478,7 +492,7 @@
}
r.callback = callback;
- r.pkgForDebug = pkgForDebug;
+ r.callingPackage = callingPackage;
r.callerUid = callerUid;
// Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
// force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
@@ -631,7 +645,7 @@
if (mRecords.get(i).binder == binder) {
if (DBG) {
Record r = mRecords.get(i);
- log("remove: binder=" + binder + "r.pkgForDebug" + r.pkgForDebug
+ log("remove: binder=" + binder + "r.callingPackage" + r.callingPackage
+ "r.callback" + r.callback);
}
mRecords.remove(i);
@@ -1380,7 +1394,8 @@
}
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
- android.Manifest.permission.READ_PHONE_STATE);
+ android.Manifest.permission.READ_PHONE_STATE,
+ AppOpsManager.OP_READ_PHONE_STATE);
}
private void broadcastDataConnectionStateChanged(int state,
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 0ca0c0e..770df82 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -143,75 +143,67 @@
+ ", mAuthClients = " + mAuthClient + ", mEnrollClient = " + mEnrollClient);
if (mEnrollClient != null) {
final IBinder token = mEnrollClient.token;
- if (doNotify(mEnrollClient, type, arg1, arg2, arg3)) {
- stopEnrollment(token);
+ if (dispatchNotify(mEnrollClient, type, arg1, arg2, arg3)) {
+ stopEnrollment(token, false);
+ removeClient(mEnrollClient);
}
}
if (mAuthClient != null) {
final IBinder token = mAuthClient.token;
- if (doNotify(mAuthClient, type, arg1, arg2, arg3)) {
- stopAuthentication(token);
+ if (dispatchNotify(mAuthClient, type, arg1, arg2, arg3)) {
+ stopAuthentication(token, false);
+ removeClient(mAuthClient);
}
}
if (mRemoveClient != null) {
- if (doNotify(mRemoveClient, type, arg1, arg2, arg3)) {
+ if (dispatchNotify(mRemoveClient, type, arg1, arg2, arg3)) {
removeClient(mRemoveClient);
}
}
}
- // Returns true if the operation is done, i.e. authentication completed
- boolean doNotify(ClientMonitor clientMonitor, int type, int arg1, int arg2, int arg3) {
+ /*
+ * Dispatch notify events to clients.
+ *
+ * @return true if the operation is done, i.e. authentication completed
+ */
+ boolean dispatchNotify(ClientMonitor clientMonitor, int type, int arg1, int arg2, int arg3) {
ContentResolver contentResolver = mContext.getContentResolver();
boolean operationCompleted = false;
+ int fpId;
+ int groupId;
+ int remaining;
+ int acquireInfo;
switch (type) {
case FINGERPRINT_ERROR:
- {
- final int error = arg1;
- clientMonitor.sendError(error);
- removeClient(clientMonitor);
- operationCompleted = true; // any error means the operation is done
- }
+ fpId = arg1;
+ operationCompleted = clientMonitor.sendError(fpId);
break;
case FINGERPRINT_ACQUIRED:
- clientMonitor.sendAcquired(arg1 /* acquireInfo */);
+ acquireInfo = arg1;
+ operationCompleted = clientMonitor.sendAcquired(acquireInfo);
break;
case FINGERPRINT_AUTHENTICATED:
- {
- final int fpId = arg1;
- final int groupId = arg2;
- clientMonitor.sendAuthenticated(fpId, groupId);
- if (fpId == 0) {
- if (clientMonitor == mAuthClient) {
- operationCompleted = handleFailedAttempt(clientMonitor);
- }
- } else {
- mLockoutReset.run(); // a valid fingerprint resets lockout
- }
- }
+ fpId = arg1;
+ groupId = arg2;
+ operationCompleted = clientMonitor.sendAuthenticated(fpId, groupId);
break;
case FINGERPRINT_TEMPLATE_ENROLLING:
- {
- final int fpId = arg1;
- final int groupId = arg2;
- final int remaining = arg3;
- clientMonitor.sendEnrollResult(fpId, groupId, remaining);
- if (remaining == 0) {
- addTemplateForUser(clientMonitor, contentResolver, fpId);
- operationCompleted = true; // enroll completed
- }
+ fpId = arg1;
+ groupId = arg2;
+ remaining = arg3;
+ operationCompleted = clientMonitor.sendEnrollResult(fpId, groupId, remaining);
+ if (remaining == 0) {
+ addTemplateForUser(clientMonitor, contentResolver, fpId);
+ operationCompleted = true; // enroll completed
}
break;
case FINGERPRINT_TEMPLATE_REMOVED:
- {
- final int fingerId = arg1;
- final int groupId = arg2;
- removeTemplateForUser(clientMonitor, contentResolver, fingerId);
- if (fingerId == 0) {
- operationCompleted = true; // remove completed
- } else {
- clientMonitor.sendRemoved(fingerId, groupId);
- }
+ fpId = arg1;
+ groupId = arg2;
+ operationCompleted = clientMonitor.sendRemoved(fpId, groupId);
+ if (fpId != 0) {
+ removeTemplateForUser(clientMonitor, contentResolver, fpId);
}
break;
}
@@ -235,7 +227,9 @@
}
private void resetFailedAttempts() {
- if (DEBUG) Slog.v(TAG, "Reset fingerprint lockout");
+ if (DEBUG && inLockoutMode()) {
+ Slog.v(TAG, "Reset fingerprint lockout");
+ }
mFailedAttempts = 0;
}
@@ -283,19 +277,21 @@
private void stopPendingOperations() {
if (mEnrollClient != null) {
- stopEnrollment(mEnrollClient.token);
+ stopEnrollment(mEnrollClient.token, true);
}
if (mAuthClient != null) {
- stopAuthentication(mAuthClient.token);
+ stopAuthentication(mAuthClient.token, true);
}
// mRemoveClient is allowed to continue
}
- void stopEnrollment(IBinder token) {
+ void stopEnrollment(IBinder token, boolean notify) {
final ClientMonitor client = mEnrollClient;
if (client == null || client.token != token) return;
int result = nativeStopEnrollment();
- client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
+ if (notify) {
+ client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
+ }
removeClient(mEnrollClient);
if (result != 0) {
Slog.w(TAG, "startEnrollCancel failed, result=" + result);
@@ -321,11 +317,13 @@
}
}
- void stopAuthentication(IBinder token) {
+ void stopAuthentication(IBinder token, boolean notify) {
final ClientMonitor client = mAuthClient;
if (client == null || client.token != token) return;
int result = nativeStopAuthentication();
- client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
+ if (notify) {
+ client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED);
+ }
removeClient(mAuthClient);
if (result != 0) {
Slog.w(TAG, "stopAuthentication failed, result=" + result);
@@ -408,74 +406,89 @@
}
}
+ /*
+ * @return true if we're done.
+ */
private boolean sendRemoved(int fingerId, int groupId) {
IFingerprintServiceReceiver rx = receiver.get();
- if (rx != null) {
- try {
- rx.onRemoved(mHalDeviceId, fingerId, groupId);
- return true;
- } catch (RemoteException e) {
- if (DEBUG) Slog.v(TAG, "Failed to invoke sendRemoved:", e);
- }
+ if (rx == null) return true; // client not listening
+ try {
+ rx.onRemoved(mHalDeviceId, fingerId, groupId);
+ return fingerId == 0;
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to notify Removed:", e);
}
- removeClient(this);
return false;
}
+ /*
+ * @return true if we're done.
+ */
private boolean sendEnrollResult(int fpId, int groupId, int remaining) {
IFingerprintServiceReceiver rx = receiver.get();
- if (rx != null) {
- try {
- rx.onEnrollResult(mHalDeviceId, fpId, groupId, remaining);
- return true;
- } catch (RemoteException e) {
- if (DEBUG) Slog.v(TAG, "Failed to invoke sendEnrollResult:", e);
- }
+ if (rx == null) return true; // client not listening
+ try {
+ rx.onEnrollResult(mHalDeviceId, fpId, groupId, remaining);
+ return remaining == 0;
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to notify EnrollResult:", e);
+ return true;
}
- removeClient(this);
- return false;
}
+ /*
+ * @return true if we're done.
+ */
private boolean sendAuthenticated(int fpId, int groupId) {
IFingerprintServiceReceiver rx = receiver.get();
+ boolean result = false;
if (rx != null) {
try {
rx.onAuthenticated(mHalDeviceId, fpId, groupId);
- return true;
} catch (RemoteException e) {
- if (DEBUG) Slog.v(TAG, "Failed to invoke sendProcessed:", e);
+ Slog.w(TAG, "Failed to notify Authenticated:", e);
+ result = true; // client failed
}
+ } else {
+ result = true; // client not listening
}
- removeClient(this);
- return false;
+ if (fpId <= 0) {
+ result |= handleFailedAttempt(this);
+ } else {
+ result |= true; // we have a valid fingerprint
+ mLockoutReset.run();
+ }
+ return result;
}
+ /*
+ * @return true if we're done.
+ */
private boolean sendAcquired(int acquiredInfo) {
IFingerprintServiceReceiver rx = receiver.get();
- if (rx != null) {
- try {
- rx.onAcquired(mHalDeviceId, acquiredInfo);
- return true;
- } catch (RemoteException e) {
- if (DEBUG) Slog.v(TAG, "Failed to invoke sendAcquired:", e);
- }
+ if (rx == null) return true; // client not listening
+ try {
+ rx.onAcquired(mHalDeviceId, acquiredInfo);
+ return false; // acquisition continues...
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to invoke sendAcquired:", e);
+ return true; // client failed
}
- removeClient(this);
- return false;
}
+ /*
+ * @return true if we're done.
+ */
private boolean sendError(int error) {
IFingerprintServiceReceiver rx = receiver.get();
if (rx != null) {
try {
rx.onError(mHalDeviceId, error);
- return true;
} catch (RemoteException e) {
- if (DEBUG) Slog.v(TAG, "Failed to invoke sendError:", e);
+ Slog.w(TAG, "Failed to invoke sendError:", e);
}
}
- removeClient(this);
- return false;
+ return true; // errors always terminate progress
}
}
@@ -507,7 +520,7 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- stopEnrollment(token);
+ stopEnrollment(token, true);
}
});
}
@@ -533,7 +546,7 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- stopAuthentication(token);
+ stopAuthentication(token, true);
}
});
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 5de7d42..4e90f97 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -74,6 +74,7 @@
import android.Manifest;
import android.app.ActivityManager;
import android.app.AppGlobals;
+import android.app.AppOpsManager;
import android.app.IActivityManager;
import android.app.INotificationManager;
import android.app.IProcessObserver;
@@ -136,6 +137,7 @@
import android.util.TrustedTime;
import android.util.Xml;
+import com.android.server.AppOpsService;
import libcore.io.IoUtils;
import com.android.internal.R;
@@ -292,6 +294,8 @@
private final AtomicFile mPolicyFile;
+ private final AppOpsManager mAppOps;
+
// TODO: keep whitelist of system-critical services that should never have
// rules enforced, such as system, phone, and radio UIDs.
@@ -326,6 +330,8 @@
mSuppressDefaultPolicy = suppressDefaultPolicy;
mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
+
+ mAppOps = context.getSystemService(AppOpsManager.class);
}
public void bindConnectivityManager(IConnectivityManager connManager) {
@@ -1593,16 +1599,21 @@
}
void addNetworkPolicyLocked(NetworkPolicy policy) {
- NetworkPolicy[] policies = getNetworkPolicies();
+ NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
policies = ArrayUtils.appendElement(NetworkPolicy.class, policies, policy);
setNetworkPolicies(policies);
}
@Override
- public NetworkPolicy[] getNetworkPolicies() {
+ public NetworkPolicy[] getNetworkPolicies(String callingPackage) {
mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
+ if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
+ callingPackage) != AppOpsManager.MODE_ALLOWED) {
+ return new NetworkPolicy[0];
+ }
+
synchronized (mRulesLock) {
final int size = mNetworkPolicy.size();
final NetworkPolicy[] policies = new NetworkPolicy[size];
@@ -1614,7 +1625,7 @@
}
private void normalizePoliciesLocked() {
- normalizePoliciesLocked(getNetworkPolicies());
+ normalizePoliciesLocked(getNetworkPolicies(mContext.getOpPackageName()));
}
private void normalizePoliciesLocked(NetworkPolicy[] policies) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 964dcc2..f29d524 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -709,6 +709,11 @@
private WindowContentFrameStats mTempWindowRenderStats;
final class DragInputEventReceiver extends InputEventReceiver {
+ // Set, if stylus button was down at the start of the drag.
+ private boolean mStylusButtonDownAtStart;
+ // Indicates the first event to check for button state.
+ private boolean mIsStartEvent = true;
+
public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
super(inputChannel, looper);
}
@@ -724,6 +729,18 @@
boolean endDrag = false;
final float newX = motionEvent.getRawX();
final float newY = motionEvent.getRawY();
+ final boolean isStylusButtonDown =
+ (motionEvent.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS)
+ && (motionEvent.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0;
+
+ if (mIsStartEvent) {
+ if (isStylusButtonDown) {
+ // First event and the button was down, check for the button being
+ // lifted in the future, if that happens we'll drop the item.
+ mStylusButtonDownAtStart = true;
+ }
+ mIsStartEvent = false;
+ }
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN: {
@@ -733,9 +750,17 @@
} break;
case MotionEvent.ACTION_MOVE: {
- synchronized (mWindowMap) {
- // move the surface and tell the involved window(s) where we are
- mDragState.notifyMoveLw(newX, newY);
+ if (mStylusButtonDownAtStart && !isStylusButtonDown) {
+ if (DEBUG_DRAG) Slog.d(TAG, "Button no longer pressed; dropping at "
+ + newX + "," + newY);
+ synchronized (mWindowMap) {
+ endDrag = mDragState.notifyDropLw(newX, newY);
+ }
+ } else {
+ synchronized (mWindowMap) {
+ // move the surface and tell the involved window(s) where we are
+ mDragState.notifyMoveLw(newX, newY);
+ }
}
} break;
@@ -759,6 +784,8 @@
synchronized (mWindowMap) {
mDragState.endDragLw();
}
+ mStylusButtonDownAtStart = false;
+ mIsStartEvent = true;
}
handled = true;
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index a5546cf..19ca2b4 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -33,7 +33,6 @@
$(JNI_H_INCLUDE) \
frameworks/base/services \
frameworks/base/libs \
- frameworks/base/libs/hwui \
frameworks/base/core/jni \
frameworks/native/services \
libcore/include \
diff --git a/services/core/jni/com_android_server_AssetAtlasService.cpp b/services/core/jni/com_android_server_AssetAtlasService.cpp
index 8f4fb51..e4f242e 100644
--- a/services/core/jni/com_android_server_AssetAtlasService.cpp
+++ b/services/core/jni/com_android_server_AssetAtlasService.cpp
@@ -47,9 +47,40 @@
#define FENCE_TIMEOUT 2000000000
// ----------------------------------------------------------------------------
+// JNI Helpers
+// ----------------------------------------------------------------------------
+
+static struct {
+ jmethodID setNativeBitmap;
+} gCanvasClassInfo;
+
+#define INVOKEV(object, method, ...) \
+ env->CallVoidMethod(object, method, __VA_ARGS__)
+
+// ----------------------------------------------------------------------------
// Canvas management
// ----------------------------------------------------------------------------
+static jlong com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject,
+ jobject canvas, jint width, jint height) {
+
+ SkBitmap* bitmap = new SkBitmap;
+ bitmap->allocN32Pixels(width, height);
+ bitmap->eraseColor(0);
+ INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, reinterpret_cast<jlong>(bitmap));
+
+ return reinterpret_cast<jlong>(bitmap);
+}
+
+static void com_android_server_AssetAtlasService_releaseCanvas(JNIEnv* env, jobject,
+ jobject canvas, jlong bitmapHandle) {
+
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ INVOKEV(canvas, gCanvasClassInfo.setNativeBitmap, (jlong)0);
+
+ delete bitmap;
+}
+
#define CLEANUP_GL_AND_RETURN(result) \
if (fence != EGL_NO_SYNC_KHR) eglDestroySyncKHR(display, fence); \
if (image) eglDestroyImageKHR(display, image); \
@@ -62,12 +93,9 @@
return result;
static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject,
- jobject graphicBuffer, jobject bitmapHandle) {
+ jobject graphicBuffer, jlong bitmapHandle) {
- SkBitmap bitmap;
- GraphicsJNI::getSkBitmap(env, bitmapHandle, &bitmap);
- SkAutoLockPixels alp(bitmap);
-
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
// The goal of this method is to copy the bitmap into the GraphicBuffer
// using the GPU to swizzle the texture content
sp<GraphicBuffer> buffer(graphicBufferForJavaObject(env, graphicBuffer));
@@ -158,9 +186,9 @@
}
// Upload the content of the bitmap in the GraphicBuffer
- glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap.bytesPerPixel());
- glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
- GL_RGBA, GL_UNSIGNED_BYTE, bitmap.getPixels());
+ glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap->width(), bitmap->height(),
+ GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
if (glGetError() != GL_NO_ERROR) {
ALOGW("Could not upload to texture");
CLEANUP_GL_AND_RETURN(JNI_FALSE);
@@ -205,11 +233,20 @@
const char* const kClassPathName = "com/android/server/AssetAtlasService";
static JNINativeMethod gMethods[] = {
- { "nUploadAtlas", "(Landroid/view/GraphicBuffer;Landroid/graphics/Bitmap;)Z",
+ { "nAcquireAtlasCanvas", "(Landroid/graphics/Canvas;II)J",
+ (void*) com_android_server_AssetAtlasService_acquireCanvas },
+ { "nReleaseAtlasCanvas", "(Landroid/graphics/Canvas;J)V",
+ (void*) com_android_server_AssetAtlasService_releaseCanvas },
+ { "nUploadAtlas", "(Landroid/view/GraphicBuffer;J)Z",
(void*) com_android_server_AssetAtlasService_upload },
};
int register_android_server_AssetAtlasService(JNIEnv* env) {
+ jclass clazz;
+
+ FIND_CLASS(clazz, "android/graphics/Canvas");
+ GET_METHOD_ID(gCanvasClassInfo.setNativeBitmap, clazz, "setNativeBitmap", "(J)V");
+
return jniRegisterNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
}
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 5abbb50..a72172c 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -359,7 +359,8 @@
public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme) {
try {
if (isServiceConnected()) {
- return getTelecomService().getDefaultOutgoingPhoneAccount(uriScheme);
+ return getTelecomService().getDefaultOutgoingPhoneAccount(uriScheme,
+ mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getDefaultOutgoingPhoneAccount", e);
@@ -443,7 +444,7 @@
public List<PhoneAccountHandle> getSimCallManagers() {
try {
if (isServiceConnected()) {
- return getTelecomService().getSimCallManagers();
+ return getTelecomService().getSimCallManagers(mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getSimCallManagers");
@@ -491,7 +492,8 @@
public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) {
try {
if (isServiceConnected()) {
- return getTelecomService().getPhoneAccountsSupportingScheme(uriScheme);
+ return getTelecomService().getPhoneAccountsSupportingScheme(uriScheme,
+ mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getPhoneAccountsSupportingScheme", e);
@@ -511,7 +513,7 @@
public List<PhoneAccountHandle> getCallCapablePhoneAccounts() {
try {
if (isServiceConnected()) {
- return getTelecomService().getCallCapablePhoneAccounts();
+ return getTelecomService().getCallCapablePhoneAccounts(mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#getCallCapablePhoneAccounts", e);
@@ -711,7 +713,8 @@
public boolean isVoiceMailNumber(PhoneAccountHandle accountHandle, String number) {
try {
if (isServiceConnected()) {
- return getTelecomService().isVoiceMailNumber(accountHandle, number);
+ return getTelecomService().isVoiceMailNumber(accountHandle, number,
+ mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling ITelecomService#isVoiceMailNumber.", e);
@@ -729,7 +732,8 @@
public String getVoiceMailNumber(PhoneAccountHandle accountHandle) {
try {
if (isServiceConnected()) {
- return getTelecomService().getVoiceMailNumber(accountHandle);
+ return getTelecomService().getVoiceMailNumber(accountHandle,
+ mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling ITelecomService#hasVoiceMailNumber.", e);
@@ -746,7 +750,8 @@
public String getLine1Number(PhoneAccountHandle accountHandle) {
try {
if (isServiceConnected()) {
- return getTelecomService().getLine1Number(accountHandle);
+ return getTelecomService().getLine1Number(accountHandle,
+ mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling ITelecomService#getLine1Number.", e);
@@ -764,7 +769,7 @@
public boolean isInCall() {
try {
if (isServiceConnected()) {
- return getTelecomService().isInCall();
+ return getTelecomService().isInCall(mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException calling isInCall().", e);
@@ -806,7 +811,7 @@
public boolean isRinging() {
try {
if (isServiceConnected()) {
- return getTelecomService().isRinging();
+ return getTelecomService().isRinging(mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException attempting to get ringing state of phone app.", e);
@@ -872,7 +877,7 @@
public boolean isTtySupported() {
try {
if (isServiceConnected()) {
- return getTelecomService().isTtySupported();
+ return getTelecomService().isTtySupported(mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException attempting to get TTY supported state.", e);
@@ -893,7 +898,7 @@
public int getCurrentTtyMode() {
try {
if (isServiceConnected()) {
- return getTelecomService().getCurrentTtyMode();
+ return getTelecomService().getCurrentTtyMode(mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "RemoteException attempting to get the current TTY mode.", e);
@@ -1045,7 +1050,7 @@
ITelecomService service = getTelecomService();
if (service != null) {
try {
- service.showInCallScreen(showDialpad);
+ service.showInCallScreen(showDialpad, mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#showCallScreen", e);
}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
index 35db97f..727fd4bb 100644
--- a/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
+++ b/telecomm/java/com/android/internal/telecom/ITelecomService.aidl
@@ -33,12 +33,12 @@
*
* @param showDialpad if true, make the dialpad visible initially.
*/
- void showInCallScreen(boolean showDialpad);
+ void showInCallScreen(boolean showDialpad, String callingPackage);
/**
* @see TelecomServiceImpl#getDefaultOutgoingPhoneAccount
*/
- PhoneAccountHandle getDefaultOutgoingPhoneAccount(in String uriScheme);
+ PhoneAccountHandle getDefaultOutgoingPhoneAccount(in String uriScheme, String callingPackage);
/**
* @see TelecomServiceImpl#getUserSelectedOutgoingPhoneAccount
@@ -53,12 +53,13 @@
/**
* @see TelecomServiceImpl#getCallCapablePhoneAccounts
*/
- List<PhoneAccountHandle> getCallCapablePhoneAccounts();
+ List<PhoneAccountHandle> getCallCapablePhoneAccounts(String callingPackage);
/**
* @see TelecomManager#getPhoneAccountsSupportingScheme
*/
- List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme);
+ List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme,
+ String callingPackage);
/**
* @see TelecomManager#getPhoneAccountsForPackage
@@ -98,7 +99,7 @@
/**
* @see TelecomServiceImpl#getSimCallManagers
*/
- List<PhoneAccountHandle> getSimCallManagers();
+ List<PhoneAccountHandle> getSimCallManagers(String callingPackage);
/**
* @see TelecomServiceImpl#registerPhoneAccount
@@ -118,17 +119,18 @@
/**
* @see TelecomServiceImpl#isVoiceMailNumber
*/
- boolean isVoiceMailNumber(in PhoneAccountHandle accountHandle, String number);
+ boolean isVoiceMailNumber(in PhoneAccountHandle accountHandle, String number,
+ String callingPackage);
/**
* @see TelecomServiceImpl#getVoiceMailNumber
*/
- String getVoiceMailNumber(in PhoneAccountHandle accountHandle);
+ String getVoiceMailNumber(in PhoneAccountHandle accountHandle, String callingPackage);
/**
* @see TelecomServiceImpl#getLine1Number
*/
- String getLine1Number(in PhoneAccountHandle accountHandle);
+ String getLine1Number(in PhoneAccountHandle accountHandle, String callingPackage);
/**
* @see TelecomServiceImpl#getDefaultPhoneApp
@@ -147,12 +149,12 @@
/**
* @see TelecomServiceImpl#isInCall
*/
- boolean isInCall();
+ boolean isInCall(String callingPackage);
/**
* @see TelecomServiceImpl#isRinging
*/
- boolean isRinging();
+ boolean isRinging(String callingPackage);
/**
* @see TelecomServiceImpl#getCallState
@@ -192,12 +194,12 @@
/**
* @see TelecomServiceImpl#isTtySupported
*/
- boolean isTtySupported();
+ boolean isTtySupported(String callingPackage);
/**
* @see TelecomServiceImpl#getCurrentTtyMode
*/
- int getCurrentTtyMode();
+ int getCurrentTtyMode(String callingPackage);
/**
* @see TelecomServiceImpl#addNewIncomingCall
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index b1fb3a6..d103fbf 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -85,7 +85,6 @@
*
* @hide
*/
- @SystemApi
public static final String STRING_VVM_DESTINATION_NUMBER = "string_vvm_destination_number";
/**
@@ -93,15 +92,13 @@
*
* @hide
*/
- @SystemApi
- public static final String SHORT_VVM_PORT_NUMBER = "string_vvm_port_number";
+ public static final String INT_VVM_PORT_NUMBER = "int_vvm_port_number";
/**
* The type of visual voicemail protocol the carrier adheres to (see below).
*
* @hide
*/
- @SystemApi
public static final String STRING_VVM_TYPE = "string_vvm_type";
/* Visual voicemail protocols */
@@ -111,7 +108,6 @@
*
* @hide
*/
- @SystemApi
public static final String VVM_TYPE_OMTP = "vvm_type_omtp";
private final static String TAG = "CarrierConfigManager";
@@ -127,6 +123,10 @@
sDefaults.putBoolean(BOOL_SHOW_APN_SETTING_CDMA, false);
sDefaults.putInt(INT_VOLTE_REPLACEMENT_RAT, 0);
+
+ sDefaults.putString(STRING_VVM_DESTINATION_NUMBER, "");
+ sDefaults.putString(STRING_VVM_TYPE, "");
+ sDefaults.putInt(INT_VVM_PORT_NUMBER, 0);
}
/**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 08aec08..3ecf5ac 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -272,10 +272,6 @@
* for #onSubscriptionsChanged to be invoked.
*/
public static class OnSubscriptionsChangedListener {
- /** @hide */
- public static final String PERMISSION_ON_SUBSCRIPTIONS_CHANGED =
- android.Manifest.permission.READ_PHONE_STATE;
-
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 128f6e3..cd3f636 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -664,7 +664,7 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getDeviceId();
+ return telephony.getDeviceId(mContext.getOpPackageName());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -1975,7 +1975,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- number = telephony.getLine1NumberForDisplay(subId);
+ number = telephony.getLine1NumberForDisplay(subId, mContext.getOpPackageName());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -2096,7 +2096,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- alphaTag = telephony.getLine1AlphaTagForDisplay(subId);
+ alphaTag = telephony.getLine1AlphaTagForDisplay(subId,
+ mContext.getOpPackageName());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -3342,7 +3343,7 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return new String[0];
- return telephony.getPcscfAddress(apnType);
+ return telephony.getPcscfAddress(apnType, mContext.getOpPackageName());
} catch (RemoteException e) {
return new String[0];
}
@@ -3759,7 +3760,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.isSimPinEnabled();
+ return telephony.isSimPinEnabled(mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isSimPinEnabled", e);
}
@@ -4026,7 +4027,7 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null)
- return telephony.isVideoCallingEnabled();
+ return telephony.isVideoCallingEnabled(mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#isVideoCallingEnabled", e);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index a24859b..4fe88c4 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -45,6 +45,7 @@
/**
* Place a call to the specified number.
+ * @param callingPackage The package making the call.
* @param number the number to be called.
*/
void call(String callingPackage, String number);
@@ -169,8 +170,9 @@
/**
* Check if the SIM pin lock is enabled.
* @return true if the SIM pin lock is enabled.
+ * @param callingPackage The package making the call.
*/
- boolean isSimPinEnabled();
+ boolean isSimPinEnabled(String callingPackage);
/**
* Supply a pin to unlock the SIM. Blocks until a result is determined.
@@ -644,10 +646,11 @@
/*
* Get the calculated preferred network type.
* Used for device configuration by some CDMA operators.
+ * @param callingPackage The package making the call.
*
* @return the calculated preferred network type, defined in RILConstants.java.
*/
- int getCalculatedPreferredNetworkType();
+ int getCalculatedPreferredNetworkType(String callingPackage);
/*
* Get the preferred network type.
@@ -701,8 +704,9 @@
/**
* Get P-CSCF address from PCO after data connection is established or modified.
* @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
+ * @param callingPackage The package making the call.
*/
- String[] getPcscfAddress(String apnType);
+ String[] getPcscfAddress(String apnType, String callingPackage);
/**
* Set IMS registration state
@@ -768,19 +772,21 @@
* {@link #setLine1NumberForDisplay}. Otherwise returns null.
*
* @param subId whose dialing number for line 1 is returned.
+ * @param callingPackage The package making the call.
* @return the displayed dialing number if set, or null if not set.
*/
- String getLine1NumberForDisplay(int subId);
+ String getLine1NumberForDisplay(int subId, String callingPackage);
/**
* Returns the displayed alphatag of the dialing number if it was set
* previously via {@link #setLine1NumberForDisplay}. Otherwise returns null.
*
* @param subId whose alphatag associated with line 1 is returned.
+ * @param callingPackage The package making the call.
* @return the displayed alphatag of the dialing number if set, or null if
* not set.
*/
- String getLine1AlphaTagForDisplay(int subId);
+ String getLine1AlphaTagForDisplay(int subId, String callingPackage);
String[] getMergedSubscriberIds();
@@ -872,9 +878,10 @@
/**
* Whether video calling has been enabled by the user.
*
+ * @param callingPackage The package making the call.
* @return {@code true} if the user has enabled video calling, {@code false} otherwise.
*/
- boolean isVideoCallingEnabled();
+ boolean isVideoCallingEnabled(String callingPackage);
/**
* Whether the DTMF tone length can be changed.
@@ -925,10 +932,11 @@
* Returns the unique device ID of phone, for example, the IMEI for
* GSM and the MEID for CDMA phones. Return null if device ID is not available.
*
+ * @param callingPackage The package making the call.
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
*/
- String getDeviceId();
+ String getDeviceId(String callingPackage);
/**
* Returns the subscription ID associated with the specified PhoneAccount.
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index b265d47..04ded9d 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -354,6 +354,13 @@
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public void sendBroadcastAsUser(Intent intent, UserHandle user,
+ String receiverPermission, int appOp) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,